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

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;
                     79:     int i, rc, count;
                     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: 
                     94:     count = conf->nif ? conf->nif : conf->bNumInterfaces;
                     95:     for (i = 0; i < count; i++) {
                     96:         rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
                     97:         if (rc < 0) {
                     98:             return rc;
                     99:         }
                    100:         wTotalLength += rc;
                    101:     }
                    102: 
                    103:     dest[0x02] = usb_lo(wTotalLength);
                    104:     dest[0x03] = usb_hi(wTotalLength);
                    105:     return wTotalLength;
                    106: }
                    107: 
                    108: int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
                    109: {
                    110:     uint8_t bLength = 0x09;
                    111:     int i, rc, pos = 0;
                    112: 
                    113:     if (len < bLength) {
                    114:         return -1;
                    115:     }
                    116: 
                    117:     dest[0x00] = bLength;
                    118:     dest[0x01] = USB_DT_INTERFACE;
                    119:     dest[0x02] = iface->bInterfaceNumber;
                    120:     dest[0x03] = iface->bAlternateSetting;
                    121:     dest[0x04] = iface->bNumEndpoints;
                    122:     dest[0x05] = iface->bInterfaceClass;
                    123:     dest[0x06] = iface->bInterfaceSubClass;
                    124:     dest[0x07] = iface->bInterfaceProtocol;
                    125:     dest[0x08] = iface->iInterface;
                    126:     pos += bLength;
                    127: 
                    128:     for (i = 0; i < iface->ndesc; i++) {
                    129:         rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
                    130:         if (rc < 0) {
                    131:             return rc;
                    132:         }
                    133:         pos += rc;
                    134:     }
                    135: 
                    136:     for (i = 0; i < iface->bNumEndpoints; i++) {
                    137:         rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
                    138:         if (rc < 0) {
                    139:             return rc;
                    140:         }
                    141:         pos += rc;
                    142:     }
                    143: 
                    144:     return pos;
                    145: }
                    146: 
                    147: int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
                    148: {
                    149:     uint8_t bLength = 0x07;
                    150: 
                    151:     if (len < bLength) {
                    152:         return -1;
                    153:     }
                    154: 
                    155:     dest[0x00] = bLength;
                    156:     dest[0x01] = USB_DT_ENDPOINT;
                    157:     dest[0x02] = ep->bEndpointAddress;
                    158:     dest[0x03] = ep->bmAttributes;
                    159:     dest[0x04] = usb_lo(ep->wMaxPacketSize);
                    160:     dest[0x05] = usb_hi(ep->wMaxPacketSize);
                    161:     dest[0x06] = ep->bInterval;
                    162: 
                    163:     return bLength;
                    164: }
                    165: 
                    166: int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
                    167: {
                    168:     int bLength = desc->length ? desc->length : desc->data[0];
                    169: 
                    170:     if (len < bLength) {
                    171:         return -1;
                    172:     }
                    173: 
                    174:     memcpy(dest, desc->data, bLength);
                    175:     return bLength;
                    176: }
                    177: 
                    178: /* ------------------------------------------------------------------ */
                    179: 
                    180: static void usb_desc_setdefaults(USBDevice *dev)
                    181: {
                    182:     const USBDesc *desc = dev->info->usb_desc;
                    183: 
                    184:     assert(desc != NULL);
                    185:     switch (dev->speed) {
                    186:     case USB_SPEED_LOW:
                    187:     case USB_SPEED_FULL:
                    188:         dev->device = desc->full;
                    189:         break;
                    190:     case USB_SPEED_HIGH:
                    191:         dev->device = desc->high;
                    192:         break;
                    193:     }
                    194:     dev->config = dev->device->confs;
                    195: }
                    196: 
                    197: void usb_desc_init(USBDevice *dev)
                    198: {
                    199:     dev->speed = USB_SPEED_FULL;
                    200:     usb_desc_setdefaults(dev);
                    201: }
                    202: 
                    203: void usb_desc_attach(USBDevice *dev)
                    204: {
                    205:     const USBDesc *desc = dev->info->usb_desc;
                    206: 
                    207:     assert(desc != NULL);
                    208:     if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
                    209:         dev->speed = USB_SPEED_HIGH;
                    210:     } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
                    211:         dev->speed = USB_SPEED_FULL;
                    212:     } else {
                    213:         fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
                    214:                 dev->info->product_desc);
                    215:         return;
                    216:     }
                    217:     usb_desc_setdefaults(dev);
                    218: }
                    219: 
                    220: void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
                    221: {
                    222:     USBDescString *s;
                    223: 
                    224:     QLIST_FOREACH(s, &dev->strings, next) {
                    225:         if (s->index == index) {
                    226:             break;
                    227:         }
                    228:     }
                    229:     if (s == NULL) {
                    230:         s = qemu_mallocz(sizeof(*s));
                    231:         s->index = index;
                    232:         QLIST_INSERT_HEAD(&dev->strings, s, next);
                    233:     }
                    234:     qemu_free(s->str);
                    235:     s->str = qemu_strdup(str);
                    236: }
                    237: 
                    238: const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
                    239: {
                    240:     USBDescString *s;
                    241: 
                    242:     QLIST_FOREACH(s, &dev->strings, next) {
                    243:         if (s->index == index) {
                    244:             return s->str;
                    245:         }
                    246:     }
                    247:     return NULL;
                    248: }
                    249: 
                    250: int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
                    251: {
                    252:     uint8_t bLength, pos, i;
                    253:     const char *str;
                    254: 
                    255:     if (len < 4) {
                    256:         return -1;
                    257:     }
                    258: 
                    259:     if (index == 0) {
                    260:         /* language ids */
                    261:         dest[0] = 4;
                    262:         dest[1] = USB_DT_STRING;
                    263:         dest[2] = 0x09;
                    264:         dest[3] = 0x04;
                    265:         return 4;
                    266:     }
                    267: 
                    268:     str = usb_desc_get_string(dev, index);
                    269:     if (str == NULL) {
                    270:         str = dev->info->usb_desc->str[index];
                    271:         if (str == NULL) {
                    272:             return 0;
                    273:         }
                    274:     }
                    275: 
                    276:     bLength = strlen(str) * 2 + 2;
                    277:     dest[0] = bLength;
                    278:     dest[1] = USB_DT_STRING;
                    279:     i = 0; pos = 2;
                    280:     while (pos+1 < bLength && pos+1 < len) {
                    281:         dest[pos++] = str[i++];
                    282:         dest[pos++] = 0;
                    283:     }
                    284:     return pos;
                    285: }
                    286: 
                    287: int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
                    288: {
                    289:     const USBDesc *desc = dev->info->usb_desc;
                    290:     const USBDescDevice *other_dev;
                    291:     uint8_t buf[256];
                    292:     uint8_t type = value >> 8;
                    293:     uint8_t index = value & 0xff;
                    294:     int ret = -1;
                    295: 
                    296:     if (dev->speed == USB_SPEED_HIGH) {
                    297:         other_dev = dev->info->usb_desc->full;
                    298:     } else {
                    299:         other_dev = dev->info->usb_desc->high;
                    300:     }
                    301: 
                    302:     switch(type) {
                    303:     case USB_DT_DEVICE:
                    304:         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
                    305:         trace_usb_desc_device(dev->addr, len, ret);
                    306:         break;
                    307:     case USB_DT_CONFIG:
                    308:         if (index < dev->device->bNumConfigurations) {
                    309:             ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
                    310:         }
                    311:         trace_usb_desc_config(dev->addr, index, len, ret);
                    312:         break;
                    313:     case USB_DT_STRING:
                    314:         ret = usb_desc_string(dev, index, buf, sizeof(buf));
                    315:         trace_usb_desc_string(dev->addr, index, len, ret);
                    316:         break;
                    317: 
                    318:     case USB_DT_DEVICE_QUALIFIER:
                    319:         if (other_dev != NULL) {
                    320:             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
                    321:         }
                    322:         trace_usb_desc_device_qualifier(dev->addr, len, ret);
                    323:         break;
                    324:     case USB_DT_OTHER_SPEED_CONFIG:
                    325:         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
                    326:             ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
                    327:             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
                    328:         }
                    329:         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
                    330:         break;
                    331: 
                    332:     default:
                    333:         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
                    334:                 dev->addr, type, len);
                    335:         break;
                    336:     }
                    337: 
                    338:     if (ret > 0) {
                    339:         if (ret > len) {
                    340:             ret = len;
                    341:         }
                    342:         memcpy(dest, buf, ret);
                    343:     }
                    344:     return ret;
                    345: }
                    346: 
                    347: int usb_desc_handle_control(USBDevice *dev, int request, int value,
                    348:                             int index, int length, uint8_t *data)
                    349: {
                    350:     const USBDesc *desc = dev->info->usb_desc;
                    351:     int i, ret = -1;
                    352: 
                    353:     assert(desc != NULL);
                    354:     switch(request) {
                    355:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
                    356:         dev->addr = value;
                    357:         trace_usb_set_addr(dev->addr);
                    358:         ret = 0;
                    359:         break;
                    360: 
                    361:     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
                    362:         ret = usb_desc_get_descriptor(dev, value, data, length);
                    363:         break;
                    364: 
                    365:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
                    366:         data[0] = dev->config->bConfigurationValue;
                    367:         ret = 1;
                    368:         break;
                    369:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
                    370:         for (i = 0; i < dev->device->bNumConfigurations; i++) {
                    371:             if (dev->device->confs[i].bConfigurationValue == value) {
                    372:                 dev->config = dev->device->confs + i;
                    373:                 ret = 0;
                    374:             }
                    375:         }
                    376:         trace_usb_set_config(dev->addr, value, ret);
                    377:         break;
                    378: 
                    379:     case DeviceRequest | USB_REQ_GET_STATUS:
                    380:         data[0] = 0;
                    381:         if (dev->config->bmAttributes & 0x40) {
                    382:             data[0] |= 1 << USB_DEVICE_SELF_POWERED;
                    383:         }
                    384:         if (dev->remote_wakeup) {
                    385:             data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
                    386:         }
                    387:         data[1] = 0x00;
                    388:         ret = 2;
                    389:         break;
                    390:     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
                    391:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    392:             dev->remote_wakeup = 0;
                    393:             ret = 0;
                    394:         }
                    395:         trace_usb_clear_device_feature(dev->addr, value, ret);
                    396:         break;
                    397:     case DeviceOutRequest | USB_REQ_SET_FEATURE:
                    398:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
                    399:             dev->remote_wakeup = 1;
                    400:             ret = 0;
                    401:         }
                    402:         trace_usb_set_device_feature(dev->addr, value, ret);
                    403:         break;
                    404:     }
                    405:     return ret;
                    406: }

unix.superglobalmegacorp.com

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