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