Annotation of qemu/hw/usb-desc.c, revision 1.1.1.3

1.1       root        1: #include "usb.h"
                      2: #include "usb-desc.h"
                      3: #include "trace.h"
                      4: 
                      5: /* ------------------------------------------------------------------ */
                      6: 
                      7: static uint8_t usb_lo(uint16_t val)
                      8: {
                      9:     return val & 0xff;
                     10: }
                     11: 
                     12: static uint8_t usb_hi(uint16_t val)
                     13: {
                     14:     return (val >> 8) & 0xff;
                     15: }
                     16: 
                     17: int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     18:                     uint8_t *dest, size_t len)
                     19: {
                     20:     uint8_t bLength = 0x12;
                     21: 
                     22:     if (len < bLength) {
                     23:         return -1;
                     24:     }
                     25: 
                     26:     dest[0x00] = bLength;
                     27:     dest[0x01] = USB_DT_DEVICE;
                     28: 
                     29:     dest[0x02] = usb_lo(dev->bcdUSB);
                     30:     dest[0x03] = usb_hi(dev->bcdUSB);
                     31:     dest[0x04] = dev->bDeviceClass;
                     32:     dest[0x05] = dev->bDeviceSubClass;
                     33:     dest[0x06] = dev->bDeviceProtocol;
                     34:     dest[0x07] = dev->bMaxPacketSize0;
                     35: 
                     36:     dest[0x08] = usb_lo(id->idVendor);
                     37:     dest[0x09] = usb_hi(id->idVendor);
                     38:     dest[0x0a] = usb_lo(id->idProduct);
                     39:     dest[0x0b] = usb_hi(id->idProduct);
                     40:     dest[0x0c] = usb_lo(id->bcdDevice);
                     41:     dest[0x0d] = usb_hi(id->bcdDevice);
                     42:     dest[0x0e] = id->iManufacturer;
                     43:     dest[0x0f] = id->iProduct;
                     44:     dest[0x10] = id->iSerialNumber;
                     45: 
                     46:     dest[0x11] = dev->bNumConfigurations;
                     47: 
                     48:     return bLength;
                     49: }
                     50: 
                     51: int usb_desc_device_qualifier(const USBDescDevice *dev,
                     52:                               uint8_t *dest, size_t len)
                     53: {
                     54:     uint8_t bLength = 0x0a;
                     55: 
                     56:     if (len < bLength) {
                     57:         return -1;
                     58:     }
                     59: 
                     60:     dest[0x00] = bLength;
                     61:     dest[0x01] = USB_DT_DEVICE_QUALIFIER;
                     62: 
                     63:     dest[0x02] = usb_lo(dev->bcdUSB);
                     64:     dest[0x03] = usb_hi(dev->bcdUSB);
                     65:     dest[0x04] = dev->bDeviceClass;
                     66:     dest[0x05] = dev->bDeviceSubClass;
                     67:     dest[0x06] = dev->bDeviceProtocol;
                     68:     dest[0x07] = dev->bMaxPacketSize0;
                     69:     dest[0x08] = dev->bNumConfigurations;
                     70:     dest[0x09] = 0; /* reserved */
                     71: 
                     72:     return bLength;
                     73: }
                     74: 
                     75: int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
                     76: {
                     77:     uint8_t  bLength = 0x09;
                     78:     uint16_t wTotalLength = 0;
1.1.1.2   root       79:     int i, rc;
1.1       root       80: 
                     81:     if (len < bLength) {
                     82:         return -1;
                     83:     }
                     84: 
                     85:     dest[0x00] = bLength;
                     86:     dest[0x01] = USB_DT_CONFIG;
                     87:     dest[0x04] = conf->bNumInterfaces;
                     88:     dest[0x05] = conf->bConfigurationValue;
                     89:     dest[0x06] = conf->iConfiguration;
                     90:     dest[0x07] = conf->bmAttributes;
                     91:     dest[0x08] = conf->bMaxPower;
                     92:     wTotalLength += bLength;
                     93: 
1.1.1.2   root       94:     /* handle grouped interfaces if any*/
                     95:     for (i = 0; i < conf->nif_groups; i++) {
                     96:         rc = usb_desc_iface_group(&(conf->if_groups[i]),
                     97:                                   dest + wTotalLength,
                     98:                                   len - wTotalLength);
                     99:         if (rc < 0) {
                    100:             return rc;
                    101:         }
                    102:         wTotalLength += rc;
                    103:     }
                    104: 
                    105:     /* handle normal (ungrouped / no IAD) interfaces if any */
                    106:     for (i = 0; i < conf->nif; i++) {
1.1       root      107:         rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
                    108:         if (rc < 0) {
                    109:             return rc;
                    110:         }
                    111:         wTotalLength += rc;
                    112:     }
                    113: 
                    114:     dest[0x02] = usb_lo(wTotalLength);
                    115:     dest[0x03] = usb_hi(wTotalLength);
                    116:     return wTotalLength;
                    117: }
                    118: 
