CTC++ Coverage Report - Execution Profile    #624/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/usb/core/config.c
Instrumentation mode: function-decision-multicondition
TER: 43 % (114/264)

Start/ End/    
True False - Line Source

  1 #include <linux/config.h>
  2 #include <linux/usb.h>
  3 #include <linux/module.h>
  4 #include <linux/init.h>
  5 #include <linux/slab.h>
  6 #include <linux/device.h>
  7 #include <asm/byteorder.h>
  8 #include "usb.h"
  9 #include "hcd.h"
  10 
  11 #define USB_MAXALTSETTING      128   /* Hard limit */
  12 #define USB_MAXENDPOINTS      30   /* Hard limit */
  13 
  14 #define USB_MAXCONFIG         8   /* Arbitrary limit */
  15 
  16 
 
  17 static inline const char *plural(int n)
  18 {
    19    return (n == 1 ? "" : "s");
- 19 ternary-?: n == 1
   19 return ( n == 1 ? "" : "s" )
  20 }
  21 
 
117   22 static int find_next_descriptor(unsigned char *buffer, int size,
  23     int dt1, int dt2, int *num_skipped)
  24 {
  25    struct usb_descriptor_header *h;
  26    int n = 0;
  27    unsigned char *buffer0 = buffer;
  28 
  29    /* Find the next descriptor of type dt1 or dt2 */
87 37   30    while (size > 0) {
  31       h = (struct usb_descriptor_header *) buffer;
80   32       if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2)
80    32     T || _
 - 32     F || T
   32     F || F
80    33          break;
  34       buffer += h->bLength;
  35       size -= h->bLength;
  36       ++n;
  37    }
  38 
  39    /* Store the number of descriptors skipped and return the
  40     * number of bytes skipped */
117 - 41    if (num_skipped)
  42       *num_skipped = n;
117    43    return buffer - buffer0;
  44 }
  45 
 
43   46 static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
  47     int asnum, struct usb_host_interface *ifp, int num_ep,
  48     unsigned char *buffer, int size)
  49 {
  50    unsigned char *buffer0 = buffer;
  51    struct usb_endpoint_descriptor *d;
  52    struct usb_host_endpoint *endpoint;
  53    int n, i;
  54 
  55    d = (struct usb_endpoint_descriptor *) buffer;
  56    buffer += d->bLength;
  57    size -= d->bLength;
  58 
43 - 59    if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
  60       n = USB_DT_ENDPOINT_AUDIO_SIZE;
43 - 61    else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
  62       n = USB_DT_ENDPOINT_SIZE;
    63    else {
    64       dev_warn(ddev, "config %d interface %d altsetting %d has an "
- 64   ternary-?: ( ddev ) -> driver
  65           "invalid endpoint descriptor of length %d, skipping\n",
  66           cfgno, inum, asnum, d->bLength);
 - 67       goto skip_to_next_endpoint_or_interface_descriptor;
  68    }
  69 
  70    i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
43 - 71    if (i >= 16 || i == 0) {
 - 71   T || _
 - 71   F || T
 43   71   F || F
    72       dev_warn(ddev, "config %d interface %d altsetting %d has an "
- 72   ternary-?: ( ddev ) -> driver
  73           "invalid endpoint with address 0x%X, skipping\n",
  74           cfgno, inum, asnum, d->bEndpointAddress);
 - 75       goto skip_to_next_endpoint_or_interface_descriptor;
  76    }
  77 
  78    /* Only store as many endpoints as we have room for */
43 - 79    if (ifp->desc.bNumEndpoints >= num_ep)
 - 80       goto skip_to_next_endpoint_or_interface_descriptor;
  81 
  82    endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
  83    ++ifp->desc.bNumEndpoints;
  84 
  85    memcpy(&endpoint->desc, d, n);
  86    INIT_LIST_HEAD(&endpoint->urb_list);
  87 
  88    /* Skip over any Class Specific or Vendor Specific descriptors;
  89     * find the next endpoint or interface descriptor */
  90    endpoint->extra = buffer;
  91    i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  92        USB_DT_INTERFACE, &n);
  93    endpoint->extralen = i;
