linux-bk/drivers/usb/core/config.c
<<
>>
Prefs
   1#include <linux/config.h>
   2
   3#ifdef CONFIG_USB_DEBUG
   4#define DEBUG
   5#endif
   6
   7#include <linux/usb.h>
   8#include <linux/module.h>
   9#include <linux/init.h>
  10#include <linux/slab.h>
  11#include <linux/device.h>
  12#include <asm/byteorder.h>
  13
  14
  15#define USB_MAXALTSETTING               128     /* Hard limit */
  16#define USB_MAXENDPOINTS                30      /* Hard limit */
  17
  18#define USB_MAXCONFIG                   8       /* Arbitrary limit */
  19
  20
  21static inline const char *plural(int n)
  22{
  23        return (n == 1 ? "" : "s");
  24}
  25
  26static int find_next_descriptor(unsigned char *buffer, int size,
  27    int dt1, int dt2, int *num_skipped)
  28{
  29        struct usb_descriptor_header *h;
  30        int n = 0;
  31        unsigned char *buffer0 = buffer;
  32
  33        /* Find the next descriptor of type dt1 or dt2 */
  34        while (size > 0) {
  35                h = (struct usb_descriptor_header *) buffer;
  36                if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2)
  37                        break;
  38                buffer += h->bLength;
  39                size -= h->bLength;
  40                ++n;
  41        }
  42
  43        /* Store the number of descriptors skipped and return the
  44         * number of bytes skipped */
  45        if (num_skipped)
  46                *num_skipped = n;
  47        return buffer - buffer0;
  48}
  49
  50static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
  51    int asnum, struct usb_host_interface *ifp, int num_ep,
  52    unsigned char *buffer, int size)
  53{
  54        unsigned char *buffer0 = buffer;
  55        struct usb_endpoint_descriptor *d;
  56        struct usb_host_endpoint *endpoint;
  57        int n, i;
  58
  59        d = (struct usb_endpoint_descriptor *) buffer;
  60        buffer += d->bLength;
  61        size -= d->bLength;
  62
  63        if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
  64                n = USB_DT_ENDPOINT_AUDIO_SIZE;
  65        else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
  66                n = USB_DT_ENDPOINT_SIZE;
  67        else {
  68                dev_warn(ddev, "config %d interface %d altsetting %d has an "
  69                    "invalid endpoint descriptor of length %d, skipping\n",
  70                    cfgno, inum, asnum, d->bLength);
  71                goto skip_to_next_endpoint_or_interface_descriptor;
  72        }
  73
  74        i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
  75        if (i >= 16 || i == 0) {
  76                dev_warn(ddev, "config %d interface %d altsetting %d has an "
  77                    "invalid endpoint with address 0x%X, skipping\n",
  78                    cfgno, inum, asnum, d->bEndpointAddress);
  79                goto skip_to_next_endpoint_or_interface_descriptor;
  80        }
  81
  82        /* Only store as many endpoints as we have room for */
  83        if (ifp->desc.bNumEndpoints >= num_ep)
  84                goto skip_to_next_endpoint_or_interface_descriptor;
  85
  86        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
  87        ++ifp->desc.bNumEndpoints;
  88
  89        memcpy(&endpoint->desc, d, n);
  90        INIT_LIST_HEAD(&endpoint->urb_list);
  91
  92        /* Skip over any Class Specific or Vendor Specific descriptors;
  93         * find the next endpoint or interface descriptor */
  94        endpoint->extra = buffer;
  95        i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
  96            USB_DT_INTERFACE, &n);
  97        endpoint->extralen = i;
  98        if (n > 0)
  99                dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
 100                    n, plural(n), "endpoint");
 101        return buffer - buffer0 + i;
 102
 103skip_to_next_endpoint_or_interface_descriptor:
 104        i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
 105            USB_DT_INTERFACE, NULL);
 106        return buffer - buffer0 + i;
 107}
 108
 109void usb_release_interface_cache(struct kref *ref)
 110{
 111        struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
 112        int j;
 113
 114        for (j = 0; j < intfc->num_altsetting; j++)
 115                kfree(intfc->altsetting[j].endpoint);
 116        kfree(intfc);
 117}
 118
 119static 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
 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;
 142        for (i = 0; i < config->desc.bNumInterfaces; ++i) {
 143                if (inums[i] == inum) {
 144                        intfc = config->intf_cache[i];
 145                        break;
 146                }
 147        }
 148        if (!intfc || intfc->num_altsetting >= nalts[i])
 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]);
 154              i < intfc->num_altsetting;
 155             (++i, ++alt)) {
 156                if (alt->desc.bAlternateSetting == asnum) {
 157                        dev_warn(ddev, "Duplicate descriptor for config %d "
 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;
 173        if (n > 0)
 174                dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
 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
 182        if (num_ep > USB_MAXENDPOINTS) {
 183                dev_warn(ddev, "too many endpoints for config %d interface %d "
 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 = kmalloc(len, GFP_KERNEL);
 191        if (!alt->endpoint)
 192                return -ENOMEM;
 193        memset(alt->endpoint, 0, len);
 194
 195        /* Parse all the endpoint descriptors */
 196        n = 0;
 197        while (size > 0) {
 198                if (((struct usb_descriptor_header *) buffer)->bDescriptorType
 199                     == USB_DT_INTERFACE)
 200                        break;
 201                retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
 202                    num_ep, buffer, size);
 203                if (retval < 0)
 204                        return retval;
 205                ++n;
 206
 207                buffer += retval;
 208                size -= retval;
 209        }
 210
 211        if (n != num_ep_orig)
 212                dev_warn(ddev, "config %d interface %d altsetting %d has %d "
 213                    "endpoint descriptor%s, different from the interface "
 214                    "descriptor's value: %d\n",
 215                    cfgno, inum, asnum, n, plural(n), num_ep_orig);
 216        return buffer - buffer0;
 217
 218skip_to_next_interface_descriptor:
 219        i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
 220            USB_DT_INTERFACE, NULL);
 221        return buffer - buffer0 + i;
 222}
 223
 224int usb_parse_configuration(struct device *ddev, int cfgidx,
 225    struct usb_host_config *config, unsigned char *buffer, int size)
 226{
 227        unsigned char *buffer0 = buffer;
 228        int cfgno;
 229        int nintf, nintf_orig;
 230        int i, j, n;
 231        struct usb_interface_cache *intfc;
 232        unsigned char *buffer2;
 233        int size2;
 234        struct usb_descriptor_header *header;
 235        int len, retval;
 236        u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
 237
 238        memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
 239        if (config->desc.bDescriptorType != USB_DT_CONFIG ||
 240            config->desc.bLength < USB_DT_CONFIG_SIZE) {
 241                dev_err(ddev, "invalid descriptor for config index %d: "
 242                    "type = 0x%X, length = %d\n", cfgidx,
 243                    config->desc.bDescriptorType, config->desc.bLength);
 244                return -EINVAL;
 245        }
 246        cfgno = config->desc.bConfigurationValue;
 247
 248        buffer += config->desc.bLength;
 249        size -= config->desc.bLength;
 250
 251        nintf = nintf_orig = config->desc.bNumInterfaces;
 252        if (nintf > USB_MAXINTERFACES) {
 253                dev_warn(ddev, "config %d has too many interfaces: %d, "
 254                    "using maximum allowed: %d\n",
 255                    cfgno, nintf, USB_MAXINTERFACES);
 256                nintf = USB_MAXINTERFACES;
 257        }
 258
 259        /* Go through the descriptors, checking their length and counting the
 260         * number of altsettings for each interface */
 261        n = 0;
 262        for ((buffer2 = buffer, size2 = size);
 263              size2 > 0;
 264             (buffer2 += header->bLength, size2 -= header->bLength)) {
 265
 266                if (size2 < sizeof(struct usb_descriptor_header)) {
 267                        dev_warn(ddev, "config %d descriptor has %d excess "
 268                            "byte%s, ignoring\n",
 269                            cfgno, size2, plural(size2));
 270                        break;
 271                }
 272
 273                header = (struct usb_descriptor_header *) buffer2;
 274                if ((header->bLength > size2) || (header->bLength < 2)) {
 275                        dev_warn(ddev, "config %d has an invalid descriptor "
 276                            "of length %d, skipping remainder of the config\n",
 277                            cfgno, header->bLength);
 278                        break;
 279                }
 280
 281                if (header->bDescriptorType == USB_DT_INTERFACE) {
 282                        struct usb_interface_descriptor *d;
 283                        int inum;
 284
 285                        d = (struct usb_interface_descriptor *) header;
 286                        if (d->bLength < USB_DT_INTERFACE_SIZE) {
 287                                dev_warn(ddev, "config %d has an invalid "
 288                                    "interface descriptor of length %d, "
 289                                    "skipping\n", cfgno, d->bLength);
 290                                continue;
 291                        }
 292
 293                        inum = d->bInterfaceNumber;
 294                        if (inum >= nintf_orig)
 295                                dev_warn(ddev, "config %d has an invalid "
 296                                    "interface number: %d but max is %d\n",
 297                                    cfgno, inum, nintf_orig - 1);
 298
 299                        /* Have we already encountered this interface?
 300                         * Count its altsettings */
 301                        for (i = 0; i < n; ++i) {
 302                                if (inums[i] == inum)
 303                                        break;
 304                        }
 305                        if (i < n) {
 306                                if (nalts[i] < 255)
 307                                        ++nalts[i];
 308                        } else if (n < USB_MAXINTERFACES) {
 309                                inums[n] = inum;
 310                                nalts[n] = 1;
 311                                ++n;
 312                        }
 313
 314                } else if (header->bDescriptorType == USB_DT_DEVICE ||
 315                            header->bDescriptorType == USB_DT_CONFIG)
 316                        dev_warn(ddev, "config %d contains an unexpected "
 317                            "descriptor of type 0x%X, skipping\n",
 318                            cfgno, header->bDescriptorType);
 319
 320        }       /* for ((buffer2 = buffer, size2 = size); ...) */
 321        size = buffer2 - buffer;
 322        config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
 323
 324        if (n != nintf)
 325                dev_warn(ddev, "config %d has %d interface%s, different from "
 326                    "the descriptor's value: %d\n",
 327                    cfgno, n, plural(n), nintf_orig);
 328        else if (n == 0)
 329                dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
 330        config->desc.bNumInterfaces = nintf = n;
 331
 332        /* Check for missing interface numbers */
 333        for (i = 0; i < nintf; ++i) {
 334                for (j = 0; j < nintf; ++j) {
 335                        if (inums[j] == i)
 336                                break;
 337                }
 338                if (j >= nintf)
 339                        dev_warn(ddev, "config %d has no interface number "
 340                            "%d\n", cfgno, i);
 341        }
 342
 343        /* Allocate the usb_interface_caches and altsetting arrays */
 344        for (i = 0; i < nintf; ++i) {
 345                j = nalts[i];
 346                if (j > USB_MAXALTSETTING) {
 347                        dev_warn(ddev, "too many alternate settings for "
 348                            "config %d interface %d: %d, "
 349                            "using maximum allowed: %d\n",
 350                            cfgno, inums[i], j, USB_MAXALTSETTING);
 351                        nalts[i] = j = USB_MAXALTSETTING;
 352                }
 353
 354                len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
 355                config->intf_cache[i] = intfc = kmalloc(len, GFP_KERNEL);
 356                if (!intfc)
 357                        return -ENOMEM;
 358                memset(intfc, 0, len);
 359                kref_init(&intfc->ref);
 360        }
 361
 362        /* Skip over any Class Specific or Vendor Specific descriptors;
 363         * find the first interface descriptor */
 364        config->extra = buffer;
 365        i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
 366            USB_DT_INTERFACE, &n);
 367        config->extralen = i;
 368        if (n > 0)
 369                dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
 370                    n, plural(n), "configuration");
 371        buffer += i;
 372        size -= i;
 373
 374        /* Parse all the interface/altsetting descriptors */
 375        while (size > 0) {
 376                retval = usb_parse_interface(ddev, cfgno, config,
 377                    buffer, size, inums, nalts);
 378                if (retval < 0)
 379                        return retval;
 380
 381                buffer += retval;
 382                size -= retval;
 383        }
 384
 385        /* Check for missing altsettings */
 386        for (i = 0; i < nintf; ++i) {
 387                intfc = config->intf_cache[i];
 388                for (j = 0; j < intfc->num_altsetting; ++j) {
 389                        for (n = 0; n < intfc->num_altsetting; ++n) {
 390                                if (intfc->altsetting[n].desc.
 391                                    bAlternateSetting == j)
 392                                        break;
 393                        }
 394                        if (n >= intfc->num_altsetting)
 395                                dev_warn(ddev, "config %d interface %d has no "
 396                                    "altsetting %d\n", cfgno, inums[i], j);
 397                }
 398        }
 399
 400        return 0;
 401}
 402
 403// hub-only!! ... and only exported for reset/reinit path.
 404// otherwise used internally on disconnect/destroy path
 405void usb_destroy_configuration(struct usb_device *dev)
 406{
 407        int c, i;
 408
 409        if (!dev->config)
 410                return;
 411
 412        if (dev->rawdescriptors) {
 413                for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
 414                        kfree(dev->rawdescriptors[i]);
 415
 416                kfree(dev->rawdescriptors);
 417                dev->rawdescriptors = NULL;
 418        }
 419
 420        for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
 421                struct usb_host_config *cf = &dev->config[c];
 422
 423                for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 424                        if (cf->intf_cache[i])
 425                                kref_put(&cf->intf_cache[i]->ref, 
 426                                          usb_release_interface_cache);
 427                }
 428        }
 429        kfree(dev->config);
 430        dev->config = NULL;
 431}
 432
 433
 434// hub-only!! ... and only in reset path, or usb_new_device()
 435// (used by real hubs and virtual root hubs)
 436int usb_get_configuration(struct usb_device *dev)
 437{
 438        struct device *ddev = &dev->dev;
 439        int ncfg = dev->descriptor.bNumConfigurations;
 440        int result = -ENOMEM;
 441        unsigned int cfgno, length;
 442        unsigned char *buffer;
 443        unsigned char *bigbuffer;
 444        struct usb_config_descriptor *desc;
 445
 446        if (ncfg > USB_MAXCONFIG) {
 447                dev_warn(ddev, "too many configurations: %d, "
 448                    "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
 449                dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
 450        }
 451
 452        if (ncfg < 1) {
 453                dev_err(ddev, "no configurations\n");
 454                return -EINVAL;
 455        }
 456
 457        length = ncfg * sizeof(struct usb_host_config);
 458        dev->config = kmalloc(length, GFP_KERNEL);
 459        if (!dev->config)
 460                goto err2;
 461        memset(dev->config, 0, length);
 462
 463        length = ncfg * sizeof(char *);
 464        dev->rawdescriptors = kmalloc(length, GFP_KERNEL);
 465        if (!dev->rawdescriptors)
 466                goto err2;
 467        memset(dev->rawdescriptors, 0, length);
 468
 469        buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
 470        if (!buffer)
 471                goto err2;
 472        desc = (struct usb_config_descriptor *)buffer;
 473
 474        for (cfgno = 0; cfgno < ncfg; cfgno++) {
 475                /* We grab just the first descriptor so we know how long
 476                 * the whole configuration is */
 477                result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
 478                    buffer, USB_DT_CONFIG_SIZE);
 479                if (result < 0) {
 480                        dev_err(ddev, "unable to read config index %d "
 481                            "descriptor/%s\n", cfgno, "start");
 482                        goto err;
 483                } else if (result < 4) {
 484                        dev_err(ddev, "config index %d descriptor too short "
 485                            "(expected %i, got %i)\n", cfgno,
 486                            USB_DT_CONFIG_SIZE, result);
 487                        result = -EINVAL;
 488                        goto err;
 489                }
 490                length = max((int) le16_to_cpu(desc->wTotalLength),
 491                    USB_DT_CONFIG_SIZE);
 492
 493                /* Now that we know the length, get the whole thing */
 494                bigbuffer = kmalloc(length, GFP_KERNEL);
 495                if (!bigbuffer) {
 496                        result = -ENOMEM;
 497                        goto err;
 498                }
 499                result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
 500                    bigbuffer, length);
 501                if (result < 0) {
 502                        dev_err(ddev, "unable to read config index %d "
 503                            "descriptor/%s\n", cfgno, "all");
 504                        kfree(bigbuffer);
 505                        goto err;
 506                }
 507                if (result < length) {
 508                        dev_warn(ddev, "config index %d descriptor too short "
 509                            "(expected %i, got %i)\n", cfgno, length, result);
 510                        length = result;
 511                }
 512
 513                dev->rawdescriptors[cfgno] = bigbuffer;
 514
 515                result = usb_parse_configuration(&dev->dev, cfgno,
 516                    &dev->config[cfgno], bigbuffer, length);
 517                if (result < 0) {
 518                        ++cfgno;
 519                        goto err;
 520                }
 521        }
 522        result = 0;
 523
 524err:
 525        kfree(buffer);
 526        dev->descriptor.bNumConfigurations = cfgno;
 527err2:
 528        if (result == -ENOMEM)
 529                dev_err(ddev, "out of memory\n");
 530        return result;
 531}
 532
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.