1.1.1.2   root      119: int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
                    120:                          size_t len)
                    121: {
                    122:     int pos = 0;
                    123:     int i = 0;
                    124: 
                    125:     /* handle interface association descriptor */
                    126:     uint8_t bLength = 0x08;
                    127: 
                    128:     if (len < bLength) {
                    129:         return -1;
                    130:     }
                    131: 
                    132:     dest[0x00] = bLength;
                    133:     dest[0x01] = USB_DT_INTERFACE_ASSOC;
                    134:     dest[0x02] = iad->bFirstInterface;
                    135:     dest[0x03] = iad->bInterfaceCount;
                    136:     dest[0x04] = iad->bFunctionClass;
                    137:     dest[0x05] = iad->bFunctionSubClass;
                    138:     dest[0x06] = iad->bFunctionProtocol;
                    139:     dest[0x07] = iad->iFunction;
                    140:     pos += bLength;
                    141: 
                    142:     /* handle associated interfaces in this group */
                    143:     for (i = 0; i < iad->nif; i++) {
                    144:         int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
                    145:         if (rc < 0) {
                    146:             return rc;
                    147:         }
                    148:         pos += rc;
                    149:     }
                    150: 
                    151:     return pos;
                    152: }
                    153: 
1.1       root      154: int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
                    155: {
                    156:     uint8_t bLength = 0x09;
                    157:     int i, rc, pos = 0;
                    158: 
                    159:     if (len < bLength) {
                    160:         return -1;
                    161:     }
                    162: 
                    163:     dest[0x00] = bLength;
                    164:     dest[0x01] = USB_DT_INTERFACE;
                    165:     dest[0x02] = iface->bInterfaceNumber;
                    166:     dest[0x03] = iface->bAlternateSetting;
                    167:     dest[0x04] = iface->bNumEndpoints;
                    168:     dest[0x05] = iface->bInterfaceClass;
                    169:     dest[0x06] = iface->bInterfaceSubClass;
                    170:     dest[0x07] = iface->bInterfaceProtocol;
                    171:     dest[0x08] = iface->iInterface;
                    172:     pos += bLength;
                    173: 
                    174:     for (i = 0; i < iface->ndesc; i++) {
                    175:         rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
                    176:         if (rc < 0) {
                    177:             return rc;
                    178:         }
                    179:         pos += rc;
                    180:     }
                    181: 
                    182:     for (i = 0; i < iface->bNumEndpoints; i++) {
                    183:         rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
                    184:         if (rc < 0) {
                    185:             return rc;
                    186:         }
                    187:         pos += rc;
                    188:     }
                    189: 
                    190:     return pos;
                    191: }
                    192: 
                    193: int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
                    194: {
                    195:     uint8_t bLength = 0x07;
                    196: 
                    197:     if (len < bLength) {
                    198:         return -1;
                    199:     }
                    200: 
                    201:     dest[0x00] = bLength;
                    202:     dest[0x01] = USB_DT_ENDPOINT;
                    203:     dest[0x02] = ep->bEndpointAddress;
                    204:     dest[0x03] = ep->bmAttributes;
                    205:     dest[0x04] = usb_lo(ep->wMaxPacketSize);
                    206:     dest[0x05] = usb_hi(ep->wMaxPacketSize);
                    207:     dest[0x06] = ep->bInterval;
                    208: 
                    209:     return bLength;
                    210: }
                    211: 
                    212: int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
                    213: {
                    214:     int bLength = desc->length ? desc->length : desc->data[0];
                    215: 
                    216:     if (len < bLength) {
                    217:         return -1;
                    218:     }
                    219: 
                    220:     memcpy(dest, desc->data, bLength);
                    221:     return bLength;
                    222: }
                    223: 
                    224: /* ------------------------------------------------------------------ */
                    225: 
                    226: static void usb_desc_setdefaults(USBDevice *dev)
                    227: {
                    228:     const USBDesc *desc = dev->info->usb_desc;
                    229: 
                    230:     assert(desc != NULL);
                    231:     switch (dev->speed) {
                    232:     case USB_SPEED_LOW:
                    233:     case USB_SPEED_FULL:
                    234:         dev->device = desc->full;
                    235:         break;
                    236:     case USB_SPEED_HIGH:
                    237:         dev->device = desc->high;
                    238:         break;
                    239:     }
                    240:     dev->config = dev->device->confs;
                    241: }
                    242: 
                    243: void usb_desc_init(USBDevice *dev)
                    244: {
1.1.1.2   root      245:     const USBDesc *desc = dev->info->usb_desc;
                    246: 
                    247:     assert(desc != NULL);
1.1       root      248:     dev->speed = USB_SPEED_FULL;
1.1.1.2   root      249:     dev->speedmask = 0;
                    250:     if (desc->full) {
                    251:         dev->speedmask |= USB_SPEED_MASK_FULL;
                    252:     }
                    253:     if (desc->high) {
                    254:         dev->speedmask |= USB_SPEED_MASK_HIGH;
                    255:     }
1.1       root      256:     usb_desc_setdefaults(dev);
                    257: }
                    258: 
                    259: void usb_desc_attach(USBDevice *dev)
                    260: {
                    261:     const USBDesc *desc = dev->info->usb_desc;
                    262: 
                    263:     assert(desc != NULL);
                    264:     if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
                    265:         dev->speed = USB_SPEED_HIGH;
                    266:     } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
                    267:         dev->speed = USB_SPEED_FULL;
                    268:     } else {
                    269:         fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
                    270:                 dev->info->product_desc);
                    271:         return;
                    272:     }
                    273:     usb_desc_setdefaults(dev);
                    274: }
                    275: 
                    276: void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
                    277: {
                    278:     USBDescString *s;
                    279: 
                    280:     QLIST_FOREACH(s, &dev->strings, next) {
                    281:         if (s->index == index) {
                    282:             break;
                    283:         }
                    284:     }
                    285:     if (s == NULL) {
1.1.1.3 ! root      286:         s = g_malloc0(sizeof(*s));
1.1       root      287:         s->index = index;
                    288:         QLIST_INSERT_HEAD(&dev->strings, s, next);
                    289:     }
1.1.1.3 ! root      290:     g_free(s->str);
        !           291:     s->str = g_strdup(str);
1.1       root      292: }
                    293: 
                    294: const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
                    295: {
                    296:     USBDescString *s;
                    297: 
                    298:     QLIST_FOREACH(s, &dev->strings, next) {
                    299:         if (s->index == index) {
                    300:             return s->str;
                    301:         }
                    302:     }
                    303:     return NULL;
                    304: }
                    305: 
                    306: int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
                    307: {
                    308:     uint8_t bLength, pos, i;
                    309:     const char *str;
                    310: 
                    311:     if (len < 4) {
                    312:         return -1;
                    313:     }
                    314: 
                    315:     if (index == 0) {
                    316:         /* language ids */
                    317:         dest[0] = 4;
                    318:         dest[1] = USB_DT_STRING;
                    319:         dest[2] = 0x09;
                    320:         dest[3] = 0x04;
                    321:         return 4;
                    322:     }
                    323: 
                    324:     str = usb_desc_get_string(dev, index);
                    325:     if (str == NULL) {
                    326:         str = dev->info->usb_desc->str[index];
                    327:         if (str == NULL) {
                    328:             return 0;
                    329:         }
                    330:     }
                    331: 
                    332:     bLength = strlen(str) * 2 + 2;
                    333:     dest[0] = bLength;
                    334:     dest[1] = USB_DT_STRING;
                    335:     i = 0; pos = 2;
                    336:     while (pos+1 < bLength && pos+1 < len) {
                    337:         dest[pos++] = str[i++];
                    338:         dest[pos++] = 0;
                    339:     }
                    340:     return pos;
                    341: }
                    342: 
                    343: int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
                    344: {
                    345:     const USBDesc *desc = dev->info->usb_desc;
                    346:     const USBDescDevice *other_dev;
                    347:     uint8_t buf[256];
                    348:     uint8_t type = value >> 8;
                    349:     uint8_t index = value & 0xff;
                    350:     int ret = -1;
                    351: 
                    352:     if (dev->speed == USB_SPEED_HIGH) {
                    353:         other_dev = dev->info->usb_desc->full;
                    354:     } else {
                    355:         other_dev = dev->info->usb_desc->high;
                    356:     }
                    357: 
                    358:     switch(type) {
                    359:     case USB_DT_DEVICE:
                    360:         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
                    361:         trace_usb_desc_device(dev->addr, len, ret);
                    362:         break;
                    363:     case USB_DT_CONFIG:
                    364:         if (index < dev->device->bNumConfigurations) {
                    365:             ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
                    366:         }
                    367:         trace_usb_desc_config(dev->addr, index, len, ret);
                    368:         break;
                    369:     case USB_DT_STRING:
                    370:         ret = usb_desc_string(dev, index, buf, sizeof(buf));
                    371:         trace_usb_desc_string(dev->addr, index, len, ret);
                    372:         break;
                    373: 
                    374:     case USB_DT_DEVICE_QUALIFIER:
                    375:         if (other_dev != NULL) {
                    376:             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
                    377:         }
                    378:         trace_usb_desc_device_qualifier(dev->addr, len, ret);
                    379:         break;
                    380:     case USB_DT_OTHER_SPEED_CONFIG:
                    381:         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
                    382:             ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
                    383:             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
                    384:         }
                    385:         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
                    386:         break;
                    387: 
1.1.1.2   root      388:     case USB_DT_DEBUG:
                    389:         /* ignore silently */
                    390:         break;
                    391: 
1.1       root      392:     default:
                    393:         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
                    394:                 dev->addr, type, len);
                    395:         break;
                    396:     }
                    397: 
                    398:     if (ret > 0) {
                    399:         if (ret > len) {
                    400:             ret = len;
                    401:         }
                    402:         memcpy(dest, buf, ret);
                    403:     }
                    404:     return ret;
                    405: }
                    406: 