43 - 94    if (n > 0)
    95       dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
- 95   ternary-?: ( ddev ) -> driver
  96           n, plural(n), "endpoint");
43    97    return buffer - buffer0 + i;
  98 
  99 skip_to_next_endpoint_or_interface_descriptor:
  100    i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  101        USB_DT_INTERFACE, NULL);
 - 102    return buffer - buffer0 + i;
  103 }
  104 
 
  105 void usb_release_interface_cache(struct kref *ref)
  106 {
  107    struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
  108    int j;
  109 
  110    for (j = 0; j < intfc->num_altsetting; j++) {
  111       struct usb_host_interface *alt = &intfc->altsetting[j];
  112 
  113       kfree(alt->endpoint);
  114       kfree(alt->string);
  115    }
  116    kfree(intfc);
  117 }
  118 
 
37   119 static int usb_parse_interface(struct device *ddev, int cfgno,
  120     struct usb_host_config *config, unsigned char *buffer, int size,
  121     u8 inums[], u8 nalts[])
  122 {
  123    unsigned char *buffer0 = buffer;
  124    struct usb_interface_descriptor   *d;
  125    int inum, asnum;
  126    struct usb_interface_cache *intfc;
  127    struct usb_host_interface *alt;
  128    int i, n;
  129    int len, retval;
  130    int num_ep, num_ep_orig;
  131 
  132    d = (struct usb_interface_descriptor *) buffer;
  133    buffer += d->bLength;
  134    size -= d->bLength;
  135 
37 - 136    if (d->bLength < USB_DT_INTERFACE_SIZE)
 - 137       goto skip_to_next_interface_descriptor;
  138 
  139    /* Which interface entry is this? */
  140    intfc = NULL;
  141    inum = d->bInterfaceNumber;
37 - 142    for (i = 0; i < config->desc.bNumInterfaces; ++i) {
37 - 143       if (inums[i] == inum) {
  144          intfc = config->intf_cache[i];
37    145          break;
  146       }
  147    }
37 - 148    if (!intfc || intfc->num_altsetting >= nalts[i])
 - 148   T || _
 - 148   F || T
 37   148   F || F
 - 149       goto skip_to_next_interface_descriptor;
  150 
  151    /* Check for duplicate altsetting entries */
  152    asnum = d->bAlternateSetting;
  153    for ((i = 0, alt = &intfc->altsetting[0]);
37 - 154          i < intfc->num_altsetting;
  155         (++i, ++alt)) {
- 156       if (alt->desc.bAlternateSetting == asnum) {
    157          dev_warn(ddev, "Duplicate descriptor for config %d "
- 157     ternary-?: ( ddev ) -> driver
  158              "interface %d altsetting %d, skipping\n",
  159              cfgno, inum, asnum);
 - 160          goto skip_to_next_interface_descriptor;
  161       }
  162    }
  163 
  164    ++intfc->num_altsetting;
  165    memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);
  166 
  167    /* Skip over any Class Specific or Vendor Specific descriptors;
  168     * find the first endpoint or interface descriptor */
  169    alt->extra = buffer;
  170    i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  171        USB_DT_INTERFACE, &n);
  172    alt->extralen = i;
30   173    if (n > 0)
    174       dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
- 174   ternary-?: ( ddev ) -> driver
  175           n, plural(n), "interface");
  176    buffer += i;
  177    size -= i;
  178 
  179    /* Allocate space for the right(?) number of endpoints */
  180    num_ep = num_ep_orig = alt->desc.bNumEndpoints;
  181    alt->desc.bNumEndpoints = 0;      // Use as a counter
