xref: /openbmc/qemu/hw/usb/desc.c (revision 4fabffc11234d0587a213418574095e036110cd2)
1 #include "hw/usb.h"
2 #include "hw/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     USBDescriptor *d = (void *)dest;
22 
23     if (len < bLength) {
24         return -1;
25     }
26 
27     d->bLength                     = bLength;
28     d->bDescriptorType             = USB_DT_DEVICE;
29 
30     d->u.device.bcdUSB_lo          = usb_lo(dev->bcdUSB);
31     d->u.device.bcdUSB_hi          = usb_hi(dev->bcdUSB);
32     d->u.device.bDeviceClass       = dev->bDeviceClass;
33     d->u.device.bDeviceSubClass    = dev->bDeviceSubClass;
34     d->u.device.bDeviceProtocol    = dev->bDeviceProtocol;
35     d->u.device.bMaxPacketSize0    = dev->bMaxPacketSize0;
36 
37     d->u.device.idVendor_lo        = usb_lo(id->idVendor);
38     d->u.device.idVendor_hi        = usb_hi(id->idVendor);
39     d->u.device.idProduct_lo       = usb_lo(id->idProduct);
40     d->u.device.idProduct_hi       = usb_hi(id->idProduct);
41     d->u.device.bcdDevice_lo       = usb_lo(id->bcdDevice);
42     d->u.device.bcdDevice_hi       = usb_hi(id->bcdDevice);
43     d->u.device.iManufacturer      = id->iManufacturer;
44     d->u.device.iProduct           = id->iProduct;
45     d->u.device.iSerialNumber      = id->iSerialNumber;
46 
47     d->u.device.bNumConfigurations = dev->bNumConfigurations;
48 
49     return bLength;
50 }
51 
52 int usb_desc_device_qualifier(const USBDescDevice *dev,
53                               uint8_t *dest, size_t len)
54 {
55     uint8_t bLength = 0x0a;
56     USBDescriptor *d = (void *)dest;
57 
58     if (len < bLength) {
59         return -1;
60     }
61 
62     d->bLength                               = bLength;
63     d->bDescriptorType                       = USB_DT_DEVICE_QUALIFIER;
64 
65     d->u.device_qualifier.bcdUSB_lo          = usb_lo(dev->bcdUSB);
66     d->u.device_qualifier.bcdUSB_hi          = usb_hi(dev->bcdUSB);
67     d->u.device_qualifier.bDeviceClass       = dev->bDeviceClass;
68     d->u.device_qualifier.bDeviceSubClass    = dev->bDeviceSubClass;
69     d->u.device_qualifier.bDeviceProtocol    = dev->bDeviceProtocol;
70     d->u.device_qualifier.bMaxPacketSize0    = dev->bMaxPacketSize0;
71     d->u.device_qualifier.bNumConfigurations = dev->bNumConfigurations;
72     d->u.device_qualifier.bReserved          = 0;
73 
74     return bLength;
75 }
76 
77 int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
78 {
79     uint8_t  bLength = 0x09;
80     uint16_t wTotalLength = 0;
81     USBDescriptor *d = (void *)dest;
82     int i, rc;
83 
84     if (len < bLength) {
85         return -1;
86     }
87 
88     d->bLength                      = bLength;
89     d->bDescriptorType              = USB_DT_CONFIG;
90 
91     d->u.config.bNumInterfaces      = conf->bNumInterfaces;
92     d->u.config.bConfigurationValue = conf->bConfigurationValue;
93     d->u.config.iConfiguration      = conf->iConfiguration;
94     d->u.config.bmAttributes        = conf->bmAttributes;
95     d->u.config.bMaxPower           = conf->bMaxPower;
96     wTotalLength += bLength;
97 
98     /* handle grouped interfaces if any */
99     for (i = 0; i < conf->nif_groups; i++) {
100         rc = usb_desc_iface_group(&(conf->if_groups[i]),
101                                   dest + wTotalLength,
102                                   len - wTotalLength);
103         if (rc < 0) {
104             return rc;
105         }
106         wTotalLength += rc;
107     }
108 
109     /* handle normal (ungrouped / no IAD) interfaces if any */
110     for (i = 0; i < conf->nif; i++) {
111         rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
112         if (rc < 0) {
113             return rc;
114         }
115         wTotalLength += rc;
116     }
117 
118     d->u.config.wTotalLength_lo = usb_lo(wTotalLength);
119     d->u.config.wTotalLength_hi = usb_hi(wTotalLength);
120     return wTotalLength;
121 }
122 
123 int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
124                          size_t len)
125 {
126     int pos = 0;
127     int i = 0;
128 
129     /* handle interface association descriptor */
130     uint8_t bLength = 0x08;
131 
132     if (len < bLength) {
133         return -1;
134     }
135 
136     dest[0x00] = bLength;
137     dest[0x01] = USB_DT_INTERFACE_ASSOC;
138     dest[0x02] = iad->bFirstInterface;
139     dest[0x03] = iad->bInterfaceCount;
140     dest[0x04] = iad->bFunctionClass;
141     dest[0x05] = iad->bFunctionSubClass;
142     dest[0x06] = iad->bFunctionProtocol;
143     dest[0x07] = iad->iFunction;
144     pos += bLength;
145 
146     /* handle associated interfaces in this group */
147     for (i = 0; i < iad->nif; i++) {
148         int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
149         if (rc < 0) {
150             return rc;
151         }
152         pos += rc;
153     }
154 
155     return pos;
156 }
157 
158 int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
159 {
160     uint8_t bLength = 0x09;
161     int i, rc, pos = 0;
162     USBDescriptor *d = (void *)dest;
163 
164     if (len < bLength) {
165         return -1;
166     }
167 
168     d->bLength                        = bLength;
169     d->bDescriptorType                = USB_DT_INTERFACE;
170 
171     d->u.interface.bInterfaceNumber   = iface->bInterfaceNumber;
172     d->u.interface.bAlternateSetting  = iface->bAlternateSetting;
173     d->u.interface.bNumEndpoints      = iface->bNumEndpoints;
174     d->u.interface.bInterfaceClass    = iface->bInterfaceClass;
175     d->u.interface.bInterfaceSubClass = iface->bInterfaceSubClass;
176     d->u.interface.bInterfaceProtocol = iface->bInterfaceProtocol;
177     d->u.interface.iInterface         = iface->iInterface;
178     pos += bLength;
179 
180     for (i = 0; i < iface->ndesc; i++) {
181         rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
182         if (rc < 0) {
183             return rc;
184         }
185         pos += rc;
186     }
187 
188     for (i = 0; i < iface->bNumEndpoints; i++) {
189         rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
190         if (rc < 0) {
191             return rc;
192         }
193         pos += rc;
194     }
195 
196     return pos;
197 }
198 
199 int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
200 {
201     uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
202     uint8_t extralen = ep->extra ? ep->extra[0] : 0;
203     USBDescriptor *d = (void *)dest;
204 
205     if (len < bLength + extralen) {
206         return -1;
207     }
208 
209     d->bLength                      = bLength;
210     d->bDescriptorType              = USB_DT_ENDPOINT;
211 
212     d->u.endpoint.bEndpointAddress  = ep->bEndpointAddress;
213     d->u.endpoint.bmAttributes      = ep->bmAttributes;
214     d->u.endpoint.wMaxPacketSize_lo = usb_lo(ep->wMaxPacketSize);
215     d->u.endpoint.wMaxPacketSize_hi = usb_hi(ep->wMaxPacketSize);
216     d->u.endpoint.bInterval         = ep->bInterval;
217     if (ep->is_audio) {
218         d->u.endpoint.bRefresh      = ep->bRefresh;
219         d->u.endpoint.bSynchAddress = ep->bSynchAddress;
220     }
221     if (ep->extra) {
222         memcpy(dest + bLength, ep->extra, extralen);
223     }
224 
225     return bLength + extralen;
226 }
227 
228 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
229 {
230     int bLength = desc->length ? desc->length : desc->data[0];
231 
232     if (len < bLength) {
233         return -1;
234     }
235 
236     memcpy(dest, desc->data, bLength);
237     return bLength;
238 }
239 
240 /* ------------------------------------------------------------------ */
241 
242 static void usb_desc_ep_init(USBDevice *dev)
243 {
244     const USBDescIface *iface;
245     int i, e, pid, ep;
246 
247     usb_ep_init(dev);
248     for (i = 0; i < dev->ninterfaces; i++) {
249         iface = dev->ifaces[i];
250         if (iface == NULL) {
251             continue;
252         }
253         for (e = 0; e < iface->bNumEndpoints; e++) {
254             pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ?
255                 USB_TOKEN_IN : USB_TOKEN_OUT;
256             ep = iface->eps[e].bEndpointAddress & 0x0f;
257             usb_ep_set_type(dev, pid, ep, iface->eps[e].bmAttributes & 0x03);
258             usb_ep_set_ifnum(dev, pid, ep, iface->bInterfaceNumber);
259             usb_ep_set_max_packet_size(dev, pid, ep,
260                                        iface->eps[e].wMaxPacketSize);
261         }
262     }
263 }
264 
265 static const USBDescIface *usb_desc_find_interface(USBDevice *dev,
266                                                    int nif, int alt)
267 {
268     const USBDescIface *iface;
269     int g, i;
270 
271     if (!dev->config) {
272         return NULL;
273     }
274     for (g = 0; g < dev->config->nif_groups; g++) {
275         for (i = 0; i < dev->config->if_groups[g].nif; i++) {
276             iface = &dev->config->if_groups[g].ifs[i];
277             if (iface->bInterfaceNumber == nif &&
278                 iface->bAlternateSetting == alt) {
279                 return iface;
280             }
281         }
282     }
283     for (i = 0; i < dev->config->nif; i++) {
284         iface = &dev->config->ifs[i];
285         if (iface->bInterfaceNumber == nif &&
286             iface->bAlternateSetting == alt) {
287             return iface;
288         }
289     }
290     return NULL;
291 }
292 
293 static int usb_desc_set_interface(USBDevice *dev, int index, int value)
294 {
295     const USBDescIface *iface;
296     int old;
297 
298     iface = usb_desc_find_interface(dev, index, value);
299     if (iface == NULL) {
300         return -1;
301     }
302 
303     old = dev->altsetting[index];
304     dev->altsetting[index] = value;
305     dev->ifaces[index] = iface;
306     usb_desc_ep_init(dev);
307 
308     if (old != value) {
309         usb_device_set_interface(dev, index, old, value);
310     }
311     return 0;
312 }
313 
314 static int usb_desc_set_config(USBDevice *dev, int value)
315 {
316     int i;
317 
318     if (value == 0) {
319         dev->configuration = 0;
320         dev->ninterfaces   = 0;
321         dev->config = NULL;
322     } else {
323         for (i = 0; i < dev->device->bNumConfigurations; i++) {
324             if (dev->device->confs[i].bConfigurationValue == value) {
325                 dev->configuration = value;
326                 dev->ninterfaces   = dev->device->confs[i].bNumInterfaces;
327                 dev->config = dev->device->confs + i;
328                 assert(dev->ninterfaces <= USB_MAX_INTERFACES);
329             }
330         }
331         if (i < dev->device->bNumConfigurations) {
332             return -1;
333         }
334     }
335 
336     for (i = 0; i < dev->ninterfaces; i++) {
337         usb_desc_set_interface(dev, i, 0);
338     }
339     for (; i < USB_MAX_INTERFACES; i++) {
340         dev->altsetting[i] = 0;
341         dev->ifaces[i] = NULL;
342     }
343 
344     return 0;
345 }
346 
347 static void usb_desc_setdefaults(USBDevice *dev)
348 {
349     const USBDesc *desc = usb_device_get_usb_desc(dev);
350 
351     assert(desc != NULL);
352     switch (dev->speed) {
353     case USB_SPEED_LOW:
354     case USB_SPEED_FULL:
355         dev->device = desc->full;
356         break;
357     case USB_SPEED_HIGH:
358         dev->device = desc->high;
359         break;
360     }
361     usb_desc_set_config(dev, 0);
362 }
363 
364 void usb_desc_init(USBDevice *dev)
365 {
366     const USBDesc *desc = usb_device_get_usb_desc(dev);
367 
368     assert(desc != NULL);
369     dev->speed = USB_SPEED_FULL;
370     dev->speedmask = 0;
371     if (desc->full) {
372         dev->speedmask |= USB_SPEED_MASK_FULL;
373     }
374     if (desc->high) {
375         dev->speedmask |= USB_SPEED_MASK_HIGH;
376     }
377     usb_desc_setdefaults(dev);
378 }
379 
380 void usb_desc_attach(USBDevice *dev)
381 {
382     const USBDesc *desc = usb_device_get_usb_desc(dev);
383 
384     assert(desc != NULL);
385     if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
386         dev->speed = USB_SPEED_HIGH;
387     } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
388         dev->speed = USB_SPEED_FULL;
389     } else {
390         fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
391                 usb_device_get_product_desc(dev));
392         return;
393     }
394     usb_desc_setdefaults(dev);
395 }
396 
397 void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
398 {
399     USBDescString *s;
400 
401     QLIST_FOREACH(s, &dev->strings, next) {
402         if (s->index == index) {
403             break;
404         }
405     }
406     if (s == NULL) {
407         s = g_malloc0(sizeof(*s));
408         s->index = index;
409         QLIST_INSERT_HEAD(&dev->strings, s, next);
410     }
411     g_free(s->str);
412     s->str = g_strdup(str);
413 }
414 
415 const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
416 {
417     USBDescString *s;
418 
419     QLIST_FOREACH(s, &dev->strings, next) {
420         if (s->index == index) {
421             return s->str;
422         }
423     }
424     return NULL;
425 }
426 
427 int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
428 {
429     uint8_t bLength, pos, i;
430     const char *str;
431 
432     if (len < 4) {
433         return -1;
434     }
435 
436     if (index == 0) {
437         /* language ids */
438         dest[0] = 4;
439         dest[1] = USB_DT_STRING;
440         dest[2] = 0x09;
441         dest[3] = 0x04;
442         return 4;
443     }
444 
445     str = usb_desc_get_string(dev, index);
446     if (str == NULL) {
447         str = usb_device_get_usb_desc(dev)->str[index];
448         if (str == NULL) {
449             return 0;
450         }
451     }
452 
453     bLength = strlen(str) * 2 + 2;
454     dest[0] = bLength;
455     dest[1] = USB_DT_STRING;
456     i = 0; pos = 2;
457     while (pos+1 < bLength && pos+1 < len) {
458         dest[pos++] = str[i++];
459         dest[pos++] = 0;
460     }
461     return pos;
462 }
463 
464 int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
465 {
466     const USBDesc *desc = usb_device_get_usb_desc(dev);
467     const USBDescDevice *other_dev;
468     uint8_t buf[256];
469     uint8_t type = value >> 8;
470     uint8_t index = value & 0xff;
471     int ret = -1;
472 
473     if (dev->speed == USB_SPEED_HIGH) {
474         other_dev = usb_device_get_usb_desc(dev)->full;
475     } else {
476         other_dev = usb_device_get_usb_desc(dev)->high;
477     }
478 
479     switch(type) {
480     case USB_DT_DEVICE:
481         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
482         trace_usb_desc_device(dev->addr, len, ret);
483         break;
484     case USB_DT_CONFIG:
485         if (index < dev->device->bNumConfigurations) {
486             ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
487         }
488         trace_usb_desc_config(dev->addr, index, len, ret);
489         break;
490     case USB_DT_STRING:
491         ret = usb_desc_string(dev, index, buf, sizeof(buf));
492         trace_usb_desc_string(dev->addr, index, len, ret);
493         break;
494 
495     case USB_DT_DEVICE_QUALIFIER:
496         if (other_dev != NULL) {
497             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
498         }
499         trace_usb_desc_device_qualifier(dev->addr, len, ret);
500         break;
501     case USB_DT_OTHER_SPEED_CONFIG:
502         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
503             ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
504             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
505         }
506         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
507         break;
508 
509     case USB_DT_DEBUG:
510         /* ignore silently */
511         break;
512 
513     default:
514         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
515                 dev->addr, type, len);
516         break;
517     }
518 
519     if (ret > 0) {
520         if (ret > len) {
521             ret = len;
522         }
523         memcpy(dest, buf, ret);
524     }
525     return ret;
526 }
527 
528 int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
529         int request, int value, int index, int length, uint8_t *data)
530 {
531     const USBDesc *desc = usb_device_get_usb_desc(dev);
532     int ret = -1;
533 
534     assert(desc != NULL);
535     switch(request) {
536     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
537         dev->addr = value;
538         trace_usb_set_addr(dev->addr);
539         ret = 0;
540         break;
541 
542     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
543         ret = usb_desc_get_descriptor(dev, value, data, length);
544         break;
545 
546     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
547         /*
548          * 9.4.2: 0 should be returned if the device is unconfigured, otherwise
549          * the non zero value of bConfigurationValue.
550          */
551         data[0] = dev->config ? dev->config->bConfigurationValue : 0;
552         ret = 1;
553         break;
554     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
555         ret = usb_desc_set_config(dev, value);
556         trace_usb_set_config(dev->addr, value, ret);
557         break;
558 
559     case DeviceRequest | USB_REQ_GET_STATUS: {
560         const USBDescConfig *config = dev->config ?
561             dev->config : &dev->device->confs[0];
562 
563         data[0] = 0;
564         /*
565          * Default state: Device behavior when this request is received while
566          *                the device is in the Default state is not specified.
567          * We return the same value that a configured device would return if
568          * it used the first configuration.
569          */
570         if (config->bmAttributes & 0x40) {
571             data[0] |= 1 << USB_DEVICE_SELF_POWERED;
572         }
573         if (dev->remote_wakeup) {
574             data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
575         }
576         data[1] = 0x00;
577         ret = 2;
578         break;
579     }
580     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
581         if (value == USB_DEVICE_REMOTE_WAKEUP) {
582             dev->remote_wakeup = 0;
583             ret = 0;
584         }
585         trace_usb_clear_device_feature(dev->addr, value, ret);
586         break;
587     case DeviceOutRequest | USB_REQ_SET_FEATURE:
588         if (value == USB_DEVICE_REMOTE_WAKEUP) {
589             dev->remote_wakeup = 1;
590             ret = 0;
591         }
592         trace_usb_set_device_feature(dev->addr, value, ret);
593         break;
594 
595     case InterfaceRequest | USB_REQ_GET_INTERFACE:
596         if (index < 0 || index >= dev->ninterfaces) {
597             break;
598         }
599         data[0] = dev->altsetting[index];
600         ret = 1;
601         break;
602     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
603         ret = usb_desc_set_interface(dev, index, value);
604         trace_usb_set_interface(dev->addr, index, value, ret);
605         break;
606 
607     }
608     return ret;
609 }
610