The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/input/usbhid.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   77 #include <dev/usb/quirk/usb_quirk.h>
   78 
   79 #include "hid_if.h"
   80 
   81 static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid");
   82 static int usbhid_enable = 0;
   83 SYSCTL_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
   86 static int usbhid_debug = 0;
   87 SYSCTL_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)
   93 enum {
   94         USBHID_INTR_OUT_DT,
   95         USBHID_INTR_IN_DT,
   96         USBHID_CTRL_DT,
   97         USBHID_N_TRANSFER,
   98 };
   99 
  100 struct usbhid_xfer_ctx;
  101 typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
  102 
  103 union usbhid_device_request {
  104         struct {                        /* INTR xfers */
  105                 uint16_t maxlen;
  106                 uint16_t actlen;
  107         } intr;
  108         struct usb_device_request ctrl; /* CTRL xfers */
  109 };
  110 
  111 /* Syncronous USB transfer context */
  112 struct usbhid_xfer_ctx {
  113         union usbhid_device_request req;
  114         uint8_t *buf;
  115         int error;
  116         usbhid_callback_t *cb;
  117         void *cb_ctx;
  118         int waiters;
  119         bool influx;
  120 };
  121 
  122 struct usbhid_softc {
  123         hid_intr_t *sc_intr_handler;
  124         void *sc_intr_ctx;
  125         void *sc_intr_buf;
  126 
  127         struct hid_device_info sc_hw;
  128 
  129         struct mtx sc_mtx;
  130         struct usb_config sc_config[USBHID_N_TRANSFER];
  131         struct usb_xfer *sc_xfer[POLL_XFER(USBHID_N_TRANSFER)];
  132         struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)];
  133         bool sc_can_poll;
  134 
  135         struct usb_device *sc_udev;
  136         uint8_t sc_iface_no;
  137         uint8_t sc_iface_index;
  138 };
  139 
  140 /* prototypes */
  141 
  142 static device_probe_t usbhid_probe;
  143 static device_attach_t usbhid_attach;
  144 static device_detach_t usbhid_detach;
  145 
  146 static usb_callback_t usbhid_intr_out_callback;
  147 static usb_callback_t usbhid_intr_in_callback;
  148 static usb_callback_t usbhid_ctrl_callback;
  149 
  150 static usbhid_callback_t usbhid_intr_handler_cb;
  151 static usbhid_callback_t usbhid_sync_wakeup_cb;
  152 
  153 static void
  154 usbhid_intr_out_callback(struct usb_xfer *xfer, usb_error_t error)
  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)) {
  161         case USB_ST_TRANSFERRED:
  162         case USB_ST_SETUP:
  163 tr_setup:
  164                 len = xfer_ctx->req.intr.maxlen;
  165                 if (len == 0) {
  166                         if (USB_IN_POLLING_MODE_FUNC())
  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);
  172                 usbd_xfer_set_frame_len(xfer, 0, len);
  173                 usbd_transfer_submit(xfer);
  174                 xfer_ctx->req.intr.maxlen = 0;
  175                 if (USB_IN_POLLING_MODE_FUNC())
  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 */
  183                         usbd_xfer_set_stall(xfer);
  184                         goto tr_setup;
  185                 }
  186                 xfer_ctx->error = EIO;
  187 tr_exit:
  188                 (void)xfer_ctx->cb(xfer_ctx);
  189                 return;
  190         }
  191 }
  192 
  193 static void
  194 usbhid_intr_in_callback(struct usb_xfer *xfer, usb_error_t error)
  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)) {
  201         case USB_ST_TRANSFERRED:
  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:
  212 re_submit:
  213                 usbd_xfer_set_frame_len(xfer, 0, xfer_ctx->req.intr.maxlen);
  214                 usbd_transfer_submit(xfer);
  215                 return;
  216 
  217         default:                        /* Error */
  218                 if (error != USB_ERR_CANCELLED) {
  219                         /* try to clear stall first */
  220                         usbd_xfer_set_stall(xfer);
  221                         goto re_submit;
  222                 }
  223                 return;
  224         }
  225 }
  226 
  227 static void
  228 usbhid_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
  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)
  247                         usbd_xfer_set_frame_len(xfer, 1, len);
  248                 usbd_xfer_set_frames(xfer, len != 0 ? 2 : 1);
  249                 usbd_transfer_submit(xfer);
  250                 return;
  251 
  252         case USB_ST_TRANSFERRED:
  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;
  264 tr_exit:
  265                 (void)xfer_ctx->cb(xfer_ctx);
  266                 return;
  267         }
  268 }
  269 
  270 static int
  271 usbhid_intr_handler_cb(struct usbhid_xfer_ctx *xfer_ctx)
  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 
  281 static int
  282 usbhid_sync_wakeup_cb(struct usbhid_xfer_ctx *xfer_ctx)
  283 {
  284 
  285         if (!USB_IN_POLLING_MODE_FUNC())
  286                 wakeup(xfer_ctx->cb_ctx);
  287 
  288         return (ECANCELED);
  289 }
  290 
  291 static const struct usb_config usbhid_config[USBHID_N_TRANSFER] = {
  292 
  293         [USBHID_INTR_OUT_DT] = {
  294                 .type = UE_INTERRUPT,
  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         },
  300         [USBHID_INTR_IN_DT] = {
  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 
  317 static inline usb_frlength_t
  318 usbhid_xfer_max_len(struct usb_xfer *xfer)
  319 {
  320         return (xfer == NULL ? 0 : usbd_xfer_max_len(xfer));
  321 }
  322 
  323 static inline int
  324 usbhid_xfer_check_len(struct usbhid_softc* sc, int xfer_idx, hid_size_t len)
  325 {
  326         if (USB_IN_POLLING_MODE_FUNC())
  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 
  335 static void
  336 usbhid_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;
  358                         error = usbd_transfer_setup(sc->sc_udev,
  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,
  365                                     usbd_errstr(error));
  366                 }
  367                 mtx_lock(&sc->sc_mtx);
  368                 if (sc->sc_xfer[USBHID_INTR_IN_DT] != NULL &&
  369                     sc->sc_xfer[USBHID_INTR_IN_DT]->flags_int.started)
  370                         usbd_transfer_start(
  371                             sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
  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;
  385         sc->sc_config[USBHID_CTRL_DT].bufsize =
  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;
  391                 error = usbd_transfer_setup(sc->sc_udev, &sc->sc_iface_index,
  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,
  396                             usbd_errstr(error));
  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 :
  403             usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]);
  404 
  405         sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
  406 }
  407 
  408 static void
  409 usbhid_intr_unsetup(device_t dev)
  410 {
  411         struct usbhid_softc* sc = device_get_softc(dev);
  412 
  413         usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
  414         if (sc->sc_can_poll)
  415                 usbd_transfer_unsetup(
  416                     sc->sc_xfer, POLL_XFER(USBHID_N_TRANSFER));
  417         sc->sc_can_poll = false;
  418         free(sc->sc_intr_buf, M_USBDEV);
  419 }
  420 
  421 static int
  422 usbhid_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);
  430         sc->sc_xfer_ctx[USBHID_INTR_IN_DT] = (struct usbhid_xfer_ctx) {
  431                 .req.intr.maxlen =
  432                     usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
  433                 .cb = usbhid_intr_handler_cb,
  434                 .cb_ctx = sc,
  435                 .buf = sc->sc_intr_buf,
  436         };
  437         sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
  438                 .req.intr.maxlen =
  439                     usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
  440                 .cb = usbhid_intr_handler_cb,
  441                 .cb_ctx = sc,
  442                 .buf = sc->sc_intr_buf,
  443         };
  444         usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
  445         if (sc->sc_can_poll)
  446                 usbd_transfer_start(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
  447         mtx_unlock(&sc->sc_mtx);
  448 
  449         return (0);
  450 }
  451 
  452 static int
  453 usbhid_intr_stop(device_t dev)
  454 {
  455         struct usbhid_softc* sc = device_get_softc(dev);
  456 
  457         usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
  458         usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
  459         if (sc->sc_can_poll)
  460                 usbd_transfer_drain(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
  461 
  462         return (0);
  463 }
  464 
  465 static void
  466 usbhid_intr_poll(device_t dev)
  467 {
  468         struct usbhid_softc* sc = device_get_softc(dev);
  469 
  470         MPASS(sc->sc_can_poll);
  471         usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
  472         usbd_transfer_poll(sc->sc_xfer + POLL_XFER(USBHID_INTR_IN_DT), 1);
  473 }
  474 
  475 /*
  476  * HID interface
  477  */
  478 static int
  479 usbhid_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 
  487         if (USB_IN_POLLING_MODE_FUNC()) {
  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 
  508         if (USB_IN_POLLING_MODE_FUNC())
  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 
  527         if (!USB_IN_POLLING_MODE_FUNC()) {
  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 
  540 static int
  541 usbhid_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 
  546         error = usbd_req_get_report_descriptor(sc->sc_udev, NULL,
  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 
  555 static int
  556 usbhid_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);
  560         union usbhid_device_request req;
  561         int error;
  562 
  563         error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, maxlen);
  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 
  574         error = usbhid_sync_xfer(sc, USBHID_CTRL_DT, &req, buf);
  575         if (!error && actlen != NULL)
  576                 *actlen = maxlen;
  577 
  578         return (error);
  579 }
  580 
  581 static int
  582 usbhid_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);
  586         union usbhid_device_request req;
  587         int error;
  588 
  589         error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, len);
  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 
  604 static int
  605 usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen)
  606 {
  607         struct usbhid_softc* sc = device_get_softc(dev);
  608         union usbhid_device_request req;
  609         int error;
  610 
  611         error = usbhid_xfer_check_len(sc, USBHID_INTR_IN_DT, maxlen);
  612         if (error)
  613                 return (error);
  614 
  615         req.intr.maxlen = maxlen;
  616         error = usbhid_sync_xfer(sc, USBHID_INTR_IN_DT, &req, buf);
  617         if (error == 0 && actlen != NULL)
  618                 *actlen = req.intr.actlen;
  619 
  620         return (error);
  621 }
  622 
  623 static int
  624 usbhid_write(device_t dev, const void *buf, hid_size_t len)
  625 {
  626         struct usbhid_softc* sc = device_get_softc(dev);
  627         union usbhid_device_request req;
  628         int error;
  629 
  630         error = usbhid_xfer_check_len(sc, USBHID_INTR_OUT_DT, len);
  631         if (error)
  632                 return (error);
  633 
  634         req.intr.maxlen = len;
  635         return (usbhid_sync_xfer(sc, USBHID_INTR_OUT_DT, &req,
  636             __DECONST(void *, buf)));
  637 }
  638 
  639 static int
  640 usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id)
  641 {
  642         struct usbhid_softc* sc = device_get_softc(dev);
  643         union usbhid_device_request req;
  644         int error;
  645 
  646         error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, 0);
  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 
  661 static int
  662 usbhid_set_protocol(device_t dev, uint16_t protocol)
  663 {
  664         struct usbhid_softc* sc = device_get_softc(dev);
  665         union usbhid_device_request req;
  666         int error;
  667 
  668         error = usbhid_xfer_check_len(sc, USBHID_CTRL_DT, 0);
  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 
  682 static int
  683 usbhid_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;
  687         union usbhid_device_request req;
  688         int error;
  689 
  690         switch (cmd) {
  691         case USB_REQUEST:
  692                 ucr = (struct usb_ctl_request *)data;
  693                 req.ctrl = ucr->ucr_request;
  694                 error = usbhid_xfer_check_len(
  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;
  701                 error = usbhid_sync_xfer(
  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 
  713 static void
  714 usbhid_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 
  726 static void
  727 usbhid_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",
  735             usb_get_manufacturer(udev), usb_get_product(udev));
  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) {
  740                 hid = hid_get_descriptor_from_usb(
  741                     usbd_get_config_descriptor(udev), iface->idesc);
  742                 if (hid != NULL)
  743                         hw->rdescsize =
  744                             UGETW(hid->descrs[0].wDescriptorLength);
  745         }
  746 
  747         /* See if there is a interrupt out endpoint. */
  748         ep = usbd_get_endpoint(udev, uaa->info.bIfaceIndex,
  749             usbhid_config + USBHID_INTR_OUT_DT);
  750         if (ep == NULL || ep->methods == NULL)
  751                 hid_add_dynamic_quirk(hw, HQ_NOWRITE);
  752 }
  753 
  754 static const STRUCT_USB_HOST_ID usbhid_devs[] = {
  755         /* the Xbox 360 gamepad doesn't use the HID class */
  756         {USB_IFACE_CLASS(UICLASS_VENDOR),
  757          USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER),
  758          USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),
  759          USB_DRIVER_INFO(HQ_IS_XBOX360GP)},
  760         /* HID keyboard with boot protocol support */
  761         {USB_IFACE_CLASS(UICLASS_HID),
  762          USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
  763          USB_IFACE_PROTOCOL(UIPROTO_BOOT_KEYBOARD),
  764          USB_DRIVER_INFO(HQ_HAS_KBD_BOOTPROTO)},
  765         /* HID mouse with boot protocol support */
  766         {USB_IFACE_CLASS(UICLASS_HID),
  767          USB_IFACE_SUBCLASS(UISUBCLASS_BOOT),
  768          USB_IFACE_PROTOCOL(UIPROTO_MOUSE),
  769          USB_DRIVER_INFO(HQ_HAS_MS_BOOTPROTO)},
  770         /* generic HID class */
  771         {USB_IFACE_CLASS(UICLASS_HID), USB_DRIVER_INFO(HQ_NONE)},
  772 };
  773 
  774 static int
  775 usbhid_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 
  789         error = usbd_lookup_id_by_uaa(usbhid_devs, sizeof(usbhid_devs), uaa);
  790         if (error)
  791                 return (error);
  792 
  793         if (usb_test_quirk(uaa, UQ_HID_IGNORE))
  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          */
  800         usbhid_init_device_info(uaa, &sc->sc_hw);
  801 
  802         if (hid_test_quirk(&sc->sc_hw, HQ_HID_IGNORE))
  803                 return (ENXIO);
  804 
  805         return (BUS_PROBE_DEFAULT + 1);
  806 }
  807 
  808 static int
  809 usbhid_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 
  818         device_set_usb_desc(dev);
  819 
  820         sc->sc_udev = uaa->device;
  821         sc->sc_iface_no = uaa->info.bIfaceNum;
  822         sc->sc_iface_index = uaa->info.bIfaceIndex;
  823 
  824         usbhid_fill_device_info(uaa, &sc->sc_hw);
  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",
  830                     usbd_errstr(error));
  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");
  837                 usbhid_detach(dev);
  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);
  845                 usbhid_detach(dev);
  846                 return (error);
  847         }
  848 
  849         return (0);                     /* success */
  850 }
  851 
  852 static int
  853 usbhid_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 
  863 static device_method_t usbhid_methods[] = {
  864         DEVMETHOD(device_probe,         usbhid_probe),
  865         DEVMETHOD(device_attach,        usbhid_attach),
  866         DEVMETHOD(device_detach,        usbhid_detach),
  867 
  868         DEVMETHOD(hid_intr_setup,       usbhid_intr_setup),
  869         DEVMETHOD(hid_intr_unsetup,     usbhid_intr_unsetup),
  870         DEVMETHOD(hid_intr_start,       usbhid_intr_start),
  871         DEVMETHOD(hid_intr_stop,        usbhid_intr_stop),
  872         DEVMETHOD(hid_intr_poll,        usbhid_intr_poll),
  873 
  874         /* HID interface */
  875         DEVMETHOD(hid_get_rdesc,        usbhid_get_rdesc),
  876         DEVMETHOD(hid_read,             usbhid_read),
  877         DEVMETHOD(hid_write,            usbhid_write),
  878         DEVMETHOD(hid_get_report,       usbhid_get_report),
  879         DEVMETHOD(hid_set_report,       usbhid_set_report),
  880         DEVMETHOD(hid_set_idle,         usbhid_set_idle),
  881         DEVMETHOD(hid_set_protocol,     usbhid_set_protocol),
  882         DEVMETHOD(hid_ioctl,            usbhid_ioctl),
  883 
  884         DEVMETHOD_END
  885 };
  886 
  887 static driver_t usbhid_driver = {
  888         .name = "usbhid",
  889         .methods = usbhid_methods,
  890         .size = sizeof(struct usbhid_softc),
  891 };
  892 
  893 DRIVER_MODULE(usbhid, uhub, usbhid_driver, NULL, NULL);
  894 MODULE_DEPEND(usbhid, usb, 1, 1, 1);
  895 MODULE_DEPEND(usbhid, hid, 1, 1, 1);
  896 MODULE_DEPEND(usbhid, hidbus, 1, 1, 1);
  897 MODULE_VERSION(usbhid, 1);
  898 USB_PNP_HOST_INFO(usbhid_devs);

Cache object: e019181163a7b54c1a84214e3a5bad52


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.