37 - 182    if (num_ep > USB_MAXENDPOINTS) {
    183       dev_warn(ddev, "too many endpoints for config %d interface %d "
- 183   ternary-?: ( ddev ) -> driver
  184           "altsetting %d: %d, using maximum allowed: %d\n",
  185           cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
  186       num_ep = USB_MAXENDPOINTS;
  187    }
  188 
  189    len = sizeof(struct usb_host_endpoint) * num_ep;
  190    alt->endpoint = kzalloc(len, GFP_KERNEL);
37 - 191    if (!alt->endpoint)
 - 192       return -ENOMEM;
  193 
  194    /* Parse all the endpoint descriptors */
  195    n = 0;
43 37   196    while (size > 0) {
  197       if (((struct usb_descriptor_header *) buffer)->bDescriptorType
43 - 198            == USB_DT_INTERFACE)
 - 199          break;
  200       retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
  201           num_ep, buffer, size);
43 - 202       if (retval < 0)
 - 203          return retval;
  204       ++n;
  205 
  206       buffer += retval;
  207       size -= retval;
  208    }
  209 
37 - 210    if (n != num_ep_orig)
    211       dev_warn(ddev, "config %d interface %d altsetting %d has %d "
- 211   ternary-?: ( ddev ) -> driver
  212           "endpoint descriptor%s, different from the interface "
  213           "descriptor's value: %d\n",
  214           cfgno, inum, asnum, n, plural(n), num_ep_orig);
37    215    return buffer - buffer0;
  216 
  217 skip_to_next_interface_descriptor:
  218    i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
  219        USB_DT_INTERFACE, NULL);
 - 220    return buffer - buffer0 + i;
  221 }
  222 
 
