xref: /freebsd/sys/dev/usb/input/usbhid.c (revision 6b3a9a0f3d2cd66145e89fdd8d07cb33a9963e8f)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
3  *
4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
5  * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org>
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Lennart Augustsson (lennart@augustsson.net) at
9  * Carlstedt Research & Technology.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 /*
37  * HID spec: https://www.usb.org/sites/default/files/documents/hid1_11.pdf
38  */
39 
40 #include <sys/stdint.h>
41 #include <sys/stddef.h>
42 #include <sys/param.h>
43 #include <sys/queue.h>
44 #include <sys/types.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/bus.h>
48 #include <sys/module.h>
49 #include <sys/lock.h>
50 #include <sys/mutex.h>
51 #include <sys/condvar.h>
52 #include <sys/sysctl.h>
53 #include <sys/sx.h>
54 #include <sys/unistd.h>
55 #include <sys/callout.h>
56 #include <sys/malloc.h>
57 #include <sys/priv.h>
58 #include <sys/conf.h>
59 #include <sys/fcntl.h>
60 
61 #include <dev/evdev/input.h>
62 
63 #include <dev/hid/hid.h>
64 #include <dev/hid/hidquirk.h>
65 
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbdi.h>
68 #include <dev/usb/usbdi_util.h>
69 #include <dev/usb/usbhid.h>
70 
71 #define	USB_DEBUG_VAR usbhid_debug
72 #include <dev/usb/usb_debug.h>
73 
74 #include <dev/usb/quirk/usb_quirk.h>
75 
76 #include "hid_if.h"
77 
78 #ifdef USB_DEBUG
79 static int usbhid_debug = 0;
80 
81 static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid");
82 SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, debug, CTLFLAG_RWTUN,
83     &usbhid_debug, 0, "Debug level");
84 #endif
85 
86 enum {
87 	USBHID_INTR_OUT_DT,
88 	USBHID_INTR_IN_DT,
89 	USBHID_CTRL_DT,
90 	USBHID_N_TRANSFER,
91 };
92 
93 struct usbhid_xfer_ctx;
94 typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
95 
96 union usbhid_device_request {
97 	struct {			/* INTR xfers */
98 		uint16_t maxlen;
99 		uint16_t actlen;
100 	} intr;
101 	struct usb_device_request ctrl;	/* CTRL xfers */
102 };
103 
104 /* Syncronous USB transfer context */
105 struct usbhid_xfer_ctx {
106 	union usbhid_device_request req;
107 	uint8_t *buf;
108 	int error;
109 	usbhid_callback_t *cb;
110 	void *cb_ctx;
111 	int waiters;
112 	bool influx;
113 };
114 
115 struct usbhid_softc {
116 	hid_intr_t *sc_intr_handler;
117 	void *sc_intr_ctx;
118 	void *sc_intr_buf;
119 
120 	struct hid_device_info sc_hw;
121 
122 	struct mtx sc_mtx;
123 	struct usb_config sc_config[USBHID_N_TRANSFER];
124 	struct usb_xfer *sc_xfer[USBHID_N_TRANSFER];
125 	struct usbhid_xfer_ctx sc_xfer_ctx[USBHID_N_TRANSFER];
126 
127 	struct usb_device *sc_udev;
128 	uint8_t	sc_iface_no;
129 	uint8_t	sc_iface_index;
130 };
131 
132 /* prototypes */
133 
134 static device_probe_t usbhid_probe;
135 static device_attach_t usbhid_attach;
136 static device_detach_t usbhid_detach;
137 
138 static usb_callback_t usbhid_intr_out_callback;
139 static usb_callback_t usbhid_intr_in_callback;
140 static usb_callback_t usbhid_ctrl_callback;
141 
142 static usbhid_callback_t usbhid_intr_handler_cb;
143 static usbhid_callback_t usbhid_sync_wakeup_cb;
144 
145 static void
146 usbhid_intr_out_callback(struct usb_xfer *xfer, usb_error_t error)
147 {
148 	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
149 	struct usb_page_cache *pc;
150 	int len;
151 
152 	switch (USB_GET_STATE(xfer)) {
153 	case USB_ST_TRANSFERRED:
154 	case USB_ST_SETUP:
155 tr_setup:
156 		len = xfer_ctx->req.intr.maxlen;
157 		if (len == 0) {
158 			if (USB_IN_POLLING_MODE_FUNC())
159 				xfer_ctx->error = 0;
160 			return;
161 		}
162 		pc = usbd_xfer_get_frame(xfer, 0);
163 		usbd_copy_in(pc, 0, xfer_ctx->buf, len);
164 		usbd_xfer_set_frame_len(xfer, 0, len);
165 		usbd_transfer_submit(xfer);
166 		xfer_ctx->req.intr.maxlen = 0;
167 		if (USB_IN_POLLING_MODE_FUNC())
168 			return;
169 		xfer_ctx->error = 0;
170 		goto tr_exit;
171 
172 	default:			/* Error */
173 		if (error != USB_ERR_CANCELLED) {
174 			/* try to clear stall first */
175 			usbd_xfer_set_stall(xfer);
176 			goto tr_setup;
177 		}
178 		xfer_ctx->error = EIO;
179 tr_exit:
180 		(void)xfer_ctx->cb(xfer_ctx);
181 		return;
182 	}
183 }
184 
185 static void
186 usbhid_intr_in_callback(struct usb_xfer *xfer, usb_error_t error)
187 {
188 	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
189 	struct usb_page_cache *pc;
190 	int actlen;
191 
192 	switch (USB_GET_STATE(xfer)) {
193 	case USB_ST_TRANSFERRED:
194 		DPRINTF("transferred!\n");
195 
196 		usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
197 		pc = usbd_xfer_get_frame(xfer, 0);
198 		usbd_copy_out(pc, 0, xfer_ctx->buf, actlen);
199 		xfer_ctx->req.intr.actlen = actlen;
200 		if (xfer_ctx->cb(xfer_ctx) != 0)
201 			return;
202 
203 	case USB_ST_SETUP:
204 re_submit:
205 		usbd_xfer_set_frame_len(xfer, 0, xfer_ctx->req.intr.maxlen);
206 		usbd_transfer_submit(xfer);
207 		return;
208 
209 	default:			/* Error */
210 		if (error != USB_ERR_CANCELLED) {
211 			/* try to clear stall first */
212 			usbd_xfer_set_stall(xfer);
213 			goto re_submit;
214 		}
215 		return;
216 	}
217 }
218 
219 static void
220 usbhid_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
221 {
222 	struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
223 	struct usb_device_request *req = &xfer_ctx->req.ctrl;
224 	struct usb_page_cache *pc;
225 	int len = UGETW(req->wLength);
226 	bool is_rd = (req->bmRequestType & UT_READ) != 0;
227 
228 	switch (USB_GET_STATE(xfer)) {
229 	case USB_ST_SETUP:
230 		if (!is_rd && len != 0) {
231 			pc = usbd_xfer_get_frame(xfer, 1);
232 			usbd_copy_in(pc, 0, xfer_ctx->buf, len);
233 		}
234 
235 		pc = usbd_xfer_get_frame(xfer, 0);
236 		usbd_copy_in(pc, 0, req, sizeof(*req));
237 		usbd_xfer_set_frame_len(xfer, 0, sizeof(*req));
238 		if (len != 0)
239 			usbd_xfer_set_frame_len(xfer, 1, len);
240 		usbd_xfer_set_frames(xfer, len != 0 ? 2 : 1);
241 		usbd_transfer_submit(xfer);
242 		return;
243 
244 	case USB_ST_TRANSFERRED:
245 		if (is_rd && len != 0) {
246 			pc = usbd_xfer_get_frame(xfer, 0);
247 			usbd_copy_out(pc, sizeof(*req), xfer_ctx->buf, len);
248 		}
249 		xfer_ctx->error = 0;
250 		goto tr_exit;
251 
252 	default:			/* Error */
253 		/* bomb out */
254 		DPRINTFN(1, "error=%s\n", usbd_errstr(error));
255 		xfer_ctx->error = EIO;
256 tr_exit:
257 		(void)xfer_ctx->cb(xfer_ctx);
258 		return;
259 	}
260 }
261 
262 static int
263 usbhid_intr_handler_cb(struct usbhid_xfer_ctx *xfer_ctx)
264 {
265 	struct usbhid_softc *sc = xfer_ctx->cb_ctx;
266 
267 	sc->sc_intr_handler(sc->sc_intr_ctx, xfer_ctx->buf,
268 	    xfer_ctx->req.intr.actlen);
269 
270 	return (0);
271 }
272 
273 static int
274 usbhid_sync_wakeup_cb(struct usbhid_xfer_ctx *xfer_ctx)
275 {
276 
277 	if (!USB_IN_POLLING_MODE_FUNC())
278 		wakeup(xfer_ctx->cb_ctx);
279 
280 	return (ECANCELED);
281 }
282 
283 static const struct usb_config usbhid_config[USBHID_N_TRANSFER] = {
284 
285 	[USBHID_INTR_OUT_DT] = {
286 		.type = UE_INTERRUPT,
287 		.endpoint = UE_ADDR_ANY,
288 		.direction = UE_DIR_OUT,
289 		.flags = {.pipe_bof = 1,.proxy_buffer = 1},
290 		.callback = &usbhid_intr_out_callback,
291 	},
292 	[USBHID_INTR_IN_DT] = {
293 		.type = UE_INTERRUPT,
294 		.endpoint = UE_ADDR_ANY,
295 		.direction = UE_DIR_IN,
296 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
297 		.callback = &usbhid_intr_in_callback,
298 	},
299 	[USBHID_CTRL_DT] = {
300 		.type = UE_CONTROL,
301 		.endpoint = 0x00,	/* Control pipe */
302 		.direction = UE_DIR_ANY,
303 		.flags = {.proxy_buffer = 1},
304 		.callback = &usbhid_ctrl_callback,
305 		.timeout = 1000,	/* 1 second */
306 	},
307 };
308 
309 static void
310 usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context,
311     struct hid_rdesc_info *rdesc)
312 {
313 	struct usbhid_softc* sc = device_get_softc(dev);
314 	uint16_t n;
315 	bool nowrite;
316 	int error;
317 
318 	sc->sc_intr_handler = intr;
319 	sc->sc_intr_ctx = context;
320 	bcopy(usbhid_config, sc->sc_config, sizeof(usbhid_config));
321 
322 	/* Set buffer sizes to match HID report sizes */
323 	sc->sc_config[USBHID_INTR_OUT_DT].bufsize = rdesc->osize;
324 	sc->sc_config[USBHID_INTR_IN_DT].bufsize = rdesc->isize;
325 	sc->sc_config[USBHID_CTRL_DT].bufsize =
326 	    MAX(rdesc->isize, MAX(rdesc->osize, rdesc->fsize));
327 
328 	nowrite = hid_test_quirk(&sc->sc_hw, HQ_NOWRITE);
329 
330 	/*
331 	 * Setup the USB transfers one by one, so they are memory independent
332 	 * which allows for handling panics triggered by the HID drivers
333 	 * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
334 	 * keyboard driver was processing a key at the moment of panic.
335 	 */
336 	for (n = 0; n != USBHID_N_TRANSFER; n++) {
337 		if (nowrite && n == USBHID_INTR_OUT_DT)
338 			continue;
339 		error = usbd_transfer_setup(sc->sc_udev, &sc->sc_iface_index,
340 		    sc->sc_xfer + n, sc->sc_config + n, 1,
341 		    (void *)(sc->sc_xfer_ctx + n), &sc->sc_mtx);
342 		if (error)
343 			break;
344 	}
345 
346 	if (error)
347 		DPRINTF("error=%s\n", usbd_errstr(error));
348 
349 	rdesc->rdsize = usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]);
350 	rdesc->grsize = usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]);
351 	rdesc->srsize = rdesc->grsize;
352 	rdesc->wrsize = nowrite ? rdesc->srsize :
353 	    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]);
354 
355 	sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
356 }
357 
358 static void
359 usbhid_intr_unsetup(device_t dev)
360 {
361 	struct usbhid_softc* sc = device_get_softc(dev);
362 
363 	usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
364 	free(sc->sc_intr_buf, M_USBDEV);
365 }
366 
367 static int
368 usbhid_intr_start(device_t dev)
369 {
370 	struct usbhid_softc* sc = device_get_softc(dev);
371 
372 	mtx_lock(&sc->sc_mtx);
373 	sc->sc_xfer_ctx[USBHID_INTR_IN_DT] = (struct usbhid_xfer_ctx) {
374 		.req.intr.maxlen =
375 		    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
376 		.cb = usbhid_intr_handler_cb,
377 		.cb_ctx = sc,
378 		.buf = sc->sc_intr_buf,
379 	};
380 	usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
381 	mtx_unlock(&sc->sc_mtx);
382 
383 	return (0);
384 }
385 
386 static int
387 usbhid_intr_stop(device_t dev)
388 {
389 	struct usbhid_softc* sc = device_get_softc(dev);
390 
391 	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
392 	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
393 
394 	return (0);
395 }
396 
397 static void
398 usbhid_intr_poll(device_t dev)
399 {
400 	struct usbhid_softc* sc = device_get_softc(dev);
401 
402 	usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
403 }
404 
405 /*
406  * HID interface
407  */
408 static int
409 usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx,
410     union usbhid_device_request *req, void *buf)
411 {
412 	int error, timeout;
413 	struct usbhid_xfer_ctx *xfer_ctx, save;
414 
415 	xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
416 
417 	if (USB_IN_POLLING_MODE_FUNC()) {
418 		save = *xfer_ctx;
419 	} else {
420 		mtx_lock(&sc->sc_mtx);
421 		++xfer_ctx->waiters;
422 		while (xfer_ctx->influx)
423 			mtx_sleep(&xfer_ctx->waiters, &sc->sc_mtx, 0,
424 			    "usbhid wt", 0);
425 		--xfer_ctx->waiters;
426 		xfer_ctx->influx = true;
427 	}
428 
429 	xfer_ctx->buf = buf;
430 	xfer_ctx->req = *req;
431 	xfer_ctx->error = ETIMEDOUT;
432 	xfer_ctx->cb = &usbhid_sync_wakeup_cb;
433 	xfer_ctx->cb_ctx = xfer_ctx;
434 	timeout = USB_DEFAULT_TIMEOUT;
435 	usbd_transfer_start(sc->sc_xfer[xfer_idx]);
436 
437 	if (USB_IN_POLLING_MODE_FUNC())
438 		while (timeout > 0 && xfer_ctx->error == ETIMEDOUT) {
439 			usbd_transfer_poll(sc->sc_xfer + xfer_idx, 1);
440 			DELAY(1000);
441 			timeout--;
442 		}
443 	 else
444 		msleep_sbt(xfer_ctx, &sc->sc_mtx, 0, "usbhid io",
445 		    SBT_1MS * timeout, 0, C_HARDCLOCK);
446 
447 	/* Perform usbhid_write() asyncronously to improve pipelining */
448 	if (USB_IN_POLLING_MODE_FUNC() || xfer_ctx->error != 0 ||
449 	    sc->sc_config[xfer_idx].type != UE_INTERRUPT ||
450 	    sc->sc_config[xfer_idx].direction != UE_DIR_OUT)
451 		usbd_transfer_stop(sc->sc_xfer[xfer_idx]);
452 	error = xfer_ctx->error;
453 	if (error == 0)
454 		*req = xfer_ctx->req;
455 
456 	if (USB_IN_POLLING_MODE_FUNC()) {
457 		*xfer_ctx = save;
458 	} else {
459 		xfer_ctx->influx = false;
460 		if (xfer_ctx->waiters != 0)
461 			wakeup_one(&xfer_ctx->waiters);
462 		mtx_unlock(&sc->sc_mtx);
463 	}
464 
465 	if (error)
466 		DPRINTF("USB IO error:%d\n", error);
467 
468 	return (error);
469 }
470 
471 static int
472 usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
473 {
474 	struct usbhid_softc* sc = device_get_softc(dev);
475 	int error;
476 
477 	error = usbd_req_get_report_descriptor(sc->sc_udev, NULL,
478 	    buf, len, sc->sc_iface_index);
479 
480 	if (error)
481 		DPRINTF("no report descriptor: %s\n", usbd_errstr(error));
482 
483 	return (error == 0 ? 0 : ENXIO);
484 }
485 
486 static int
487 usbhid_get_report(device_t dev, void *buf, hid_size_t maxlen,
488     hid_size_t *actlen, uint8_t type, uint8_t id)
489 {
490 	struct usbhid_softc* sc = device_get_softc(dev);
491 	union usbhid_device_request req;
492 	int error;
493 
494 	if (maxlen > usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]))
495 		return (ENOBUFS);
496 
497 	req.ctrl.bmRequestType = UT_READ_CLASS_INTERFACE;
498 	req.ctrl.bRequest = UR_GET_REPORT;
499 	USETW2(req.ctrl.wValue, type, id);
500 	req.ctrl.wIndex[0] = sc->sc_iface_no;
501 	req.ctrl.wIndex[1] = 0;
502 	USETW(req.ctrl.wLength, maxlen);
503 
504 	error = usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, buf);
505 	if (!error && actlen != NULL)
506 		*actlen = maxlen;
507 
508 	return (error);
509 }
510 
511 static int
512 usbhid_set_report(device_t dev, const void *buf, hid_size_t len, uint8_t type,
513     uint8_t id)
514 {
515 	struct usbhid_softc* sc = device_get_softc(dev);
516 	union usbhid_device_request req;
517 
518 	if (len > usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]))
519 		return (ENOBUFS);
520 
521 	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
522 	req.ctrl.bRequest = UR_SET_REPORT;
523 	USETW2(req.ctrl.wValue, type, id);
524 	req.ctrl.wIndex[0] = sc->sc_iface_no;
525 	req.ctrl.wIndex[1] = 0;
526 	USETW(req.ctrl.wLength, len);
527 
528 	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req,
529 	    __DECONST(void *, buf)));
530 }
531 
532 static int
533 usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen)
534 {
535 	struct usbhid_softc* sc = device_get_softc(dev);
536 	union usbhid_device_request req;
537 	int error;
538 
539 	if (maxlen > usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]))
540 		return (ENOBUFS);
541 
542 	req.intr.maxlen = maxlen;
543 	error = usbhid_sync_xfer(sc, USBHID_INTR_IN_DT, &req, buf);
544 	if (error == 0 && actlen != NULL)
545 		*actlen = req.intr.actlen;
546 
547 	return (error);
548 }
549 
550 static int
551 usbhid_write(device_t dev, const void *buf, hid_size_t len)
552 {
553 	struct usbhid_softc* sc = device_get_softc(dev);
554 	union usbhid_device_request req;
555 
556 	if (len > usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]))
557 		return (ENOBUFS);
558 
559 	req.intr.maxlen = len;
560 	return (usbhid_sync_xfer(sc, USBHID_INTR_OUT_DT, &req,
561 	    __DECONST(void *, buf)));
562 }
563 
564 static int
565 usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id)
566 {
567 	struct usbhid_softc* sc = device_get_softc(dev);
568 	union usbhid_device_request req;
569 
570 	/* Duration is measured in 4 milliseconds per unit. */
571 	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
572 	req.ctrl.bRequest = UR_SET_IDLE;
573 	USETW2(req.ctrl.wValue, (duration + 3) / 4, id);
574 	req.ctrl.wIndex[0] = sc->sc_iface_no;
575 	req.ctrl.wIndex[1] = 0;
576 	USETW(req.ctrl.wLength, 0);
577 
578 	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
579 }
580 
581 static int
582 usbhid_set_protocol(device_t dev, uint16_t protocol)
583 {
584 	struct usbhid_softc* sc = device_get_softc(dev);
585 	union usbhid_device_request req;
586 
587 	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
588 	req.ctrl.bRequest = UR_SET_PROTOCOL;
589 	USETW(req.ctrl.wValue, protocol);
590 	req.ctrl.wIndex[0] = sc->sc_iface_no;
591 	req.ctrl.wIndex[1] = 0;
592 	USETW(req.ctrl.wLength, 0);
593 
594 	return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
595 }
596 
597 static void
598 usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
599 {
600 
601 	hw->idBus = BUS_USB;
602 	hw->idVendor = uaa->info.idVendor;
603 	hw->idProduct = uaa->info.idProduct;
604 	hw->idVersion = uaa->info.bcdDevice;
605 
606 	/* Set various quirks based on usb_attach_arg */
607 	hid_add_dynamic_quirk(hw, USB_GET_DRIVER_INFO(uaa));
608 }
609 
610 static void
611 usbhid_fill_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
612 {
613 	struct usb_device *udev = uaa->device;
614 	struct usb_interface *iface = uaa->iface;
615 	struct usb_hid_descriptor *hid;
616 	struct usb_endpoint *ep;
617 
618 	snprintf(hw->name, sizeof(hw->name), "%s %s",
619 	    usb_get_manufacturer(udev), usb_get_product(udev));
620 	strlcpy(hw->serial, usb_get_serial(udev), sizeof(hw->serial));
621 
622 	if (uaa->info.bInterfaceClass == UICLASS_HID &&
623 	    iface != NULL && iface->idesc != NULL) {
624 		hid = hid_get_descriptor_from_usb(
625 		    usbd_get_config_descriptor(udev), iface->idesc);
626 		if (hid != NULL)
627 			hw->rdescsize =
628 			    UGETW(hid->descrs[0].wDescriptorLength);
629 	}
630 
631 	/* See if there is a interrupt out endpoint. */
632 	ep = usbd_get_endpoint(udev, uaa->info.bIfaceIndex,
633 	    usbhid_config + USBHID_INTR_OUT_DT);
634 	if (ep == NULL || ep->methods == NULL)
635 		hid_add_dynamic_quirk(hw, HQ_NOWRITE);
636 }
637 
638 static const STRUCT_USB_HOST_ID usbhid_devs[] = {
639 	/* the Xbox 360 gamepad doesn't use the HID class */
640 	{USB_IFACE_CLASS(UICLASS_VENDOR),
641 	 USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
642 	 USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),
643 	 USB_DRIVER_INFO(HQ_IS_XBOX360GP)},
644 	/* HID keyboard with boot protocol support */
645 	{USB_IFACE_CLASS(UICLASS_HID),
646 	 USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
647 	 USB_IFACE_PROTOCOL(UIPROTO_BOOT_KEYBOARD),
648 	 USB_DRIVER_INFO(HQ_HAS_KBD_BOOTPROTO)},
649 	/* HID mouse with boot protocol support */
650 	{USB_IFACE_CLASS(UICLASS_HID),
651 	 USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
652 	 USB_IFACE_PROTOCOL(UIPROTO_MOUSE),
653 	 USB_DRIVER_INFO(HQ_HAS_MS_BOOTPROTO)},
654 	/* generic HID class */
655 	{USB_IFACE_CLASS(UICLASS_HID), USB_DRIVER_INFO(HQ_NONE)},
656 };
657 
658 static int
659 usbhid_probe(device_t dev)
660 {
661 	struct usb_attach_arg *uaa = device_get_ivars(dev);
662 	struct usbhid_softc *sc = device_get_softc(dev);
663 	int error;
664 
665 	DPRINTFN(11, "\n");
666 
667 	if (uaa->usb_mode != USB_MODE_HOST)
668 		return (ENXIO);
669 
670 	error = usbd_lookup_id_by_uaa(usbhid_devs, sizeof(usbhid_devs), uaa);
671 	if (error)
672 		return (error);
673 
674 	if (usb_test_quirk(uaa, UQ_HID_IGNORE))
675 		return (ENXIO);
676 
677 	/*
678 	 * Setup temporary hid_device_info so that we can figure out some
679 	 * basic quirks for this device.
680 	 */
681 	usbhid_init_device_info(uaa, &sc->sc_hw);
682 
683 	if (hid_test_quirk(&sc->sc_hw, HQ_HID_IGNORE))
684 		return (ENXIO);
685 
686 #ifdef USBHID_ENABLED
687 	return (BUS_PROBE_GENERIC + 1);
688 #else
689 	return (BUS_PROBE_GENERIC - 1);
690 #endif
691 }
692 
693 static int
694 usbhid_attach(device_t dev)
695 {
696 	struct usb_attach_arg *uaa = device_get_ivars(dev);
697 	struct usbhid_softc *sc = device_get_softc(dev);
698 	device_t child;
699 	int error = 0;
700 
701 	DPRINTFN(10, "sc=%p\n", sc);
702 
703 	device_set_usb_desc(dev);
704 
705 	sc->sc_udev = uaa->device;
706 	sc->sc_iface_no = uaa->info.bIfaceNum;
707 	sc->sc_iface_index = uaa->info.bIfaceIndex;
708 
709 	usbhid_fill_device_info(uaa, &sc->sc_hw);
710 
711 	error = usbd_req_set_idle(uaa->device, NULL,
712 	    uaa->info.bIfaceIndex, 0, 0);
713 	if (error)
714 		DPRINTF("set idle failed, error=%s (ignored)\n",
715 		    usbd_errstr(error));
716 
717 	mtx_init(&sc->sc_mtx, "usbhid lock", NULL, MTX_DEF);
718 
719 	child = device_add_child(dev, "hidbus", -1);
720 	if (child == NULL) {
721 		device_printf(dev, "Could not add hidbus device\n");
722 		usbhid_detach(dev);
723 		return (ENOMEM);
724 	}
725 
726 	device_set_ivars(child, &sc->sc_hw);
727 	error = bus_generic_attach(dev);
728 	if (error) {
729 		device_printf(dev, "failed to attach child: %d\n", error);
730 		usbhid_detach(dev);
731 		return (error);
732 	}
733 
734 	return (0);			/* success */
735 }
736 
737 static int
738 usbhid_detach(device_t dev)
739 {
740 	struct usbhid_softc *sc = device_get_softc(dev);
741 
742 	device_delete_children(dev);
743 	mtx_destroy(&sc->sc_mtx);
744 
745 	return (0);
746 }
747 
748 static devclass_t usbhid_devclass;
749 
750 static device_method_t usbhid_methods[] = {
751 	DEVMETHOD(device_probe,		usbhid_probe),
752 	DEVMETHOD(device_attach,	usbhid_attach),
753 	DEVMETHOD(device_detach,	usbhid_detach),
754 
755 	DEVMETHOD(hid_intr_setup,	usbhid_intr_setup),
756 	DEVMETHOD(hid_intr_unsetup,	usbhid_intr_unsetup),
757 	DEVMETHOD(hid_intr_start,	usbhid_intr_start),
758 	DEVMETHOD(hid_intr_stop,	usbhid_intr_stop),
759 	DEVMETHOD(hid_intr_poll,	usbhid_intr_poll),
760 
761 	/* HID interface */
762 	DEVMETHOD(hid_get_rdesc,	usbhid_get_rdesc),
763 	DEVMETHOD(hid_read,		usbhid_read),
764 	DEVMETHOD(hid_write,		usbhid_write),
765 	DEVMETHOD(hid_get_report,	usbhid_get_report),
766 	DEVMETHOD(hid_set_report,	usbhid_set_report),
767 	DEVMETHOD(hid_set_idle,		usbhid_set_idle),
768 	DEVMETHOD(hid_set_protocol,	usbhid_set_protocol),
769 
770 	DEVMETHOD_END
771 };
772 
773 static driver_t usbhid_driver = {
774 	.name = "usbhid",
775 	.methods = usbhid_methods,
776 	.size = sizeof(struct usbhid_softc),
777 };
778 
779 DRIVER_MODULE(usbhid, uhub, usbhid_driver, usbhid_devclass, NULL, 0);
780 MODULE_DEPEND(usbhid, usb, 1, 1, 1);
781 MODULE_DEPEND(usbhid, hid, 1, 1, 1);
782 MODULE_DEPEND(usbhid, hidbus, 1, 1, 1);
783 MODULE_VERSION(usbhid, 1);
784 #ifdef USBHID_ENABLED
785 USB_PNP_HOST_INFO(usbhid_devs);
786 #endif
787