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/usb_parse.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 /* $FreeBSD: releng/11.2/sys/dev/usb/usb_parse.c 331722 2018-03-29 02:50:57Z eadler $ */
    2 /*-
    3  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #ifdef USB_GLOBAL_INCLUDE_FILE
   28 #include USB_GLOBAL_INCLUDE_FILE
   29 #else
   30 #include <sys/stdint.h>
   31 #include <sys/stddef.h>
   32 #include <sys/param.h>
   33 #include <sys/queue.h>
   34 #include <sys/types.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/bus.h>
   38 #include <sys/module.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/condvar.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/sx.h>
   44 #include <sys/unistd.h>
   45 #include <sys/callout.h>
   46 #include <sys/malloc.h>
   47 #include <sys/priv.h>
   48 
   49 #include <dev/usb/usb.h>
   50 #include <dev/usb/usbdi.h>
   51 #include <dev/usb/usbdi_util.h>
   52 
   53 #define USB_DEBUG_VAR usb_debug
   54 
   55 #include <dev/usb/usb_core.h>
   56 #include <dev/usb/usb_debug.h>
   57 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
   58 
   59 /*------------------------------------------------------------------------*
   60  *      usb_desc_foreach
   61  *
   62  * This function is the safe way to iterate across the USB config
   63  * descriptor. It contains several checks against invalid
   64  * descriptors. If the "desc" argument passed to this function is
   65  * "NULL" the first descriptor, if any, will be returned.
   66  *
   67  * Return values:
   68  *   NULL: End of descriptors
   69  *   Else: Next descriptor after "desc"
   70  *------------------------------------------------------------------------*/
   71 struct usb_descriptor *
   72 usb_desc_foreach(struct usb_config_descriptor *cd, 
   73     struct usb_descriptor *_desc)
   74 {
   75         uint8_t *desc_next;
   76         uint8_t *start;
   77         uint8_t *end;
   78         uint8_t *desc;
   79 
   80         /* be NULL safe */
   81         if (cd == NULL)
   82                 return (NULL);
   83 
   84         /* We assume that the "wTotalLength" has been checked. */
   85         start = (uint8_t *)cd;
   86         end = start + UGETW(cd->wTotalLength);
   87         desc = (uint8_t *)_desc;
   88 
   89         /* Get start of next USB descriptor. */
   90         if (desc == NULL)
   91                 desc = start;
   92         else
   93                 desc = desc + desc[0];
   94 
   95         /* Check that the next USB descriptor is within the range. */
   96         if ((desc < start) || (desc >= end))
   97                 return (NULL);          /* out of range, or EOD */
   98 
   99         /* Check that the second next USB descriptor is within range. */
  100         desc_next = desc + desc[0];
  101         if ((desc_next < start) || (desc_next > end))
  102                 return (NULL);          /* out of range */
  103 
  104         /* Check minimum descriptor length. */
  105         if (desc[0] < 3)
  106                 return (NULL);          /* too short descriptor */
  107 
  108         /* Return start of next descriptor. */
  109         return ((struct usb_descriptor *)desc);
  110 }
  111 
  112 /*------------------------------------------------------------------------*
  113  *      usb_idesc_foreach
  114  *
  115  * This function will iterate the interface descriptors in the config
  116  * descriptor. The parse state structure should be zeroed before
  117  * calling this function the first time.
  118  *
  119  * Return values:
  120  *   NULL: End of descriptors
  121  *   Else: A valid interface descriptor
  122  *------------------------------------------------------------------------*/
  123 struct usb_interface_descriptor *
  124 usb_idesc_foreach(struct usb_config_descriptor *cd,
  125     struct usb_idesc_parse_state *ps)
  126 {
  127         struct usb_interface_descriptor *id;
  128         uint8_t new_iface;
  129 
  130         /* retrieve current descriptor */
  131         id = (struct usb_interface_descriptor *)ps->desc;
  132         /* default is to start a new interface */
  133         new_iface = 1;
  134 
  135         while (1) {
  136                 id = (struct usb_interface_descriptor *)
  137                     usb_desc_foreach(cd, (struct usb_descriptor *)id);
  138                 if (id == NULL)
  139                         break;
  140                 if ((id->bDescriptorType == UDESC_INTERFACE) &&
  141                     (id->bLength >= sizeof(*id))) {
  142                         if (ps->iface_no_last == id->bInterfaceNumber)
  143                                 new_iface = 0;
  144                         ps->iface_no_last = id->bInterfaceNumber;
  145                         break;
  146                 }
  147         }
  148 
  149         if (ps->desc == NULL) {
  150                 /* first time or zero descriptors */
  151         } else if (new_iface) {
  152                 /* new interface */
  153                 ps->iface_index ++;
  154                 ps->iface_index_alt = 0;
  155         } else {
  156                 /* new alternate interface */
  157                 ps->iface_index_alt ++;
  158         }
  159 #if (USB_IFACE_MAX <= 0)
  160 #error "USB_IFACE_MAX must be defined greater than zero"
  161 #endif
  162         /* check for too many interfaces */
  163         if (ps->iface_index >= USB_IFACE_MAX) {
  164                 DPRINTF("Interface limit reached\n");
  165                 id = NULL;
  166         }
  167 
  168         /* store and return current descriptor */
  169         ps->desc = (struct usb_descriptor *)id;
  170         return (id);
  171 }
  172 
  173 /*------------------------------------------------------------------------*
  174  *      usb_edesc_foreach
  175  *
  176  * This function will iterate all the endpoint descriptors within an
  177  * interface descriptor. Starting value for the "ped" argument should
  178  * be a valid interface descriptor.
  179  *
  180  * Return values:
  181  *   NULL: End of descriptors
  182  *   Else: A valid endpoint descriptor
  183  *------------------------------------------------------------------------*/
  184 struct usb_endpoint_descriptor *
  185 usb_edesc_foreach(struct usb_config_descriptor *cd,
  186     struct usb_endpoint_descriptor *ped)
  187 {
  188         struct usb_descriptor *desc;
  189 
  190         desc = ((struct usb_descriptor *)ped);
  191 
  192         while ((desc = usb_desc_foreach(cd, desc))) {
  193                 if (desc->bDescriptorType == UDESC_INTERFACE) {
  194                         break;
  195                 }
  196                 if (desc->bDescriptorType == UDESC_ENDPOINT) {
  197                         if (desc->bLength < sizeof(*ped)) {
  198                                 /* endpoint descriptor is invalid */
  199                                 break;
  200                         }
  201                         return ((struct usb_endpoint_descriptor *)desc);
  202                 }
  203         }
  204         return (NULL);
  205 }
  206 
  207 /*------------------------------------------------------------------------*
  208  *      usb_ed_comp_foreach
  209  *
  210  * This function will iterate all the endpoint companion descriptors
  211  * within an endpoint descriptor in an interface descriptor. Starting
  212  * value for the "ped" argument should be a valid endpoint companion
  213  * descriptor.
  214  *
  215  * Return values:
  216  *   NULL: End of descriptors
  217  *   Else: A valid endpoint companion descriptor
  218  *------------------------------------------------------------------------*/
  219 struct usb_endpoint_ss_comp_descriptor *
  220 usb_ed_comp_foreach(struct usb_config_descriptor *cd,
  221     struct usb_endpoint_ss_comp_descriptor *ped)
  222 {
  223         struct usb_descriptor *desc;
  224 
  225         desc = ((struct usb_descriptor *)ped);
  226 
  227         while ((desc = usb_desc_foreach(cd, desc))) {
  228                 if (desc->bDescriptorType == UDESC_INTERFACE)
  229                         break;
  230                 if (desc->bDescriptorType == UDESC_ENDPOINT)
  231                         break;
  232                 if (desc->bDescriptorType == UDESC_ENDPOINT_SS_COMP) {
  233                         if (desc->bLength < sizeof(*ped)) {
  234                                 /* endpoint companion descriptor is invalid */
  235                                 break;
  236                         }
  237                         return ((struct usb_endpoint_ss_comp_descriptor *)desc);
  238                 }
  239         }
  240         return (NULL);
  241 }
  242 
  243 /*------------------------------------------------------------------------*
  244  *      usbd_get_no_descriptors
  245  *
  246  * This function will count the total number of descriptors in the
  247  * configuration descriptor of type "type".
  248  *------------------------------------------------------------------------*/
  249 uint8_t
  250 usbd_get_no_descriptors(struct usb_config_descriptor *cd, uint8_t type)
  251 {
  252         struct usb_descriptor *desc = NULL;
  253         uint8_t count = 0;
  254 
  255         while ((desc = usb_desc_foreach(cd, desc))) {
  256                 if (desc->bDescriptorType == type) {
  257                         count++;
  258                         if (count == 0xFF)
  259                                 break;                  /* crazy */
  260                 }
  261         }
  262         return (count);
  263 }
  264 
  265 /*------------------------------------------------------------------------*
  266  *      usbd_get_no_alts
  267  *
  268  * Return value:
  269  *   Number of alternate settings for the given interface descriptor
  270  *   pointer. If the USB descriptor is corrupt, the returned value can
  271  *   be greater than the actual number of alternate settings.
  272  *------------------------------------------------------------------------*/
  273 uint8_t
  274 usbd_get_no_alts(struct usb_config_descriptor *cd,
  275     struct usb_interface_descriptor *id)
  276 {
  277         struct usb_descriptor *desc;
  278         uint8_t n;
  279         uint8_t ifaceno;
  280 
  281         /* Reset interface count */
  282 
  283         n = 0;
  284 
  285         /* Get the interface number */
  286 
  287         ifaceno = id->bInterfaceNumber;
  288 
  289         /* Iterate all the USB descriptors */
  290 
  291         desc = NULL;
  292         while ((desc = usb_desc_foreach(cd, desc))) {
  293                 if ((desc->bDescriptorType == UDESC_INTERFACE) &&
  294                     (desc->bLength >= sizeof(*id))) {
  295                         id = (struct usb_interface_descriptor *)desc;
  296                         if (id->bInterfaceNumber == ifaceno) {
  297                                 n++;
  298                                 if (n == 0xFF)
  299                                         break;          /* crazy */
  300                         }
  301                 }
  302         }
  303         return (n);
  304 }

Cache object: cfcae5feec9f8ab3253bc5a2dea062e7


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