37   223 static int usb_parse_configuration(struct device *ddev, int cfgidx,
  224     struct usb_host_config *config, unsigned char *buffer, int size)
  225 {
  226    unsigned char *buffer0 = buffer;
  227    int cfgno;
  228    int nintf, nintf_orig;
  229    int i, j, n;
  230    struct usb_interface_cache *intfc;
  231    unsigned char *buffer2;
  232    int size2;
  233    struct usb_descriptor_header *header;
  234    int len, retval;
  235    u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
  236 
  237    memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
  238    if (config->desc.bDescriptorType != USB_DT_CONFIG ||
37 - 239        config->desc.bLength < USB_DT_CONFIG_SIZE) {
 - 239   T || _
 - 239   F || T
 37   239   F || F
    240       dev_err(ddev, "invalid descriptor for config index %d: "
- 240   ternary-?: ( ddev ) -> driver
  241           "type = 0x%X, length = %d\n", cfgidx,
  242           config->desc.bDescriptorType, config->desc.bLength);
 - 243       return -EINVAL;
  244    }
  245    cfgno = config->desc.bConfigurationValue;
  246 
  247    buffer += config->desc.bLength;
  248    size -= config->desc.bLength;
  249 
  250    nintf = nintf_orig = config->desc.bNumInterfaces;
37 - 251    if (nintf > USB_MAXINTERFACES) {
    252       dev_warn(ddev, "config %d has too many interfaces: %d, "
- 252   ternary-?: ( ddev ) -> driver
  253           "using maximum allowed: %d\n",
  254           cfgno, nintf, USB_MAXINTERFACES);
  255       nintf = USB_MAXINTERFACES;
  256    }
  257 
  258    /* Go through the descriptors, checking their length and counting the
  259     * number of altsettings for each interface */
  260    n = 0;
  261    for ((buffer2 = buffer, size2 = size);
87 37   262          size2 > 0;
  263         (buffer2 += header->bLength, size2 -= header->bLength)) {
  264 
87 - 265       if (size2 < sizeof(struct usb_descriptor_header)) {
    266          dev_warn(ddev, "config %d descriptor has %d excess "
- 266     ternary-?: ( ddev ) -> driver
  267              "byte%s, ignoring\n",
  268              cfgno, size2, plural(size2));
 - 269          break;
  270       }
  271 
  272       header = (struct usb_descriptor_header *) buffer2;
87 - 273       if ((header->bLength > size2) || (header->bLength < 2)) {
 - 273     (T) || (_)
 - 273     (F) || (T)
 87   273     (F) || (F)
    274          dev_warn(ddev, "config %d has an invalid descriptor "
- 274     ternary-?: ( ddev ) -> driver
  275              "of length %d, skipping remainder of the config\n",
  276              cfgno, header->bLength);
 - 277          break;
  278       }
  279 
37 50   280       if (header->bDescriptorType == USB_DT_INTERFACE) {
  281          struct usb_interface_descriptor *d;
  282          int inum;
  283 
  284          d = (struct usb_interface_descriptor *) header;
37 - 285          if (d->bLength < USB_DT_INTERFACE_SIZE) {
    286             dev_warn(ddev, "config %d has an invalid "
- 286       ternary-?: ( ddev ) -> driver
  287                 "interface descriptor of length %d, "
  288                 "skipping\n", cfgno, d->bLength);
 - 289             continue;
  290          }
  291 
  292          inum = d->bInterfaceNumber;
37 - 293          if (inum >= nintf_orig)
    294             dev_warn(ddev, "config %d has an invalid "
- 294       ternary-?: ( ddev ) -> driver
  295                 "interface number: %d but max is %d\n",
  296                 cfgno, inum, nintf_orig - 1);
  297 
  298          /* Have we already encountered this interface?
  299           * Count its altsettings */
37 - 300          for (i = 0; i < n; ++i) {
- 301             if (inums[i] == inum)
 - 302                break;
  303          }
37 - 304          if (i < n) {
- 305             if (nalts[i] < 255)
  306                ++nalts[i];
37 - 307          } else if (n < USB_MAXINTERFACES) {
  308             inums[n] = inum;
  309             nalts[n] = 1;
  310             ++n;
  311          }
  312 
  313       } else if (header->bDescriptorType == USB_DT_DEVICE ||
50 - 314              header->bDescriptorType == USB_DT_CONFIG)
 - 314     T || _
 - 314     F || T
 50   314     F || F
    315          dev_warn(ddev, "config %d contains an unexpected "
- 315     ternary-?: ( ddev ) -> driver
  316              "descriptor of type 0x%X, skipping\n",
  317              cfgno, header->bDescriptorType);
  318 
  319    }   /* for ((buffer2 = buffer, size2 = size); ...) */
  320    size = buffer2 - buffer;
  321    config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
  322 
37 - 323    if (n != nintf)
    324       dev_warn(ddev, "config %d has %d interface%s, different from "
- 324   ternary-?: ( ddev ) -> driver
  325           "the descriptor's value: %d\n",
  326           cfgno, n, plural(n), nintf_orig);
37 - 327    else if (n == 0)
    328       dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
- 328   ternary-?: ( ddev ) -> driver
  329    config->desc.bNumInterfaces = nintf = n;
  330 
  331    /* Check for missing interface numbers */
37 37   332    for (i = 0; i < nintf; ++i) {
37 - 333       for (j = 0; j < nintf; ++j) {
37 - 334          if (inums[j] == i)
37    335             break;
  336       }
37 - 337       if (j >= nintf)
    338          dev_warn(ddev, "config %d has no interface number "
- 338     ternary-?: ( ddev ) -> driver
  339              "%d\n", cfgno, i);
  340    }
  341 
  342    /* Allocate the usb_interface_caches and altsetting arrays */
37 37   343    for (i = 0; i < nintf; ++i) {
  344       j = nalts[i];
37 - 345       if (j > USB_MAXALTSETTING) {
    346          dev_warn(ddev, "too many alternate settings for "
- 346     ternary-?: ( ddev ) -> driver
  347              "config %d interface %d: %d, "
  348              "using maximum allowed: %d\n",
  349              cfgno, inums[i], j, USB_MAXALTSETTING);
  350          nalts[i] = j = USB_MAXALTSETTING;
  351       }
  352 
  353       len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
  354       config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
37 - 355       if (!intfc)
 - 356          return -ENOMEM;
  357       kref_init(&intfc->ref);
  358    }
  359 
  360    /* Skip over any Class Specific or Vendor Specific descriptors;
  361     * find the first interface descriptor */
  362    config->extra = buffer;
  363    i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
  364        USB_DT_INTERFACE, &n);
  365    config->extralen = i;
