FreeBSD kernel usb device Code
usbhid.c
Go to the documentation of this file.
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#include <dev/usb/usb_core.h>
71#include <dev/usb/usb_ioctl.h>
72#include <dev/usb/usb_util.h>
73
74#define USB_DEBUG_VAR usbhid_debug
75#include <dev/usb/usb_debug.h>
76
78
79#include "hid_if.h"
80
81static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid");
82static int usbhid_enable = 0;
83SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, enable, CTLFLAG_RWTUN,
84 &usbhid_enable, 0, "Enable usbhid and prefer it to other USB HID drivers");
85#ifdef USB_DEBUG
86static int usbhid_debug = 0;
87SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, debug, CTLFLAG_RWTUN,
88 &usbhid_debug, 0, "Debug level");
89#endif
90
91/* Second set of USB transfers for polling mode */
92#define POLL_XFER(xfer) ((xfer) + USBHID_N_TRANSFER)
93enum {
98};
99
100struct usbhid_xfer_ctx;
101typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
102
104 struct { /* INTR xfers */
105 uint16_t maxlen;
106 uint16_t actlen;
108 struct usb_device_request ctrl; /* CTRL xfers */
109};
110
111/* Syncronous USB transfer context */
114 uint8_t *buf;
115 int error;
117 void *cb_ctx;
119 bool influx;
120};
121
123 hid_intr_t *sc_intr_handler;
126
127 struct hid_device_info sc_hw;
128
129 struct mtx sc_mtx;
134
136 uint8_t sc_iface_no;
138};
139
140/* prototypes */
141
142static device_probe_t usbhid_probe;
143static device_attach_t usbhid_attach;
144static device_detach_t usbhid_detach;
145
149
152
153static void
155{
156 struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
157 struct usb_page_cache *pc;
158 int len;
159
160 switch (USB_GET_STATE(xfer)) {
162 case USB_ST_SETUP:
163tr_setup:
164 len = xfer_ctx->req.intr.maxlen;
165 if (len == 0) {
167 xfer_ctx->error = 0;
168 return;
169 }
170 pc = usbd_xfer_get_frame(xfer, 0);
171 usbd_copy_in(pc, 0, xfer_ctx->buf, len);
174 xfer_ctx->req.intr.maxlen = 0;
176 return;
177 xfer_ctx->error = 0;
178 goto tr_exit;
179
180 default: /* Error */
181 if (error != USB_ERR_CANCELLED) {
182 /* try to clear stall first */
184 goto tr_setup;
185 }
186 xfer_ctx->error = EIO;
187tr_exit:
188 (void)xfer_ctx->cb(xfer_ctx);
189 return;
190 }
191}
192
193static void
195{
196 struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
197 struct usb_page_cache *pc;
198 int actlen;
199
200 switch (USB_GET_STATE(xfer)) {
202 DPRINTF("transferred!\n");
203
204 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
205 pc = usbd_xfer_get_frame(xfer, 0);
206 usbd_copy_out(pc, 0, xfer_ctx->buf, actlen);
207 xfer_ctx->req.intr.actlen = actlen;
208 if (xfer_ctx->cb(xfer_ctx) != 0)
209 return;
210
211 case USB_ST_SETUP:
212re_submit:
213 usbd_xfer_set_frame_len(xfer, 0, xfer_ctx->req.intr.maxlen);
215 return;
216
217 default: /* Error */
218 if (error != USB_ERR_CANCELLED) {
219 /* try to clear stall first */
221 goto re_submit;
222 }
223 return;
224 }
225}
226
227static void
229{
230 struct usbhid_xfer_ctx *xfer_ctx = usbd_xfer_softc(xfer);
231 struct usb_device_request *req = &xfer_ctx->req.ctrl;
232 struct usb_page_cache *pc;
233 int len = UGETW(req->wLength);
234 bool is_rd = (req->bmRequestType & UT_READ) != 0;
235
236 switch (USB_GET_STATE(xfer)) {
237 case USB_ST_SETUP:
238 if (!is_rd && len != 0) {
239 pc = usbd_xfer_get_frame(xfer, 1);
240 usbd_copy_in(pc, 0, xfer_ctx->buf, len);
241 }
242
243 pc = usbd_xfer_get_frame(xfer, 0);
244 usbd_copy_in(pc, 0, req, sizeof(*req));
245 usbd_xfer_set_frame_len(xfer, 0, sizeof(*req));
246 if (len != 0)
248 usbd_xfer_set_frames(xfer, len != 0 ? 2 : 1);
250 return;
251
253 if (is_rd && len != 0) {
254 pc = usbd_xfer_get_frame(xfer, 0);
255 usbd_copy_out(pc, sizeof(*req), xfer_ctx->buf, len);
256 }
257 xfer_ctx->error = 0;
258 goto tr_exit;
259
260 default: /* Error */
261 /* bomb out */
262 DPRINTFN(1, "error=%s\n", usbd_errstr(error));
263 xfer_ctx->error = EIO;
264tr_exit:
265 (void)xfer_ctx->cb(xfer_ctx);
266 return;
267 }
268}
269
270static int
272{
273 struct usbhid_softc *sc = xfer_ctx->cb_ctx;
274
275 sc->sc_intr_handler(sc->sc_intr_ctx, xfer_ctx->buf,
276 xfer_ctx->req.intr.actlen);
277
278 return (0);
279}
280
281static int
283{
284
286 wakeup(xfer_ctx->cb_ctx);
287
288 return (ECANCELED);
289}
290
292
295 .endpoint = UE_ADDR_ANY,
296 .direction = UE_DIR_OUT,
297 .flags = {.pipe_bof = 1,.proxy_buffer = 1},
298 .callback = &usbhid_intr_out_callback,
299 },
301 .type = UE_INTERRUPT,
302 .endpoint = UE_ADDR_ANY,
303 .direction = UE_DIR_IN,
304 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
305 .callback = &usbhid_intr_in_callback,
306 },
307 [USBHID_CTRL_DT] = {
308 .type = UE_CONTROL,
309 .endpoint = 0x00, /* Control pipe */
310 .direction = UE_DIR_ANY,
311 .flags = {.proxy_buffer = 1},
312 .callback = &usbhid_ctrl_callback,
313 .timeout = 1000, /* 1 second */
314 },
315};
316
317static inline usb_frlength_t
319{
320 return (xfer == NULL ? 0 : usbd_xfer_max_len(xfer));
321}
322
323static inline int
324usbhid_xfer_check_len(struct usbhid_softc* sc, int xfer_idx, hid_size_t len)
325{
327 xfer_idx = POLL_XFER(xfer_idx);
328 if (sc->sc_xfer[xfer_idx] == NULL)
329 return (ENODEV);
330 if (len > usbd_xfer_max_len(sc->sc_xfer[xfer_idx]))
331 return (ENOBUFS);
332 return (0);
333}
334
335static void
336usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context,
337 struct hid_rdesc_info *rdesc)
338{
339 struct usbhid_softc* sc = device_get_softc(dev);
340 uint16_t n;
341 bool nowrite;
342 int error;
343
344 nowrite = hid_test_quirk(&sc->sc_hw, HQ_NOWRITE);
345
346 /*
347 * Setup the USB transfers one by one, so they are memory independent
348 * which allows for handling panics triggered by the HID drivers
349 * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
350 * keyboard driver was processing a key at the moment of panic.
351 */
352 if (intr == NULL) {
353 if (sc->sc_can_poll)
354 return;
355 for (n = 0; n != USBHID_N_TRANSFER; n++) {
356 if (nowrite && n == USBHID_INTR_OUT_DT)
357 continue;
359 &sc->sc_iface_index, sc->sc_xfer + POLL_XFER(n),
360 sc->sc_config + n, 1,
361 (void *)(sc->sc_xfer_ctx + POLL_XFER(n)),
362 &sc->sc_mtx);
363 if (error)
364 DPRINTF("xfer %d setup error=%s\n", n,
366 }
367 mtx_lock(&sc->sc_mtx);
368 if (sc->sc_xfer[USBHID_INTR_IN_DT] != NULL &&
372 mtx_unlock(&sc->sc_mtx);
373 sc->sc_can_poll = true;
374 return;
375 }
376
377 sc->sc_intr_handler = intr;
378 sc->sc_intr_ctx = context;
379 bcopy(usbhid_config, sc->sc_config, sizeof(usbhid_config));
380 bzero(sc->sc_xfer, sizeof(sc->sc_xfer));
381
382 /* Set buffer sizes to match HID report sizes */
383 sc->sc_config[USBHID_INTR_OUT_DT].bufsize = rdesc->osize;
384 sc->sc_config[USBHID_INTR_IN_DT].bufsize = rdesc->isize;
386 MAX(rdesc->isize, MAX(rdesc->osize, rdesc->fsize));
387
388 for (n = 0; n != USBHID_N_TRANSFER; n++) {
389 if (nowrite && n == USBHID_INTR_OUT_DT)
390 continue;
392 sc->sc_xfer + n, sc->sc_config + n, 1,
393 (void *)(sc->sc_xfer_ctx + n), &sc->sc_mtx);
394 if (error)
395 DPRINTF("xfer %d setup error=%s\n", n,
397 }
398
399 rdesc->rdsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]);
400 rdesc->grsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]);
401 rdesc->srsize = rdesc->grsize;
402 rdesc->wrsize = nowrite ? rdesc->srsize :
404
405 sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
406}
407
408static void
410{
411 struct usbhid_softc* sc = device_get_softc(dev);
412
414 if (sc->sc_can_poll)
417 sc->sc_can_poll = false;
418 free(sc->sc_intr_buf, M_USBDEV);
419}
420
421static int
422usbhid_intr_start(device_t dev)
423{
424 struct usbhid_softc* sc = device_get_softc(dev);
425
426 if (sc->sc_xfer[USBHID_INTR_IN_DT] == NULL)
427 return (ENODEV);
428
429 mtx_lock(&sc->sc_mtx);
431 .req.intr.maxlen =
434 .cb_ctx = sc,
435 .buf = sc->sc_intr_buf,
436 };
438 .req.intr.maxlen =
441 .cb_ctx = sc,
442 .buf = sc->sc_intr_buf,
443 };
445 if (sc->sc_can_poll)
447 mtx_unlock(&sc->sc_mtx);
448
449 return (0);
450}
451
452static int
453usbhid_intr_stop(device_t dev)
454{
455 struct usbhid_softc* sc = device_get_softc(dev);
456
459 if (sc->sc_can_poll)
461
462 return (0);
463}
464
465static void
466usbhid_intr_poll(device_t dev)
467{
468 struct usbhid_softc* sc = device_get_softc(dev);
469
470 MPASS(sc->sc_can_poll);
473}
474
475/*
476 * HID interface
477 */
478static int
479usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx,
480 union usbhid_device_request *req, void *buf)
481{
482 int error, timeout;
483 struct usbhid_xfer_ctx *xfer_ctx;
484
485 xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
486
488 xfer_ctx = POLL_XFER(xfer_ctx);
489 xfer_idx = POLL_XFER(xfer_idx);
490 } else {
491 mtx_lock(&sc->sc_mtx);
492 ++xfer_ctx->waiters;
493 while (xfer_ctx->influx)
494 mtx_sleep(&xfer_ctx->waiters, &sc->sc_mtx, 0,
495 "usbhid wt", 0);
496 --xfer_ctx->waiters;
497 xfer_ctx->influx = true;
498 }
499
500 xfer_ctx->buf = buf;
501 xfer_ctx->req = *req;
502 xfer_ctx->error = ETIMEDOUT;
503 xfer_ctx->cb = &usbhid_sync_wakeup_cb;
504 xfer_ctx->cb_ctx = xfer_ctx;
505 timeout = USB_DEFAULT_TIMEOUT;
506 usbd_transfer_start(sc->sc_xfer[xfer_idx]);
507
509 while (timeout > 0 && xfer_ctx->error == ETIMEDOUT) {
510 usbd_transfer_poll(sc->sc_xfer + xfer_idx, 1);
511 DELAY(1000);
512 timeout--;
513 }
514 else
515 msleep_sbt(xfer_ctx, &sc->sc_mtx, 0, "usbhid io",
516 SBT_1MS * timeout, 0, C_HARDCLOCK);
517
518 /* Perform usbhid_write() asyncronously to improve pipelining */
519 if (USB_IN_POLLING_MODE_FUNC() || xfer_ctx->error != 0 ||
520 sc->sc_config[xfer_idx].type != UE_INTERRUPT ||
521 sc->sc_config[xfer_idx].direction != UE_DIR_OUT)
522 usbd_transfer_stop(sc->sc_xfer[xfer_idx]);
523 error = xfer_ctx->error;
524 if (error == 0)
525 *req = xfer_ctx->req;
526
528 xfer_ctx->influx = false;
529 if (xfer_ctx->waiters != 0)
530 wakeup_one(&xfer_ctx->waiters);
531 mtx_unlock(&sc->sc_mtx);
532 }
533
534 if (error)
535 DPRINTF("USB IO error:%d\n", error);
536
537 return (error);
538}
539
540static int
541usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
542{
543 struct usbhid_softc* sc = device_get_softc(dev);
544 int error;
545
547 buf, len, sc->sc_iface_index);
548
549 if (error)
550 DPRINTF("no report descriptor: %s\n", usbd_errstr(error));
551
552 return (error == 0 ? 0 : ENXIO);
553}
554
555static int
556usbhid_get_report(device_t dev, void *buf, hid_size_t maxlen,
557 hid_size_t *actlen, uint8_t type, uint8_t id)
558{
559 struct usbhid_softc* sc = device_get_softc(dev);
561 int error;
562
564 if (error)
565 return (error);
566
567 req.ctrl.bmRequestType = UT_READ_CLASS_INTERFACE;
568 req.ctrl.bRequest = UR_GET_REPORT;
569 USETW2(req.ctrl.wValue, type, id);
570 req.ctrl.wIndex[0] = sc->sc_iface_no;
571 req.ctrl.wIndex[1] = 0;
572 USETW(req.ctrl.wLength, maxlen);
573
575 if (!error && actlen != NULL)
576 *actlen = maxlen;
577
578 return (error);
579}
580
581static int
582usbhid_set_report(device_t dev, const void *buf, hid_size_t len, uint8_t type,
583 uint8_t id)
584{
585 struct usbhid_softc* sc = device_get_softc(dev);
587 int error;
588
590 if (error)
591 return (error);
592
593 req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
594 req.ctrl.bRequest = UR_SET_REPORT;
595 USETW2(req.ctrl.wValue, type, id);
596 req.ctrl.wIndex[0] = sc->sc_iface_no;
597 req.ctrl.wIndex[1] = 0;
598 USETW(req.ctrl.wLength, len);
599
600 return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req,
601 __DECONST(void *, buf)));
602}
603
604static int
605usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen)
606{
607 struct usbhid_softc* sc = device_get_softc(dev);
609 int error;
610
612 if (error)
613 return (error);
614
615 req.intr.maxlen = maxlen;
617 if (error == 0 && actlen != NULL)
618 *actlen = req.intr.actlen;
619
620 return (error);
621}
622
623static int
624usbhid_write(device_t dev, const void *buf, hid_size_t len)
625{
626 struct usbhid_softc* sc = device_get_softc(dev);
628 int error;
629
631 if (error)
632 return (error);
633
634 req.intr.maxlen = len;
636 __DECONST(void *, buf)));
637}
638
639static int
640usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id)
641{
642 struct usbhid_softc* sc = device_get_softc(dev);
644 int error;
645
647 if (error)
648 return (error);
649
650 /* Duration is measured in 4 milliseconds per unit. */
651 req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
652 req.ctrl.bRequest = UR_SET_IDLE;
653 USETW2(req.ctrl.wValue, (duration + 3) / 4, id);
654 req.ctrl.wIndex[0] = sc->sc_iface_no;
655 req.ctrl.wIndex[1] = 0;
656 USETW(req.ctrl.wLength, 0);
657
658 return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
659}
660
661static int
662usbhid_set_protocol(device_t dev, uint16_t protocol)
663{
664 struct usbhid_softc* sc = device_get_softc(dev);
666 int error;
667
669 if (error)
670 return (error);
671
672 req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
673 req.ctrl.bRequest = UR_SET_PROTOCOL;
674 USETW(req.ctrl.wValue, protocol);
675 req.ctrl.wIndex[0] = sc->sc_iface_no;
676 req.ctrl.wIndex[1] = 0;
677 USETW(req.ctrl.wLength, 0);
678
679 return (usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, NULL));
680}
681
682static int
683usbhid_ioctl(device_t dev, unsigned long cmd, uintptr_t data)
684{
685 struct usbhid_softc* sc = device_get_softc(dev);
686 struct usb_ctl_request *ucr;
688 int error;
689
690 switch (cmd) {
691 case USB_REQUEST:
692 ucr = (struct usb_ctl_request *)data;
693 req.ctrl = ucr->ucr_request;
695 sc, USBHID_CTRL_DT, UGETW(req.ctrl.wLength));
696 if (error)
697 break;
698 error = usb_check_request(sc->sc_udev, &req.ctrl);
699 if (error)
700 break;
702 sc, USBHID_CTRL_DT, &req, ucr->ucr_data);
703 if (error == 0)
704 ucr->ucr_actlen = UGETW(req.ctrl.wLength);
705 break;
706 default:
707 error = EINVAL;
708 }
709
710 return (error);
711}
712
713static void
714usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
715{
716
717 hw->idBus = BUS_USB;
718 hw->idVendor = uaa->info.idVendor;
719 hw->idProduct = uaa->info.idProduct;
720 hw->idVersion = uaa->info.bcdDevice;
721
722 /* Set various quirks based on usb_attach_arg */
723 hid_add_dynamic_quirk(hw, USB_GET_DRIVER_INFO(uaa));
724}
725
726static void
727usbhid_fill_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
728{
729 struct usb_device *udev = uaa->device;
730 struct usb_interface *iface = uaa->iface;
731 struct usb_hid_descriptor *hid;
732 struct usb_endpoint *ep;
733
734 snprintf(hw->name, sizeof(hw->name), "%s %s",
736 strlcpy(hw->serial, usb_get_serial(udev), sizeof(hw->serial));
737
738 if (uaa->info.bInterfaceClass == UICLASS_HID &&
739 iface != NULL && iface->idesc != NULL) {
741 usbd_get_config_descriptor(udev), iface->idesc);
742 if (hid != NULL)
743 hw->rdescsize =
745 }
746
747 /* See if there is a interrupt out endpoint. */
748 ep = usbd_get_endpoint(udev, uaa->info.bIfaceIndex,
750 if (ep == NULL || ep->methods == NULL)
751 hid_add_dynamic_quirk(hw, HQ_NOWRITE);
752}
753
755 /* the Xbox 360 gamepad doesn't use the HID class */
759 USB_DRIVER_INFO(HQ_IS_XBOX360GP)},
760 /* HID keyboard with boot protocol support */
764 USB_DRIVER_INFO(HQ_HAS_KBD_BOOTPROTO)},
765 /* HID mouse with boot protocol support */
769 USB_DRIVER_INFO(HQ_HAS_MS_BOOTPROTO)},
770 /* generic HID class */
772};
773
774static int
775usbhid_probe(device_t dev)
776{
777 struct usb_attach_arg *uaa = device_get_ivars(dev);
778 struct usbhid_softc *sc = device_get_softc(dev);
779 int error;
780
781 DPRINTFN(11, "\n");
782
783 if (usbhid_enable == 0)
784 return (ENXIO);
785
786 if (uaa->usb_mode != USB_MODE_HOST)
787 return (ENXIO);
788
790 if (error)
791 return (error);
792
794 return (ENXIO);
795
796 /*
797 * Setup temporary hid_device_info so that we can figure out some
798 * basic quirks for this device.
799 */
801
802 if (hid_test_quirk(&sc->sc_hw, HQ_HID_IGNORE))
803 return (ENXIO);
804
805 return (BUS_PROBE_GENERIC + 1);
806}
807
808static int
809usbhid_attach(device_t dev)
810{
811 struct usb_attach_arg *uaa = device_get_ivars(dev);
812 struct usbhid_softc *sc = device_get_softc(dev);
813 device_t child;
814 int error = 0;
815
816 DPRINTFN(10, "sc=%p\n", sc);
817
819
820 sc->sc_udev = uaa->device;
821 sc->sc_iface_no = uaa->info.bIfaceNum;
823
825
826 error = usbd_req_set_idle(uaa->device, NULL,
827 uaa->info.bIfaceIndex, 0, 0);
828 if (error)
829 DPRINTF("set idle failed, error=%s (ignored)\n",
831
832 mtx_init(&sc->sc_mtx, "usbhid lock", NULL, MTX_DEF);
833
834 child = device_add_child(dev, "hidbus", -1);
835 if (child == NULL) {
836 device_printf(dev, "Could not add hidbus device\n");
838 return (ENOMEM);
839 }
840
841 device_set_ivars(child, &sc->sc_hw);
842 error = bus_generic_attach(dev);
843 if (error) {
844 device_printf(dev, "failed to attach child: %d\n", error);
846 return (error);
847 }
848
849 return (0); /* success */
850}
851
852static int
853usbhid_detach(device_t dev)
854{
855 struct usbhid_softc *sc = device_get_softc(dev);
856
857 device_delete_children(dev);
858 mtx_destroy(&sc->sc_mtx);
859
860 return (0);
861}
862
863static devclass_t usbhid_devclass;
864
865static device_method_t usbhid_methods[] = {
866 DEVMETHOD(device_probe, usbhid_probe),
867 DEVMETHOD(device_attach, usbhid_attach),
868 DEVMETHOD(device_detach, usbhid_detach),
869
870 DEVMETHOD(hid_intr_setup, usbhid_intr_setup),
871 DEVMETHOD(hid_intr_unsetup, usbhid_intr_unsetup),
872 DEVMETHOD(hid_intr_start, usbhid_intr_start),
873 DEVMETHOD(hid_intr_stop, usbhid_intr_stop),
874 DEVMETHOD(hid_intr_poll, usbhid_intr_poll),
875
876 /* HID interface */
877 DEVMETHOD(hid_get_rdesc, usbhid_get_rdesc),
878 DEVMETHOD(hid_read, usbhid_read),
879 DEVMETHOD(hid_write, usbhid_write),
880 DEVMETHOD(hid_get_report, usbhid_get_report),
881 DEVMETHOD(hid_set_report, usbhid_set_report),
882 DEVMETHOD(hid_set_idle, usbhid_set_idle),
883 DEVMETHOD(hid_set_protocol, usbhid_set_protocol),
884 DEVMETHOD(hid_ioctl, usbhid_ioctl),
885
886 DEVMETHOD_END
887};
888
889static driver_t usbhid_driver = {
890 .name = "usbhid",
891 .methods = usbhid_methods,
892 .size = sizeof(struct usbhid_softc),
893};
894
896MODULE_DEPEND(usbhid, usb, 1, 1, 1);
897MODULE_DEPEND(usbhid, hid, 1, 1, 1);
898MODULE_DEPEND(usbhid, hidbus, 1, 1, 1);
899MODULE_VERSION(usbhid, 1);
static int debug
Definition: cfumass.c:73
uint16_t len
Definition: ehci.h:41
uint8_t n
Definition: if_run.c:612
struct @109 error
uint16_t data
device_t child
enum pci_id_type type
device_t dev
enum usb_hc_mode usb_mode
Definition: usbdi.h:432
struct usbd_lookup_info info
Definition: usbdi.h:426
struct usb_interface * iface
Definition: usbdi.h:431
struct usb_device * device
Definition: usbdi.h:430
uint8_t type
Definition: usbdi.h:238
usb_frlength_t bufsize
Definition: usbdi.h:230
uint8_t direction
Definition: usbdi.h:240
void * ucr_data
Definition: usb_ioctl.h:74
struct usb_device_request ucr_request
Definition: usb_ioctl.h:78
uint16_t ucr_actlen
Definition: usb_ioctl.h:76
const struct usb_pipe_methods * methods
Definition: usbdi.h:146
uWord wDescriptorLength
Definition: usbhid.h:60
struct usb_hid_descriptor::@92 descrs[1]
struct usb_interface_descriptor * idesc
Definition: usbdi.h:175
struct usb_xfer_flags_int flags_int
Definition: usb_core.h:182
uint8_t bIfaceNum
Definition: usbdi.h:418
uint16_t idProduct
Definition: usbdi.h:409
uint8_t bIfaceIndex
Definition: usbdi.h:417
uint8_t bInterfaceClass
Definition: usbdi.h:414
uint16_t idVendor
Definition: usbdi.h:408
uint16_t bcdDevice
Definition: usbdi.h:410
void * sc_intr_ctx
Definition: usbhid.c:124
struct usb_xfer * sc_xfer[POLL_XFER(USBHID_N_TRANSFER)]
Definition: usbhid.c:131
void * sc_intr_buf
Definition: usbhid.c:125
hid_intr_t * sc_intr_handler
Definition: usbhid.c:123
uint8_t sc_iface_index
Definition: usbhid.c:137
struct mtx sc_mtx
Definition: usbhid.c:129
uint8_t sc_iface_no
Definition: usbhid.c:136
struct hid_device_info sc_hw
Definition: usbhid.c:127
struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)]
Definition: usbhid.c:132
bool sc_can_poll
Definition: usbhid.c:133
struct usb_config sc_config[USBHID_N_TRANSFER]
Definition: usbhid.c:130
struct usb_device * sc_udev
Definition: usbhid.c:135
uint8_t * buf
Definition: usbhid.c:114
union usbhid_device_request req
Definition: usbhid.c:113
usbhid_callback_t * cb
Definition: usbhid.c:116
void * cb_ctx
Definition: usbhid.c:117
#define DPRINTF(...)
Definition: umass.c:179
struct usb_device_request ctrl
Definition: usbhid.c:108
struct usbhid_device_request::@14 intr
#define UE_INTERRUPT
Definition: usb.h:544
#define UE_DIR_ANY
Definition: usb.h:535
#define UE_ADDR_ANY
Definition: usb.h:537
#define UISUBCLASS_XBOX360_CONTROLLER
Definition: usb.h:521
#define UT_READ_CLASS_INTERFACE
Definition: usb.h:173
#define UISUBCLASS_BOOT
Definition: usb.h:454
#define UICLASS_VENDOR
Definition: usb.h:520
#define UIPROTO_XBOX360_GAMEPAD
Definition: usb.h:523
#define UE_DIR_IN
Definition: usb.h:531
#define UICLASS_HID
Definition: usb.h:453
#define UE_DIR_OUT
Definition: usb.h:532
@ USB_MODE_HOST
Definition: usb.h:778
#define UT_WRITE_CLASS_INTERFACE
Definition: usb.h:177
#define UIPROTO_MOUSE
Definition: usb.h:456
#define UE_CONTROL
Definition: usb.h:541
#define UT_READ
Definition: usb.h:157
#define UIPROTO_BOOT_KEYBOARD
Definition: usb.h:455
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset, const void *ptr, usb_frlength_t len)
Definition: usb_busdma.c:166
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
Definition: usb_busdma.c:283
struct usb_config_descriptor * usbd_get_config_descriptor(struct usb_device *udev)
Definition: usb_device.c:2616
const char * usb_get_serial(struct usb_device *udev)
Definition: usb_device.c:293
const char * usb_get_product(struct usb_device *udev)
Definition: usb_device.c:287
struct usb_endpoint * usbd_get_endpoint(struct usb_device *udev, uint8_t iface_index, const struct usb_config *setup)
Definition: usb_device.c:362
const char * usb_get_manufacturer(struct usb_device *udev)
Definition: usb_device.c:281
#define USETW2(w, b1, b0)
Definition: usb_endian.h:100
#define USETW(w, v)
Definition: usb_endian.h:77
#define UGETW(w)
Definition: usb_endian.h:53
const char * usbd_errstr(usb_error_t err)
Definition: usb_error.c:93
uint32_t usb_frlength_t
Definition: usb_freebsd.h:100
#define USB_IN_POLLING_MODE_FUNC()
Definition: usb_freebsd.h:96
struct usb_hid_descriptor * hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, struct usb_interface_descriptor *id)
Definition: usb_hid.c:82
const void * req
Definition: usb_if.m:51
INTERFACE usb
Definition: usb_if.m:35
#define USB_REQUEST
Definition: usb_ioctl.h:235
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
Definition: usb_lookup.c:143
@ UQ_HID_IGNORE
Definition: usb_quirk.h:51
uint8_t usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
Definition: usb_device.c:2631
usb_error_t usbd_req_get_report_descriptor(struct usb_device *udev, struct mtx *mtx, void *d, uint16_t size, uint8_t iface_index)
Definition: usb_request.c:1890
usb_error_t usbd_req_set_idle(struct usb_device *udev, struct mtx *mtx, uint8_t iface_index, uint8_t duration, uint8_t id)
Definition: usb_request.c:1862
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
Definition: usb_transfer.c:987
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_transfer_drain(struct usb_xfer *xfer)
void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
Definition: usb_util.c:73
int usb_check_request(struct usb_device *, struct usb_device_request *)
#define USB_DEFAULT_TIMEOUT
Definition: usbdi.h:89
#define USB_IFACE_SUBCLASS(isc)
Definition: usbdi.h:388
#define USB_ST_SETUP
Definition: usbdi.h:502
usb_error_t
Definition: usbdi.h:45
@ USB_ERR_CANCELLED
Definition: usbdi.h:51
#define USB_IFACE_CLASS(ic)
Definition: usbdi.h:385
#define USB_ST_TRANSFERRED
Definition: usbdi.h:503
#define USB_IFACE_PROTOCOL(ip)
Definition: usbdi.h:391
void() usb_callback_t(struct usb_xfer *, usb_error_t)
Definition: usbdi.h:94
#define STRUCT_USB_HOST_ID
Definition: usbdi.h:258
#define USB_GET_DRIVER_INFO(did)
Definition: usbdi.h:400
#define USB_GET_STATE(xfer)
Definition: usbdi.h:515
#define USB_DRIVER_INFO(n)
Definition: usbdi.h:397
@ USBHID_INTR_IN_DT
Definition: usbhid.c:95
@ USBHID_CTRL_DT
Definition: usbhid.c:96
@ USBHID_INTR_OUT_DT
Definition: usbhid.c:94
@ USBHID_N_TRANSFER
Definition: usbhid.c:97
static const STRUCT_USB_HOST_ID usbhid_devs[]
Definition: usbhid.c:754
static int usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen)
Definition: usbhid.c:605
static driver_t usbhid_driver
Definition: usbhid.c:889
MODULE_VERSION(usbhid, 1)
#define POLL_XFER(xfer)
Definition: usbhid.c:92
static void usbhid_fill_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
Definition: usbhid.c:727
static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid")
static usb_callback_t usbhid_intr_out_callback
Definition: usbhid.c:146
static void usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context, struct hid_rdesc_info *rdesc)
Definition: usbhid.c:336
static usbhid_callback_t usbhid_sync_wakeup_cb
Definition: usbhid.c:151
DRIVER_MODULE(usbhid, uhub, usbhid_driver, usbhid_devclass, NULL, 0)
static usb_callback_t usbhid_intr_in_callback
Definition: usbhid.c:147
MODULE_DEPEND(usbhid, usb, 1, 1, 1)
USB_PNP_HOST_INFO(usbhid_devs)
static device_detach_t usbhid_detach
Definition: usbhid.c:144
static int usbhid_sync_xfer(struct usbhid_softc *sc, int xfer_idx, union usbhid_device_request *req, void *buf)
Definition: usbhid.c:479
static int usbhid_set_protocol(device_t dev, uint16_t protocol)
Definition: usbhid.c:662
static usb_callback_t usbhid_ctrl_callback
Definition: usbhid.c:148
SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, enable, CTLFLAG_RWTUN, &usbhid_enable, 0, "Enable usbhid and prefer it to other USB HID drivers")
static void usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
Definition: usbhid.c:714
static void usbhid_intr_poll(device_t dev)
Definition: usbhid.c:466
static int usbhid_xfer_check_len(struct usbhid_softc *sc, int xfer_idx, hid_size_t len)
Definition: usbhid.c:324
int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx)
Definition: usbhid.c:101
__FBSDID("$FreeBSD$")
static device_attach_t usbhid_attach
Definition: usbhid.c:143
static usbhid_callback_t usbhid_intr_handler_cb
Definition: usbhid.c:150
static int usbhid_write(device_t dev, const void *buf, hid_size_t len)
Definition: usbhid.c:624
static device_method_t usbhid_methods[]
Definition: usbhid.c:865
static int usbhid_enable
Definition: usbhid.c:82
static const struct usb_config usbhid_config[USBHID_N_TRANSFER]
Definition: usbhid.c:291
static devclass_t usbhid_devclass
Definition: usbhid.c:863
static int usbhid_ioctl(device_t dev, unsigned long cmd, uintptr_t data)
Definition: usbhid.c:683
static int usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id)
Definition: usbhid.c:640
static device_probe_t usbhid_probe
Definition: usbhid.c:142
static int usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
Definition: usbhid.c:541
static int usbhid_intr_start(device_t dev)
Definition: usbhid.c:422
static int usbhid_get_report(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen, uint8_t type, uint8_t id)
Definition: usbhid.c:556
static usb_frlength_t usbhid_xfer_max_len(struct usb_xfer *xfer)
Definition: usbhid.c:318
static void usbhid_intr_unsetup(device_t dev)
Definition: usbhid.c:409
static int usbhid_set_report(device_t dev, const void *buf, hid_size_t len, uint8_t type, uint8_t id)
Definition: usbhid.c:582
static int usbhid_intr_stop(device_t dev)
Definition: usbhid.c:453
#define UR_GET_REPORT
Definition: usbhid.h:45
#define UR_SET_REPORT
Definition: usbhid.h:46
#define UR_SET_IDLE
Definition: usbhid.h:48
#define UR_SET_PROTOCOL
Definition: usbhid.h:50