Annotation of qemu/hw/usb/desc.c, revision 1.1.1.1

1.1       root        1: #include <ctype.h>
                      2: 
                      3: #include "hw/usb.h"
                      4: #include "hw/usb/desc.h"
                      5: #include "trace.h"
                      6: 
                      7: /* ------------------------------------------------------------------ */
                      8: 
                      9: static uint8_t usb_lo(uint16_t val)
                     10: {
                     11:     return val & 0xff;
                     12: }
                     13: 
                     14: static uint8_t usb_hi(uint16_t val)
                     15: {
                     16:     return (val >> 8) & 0xff;
                     17: }
                     18: 
                     19: int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     20:                     uint8_t *dest, size_t len)
                     21: {
                     22:     uint8_t bLength = 0x12;
                     23:     USBDescriptor *d = (void *)dest;
                     24: 
                     25:     if (len < bLength) {
                     26:         return -1;
                     27:     }
                     28: 
                     29:     d->bLength                     = bLength;
                     30:     d->bDescriptorType             = USB_DT_DEVICE;
                     31: 
                     32:     d->u.device.bcdUSB_lo          = usb_lo(dev->bcdUSB);
                     33:     d->u.device.bcdUSB_hi          = usb_hi(dev->bcdUSB);
                     34:     d->u.device.bDeviceClass       = dev->bDeviceClass;
                     35:     d->u.device.bDeviceSubClass    = dev->bDeviceSubClass;
                     36:     d->u.device.bDeviceProtocol    = dev->bDeviceProtocol;
                     37:     d->u.device.bMaxPacketSize0    = dev->bMaxPacketSize0;
                     38: 
                     39:     d->u.device.idVendor_lo        = usb_lo(id->idVendor);
                     40:     d->u.device.idVendor_hi        = usb_hi(id->idVendor);
                     41:     d->u.device.idProduct_lo       = usb_lo(id->idProduct);
                     42:     d->u.device.idProduct_hi       = usb_hi(id->idProduct);
                     43:     d->u.device.bcdDevice_lo       = usb_lo(id->bcdDevice);
                     44:     d->u.device.bcdDevice_hi       = usb_hi(id->bcdDevice);
                     45:     d->u.device.iManufacturer      = id->iManufacturer;
                     46:     d->u.device.iProduct           = id->iProduct;
                     47:     d->u.device.iSerialNumber      = id->iSerialNumber;
                     48: 
                     49:     d->u.device.bNumConfigurations = dev->bNumConfigurations;
                     50: 
                     51:     return bLength;
                     52: }
                     53: 
                     54: int usb_desc_device_qualifier(const USBDescDevice *dev,
                     55:                               uint8_t *dest, size_t len)
                     56: {
                     57:     uint8_t bLength = 0x0a;
                     58:     USBDescriptor *d = (void *)dest;
                     59: 
                     60:     if (len < bLength) {
                     61:         return -1;
                     62:     }
                     63: 
                     64:     d->bLength                               = bLength;
                     65:     d->bDescriptorType                       = USB_DT_DEVICE_QUALIFIER;
                     66: 
                     67:     d->u.device_qualifier.bcdUSB_lo          = usb_lo(dev->bcdUSB);
                     68:     d->u.device_qualifier.bcdUSB_hi          = usb_hi(dev->bcdUSB);
                     69:     d->u.device_qualifier.bDeviceClass       = dev->bDeviceClass;
                     70:     d->u.device_qualifier.bDeviceSubClass    = dev->bDeviceSubClass;
                     71:     d->u.device_qualifier.bDeviceProtocol    = dev->bDeviceProtocol;
                     72:     d->u.device_qualifier.bMaxPacketSize0    = dev->bMaxPacketSize0;
                     73:     d->u.device_qualifier.bNumConfigurations = dev->bNumConfigurations;
                     74:     d->u.device_qualifier.bReserved          = 0;
                     75: 
                     76:     return bLength;
                     77: }
                     78: 
                     79: int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
                     80: {
                     81:     uint8_t  bLength = 0x09;
                     82:     uint16_t wTotalLength = 0;
                     83:     USBDescriptor *d = (void *)dest;
                     84:     int i, rc;
                     85: 
                     86:     if (len < bLength) {
                     87:         return -1;
                     88:     }
                     89: 
                     90:     d->bLength                      = bLength;
                     91:     d->bDescriptorType              = USB_DT_CONFIG;
                     92: 
                     93:     d->u.config.bNumInterfaces      = conf->bNumInterfaces;
                     94:     d->u.config.bConfigurationValue = conf->bConfigurationValue;
                     95:     d->u.config.iConfiguration      = conf->iConfiguration;
                     96:     d->u.config.bmAttributes        = conf->bmAttributes;
                     97:     d->u.config.bMaxPower           = conf->bMaxPower;
                     98:     wTotalLength += bLength;
                     99: 
                    100:     /* handle grouped interfaces if any */
                    101:     for (i = 0; i < conf->nif_groups; i++) {
                    102:         rc = usb_desc_iface_group(&(conf->if_groups[i]),
                    103:                                   dest + wTotalLength,
                    104:                                   len - wTotalLength);
                    105:         if (rc < 0) {
                    106:             return rc;
                    107:         }
                    108:         wTotalLength += rc;
                    109:     }
                    110: 
                    111:     /* handle normal (ungrouped / no IAD) interfaces if any */
                    112:     for (i = 0; i < conf->nif; i++) {
                    113:         rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
                    114:         if (rc < 0) {
                    115:             return rc;
                    116:         }
                    117:         wTotalLength += rc;
                    118:     }
                    119: 
                    120:     d->u.config.wTotalLength_lo = usb_lo(wTotalLength);
                    121:     d->u.config.wTotalLength_hi = usb_hi(wTotalLength);
                    122:     return wTotalLength;
                    123: }
                    124: 
                    125: int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
                    126:                          size_t len)
                    127: {
                    128:     int pos = 0;
                    129:     int i = 0;
                    130: 
                    131:     /* handle interface association descriptor */
                    132:     uint8_t bLength = 0x08;
                    133: 
                    134:     if (len < bLength) {
                    135:         return -1;
                    136:     }
                    137: 
                    138:     dest[0x00] = bLength;
                    139:     dest[0x01] = USB_DT_INTERFACE_ASSOC;
                    140:     dest[0x02] = iad->bFirstInterface;
                    141:     dest[0x03] = iad->bInterfaceCount;
                    142:     dest[0x04] = iad->bFunctionClass;
                    143:     dest[0x05] = iad->bFunctionSubClass;
                    144:     dest[0x06] = iad->bFunctionProtocol;
                    145:     dest[0x07] = iad->iFunction;
                    146:     pos += bLength;
                    147: 
                    148:     /* handle associated interfaces in this group */
                    149:     for (i = 0; i < iad->nif; i++) {
                    150:         int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
                    151:         if (rc < 0) {
                    152:             return rc;
                    153:         }
                    154:         pos += rc;
                    155:     }
                    156: 
                    157:     return pos;
                    158: }
                    159: 
                    160: int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
                    161: {
                    162:     uint8_t bLength = 0x09;
                    163:     int i, rc, pos = 0;
                    164:     USBDescriptor *d = (void *)dest;
                    165: 
                    166:     if (len < bLength) {
                    167:         return -1;
                    168:     }
                    169: 
                    170:     d->bLength                        = bLength;
                    171:     d->bDescriptorType                = USB_DT_INTERFACE;
                    172: 
                    173:     d->u.interface.bInterfaceNumber   = iface->bInterfaceNumber;
                    174:     d->u.interface.bAlternateSetting  = iface->bAlternateSetting;
                    175:     d->u.interface.bNumEndpoints      = iface->bNumEndpoints;
                    176:     d->u.interface.bInterfaceClass    = iface->bInterfaceClass;
                    177:     d->u.interface.bInterfaceSubClass = iface->bInterfaceSubClass;
                    178:     d->u.interface.bInterfaceProtocol = iface->bInterfaceProtocol;
                    179:     d->u.interface.iInterface         = iface->iInterface;
                    180:     pos += bLength;
                    181: 
                    182:     for (i = 0; i < iface->ndesc; i++) {
                    183:         rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
                    184:         if (rc < 0) {
                    185:             return rc;
                    186:         }
                    187:         pos += rc;
                    188:     }
                    189: 
                    190:     for (i = 0; i < iface->bNumEndpoints; i++) {
                    191:         rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
                    192:         if (rc < 0) {
                    193:             return rc;
                    194:         }
                    195:         pos += rc;
                    196:     }
                    197: 
                    198:     return pos;
                    199: }
                    200: 
                    201: int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
                    202: {
                    203:     uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
                    204:     uint8_t extralen = ep->extra ? ep->extra[0] : 0;
                    205:     USBDescriptor *d = (void *)dest;
                    206: 
                    207:     if (len < bLength + extralen) {
                    208:         return -1;
                    209:     }
                    210: 
                    211:     d->bLength                      = bLength;
                    212:     d->bDescriptorType              = USB_DT_ENDPOINT;
                    213: 
                    214:     d->u.endpoint.bEndpointAddress  = ep->bEndpointAddress;
                    215:     d->u.endpoint.bmAttributes      = ep->bmAttributes;
                    216:     d->u.endpoint.wMaxPacketSize_lo = usb_lo(ep->wMaxPacketSize);
                    217:     d->u.endpoint.wMaxPacketSize_hi = usb_hi(ep->wMaxPacketSize);
                    218:     d->u.endpoint.bInterval         = ep->bInterval;
                    219:     if (ep->is_audio) {
                    220:         d->u.endpoint.bRefresh      = ep->bRefresh;
                    221:         d->u.endpoint.bSynchAddress = ep->bSynchAddress;
                    222:     }
                    223:     if (ep->extra) {
                    224:         memcpy(dest + bLength, ep->extra, extralen);
                    225:     }
                    226: 
                    227:     return bLength + extralen;
                    228: }
                    229: 
                    230: int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
                    231: {
                    232:     int bLength = desc->length ? desc->length : desc->data[0];
                    233: 
                    234:     if (len < bLength) {
                    235:         return -1;
                    236:     }
                    237: 
                    238:     memcpy(dest, desc->data, bLength);
                    239:     return bLength;
                    240: }
                    241: 
                    242: /* ------------------------------------------------------------------ */
                    243: 
                    244: static void usb_desc_ep_init(USBDevice *dev)
                    245: {
                    246:     const USBDescIface *iface;
                    247:     int i, e, pid, ep;
                    248: 
                    249:     usb_ep_init(dev);
                    250:     for (i = 0; i < dev->ninterfaces; i++) {
                    251:         iface = dev->ifaces[i];
                    252:         if (iface == NULL) {
                    253:             continue;
                    254:         }
                    255:         for (e = 0; e < iface->bNumEndpoints; e++) {
                    256:             pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
                    257:                 USB_TOKEN_IN : USB_TOKEN_OUT;
                    258:             ep = iface->eps[e].bEndpointAddress & 0x0f;
                    259:             usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
                    260:             usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
                    261:             usb_ep_set_max_packet_size(dev, pid, ep,
                    262:                                        iface->eps[e].wMaxPacketSize);
                    263:         }
                    264:     }
                    265: }
                    266: 
                    267: static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
                    268:                                                    int nif, int alt)
                    269: {
                    270:     const USBDescIface *iface;
                    271:     int g, i;
                    272: 
                    273:     if (!dev->config) {
                    274:         return NULL;
                    275:     }
                    276:     for (g = 0; g < dev->config->nif_groups; g++) {
                    277:         for (i = 0; i < dev->config->if_groups[g].nif; i++) {
                    278:             iface = &dev->config->if_groups[g].ifs[i];
                    279:             if (iface->bInterfaceNumber == nif &&
                    280:                 iface->bAlternateSetting == alt) {
                    281:                 return iface;
                    282:             }
                    283:         }
                    284:     }
                    285:     for (i = 0; i < dev->config->nif; i++) {
                    286:         iface = &dev->config->ifs[i];
                    287:         if (iface->bInterfaceNumber == nif &&
                    288:             iface->bAlternateSetting == alt) {
                    289:             return iface;
                    290:         }
                    291:     }
                    292:     return NULL;
                    293: }
                    294: 
                    295: static int usb_desc_set_interface(USBDevice *dev, int index, int value)
                    296: {
                    297:     const USBDescIface *iface;
                    298:     int old;
                    299: 
                    300:     iface = usb_desc_find_interface(dev, index, value);
                    301:     if (iface == NULL) {
                    302:         return -1;
                    303:     }
                    304: 
                    305:     old = dev->altsetting[index];
                    306:     dev->altsetting[index] = value;
                    307:     dev->ifaces[index] = iface;
                    308:     usb_desc_ep_init(dev);
                    309: 
                    310:     if (old != value) {
                    311:         usb_device_set_interface(dev, index, old, value);
                    312:     }
                    313:     return 0;
                    314: }
                    315: 
                    316: static int usb_desc_set_config(USBDevice *dev, int value)
                    317: {
                    318:     int i;
                    319: 
                    320:     if (value == 0) {
                    321:         dev->configuration = 0;
                    322:         dev->ninterfaces   = 0;
                    323:         dev->config = NULL;
                    324:     } else {
                    325:         for (i = 0; i < dev->device->bNumConfigurations; i++) {
                    326:             if (dev->device->confs[i].bConfigurationValue == value) {
                    327:                 dev->configuration = value;
                    328:                 dev->ninterfaces   = dev->device->confs[i].bNumInterfaces;
                    329:                 dev->config = dev->device->confs + i;
                    330:                 assert(dev->ninterfaces <= USB_MAX_INTERFACES);
                    331:             }
                    332:         }
                    333:         if (i < dev->device->bNumConfigurations) {
                    334:             return -1;
                    335:         }
                    336:     }
                    337: 
                    338:     for (i = 0; i < dev->ninterfaces; i++) {
                    339:         usb_desc_set_interface(dev, i, 0);
                    340:     }
                    341:     for (; i < USB_MAX_INTERFACES; i++) {
                    342:         dev->altsetting[i] = 0;
                    343:         dev->ifaces[i] = NULL;
                    344:     }
                    345: 
                    346:     return 0;
                    347: }
                    348: 
                    349: static void usb_desc_setdefaults(USBDevice *dev)
                    350: {
                    351:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    352: 
                    353:     assert(desc != NULL);
                    354:     switch (dev->speed) {
                    355:     case USB_SPEED_LOW:
                    356:     case USB_SPEED_FULL:
                    357:         dev->device = desc->full;
                    358:         break;
                    359:     case USB_SPEED_HIGH:
                    360:         dev->device = desc->high;
                    361:         break;
                    362:     }
                    363:     usb_desc_set_config(dev, 0);
                    364: }
                    365: 
                    366: void usb_desc_init(USBDevice *dev)
                    367: {
                    368:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    369: 
                    370:     assert(desc != NULL);
                    371:     dev->speed = USB_SPEED_FULL;
                    372:     dev->speedmask = 0;
                    373:     if (desc->full) {
                    374:         dev->speedmask |= USB_SPEED_MASK_FULL;
                    375:     }
                    376:     if (desc->high) {
                    377:         dev->speedmask |= USB_SPEED_MASK_HIGH;
                    378:     }
                    379:     usb_desc_setdefaults(dev);
                    380: }
                    381: 
                    382: void usb_desc_attach(USBDevice *dev)
                    383: {
                    384:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    385: 
                    386:     assert(desc != NULL);
                    387:     if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
                    388:         dev->speed = USB_SPEED_HIGH;
                    389:     } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
                    390:         dev->speed = USB_SPEED_FULL;
                    391:     } else {
                    392:         fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
                    393:                 usb_device_get_product_desc(dev));
                    394:         return;
                    395:     }
                    396:     usb_desc_setdefaults(dev);
                    397: }
                    398: 
                    399: void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
                    400: {
                    401:     USBDescString *s;
                    402: 
                    403:     QLIST_FOREACH(s, &dev->strings, next) {
                    404:         if (s->index == index) {
                    405:             break;
                    406:         }
                    407:     }
                    408:     if (s == NULL) {
                    409:         s = g_malloc0(sizeof(*s));
                    410:         s->index = index;
                    411:         QLIST_INSERT_HEAD(&dev->strings, s, next);
                    412:     }
                    413:     g_free(s->str);
                    414:     s->str = g_strdup(str);
                    415: }
                    416: 
                    417: /*
                    418:  * This function creates a serial number for a usb device.
                    419:  * The serial number should:
                    420:  *   (a) Be unique within the virtual machine.
                    421:  *   (b) Be constant, so you don't get a new one each
                    422:  *       time the guest is started.
                    423:  * So we are using the physical location to generate a serial number
                    424:  * from it.  It has three pieces:  First a fixed, device-specific
                    425:  * prefix.  Second the device path of the host controller (which is
                    426:  * the pci address in most cases).  Third the physical port path.
                    427:  * Results in serial numbers like this: "314159-0000:00:1d.7-3".
                    428:  */
                    429: void usb_desc_create_serial(USBDevice *dev)
                    430: {
                    431:     DeviceState *hcd = dev->qdev.parent_bus->parent;
                    432:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    433:     int index = desc->id.iSerialNumber;
                    434:     char serial[64];
                    435:     int dst;
                    436: 
                    437:     assert(index != 0 && desc->str[index] != NULL);
                    438:     dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]);
                    439:     if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) {
                    440:         char *path = hcd->parent_bus->info->get_dev_path(hcd);
                    441:         dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path);
                    442:     }
                    443:     dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path);
                    444:     usb_desc_set_string(dev, index, serial);
                    445: }
                    446: 
                    447: const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
                    448: {
                    449:     USBDescString *s;
                    450: 
                    451:     QLIST_FOREACH(s, &dev->strings, next) {
                    452:         if (s->index == index) {
                    453:             return s->str;
                    454:         }
                    455:     }
                    456:     return NULL;
                    457: }
                    458: 
                    459: int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
                    460: {
                    461:     uint8_t bLength, pos, i;
                    462:     const char *str;
                    463: 
                    464:     if (len < 4) {
                    465:         return -1;
                    466:     }
                    467: 
                    468:     if (index == 0) {
                    469:         /* language ids */
                    470:         dest[0] = 4;
                    471:         dest[1] = USB_DT_STRING;
                    472:         dest[2] = 0x09;
                    473:         dest[3] = 0x04;
                    474:         return 4;
                    475:     }
                    476: 
                    477:     str = usb_desc_get_string(dev, index);
                    478:     if (str == NULL) {
                    479:         str = usb_device_get_usb_desc(dev)->str[index];
                    480:         if (str == NULL) {
                    481:             return 0;
                    482:         }
                    483:     }
                    484: 
                    485:     bLength = strlen(str) * 2 + 2;
                    486:     dest[0] = bLength;
                    487:     dest[1] = USB_DT_STRING;
                    488:     i = 0; pos = 2;
                    489:     while (pos+1 < bLength && pos+1 < len) {
                    490:         dest[pos++] = str[i++];
                    491:         dest[pos++] = 0;
                    492:     }
                    493:     return pos;
                    494: }
                    495: 
                    496: int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
                    497: {
                    498:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    499:     const USBDescDevice *other_dev;
                    500:     uint8_t buf[256];
                    501:     uint8_t type = value >> 8;
                    502:     uint8_t index = value & 0xff;
                    503:     int ret = -1;
                    504: 
                    505:     if (dev->speed == USB_SPEED_HIGH) {
                    506:         other_dev = usb_device_get_usb_desc(dev)->full;
                    507:     } else {
                    508:         other_dev = usb_device_get_usb_desc(dev)->high;
                    509:     }
                    510: 
                    511:     switch(type) {
                    512:     case USB_DT_DEVICE:
                    513:         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
                    514:         trace_usb_desc_device(dev->addr, len, ret);
                    515:         break;
                    516:     case USB_DT_CONFIG:
                    517:         if (index < dev->device->bNumConfigurations) {
                    518:             ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
                    519:         }
                    520:         trace_usb_desc_config(dev->addr, index, len, ret);
                    521:         break;
                    522:     case USB_DT_STRING:
                    523:         ret = usb_desc_string(dev, index, buf, sizeof(buf));
                    524:         trace_usb_desc_string(dev->addr, index, len, ret);
                    525:         break;
                    526: 
                    527:     case USB_DT_DEVICE_QUALIFIER:
                    528:         if (other_dev != NULL) {
                    529:             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
                    530:         }
                    531:         trace_usb_desc_device_qualifier(dev->addr, len, ret);
                    532:         break;
                    533:     case USB_DT_OTHER_SPEED_CONFIG:
                    534:         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
                    535:             ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
                    536:             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
                    537:         }
                    538:         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
                    539:         break;
                    540: 
                    541:     case USB_DT_DEBUG:
                    542:         /* ignore silently */
                    543:         break;
                    544: 
                    545:     default:
                    546:         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
                    547:                 dev->addr, type, len);
                    548:         break;
                    549:     }
                    550: 
                    551:     if (ret > 0) {
                    552:         if (ret > len) {
                    553:             ret = len;
                    554:         }
                    555:         memcpy(dest, buf, ret);
                    556:     }
                    557:     return ret;
                    558: }
                    559: 
                    560: int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
                    561:         int request, int value, int index, int length, uint8_t *data)
                    562: {
                    563:     const USBDesc *desc = usb_device_get_usb_desc(dev);
                    564:     int ret = -1;
                    565: 
                    566:     assert(desc != NULL);
                    567:     switch(request) {
                    568:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
                    569:         dev->addr = value;
                    570:         trace_usb_set_addr(dev->addr);
                    571:         ret = 0;
                    572:         break;
                    573: 
                    574:     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
                    575:         ret = usb_desc_get_descriptor(dev, value, data, length);
                    576:         break;
                    577: 
                    578:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
                    579:         /*
                    580:          * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
                    581:          * the non zero value of bConfigurationValue.
                    582:          */
                    583:         data[0] = dev->config ? dev->config->bConfigurationValue : 0;
                    584:         ret = 1;
                    585:         break;
                    586:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
                    587:         ret = usb_desc_set_config(dev, value);
                    588:         trace_usb_set_config(dev->addr, value, ret);
                    589:         break;
                    590: 
                    591:     case DeviceRequest | USB_REQ_GET_STATUS: {
                    592:         const USBDescConfig *config = dev->config ?
                    593:             dev->config : &dev->device->confs[0];
                    594: 
                    595:         data[0] = 0;
                    596:         /*
                    597:          * Default state: Device behavior when this request is received while
                    598:          *                the device is in the Default state is not specified.
                    599:          * We return the same value that a configured device would return if
                    600:          * it used the first configuration.
                    601:          */
                    602:         if (config->bmAttributes & 0x40) {
                    603:             data[0] |= 1 << USB_DEVICE_SELF_POWERED;
                    604:         }
                    605:         if (dev->remote_wakeup) {
                    606:             data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
                    607:         }
                    608:         data[1] = 0x00;
                    609:         ret = 2;
                    610:         break;
                    611:     }
                    612:     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
                    613:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    614:             dev->remote_wakeup = 0;
                    615:             ret = 0;
                    616:         }
                    617:         trace_usb_clear_device_feature(dev->addr, value, ret);
                    618:         break;
                    619:     case DeviceOutRequest | USB_REQ_SET_FEATURE:
                    620:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    621:             dev->remote_wakeup = 1;
                    622:             ret = 0;
                    623:         }
                    624:         trace_usb_set_device_feature(dev->addr, value, ret);
                    625:         break;
                    626: 
                    627:     case InterfaceRequest | USB_REQ_GET_INTERFACE:
                    628:         if (index < 0 || index >= dev->ninterfaces) {
                    629:             break;
                    630:         }
                    631:         data[0] = dev->altsetting[index];
                    632:         ret = 1;
                    633:         break;
                    634:     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
                    635:         ret = usb_desc_set_interface(dev, index, value);
                    636:         trace_usb_set_interface(dev->addr, index, value, ret);
                    637:         break;
                    638: 
                    639:     }
                    640:     return ret;
                    641: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.