1.1.1.2   root      407: int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
                    408:         int request, int value, int index, int length, uint8_t *data)
1.1       root      409: {
                    410:     const USBDesc *desc = dev->info->usb_desc;
                    411:     int i, ret = -1;
                    412: 
                    413:     assert(desc != NULL);
                    414:     switch(request) {
                    415:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
                    416:         dev->addr = value;
                    417:         trace_usb_set_addr(dev->addr);
                    418:         ret = 0;
                    419:         break;
                    420: 
                    421:     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
                    422:         ret = usb_desc_get_descriptor(dev, value, data, length);
                    423:         break;
                    424: 
                    425:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
                    426:         data[0] = dev->config->bConfigurationValue;
                    427:         ret = 1;
                    428:         break;
                    429:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
                    430:         for (i = 0; i < dev->device->bNumConfigurations; i++) {
                    431:             if (dev->device->confs[i].bConfigurationValue == value) {
                    432:                 dev->config = dev->device->confs + i;
                    433:                 ret = 0;
                    434:             }
                    435:         }
                    436:         trace_usb_set_config(dev->addr, value, ret);
                    437:         break;
                    438: 
                    439:     case DeviceRequest | USB_REQ_GET_STATUS:
                    440:         data[0] = 0;
                    441:         if (dev->config->bmAttributes & 0x40) {
                    442:             data[0] |= 1 << USB_DEVICE_SELF_POWERED;
                    443:         }
                    444:         if (dev->remote_wakeup) {
                    445:             data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
                    446:         }
                    447:         data[1] = 0x00;
                    448:         ret = 2;
                    449:         break;
                    450:     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
                    451:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    452:             dev->remote_wakeup = 0;
                    453:             ret = 0;
                    454:         }
                    455:         trace_usb_clear_device_feature(dev->addr, value, ret);
                    456:         break;
                    457:     case DeviceOutRequest | USB_REQ_SET_FEATURE:
                    458:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    459:             dev->remote_wakeup = 1;
                    460:             ret = 0;
                    461:         }
                    462:         trace_usb_set_device_feature(dev->addr, value, ret);
                    463:         break;
                    464:     }
                    465:     return ret;
                    466: }

unix.superglobalmegacorp.com

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