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