Annotation of qemu/hw/usb/desc.c, revision 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.