]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/input/usbhid.c
hid: Import usbhid - USB transport backend for HID subsystem.
[FreeBSD/FreeBSD.git] / sys / dev / usb / input / usbhid.c
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