37 - 366    if (n > 0)
    367       dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
- 367   ternary-?: ( ddev ) -> driver
  368           n, plural(n), "configuration");
  369    buffer += i;
  370    size -= i;
  371 
  372    /* Parse all the interface/altsetting descriptors */
37 37   373    while (size > 0) {
  374       retval = usb_parse_interface(ddev, cfgno, config,
  375           buffer, size, inums, nalts);
37 - 376       if (retval < 0)
 - 377          return retval;
  378 
  379       buffer += retval;
  380       size -= retval;
  381    }
  382 
  383    /* Check for missing altsettings */
37 37   384    for (i = 0; i < nintf; ++i) {
  385       intfc = config->intf_cache[i];
37 37   386       for (j = 0; j < intfc->num_altsetting; ++j) {
37 - 387          for (n = 0; n < intfc->num_altsetting; ++n) {
  388             if (intfc->altsetting[n].desc.
37 - 389                 bAlternateSetting == j)
37    390                break;
  391          }
37 - 392          if (n >= intfc->num_altsetting)
    393             dev_warn(ddev, "config %d interface %d has no "
- 393       ternary-?: ( ddev ) -> driver
  394                 "altsetting %d\n", cfgno, inums[i], j);
  395       }
  396    }
  397 
37    398    return 0;
  399 }
  400 
  401 // hub-only!! ... and only exported for reset/reinit path.
  402 // otherwise used internally on disconnect/destroy path
 
14   403 void usb_destroy_configuration(struct usb_device *dev)
  404 {
  405    int c, i;
  406 
13   407    if (!dev->config)
13    408       return;
  409 
- 410    if (dev->rawdescriptors) {
  411       for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
  412          kfree(dev->rawdescriptors[i]);
  413 
  414       kfree(dev->rawdescriptors);
  415       dev->rawdescriptors = NULL;
  416    }
  417 
  418    for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
  419       struct usb_host_config *cf = &dev->config[c];
  420 
  421       kfree(cf->string);
  422       for (i = 0; i < cf->desc.bNumInterfaces; i++) {
- 423          if (cf->intf_cache[i])
  424             kref_put(&cf->intf_cache[i]->ref, 
  425                  usb_release_interface_cache);
  426       }
  427    }
  428    kfree(dev->config);
  429    dev->config = NULL;
  430 }
  431 
  432 
  433 // hub-only!! ... and only in reset path, or usb_new_device()
  434 // (used by real hubs and virtual root hubs)
 
37   435 int usb_get_configuration(struct usb_device *dev)
  436 {
  437    struct device *ddev = &dev->dev;
  438    int ncfg = dev->descriptor.bNumConfigurations;
  439    int result = -ENOMEM;
  440    unsigned int cfgno, length;
  441    unsigned char *buffer;
  442    unsigned char *bigbuffer;
  443     struct usb_config_descriptor *desc;
  444 
37 - 445    if (ncfg > USB_MAXCONFIG) {
    446       dev_warn(ddev, "too many configurations: %d, "
- 446   ternary-?: ( ddev ) -> driver
  447           "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
  448       dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
  449    }
  450 
37 - 451    if (ncfg < 1) {
    452       dev_err(ddev, "no configurations\n");
- 452   ternary-?: ( ddev ) -> driver
 - 453       return -EINVAL;
  454    }
  455 
  456    length = ncfg * sizeof(struct usb_host_config);
  457    dev->config = kzalloc(length, GFP_KERNEL);
37 - 458