cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

desc.c (24182B)


      1#include "qemu/osdep.h"
      2
      3#include "hw/usb.h"
      4#include "desc.h"
      5#include "trace.h"
      6
      7/* ------------------------------------------------------------------ */
      8
      9int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
     10                    bool msos, uint8_t *dest, size_t len)
     11{
     12    uint8_t bLength = 0x12;
     13    USBDescriptor *d = (void *)dest;
     14
     15    if (len < bLength) {
     16        return -1;
     17    }
     18
     19    d->bLength                     = bLength;
     20    d->bDescriptorType             = USB_DT_DEVICE;
     21
     22    if (msos && dev->bcdUSB < 0x0200) {
     23        /*
     24         * Version 2.0+ required for microsoft os descriptors to work.
     25         * Done this way so msos-desc compat property will handle both
     26         * the version and the new descriptors being present.
     27         */
     28        d->u.device.bcdUSB_lo          = usb_lo(0x0200);
     29        d->u.device.bcdUSB_hi          = usb_hi(0x0200);
     30    } else {
     31        d->u.device.bcdUSB_lo          = usb_lo(dev->bcdUSB);
     32        d->u.device.bcdUSB_hi          = usb_hi(dev->bcdUSB);
     33    }
     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
     54int 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
     79int usb_desc_config(const USBDescConfig *conf, int flags,
     80                    uint8_t *dest, size_t len)
     81{
     82    uint8_t  bLength = 0x09;
     83    uint16_t wTotalLength = 0;
     84    USBDescriptor *d = (void *)dest;
     85    int i, rc;
     86
     87    if (len < bLength) {
     88        return -1;
     89    }
     90
     91    d->bLength                      = bLength;
     92    d->bDescriptorType              = USB_DT_CONFIG;
     93
     94    d->u.config.bNumInterfaces      = conf->bNumInterfaces;
     95    d->u.config.bConfigurationValue = conf->bConfigurationValue;
     96    d->u.config.iConfiguration      = conf->iConfiguration;
     97    d->u.config.bmAttributes        = conf->bmAttributes;
     98    d->u.config.bMaxPower           = conf->bMaxPower;
     99    wTotalLength += bLength;
    100
    101    /* handle grouped interfaces if any */
    102    for (i = 0; i < conf->nif_groups; i++) {
    103        rc = usb_desc_iface_group(&(conf->if_groups[i]), flags,
    104                                  dest + wTotalLength,
    105                                  len - wTotalLength);
    106        if (rc < 0) {
    107            return rc;
    108        }
    109        wTotalLength += rc;
    110    }
    111
    112    /* handle normal (ungrouped / no IAD) interfaces if any */
    113    for (i = 0; i < conf->nif; i++) {
    114        rc = usb_desc_iface(conf->ifs + i, flags,
    115                            dest + wTotalLength, len - wTotalLength);
    116        if (rc < 0) {
    117            return rc;
    118        }
    119        wTotalLength += rc;
    120    }
    121
    122    d->u.config.wTotalLength_lo = usb_lo(wTotalLength);
    123    d->u.config.wTotalLength_hi = usb_hi(wTotalLength);
    124    return wTotalLength;
    125}
    126
    127int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
    128                         uint8_t *dest, size_t len)
    129{
    130    int pos = 0;
    131    int i = 0;
    132
    133    /* handle interface association descriptor */
    134    uint8_t bLength = 0x08;
    135
    136    if (len < bLength) {
    137        return -1;
    138    }
    139
    140    dest[0x00] = bLength;
    141    dest[0x01] = USB_DT_INTERFACE_ASSOC;
    142    dest[0x02] = iad->bFirstInterface;
    143    dest[0x03] = iad->bInterfaceCount;
    144    dest[0x04] = iad->bFunctionClass;
    145    dest[0x05] = iad->bFunctionSubClass;
    146    dest[0x06] = iad->bFunctionProtocol;
    147    dest[0x07] = iad->iFunction;
    148    pos += bLength;
    149
    150    /* handle associated interfaces in this group */
    151    for (i = 0; i < iad->nif; i++) {
    152        int rc = usb_desc_iface(&(iad->ifs[i]), flags, dest + pos, len - pos);
    153        if (rc < 0) {
    154            return rc;
    155        }
    156        pos += rc;
    157    }
    158
    159    return pos;
    160}
    161
    162int usb_desc_iface(const USBDescIface *iface, int flags,
    163                   uint8_t *dest, size_t len)
    164{
    165    uint8_t bLength = 0x09;
    166    int i, rc, pos = 0;
    167    USBDescriptor *d = (void *)dest;
    168
    169    if (len < bLength) {
    170        return -1;
    171    }
    172
    173    d->bLength                        = bLength;
    174    d->bDescriptorType                = USB_DT_INTERFACE;
    175
    176    d->u.interface.bInterfaceNumber   = iface->bInterfaceNumber;
    177    d->u.interface.bAlternateSetting  = iface->bAlternateSetting;
    178    d->u.interface.bNumEndpoints      = iface->bNumEndpoints;
    179    d->u.interface.bInterfaceClass    = iface->bInterfaceClass;
    180    d->u.interface.bInterfaceSubClass = iface->bInterfaceSubClass;
    181    d->u.interface.bInterfaceProtocol = iface->bInterfaceProtocol;
    182    d->u.interface.iInterface         = iface->iInterface;
    183    pos += bLength;
    184
    185    for (i = 0; i < iface->ndesc; i++) {
    186        rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
    187        if (rc < 0) {
    188            return rc;
    189        }
    190        pos += rc;
    191    }
    192
    193    for (i = 0; i < iface->bNumEndpoints; i++) {
    194        rc = usb_desc_endpoint(iface->eps + i, flags, dest + pos, len - pos);
    195        if (rc < 0) {
    196            return rc;
    197        }
    198        pos += rc;
    199    }
    200
    201    return pos;
    202}
    203
    204int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
    205                      uint8_t *dest, size_t len)
    206{
    207    uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
    208    uint8_t extralen = ep->extra ? ep->extra[0] : 0;
    209    uint8_t superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0;
    210    USBDescriptor *d = (void *)dest;
    211
    212    if (len < bLength + extralen + superlen) {
    213        return -1;
    214    }
    215
    216    d->bLength                      = bLength;
    217    d->bDescriptorType              = USB_DT_ENDPOINT;
    218
    219    d->u.endpoint.bEndpointAddress  = ep->bEndpointAddress;
    220    d->u.endpoint.bmAttributes      = ep->bmAttributes;
    221    d->u.endpoint.wMaxPacketSize_lo = usb_lo(ep->wMaxPacketSize);
    222    d->u.endpoint.wMaxPacketSize_hi = usb_hi(ep->wMaxPacketSize);
    223    d->u.endpoint.bInterval         = ep->bInterval;
    224    if (ep->is_audio) {
    225        d->u.endpoint.bRefresh      = ep->bRefresh;
    226        d->u.endpoint.bSynchAddress = ep->bSynchAddress;
    227    }
    228
    229    if (superlen) {
    230        USBDescriptor *d = (void *)(dest + bLength);
    231
    232        d->bLength                       = 0x06;
    233        d->bDescriptorType               = USB_DT_ENDPOINT_COMPANION;
    234
    235        d->u.super_endpoint.bMaxBurst    = ep->bMaxBurst;
    236        d->u.super_endpoint.bmAttributes = ep->bmAttributes_super;
    237        d->u.super_endpoint.wBytesPerInterval_lo =
    238            usb_lo(ep->wBytesPerInterval);
    239        d->u.super_endpoint.wBytesPerInterval_hi =
    240            usb_hi(ep->wBytesPerInterval);
    241    }
    242
    243    if (ep->extra) {
    244        memcpy(dest + bLength + superlen, ep->extra, extralen);
    245    }
    246
    247    return bLength + extralen + superlen;
    248}
    249
    250int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
    251{
    252    int bLength = desc->length ? desc->length : desc->data[0];
    253
    254    if (len < bLength) {
    255        return -1;
    256    }
    257
    258    memcpy(dest, desc->data, bLength);
    259    return bLength;
    260}
    261
    262static int usb_desc_cap_usb2_ext(const USBDesc *desc, uint8_t *dest, size_t len)
    263{
    264    uint8_t  bLength = 0x07;
    265    USBDescriptor *d = (void *)dest;
    266
    267    if (len < bLength) {
    268        return -1;
    269    }
    270
    271    d->bLength                          = bLength;
    272    d->bDescriptorType                  = USB_DT_DEVICE_CAPABILITY;
    273    d->u.cap.bDevCapabilityType         = USB_DEV_CAP_USB2_EXT;
    274
    275    d->u.cap.u.usb2_ext.bmAttributes_1  = (1 << 1);  /* LPM */
    276    d->u.cap.u.usb2_ext.bmAttributes_2  = 0;
    277    d->u.cap.u.usb2_ext.bmAttributes_3  = 0;
    278    d->u.cap.u.usb2_ext.bmAttributes_4  = 0;
    279
    280    return bLength;
    281}
    282
    283static int usb_desc_cap_super(const USBDesc *desc, uint8_t *dest, size_t len)
    284{
    285    uint8_t  bLength = 0x0a;
    286    USBDescriptor *d = (void *)dest;
    287
    288    if (len < bLength) {
    289        return -1;
    290    }
    291
    292    d->bLength                           = bLength;
    293    d->bDescriptorType                   = USB_DT_DEVICE_CAPABILITY;
    294    d->u.cap.bDevCapabilityType          = USB_DEV_CAP_SUPERSPEED;
    295
    296    d->u.cap.u.super.bmAttributes        = 0;
    297    d->u.cap.u.super.wSpeedsSupported_lo = 0;
    298    d->u.cap.u.super.wSpeedsSupported_hi = 0;
    299    d->u.cap.u.super.bFunctionalitySupport = 0;
    300    d->u.cap.u.super.bU1DevExitLat       = 0x0a;
    301    d->u.cap.u.super.wU2DevExitLat_lo    = 0x20;
    302    d->u.cap.u.super.wU2DevExitLat_hi    = 0;
    303
    304    if (desc->full) {
    305        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 1);
    306        d->u.cap.u.super.bFunctionalitySupport = 1;
    307    }
    308    if (desc->high) {
    309        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 2);
    310        if (!d->u.cap.u.super.bFunctionalitySupport) {
    311            d->u.cap.u.super.bFunctionalitySupport = 2;
    312        }
    313    }
    314    if (desc->super) {
    315        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 3);
    316        if (!d->u.cap.u.super.bFunctionalitySupport) {
    317            d->u.cap.u.super.bFunctionalitySupport = 3;
    318        }
    319    }
    320
    321    return bLength;
    322}
    323
    324static int usb_desc_bos(const USBDesc *desc, uint8_t *dest, size_t len)
    325{
    326    uint8_t  bLength = 0x05;
    327    uint16_t wTotalLength = 0;
    328    uint8_t  bNumDeviceCaps = 0;
    329    USBDescriptor *d = (void *)dest;
    330    int rc;
    331
    332    if (len < bLength) {
    333        return -1;
    334    }
    335
    336    d->bLength                      = bLength;
    337    d->bDescriptorType              = USB_DT_BOS;
    338
    339    wTotalLength += bLength;
    340
    341    if (desc->high != NULL) {
    342        rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
    343                                   len - wTotalLength);
    344        if (rc < 0) {
    345            return rc;
    346        }
    347        wTotalLength += rc;
    348        bNumDeviceCaps++;
    349    }
    350
    351    if (desc->super != NULL) {
    352        rc = usb_desc_cap_super(desc, dest + wTotalLength,
    353                                len - wTotalLength);
    354        if (rc < 0) {
    355            return rc;
    356        }
    357        wTotalLength += rc;
    358        bNumDeviceCaps++;
    359    }
    360
    361    d->u.bos.wTotalLength_lo = usb_lo(wTotalLength);
    362    d->u.bos.wTotalLength_hi = usb_hi(wTotalLength);
    363    d->u.bos.bNumDeviceCaps  = bNumDeviceCaps;
    364    return wTotalLength;
    365}
    366
    367/* ------------------------------------------------------------------ */
    368
    369static void usb_desc_ep_init(USBDevice *dev)
    370{
    371    const USBDescIface *iface;
    372    int i, e, pid, ep;
    373
    374    usb_ep_init(dev);
    375    for (i = 0; i < dev->ninterfaces; i++) {
    376        iface = dev->ifaces[i];
    377        if (iface == NULL) {
    378            continue;
    379        }
    380        for (e = 0; e < iface->bNumEndpoints; e++) {
    381            pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
    382                USB_TOKEN_IN : USB_TOKEN_OUT;
    383            ep = iface->eps[e].bEndpointAddress & 0x0f;
    384            usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
    385            usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
    386            usb_ep_set_max_packet_size(dev, pid, ep,
    387                                       iface->eps[e].wMaxPacketSize);
    388            usb_ep_set_max_streams(dev, pid, ep,
    389                                   iface->eps[e].bmAttributes_super);
    390        }
    391    }
    392}
    393
    394static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
    395                                                   int nif, int alt)
    396{
    397    const USBDescIface *iface;
    398    int g, i;
    399
    400    if (!dev->config) {
    401        return NULL;
    402    }
    403    for (g = 0; g < dev->config->nif_groups; g++) {
    404        for (i = 0; i < dev->config->if_groups[g].nif; i++) {
    405            iface = &dev->config->if_groups[g].ifs[i];
    406            if (iface->bInterfaceNumber == nif &&
    407                iface->bAlternateSetting == alt) {
    408                return iface;
    409            }
    410        }
    411    }
    412    for (i = 0; i < dev->config->nif; i++) {
    413        iface = &dev->config->ifs[i];
    414        if (iface->bInterfaceNumber == nif &&
    415            iface->bAlternateSetting == alt) {
    416            return iface;
    417        }
    418    }
    419    return NULL;
    420}
    421
    422static int usb_desc_set_interface(USBDevice *dev, int index, int value)
    423{
    424    const USBDescIface *iface;
    425    int old;
    426
    427    iface = usb_desc_find_interface(dev, index, value);
    428    if (iface == NULL) {
    429        return -1;
    430    }
    431
    432    old = dev->altsetting[index];
    433    dev->altsetting[index] = value;
    434    dev->ifaces[index] = iface;
    435    usb_desc_ep_init(dev);
    436
    437    if (old != value) {
    438        usb_device_set_interface(dev, index, old, value);
    439    }
    440    return 0;
    441}
    442
    443static int usb_desc_set_config(USBDevice *dev, int value)
    444{
    445    int i;
    446
    447    if (value == 0) {
    448        dev->configuration = 0;
    449        dev->ninterfaces   = 0;
    450        dev->config = NULL;
    451    } else {
    452        for (i = 0; i < dev->device->bNumConfigurations; i++) {
    453            if (dev->device->confs[i].bConfigurationValue == value) {
    454                dev->configuration = value;
    455                dev->ninterfaces   = dev->device->confs[i].bNumInterfaces;
    456                dev->config = dev->device->confs + i;
    457                assert(dev->ninterfaces <= USB_MAX_INTERFACES);
    458            }
    459        }
    460        if (i < dev->device->bNumConfigurations) {
    461            return -1;
    462        }
    463    }
    464
    465    for (i = 0; i < dev->ninterfaces; i++) {
    466        usb_desc_set_interface(dev, i, 0);
    467    }
    468    for (; i < USB_MAX_INTERFACES; i++) {
    469        dev->altsetting[i] = 0;
    470        dev->ifaces[i] = NULL;
    471    }
    472
    473    return 0;
    474}
    475
    476static void usb_desc_setdefaults(USBDevice *dev)
    477{
    478    const USBDesc *desc = usb_device_get_usb_desc(dev);
    479
    480    assert(desc != NULL);
    481    switch (dev->speed) {
    482    case USB_SPEED_LOW:
    483    case USB_SPEED_FULL:
    484        dev->device = desc->full;
    485        break;
    486    case USB_SPEED_HIGH:
    487        dev->device = desc->high;
    488        break;
    489    case USB_SPEED_SUPER:
    490        dev->device = desc->super;
    491        break;
    492    }
    493    usb_desc_set_config(dev, 0);
    494}
    495
    496void usb_desc_init(USBDevice *dev)
    497{
    498    const USBDesc *desc = usb_device_get_usb_desc(dev);
    499
    500    assert(desc != NULL);
    501    dev->speed = USB_SPEED_FULL;
    502    dev->speedmask = 0;
    503    if (desc->full) {
    504        dev->speedmask |= USB_SPEED_MASK_FULL;
    505    }
    506    if (desc->high) {
    507        dev->speedmask |= USB_SPEED_MASK_HIGH;
    508    }
    509    if (desc->super) {
    510        dev->speedmask |= USB_SPEED_MASK_SUPER;
    511    }
    512    if (desc->msos && (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_ENABLE))) {
    513        dev->flags |= (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE);
    514        usb_desc_set_string(dev, 0xee, "MSFT100Q");
    515    }
    516    usb_desc_setdefaults(dev);
    517}
    518
    519void usb_desc_attach(USBDevice *dev)
    520{
    521    usb_desc_setdefaults(dev);
    522}
    523
    524void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
    525{
    526    USBDescString *s;
    527
    528    QLIST_FOREACH(s, &dev->strings, next) {
    529        if (s->index == index) {
    530            break;
    531        }
    532    }
    533    if (s == NULL) {
    534        s = g_malloc0(sizeof(*s));
    535        s->index = index;
    536        QLIST_INSERT_HEAD(&dev->strings, s, next);
    537    }
    538    g_free(s->str);
    539    s->str = g_strdup(str);
    540}
    541
    542/*
    543 * This function creates a serial number for a usb device.
    544 * The serial number should:
    545 *   (a) Be unique within the virtual machine.
    546 *   (b) Be constant, so you don't get a new one each
    547 *       time the guest is started.
    548 * So we are using the physical location to generate a serial number
    549 * from it.  It has three pieces:  First a fixed, device-specific
    550 * prefix.  Second the device path of the host controller (which is
    551 * the pci address in most cases).  Third the physical port path.
    552 * Results in serial numbers like this: "314159-0000:00:1d.7-3".
    553 */
    554void usb_desc_create_serial(USBDevice *dev)
    555{
    556    DeviceState *hcd = dev->qdev.parent_bus->parent;
    557    const USBDesc *desc = usb_device_get_usb_desc(dev);
    558    int index = desc->id.iSerialNumber;
    559    char *path, *serial;
    560
    561    if (dev->serial) {
    562        /* 'serial' usb bus property has priority if present */
    563        usb_desc_set_string(dev, index, dev->serial);
    564        return;
    565    }
    566
    567    assert(index != 0 && desc->str[index] != NULL);
    568    path = qdev_get_dev_path(hcd);
    569    if (path) {
    570        serial = g_strdup_printf("%s-%s-%s", desc->str[index],
    571                                 path, dev->port->path);
    572    } else {
    573        serial = g_strdup_printf("%s-%s", desc->str[index], dev->port->path);
    574    }
    575    usb_desc_set_string(dev, index, serial);
    576    g_free(path);
    577    g_free(serial);
    578}
    579
    580const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
    581{
    582    USBDescString *s;
    583
    584    QLIST_FOREACH(s, &dev->strings, next) {
    585        if (s->index == index) {
    586            return s->str;
    587        }
    588    }
    589    return NULL;
    590}
    591
    592int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
    593{
    594    uint8_t bLength, pos, i;
    595    const char *str;
    596
    597    if (len < 4) {
    598        return -1;
    599    }
    600
    601    if (index == 0) {
    602        /* language ids */
    603        dest[0] = 4;
    604        dest[1] = USB_DT_STRING;
    605        dest[2] = 0x09;
    606        dest[3] = 0x04;
    607        return 4;
    608    }
    609
    610    str = usb_desc_get_string(dev, index);
    611    if (str == NULL) {
    612        str = usb_device_get_usb_desc(dev)->str[index];
    613        if (str == NULL) {
    614            return 0;
    615        }
    616    }
    617
    618    bLength = strlen(str) * 2 + 2;
    619    dest[0] = bLength;
    620    dest[1] = USB_DT_STRING;
    621    i = 0; pos = 2;
    622    while (pos+1 < bLength && pos+1 < len) {
    623        dest[pos++] = str[i++];
    624        dest[pos++] = 0;
    625    }
    626    return pos;
    627}
    628
    629int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
    630                            int value, uint8_t *dest, size_t len)
    631{
    632    bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE));
    633    const USBDesc *desc = usb_device_get_usb_desc(dev);
    634    const USBDescDevice *other_dev;
    635    uint8_t buf[256];
    636    uint8_t type = value >> 8;
    637    uint8_t index = value & 0xff;
    638    int flags, ret = -1;
    639
    640    if (dev->speed == USB_SPEED_HIGH) {
    641        other_dev = usb_device_get_usb_desc(dev)->full;
    642    } else {
    643        other_dev = usb_device_get_usb_desc(dev)->high;
    644    }
    645
    646    flags = 0;
    647    if (dev->device->bcdUSB >= 0x0300) {
    648        flags |= USB_DESC_FLAG_SUPER;
    649    }
    650
    651    switch(type) {
    652    case USB_DT_DEVICE:
    653        ret = usb_desc_device(&desc->id, dev->device, msos, buf, sizeof(buf));
    654        trace_usb_desc_device(dev->addr, len, ret);
    655        break;
    656    case USB_DT_CONFIG:
    657        if (index < dev->device->bNumConfigurations) {
    658            ret = usb_desc_config(dev->device->confs + index, flags,
    659                                  buf, sizeof(buf));
    660        }
    661        trace_usb_desc_config(dev->addr, index, len, ret);
    662        break;
    663    case USB_DT_STRING:
    664        ret = usb_desc_string(dev, index, buf, sizeof(buf));
    665        trace_usb_desc_string(dev->addr, index, len, ret);
    666        break;
    667    case USB_DT_DEVICE_QUALIFIER:
    668        if (other_dev != NULL) {
    669            ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
    670        }
    671        trace_usb_desc_device_qualifier(dev->addr, len, ret);
    672        break;
    673    case USB_DT_OTHER_SPEED_CONFIG:
    674        if (other_dev != NULL && index < other_dev->bNumConfigurations) {
    675            ret = usb_desc_config(other_dev->confs + index, flags,
    676                                  buf, sizeof(buf));
    677            buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
    678        }
    679        trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
    680        break;
    681    case USB_DT_BOS:
    682        ret = usb_desc_bos(desc, buf, sizeof(buf));
    683        trace_usb_desc_bos(dev->addr, len, ret);
    684        break;
    685
    686    case USB_DT_DEBUG:
    687        /* ignore silently */
    688        break;
    689
    690    default:
    691        fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __func__,
    692                dev->addr, type, len);
    693        break;
    694    }
    695
    696    if (ret > 0) {
    697        if (ret > len) {
    698            ret = len;
    699        }
    700        memcpy(dest, buf, ret);
    701        p->actual_length = ret;
    702        ret = 0;
    703    }
    704    return ret;
    705}
    706
    707int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
    708        int request, int value, int index, int length, uint8_t *data)
    709{
    710    bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE));
    711    const USBDesc *desc = usb_device_get_usb_desc(dev);
    712    int ret = -1;
    713
    714    assert(desc != NULL);
    715    switch(request) {
    716    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
    717        dev->addr = value;
    718        trace_usb_set_addr(dev->addr);
    719        ret = 0;
    720        break;
    721
    722    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
    723        ret = usb_desc_get_descriptor(dev, p, value, data, length);
    724        break;
    725
    726    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
    727        /*
    728         * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
    729         * the non zero value of bConfigurationValue.
    730         */
    731        data[0] = dev->config ? dev->config->bConfigurationValue : 0;
    732        p->actual_length = 1;
    733        ret = 0;
    734        break;
    735    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
    736        ret = usb_desc_set_config(dev, value);
    737        trace_usb_set_config(dev->addr, value, ret);
    738        break;
    739
    740    case DeviceRequest | USB_REQ_GET_STATUS: {
    741        const USBDescConfig *config = dev->config ?
    742            dev->config : &dev->device->confs[0];
    743
    744        data[0] = 0;
    745        /*
    746         * Default state: Device behavior when this request is received while
    747         *                the device is in the Default state is not specified.
    748         * We return the same value that a configured device would return if
    749         * it used the first configuration.
    750         */
    751        if (config->bmAttributes & USB_CFG_ATT_SELFPOWER) {
    752            data[0] |= 1 << USB_DEVICE_SELF_POWERED;
    753        }
    754        if (dev->remote_wakeup) {
    755            data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
    756        }
    757        data[1] = 0x00;
    758        p->actual_length = 2;
    759        ret = 0;
    760        break;
    761    }
    762    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
    763        if (value == USB_DEVICE_REMOTE_WAKEUP) {
    764            dev->remote_wakeup = 0;
    765            ret = 0;
    766        }
    767        trace_usb_clear_device_feature(dev->addr, value, ret);
    768        break;
    769    case DeviceOutRequest | USB_REQ_SET_FEATURE:
    770        if (value == USB_DEVICE_REMOTE_WAKEUP) {
    771            dev->remote_wakeup = 1;
    772            ret = 0;
    773        }
    774        trace_usb_set_device_feature(dev->addr, value, ret);
    775        break;
    776
    777    case DeviceOutRequest | USB_REQ_SET_SEL:
    778    case DeviceOutRequest | USB_REQ_SET_ISOCH_DELAY:
    779        if (dev->speed == USB_SPEED_SUPER) {
    780            ret = 0;
    781        }
    782        break;
    783
    784    case InterfaceRequest | USB_REQ_GET_INTERFACE:
    785        if (index < 0 || index >= dev->ninterfaces) {
    786            break;
    787        }
    788        data[0] = dev->altsetting[index];
    789        p->actual_length = 1;
    790        ret = 0;
    791        break;
    792    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
    793        ret = usb_desc_set_interface(dev, index, value);
    794        trace_usb_set_interface(dev->addr, index, value, ret);
    795        break;
    796
    797    case VendorDeviceRequest | 'Q':
    798        if (msos) {
    799            ret = usb_desc_msos(desc, p, index, data, length);
    800            trace_usb_desc_msos(dev->addr, index, length, ret);
    801        }
    802        break;
    803    case VendorInterfaceRequest | 'Q':
    804        if (msos) {
    805            ret = usb_desc_msos(desc, p, index, data, length);
    806            trace_usb_desc_msos(dev->addr, index, length, ret);
    807        }
    808        break;
    809
    810    }
    811    return ret;
    812}