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/usbdi_util.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 /*      $NetBSD: usbdi_util.c,v 1.40 2002/07/11 21:14:36 augustss Exp $ */
    2 /*      $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.14 1999/11/17 22:33:50 n_hibma Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.40 2002/07/11 21:14:36 augustss Exp $");
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/malloc.h>
   48 #if defined(__NetBSD__) || defined(__OpenBSD__)
   49 #include <sys/proc.h>
   50 #include <sys/device.h>
   51 #elif defined(__FreeBSD__)
   52 #include <sys/bus.h>
   53 #endif
   54 
   55 #include <dev/usb/usb.h>
   56 #include <dev/usb/usbhid.h>
   57 
   58 #include <dev/usb/usbdi.h>
   59 #include <dev/usb/usbdi_util.h>
   60 
   61 #ifdef USB_DEBUG
   62 #define DPRINTF(x)      if (usbdebug) logprintf x
   63 #define DPRINTFN(n,x)   if (usbdebug>(n)) logprintf x
   64 extern int usbdebug;
   65 #else
   66 #define DPRINTF(x)
   67 #define DPRINTFN(n,x)
   68 #endif
   69 
   70 usbd_status
   71 usbd_get_desc(usbd_device_handle dev, int type, int index, int len, void *desc)
   72 {
   73         usb_device_request_t req;
   74 
   75         DPRINTFN(3,("usbd_get_desc: type=%d, index=%d, len=%d\n",
   76                     type, index, len));
   77 
   78         req.bmRequestType = UT_READ_DEVICE;
   79         req.bRequest = UR_GET_DESCRIPTOR;
   80         USETW2(req.wValue, type, index);
   81         USETW(req.wIndex, 0);
   82         USETW(req.wLength, len);
   83         return (usbd_do_request(dev, &req, desc));
   84 }
   85 
   86 usbd_status
   87 usbd_get_config_desc(usbd_device_handle dev, int confidx,
   88                      usb_config_descriptor_t *d)
   89 {
   90         usbd_status err;
   91 
   92         DPRINTFN(3,("usbd_get_config_desc: confidx=%d\n", confidx));
   93         err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
   94                             USB_CONFIG_DESCRIPTOR_SIZE, d);
   95         if (err)
   96                 return (err);
   97         if (d->bDescriptorType != UDESC_CONFIG) {
   98                 DPRINTFN(-1,("usbd_get_config_desc: confidx=%d, bad desc "
   99                              "len=%d type=%d\n",
  100                              confidx, d->bLength, d->bDescriptorType));
  101                 return (USBD_INVAL);
  102         }
  103         return (USBD_NORMAL_COMPLETION);
  104 }
  105 
  106 usbd_status
  107 usbd_get_config_desc_full(usbd_device_handle dev, int conf, void *d, int size)
  108 {
  109         DPRINTFN(3,("usbd_get_config_desc_full: conf=%d\n", conf));
  110         return (usbd_get_desc(dev, UDESC_CONFIG, conf, size, d));
  111 }
  112 
  113 usbd_status
  114 usbd_get_device_desc(usbd_device_handle dev, usb_device_descriptor_t *d)
  115 {
  116         DPRINTFN(3,("usbd_get_device_desc:\n"));
  117         return (usbd_get_desc(dev, UDESC_DEVICE,
  118                              0, USB_DEVICE_DESCRIPTOR_SIZE, d));
  119 }
  120 
  121 usbd_status
  122 usbd_get_device_status(usbd_device_handle dev, usb_status_t *st)
  123 {
  124         usb_device_request_t req;
  125 
  126         req.bmRequestType = UT_READ_DEVICE;
  127         req.bRequest = UR_GET_STATUS;
  128         USETW(req.wValue, 0);
  129         USETW(req.wIndex, 0);
  130         USETW(req.wLength, sizeof(usb_status_t));
  131         return (usbd_do_request(dev, &req, st));
  132 }
  133 
  134 usbd_status
  135 usbd_get_hub_status(usbd_device_handle dev, usb_hub_status_t *st)
  136 {
  137         usb_device_request_t req;
  138 
  139         req.bmRequestType = UT_READ_CLASS_DEVICE;
  140         req.bRequest = UR_GET_STATUS;
  141         USETW(req.wValue, 0);
  142         USETW(req.wIndex, 0);
  143         USETW(req.wLength, sizeof(usb_hub_status_t));
  144         return (usbd_do_request(dev, &req, st));
  145 }
  146 
  147 usbd_status
  148 usbd_set_address(usbd_device_handle dev, int addr)
  149 {
  150         usb_device_request_t req;
  151 
  152         req.bmRequestType = UT_WRITE_DEVICE;
  153         req.bRequest = UR_SET_ADDRESS;
  154         USETW(req.wValue, addr);
  155         USETW(req.wIndex, 0);
  156         USETW(req.wLength, 0);
  157         return usbd_do_request(dev, &req, 0);
  158 }
  159 
  160 usbd_status
  161 usbd_get_port_status(usbd_device_handle dev, int port, usb_port_status_t *ps)
  162 {
  163         usb_device_request_t req;
  164 
  165         req.bmRequestType = UT_READ_CLASS_OTHER;
  166         req.bRequest = UR_GET_STATUS;
  167         USETW(req.wValue, 0);
  168         USETW(req.wIndex, port);
  169         USETW(req.wLength, sizeof *ps);
  170         return (usbd_do_request(dev, &req, ps));
  171 }
  172 
  173 usbd_status
  174 usbd_clear_hub_feature(usbd_device_handle dev, int sel)
  175 {
  176         usb_device_request_t req;
  177 
  178         req.bmRequestType = UT_WRITE_CLASS_DEVICE;
  179         req.bRequest = UR_CLEAR_FEATURE;
  180         USETW(req.wValue, sel);
  181         USETW(req.wIndex, 0);
  182         USETW(req.wLength, 0);
  183         return (usbd_do_request(dev, &req, 0));
  184 }
  185 
  186 usbd_status
  187 usbd_set_hub_feature(usbd_device_handle dev, int sel)
  188 {
  189         usb_device_request_t req;
  190 
  191         req.bmRequestType = UT_WRITE_CLASS_DEVICE;
  192         req.bRequest = UR_SET_FEATURE;
  193         USETW(req.wValue, sel);
  194         USETW(req.wIndex, 0);
  195         USETW(req.wLength, 0);
  196         return (usbd_do_request(dev, &req, 0));
  197 }
  198 
  199 usbd_status
  200 usbd_clear_port_feature(usbd_device_handle dev, int port, int sel)
  201 {
  202         usb_device_request_t req;
  203 
  204         req.bmRequestType = UT_WRITE_CLASS_OTHER;
  205         req.bRequest = UR_CLEAR_FEATURE;
  206         USETW(req.wValue, sel);
  207         USETW(req.wIndex, port);
  208         USETW(req.wLength, 0);
  209         return (usbd_do_request(dev, &req, 0));
  210 }
  211 
  212 usbd_status
  213 usbd_set_port_feature(usbd_device_handle dev, int port, int sel)
  214 {
  215         usb_device_request_t req;
  216 
  217         req.bmRequestType = UT_WRITE_CLASS_OTHER;
  218         req.bRequest = UR_SET_FEATURE;
  219         USETW(req.wValue, sel);
  220         USETW(req.wIndex, port);
  221         USETW(req.wLength, 0);
  222         return (usbd_do_request(dev, &req, 0));
  223 }
  224 
  225 usbd_status
  226 usbd_get_protocol(usbd_interface_handle iface, u_int8_t *report)
  227 {
  228         usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
  229         usbd_device_handle dev;
  230         usb_device_request_t req;
  231 
  232         DPRINTFN(4, ("usbd_get_protocol: iface=%p, endpt=%d\n",
  233                      iface, id->bInterfaceNumber));
  234         if (id == NULL)
  235                 return (USBD_IOERROR);
  236         usbd_interface2device_handle(iface, &dev);
  237         req.bmRequestType = UT_READ_CLASS_INTERFACE;
  238         req.bRequest = UR_GET_PROTOCOL;
  239         USETW(req.wValue, 0);
  240         USETW(req.wIndex, id->bInterfaceNumber);
  241         USETW(req.wLength, 1);
  242         return (usbd_do_request(dev, &req, report));
  243 }
  244 
  245 usbd_status
  246 usbd_set_protocol(usbd_interface_handle iface, int report)
  247 {
  248         usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
  249         usbd_device_handle dev;
  250         usb_device_request_t req;
  251 
  252         DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n",
  253                      iface, report, id->bInterfaceNumber));
  254         if (id == NULL)
  255                 return (USBD_IOERROR);
  256         usbd_interface2device_handle(iface, &dev);
  257         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  258         req.bRequest = UR_SET_PROTOCOL;
  259         USETW(req.wValue, report);
  260         USETW(req.wIndex, id->bInterfaceNumber);
  261         USETW(req.wLength, 0);
  262         return (usbd_do_request(dev, &req, 0));
  263 }
  264 
  265 usbd_status
  266 usbd_set_report(usbd_interface_handle iface, int type, int id, void *data,
  267                 int len)
  268 {
  269         usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  270         usbd_device_handle dev;
  271         usb_device_request_t req;
  272 
  273         DPRINTFN(4, ("usbd_set_report: len=%d\n", len));
  274         if (ifd == NULL)
  275                 return (USBD_IOERROR);
  276         usbd_interface2device_handle(iface, &dev);
  277         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  278         req.bRequest = UR_SET_REPORT;
  279         USETW2(req.wValue, type, id);
  280         USETW(req.wIndex, ifd->bInterfaceNumber);
  281         USETW(req.wLength, len);
  282         return (usbd_do_request(dev, &req, data));
  283 }
  284 
  285 usbd_status
  286 usbd_set_report_async(usbd_interface_handle iface, int type, int id, void *data,
  287                       int len)
  288 {
  289         usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  290         usbd_device_handle dev;
  291         usb_device_request_t req;
  292 
  293         DPRINTFN(4, ("usbd_set_report_async: len=%d\n", len));
  294         if (ifd == NULL)
  295                 return (USBD_IOERROR);
  296         usbd_interface2device_handle(iface, &dev);
  297         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  298         req.bRequest = UR_SET_REPORT;
  299         USETW2(req.wValue, type, id);
  300         USETW(req.wIndex, ifd->bInterfaceNumber);
  301         USETW(req.wLength, len);
  302         return (usbd_do_request_async(dev, &req, data));
  303 }
  304 
  305 usbd_status
  306 usbd_get_report(usbd_interface_handle iface, int type, int id, void *data,
  307                 int len)
  308 {
  309         usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  310         usbd_device_handle dev;
  311         usb_device_request_t req;
  312 
  313         DPRINTFN(4, ("usbd_get_report: len=%d\n", len));
  314         if (ifd == NULL)
  315                 return (USBD_IOERROR);
  316         usbd_interface2device_handle(iface, &dev);
  317         req.bmRequestType = UT_READ_CLASS_INTERFACE;
  318         req.bRequest = UR_GET_REPORT;
  319         USETW2(req.wValue, type, id);
  320         USETW(req.wIndex, ifd->bInterfaceNumber);
  321         USETW(req.wLength, len);
  322         return (usbd_do_request(dev, &req, data));
  323 }
  324 
  325 usbd_status
  326 usbd_set_idle(usbd_interface_handle iface, int duration, int id)
  327 {
  328         usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface);
  329         usbd_device_handle dev;
  330         usb_device_request_t req;
  331 
  332         DPRINTFN(4, ("usbd_set_idle: %d %d\n", duration, id));
  333         if (ifd == NULL)
  334                 return (USBD_IOERROR);
  335         usbd_interface2device_handle(iface, &dev);
  336         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  337         req.bRequest = UR_SET_IDLE;
  338         USETW2(req.wValue, duration, id);
  339         USETW(req.wIndex, ifd->bInterfaceNumber);
  340         USETW(req.wLength, 0);
  341         return (usbd_do_request(dev, &req, 0));
  342 }
  343 
  344 usbd_status
  345 usbd_get_report_descriptor(usbd_device_handle dev, int ifcno,
  346                            int size, void *d)
  347 {
  348         usb_device_request_t req;
  349 
  350         req.bmRequestType = UT_READ_INTERFACE;
  351         req.bRequest = UR_GET_DESCRIPTOR;
  352         USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
  353         USETW(req.wIndex, ifcno);
  354         USETW(req.wLength, size);
  355         return (usbd_do_request(dev, &req, d));
  356 }
  357 
  358 usb_hid_descriptor_t *
  359 usbd_get_hid_descriptor(usbd_interface_handle ifc)
  360 {
  361         usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc);
  362         usbd_device_handle dev;
  363         usb_config_descriptor_t *cdesc;
  364         usb_hid_descriptor_t *hd;
  365         char *p, *end;
  366 
  367         if (idesc == NULL)
  368                 return (0);
  369          usbd_interface2device_handle(ifc, &dev);
  370         cdesc = usbd_get_config_descriptor(dev);
  371 
  372         p = (char *)idesc + idesc->bLength;
  373         end = (char *)cdesc + UGETW(cdesc->wTotalLength);
  374 
  375         for (; p < end; p += hd->bLength) {
  376                 hd = (usb_hid_descriptor_t *)p;
  377                 if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID)
  378                         return (hd);
  379                 if (hd->bDescriptorType == UDESC_INTERFACE)
  380                         break;
  381         }
  382         return (0);
  383 }
  384 
  385 usbd_status
  386 usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep,
  387                        usb_malloc_type mem)
  388 {
  389         usb_interface_descriptor_t *id;
  390         usb_hid_descriptor_t *hid;
  391         usbd_device_handle dev;
  392         usbd_status err;
  393 
  394         usbd_interface2device_handle(ifc, &dev);
  395         id = usbd_get_interface_descriptor(ifc);
  396         if (id == NULL)
  397                 return (USBD_INVAL);
  398         hid = usbd_get_hid_descriptor(ifc);
  399         if (hid == NULL)
  400                 return (USBD_IOERROR);
  401         *sizep = UGETW(hid->descrs[0].wDescriptorLength);
  402         *descp = malloc(*sizep, mem, M_NOWAIT);
  403         if (*descp == NULL)
  404                 return (USBD_NOMEM);
  405         err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
  406                                          *sizep, *descp);
  407         if (err) {
  408                 free(*descp, mem);
  409                 *descp = NULL;
  410                 return (err);
  411         }
  412         return (USBD_NORMAL_COMPLETION);
  413 }
  414 
  415 usbd_status
  416 usbd_get_config(usbd_device_handle dev, u_int8_t *conf)
  417 {
  418         usb_device_request_t req;
  419 
  420         req.bmRequestType = UT_READ_DEVICE;
  421         req.bRequest = UR_GET_CONFIG;
  422         USETW(req.wValue, 0);
  423         USETW(req.wIndex, 0);
  424         USETW(req.wLength, 1);
  425         return (usbd_do_request(dev, &req, conf));
  426 }
  427 
  428 Static void usbd_bulk_transfer_cb(usbd_xfer_handle xfer,
  429                                   usbd_private_handle priv, usbd_status status);
  430 Static void
  431 usbd_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
  432                       usbd_status status)
  433 {
  434         wakeup(xfer);
  435 }
  436 
  437 usbd_status
  438 usbd_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
  439                    u_int16_t flags, u_int32_t timeout, void *buf,
  440                    u_int32_t *size, char *lbl)
  441 {
  442         usbd_status err;
  443         int s, error;
  444 
  445         usbd_setup_xfer(xfer, pipe, 0, buf, *size,
  446                         flags, timeout, usbd_bulk_transfer_cb);
  447         DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
  448         s = splusb();           /* don't want callback until tsleep() */
  449         err = usbd_transfer(xfer);
  450         if (err != USBD_IN_PROGRESS) {
  451                 splx(s);
  452                 return (err);
  453         }
  454         error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
  455         splx(s);
  456         if (error) {
  457                 DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
  458                 usbd_abort_pipe(pipe);
  459                 return (USBD_INTERRUPTED);
  460         }
  461         usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
  462         DPRINTFN(1,("usbd_bulk_transfer: transferred %d\n", *size));
  463         if (err) {
  464                 DPRINTF(("usbd_bulk_transfer: error=%d\n", err));
  465                 usbd_clear_endpoint_stall(pipe);
  466         }
  467         return (err);
  468 }
  469 
  470 void
  471 usb_detach_wait(device_ptr_t dv)
  472 {
  473         DPRINTF(("usb_detach_wait: waiting for %s\n", USBDEVPTRNAME(dv)));
  474         if (tsleep(dv, PZERO, "usbdet", hz * 60))
  475                 printf("usb_detach_wait: %s didn't detach\n",
  476                         USBDEVPTRNAME(dv));
  477         DPRINTF(("usb_detach_wait: %s done\n", USBDEVPTRNAME(dv)));
  478 }
  479 
  480 void
  481 usb_detach_wakeup(device_ptr_t dv)
  482 {
  483         DPRINTF(("usb_detach_wakeup: for %s\n", USBDEVPTRNAME(dv)));
  484         wakeup(dv);
  485 }
  486 
  487 usb_descriptor_t *
  488 usb_find_desc(usbd_device_handle dev, int type)
  489 {
  490         usb_descriptor_t *desc;
  491         usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
  492         uByte *p = (uByte *)cd;
  493         uByte *end = p + UGETW(cd->wTotalLength);
  494 
  495         while (p < end) {
  496                 desc = (usb_descriptor_t *)p;
  497                 if (desc->bDescriptorType == type)
  498                         return (desc);
  499                 p += desc->bLength;
  500         }
  501 
  502         return (NULL);
  503 }

Cache object: 2999a85483ade1b8eef240392082260c


[ 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.