5 /* ------------------------------------------------------------------ */
7 static uint8_t usb_lo(uint16_t val
)
12 static uint8_t usb_hi(uint16_t val
)
14 return (val
>> 8) & 0xff;
17 int usb_desc_device(const USBDescID
*id
, const USBDescDevice
*dev
,
18 uint8_t *dest
, size_t len
)
20 uint8_t bLength
= 0x12;
27 dest
[0x01] = USB_DT_DEVICE
;
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
;
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
;
46 dest
[0x11] = dev
->bNumConfigurations
;
51 int usb_desc_device_qualifier(const USBDescDevice
*dev
,
52 uint8_t *dest
, size_t len
)
54 uint8_t bLength
= 0x0a;
61 dest
[0x01] = USB_DT_DEVICE_QUALIFIER
;
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 */
75 int usb_desc_config(const USBDescConfig
*conf
, uint8_t *dest
, size_t len
)
77 uint8_t bLength
= 0x09;
78 uint16_t wTotalLength
= 0;
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
;
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
]),
105 /* handle normal (ungrouped / no IAD) interfaces if any */
106 for (i
= 0; i
< conf
->nif
; i
++) {
107 rc
= usb_desc_iface(conf
->ifs
+ i
, dest
+ wTotalLength
, len
- wTotalLength
);
114 dest
[0x02] = usb_lo(wTotalLength
);
115 dest
[0x03] = usb_hi(wTotalLength
);
119 int usb_desc_iface_group(const USBDescIfaceAssoc
*iad
, uint8_t *dest
,
125 /* handle interface association descriptor */
126 uint8_t bLength
= 0x08;
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
;
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
);
154 int usb_desc_iface(const USBDescIface
*iface
, uint8_t *dest
, size_t len
)
156 uint8_t bLength
= 0x09;
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
;
174 for (i
= 0; i
< iface
->ndesc
; i
++) {
175 rc
= usb_desc_other(iface
->descs
+ i
, dest
+ pos
, len
- pos
);
182 for (i
= 0; i
< iface
->bNumEndpoints
; i
++) {
183 rc
= usb_desc_endpoint(iface
->eps
+ i
, dest
+ pos
, len
- pos
);
193 int usb_desc_endpoint(const USBDescEndpoint
*ep
, uint8_t *dest
, size_t len
)
195 uint8_t bLength
= ep
->is_audio
? 0x09 : 0x07;
196 uint8_t extralen
= ep
->extra
? ep
->extra
[0] : 0;
198 if (len
< bLength
+ extralen
) {
202 dest
[0x00] = bLength
;
203 dest
[0x01] = USB_DT_ENDPOINT
;
204 dest
[0x02] = ep
->bEndpointAddress
;
205 dest
[0x03] = ep
->bmAttributes
;
206 dest
[0x04] = usb_lo(ep
->wMaxPacketSize
);
207 dest
[0x05] = usb_hi(ep
->wMaxPacketSize
);
208 dest
[0x06] = ep
->bInterval
;
210 dest
[0x07] = ep
->bRefresh
;
211 dest
[0x08] = ep
->bSynchAddress
;
214 memcpy(dest
+ bLength
, ep
->extra
, extralen
);
217 return bLength
+ extralen
;
220 int usb_desc_other(const USBDescOther
*desc
, uint8_t *dest
, size_t len
)
222 int bLength
= desc
->length
? desc
->length
: desc
->data
[0];
228 memcpy(dest
, desc
->data
, bLength
);
232 /* ------------------------------------------------------------------ */
234 static void usb_desc_ep_init(USBDevice
*dev
)
236 const USBDescIface
*iface
;
240 for (i
= 0; i
< dev
->ninterfaces
; i
++) {
241 iface
= dev
->ifaces
[i
];
245 for (e
= 0; e
< iface
->bNumEndpoints
; e
++) {
246 pid
= (iface
->eps
[e
].bEndpointAddress
& USB_DIR_IN
) ?
247 USB_TOKEN_IN
: USB_TOKEN_OUT
;
248 ep
= iface
->eps
[e
].bEndpointAddress
& 0x0f;
249 usb_ep_set_type(dev
, pid
, ep
, iface
->eps
[e
].bmAttributes
& 0x03);
250 usb_ep_set_ifnum(dev
, pid
, ep
, iface
->bInterfaceNumber
);
251 usb_ep_set_max_packet_size(dev
, pid
, ep
,
252 iface
->eps
[e
].wMaxPacketSize
);
257 static const USBDescIface
*usb_desc_find_interface(USBDevice
*dev
,
260 const USBDescIface
*iface
;
266 for (g
= 0; g
< dev
->config
->nif_groups
; g
++) {
267 for (i
= 0; i
< dev
->config
->if_groups
[g
].nif
; i
++) {
268 iface
= &dev
->config
->if_groups
[g
].ifs
[i
];
269 if (iface
->bInterfaceNumber
== nif
&&
270 iface
->bAlternateSetting
== alt
) {
275 for (i
= 0; i
< dev
->config
->nif
; i
++) {
276 iface
= &dev
->config
->ifs
[i
];
277 if (iface
->bInterfaceNumber
== nif
&&
278 iface
->bAlternateSetting
== alt
) {
285 static int usb_desc_set_interface(USBDevice
*dev
, int index
, int value
)
287 const USBDescIface
*iface
;
290 iface
= usb_desc_find_interface(dev
, index
, value
);
295 old
= dev
->altsetting
[index
];
296 dev
->altsetting
[index
] = value
;
297 dev
->ifaces
[index
] = iface
;
298 usb_desc_ep_init(dev
);
301 usb_device_set_interface(dev
, index
, old
, value
);
306 static int usb_desc_set_config(USBDevice
*dev
, int value
)
311 dev
->configuration
= 0;
312 dev
->ninterfaces
= 0;
315 for (i
= 0; i
< dev
->device
->bNumConfigurations
; i
++) {
316 if (dev
->device
->confs
[i
].bConfigurationValue
== value
) {
317 dev
->configuration
= value
;
318 dev
->ninterfaces
= dev
->device
->confs
[i
].bNumInterfaces
;
319 dev
->config
= dev
->device
->confs
+ i
;
320 assert(dev
->ninterfaces
<= USB_MAX_INTERFACES
);
323 if (i
< dev
->device
->bNumConfigurations
) {
328 for (i
= 0; i
< dev
->ninterfaces
; i
++) {
329 usb_desc_set_interface(dev
, i
, 0);
331 for (; i
< USB_MAX_INTERFACES
; i
++) {
332 dev
->altsetting
[i
] = 0;
333 dev
->ifaces
[i
] = NULL
;
339 static void usb_desc_setdefaults(USBDevice
*dev
)
341 const USBDesc
*desc
= usb_device_get_usb_desc(dev
);
343 assert(desc
!= NULL
);
344 switch (dev
->speed
) {
347 dev
->device
= desc
->full
;
350 dev
->device
= desc
->high
;
353 usb_desc_set_config(dev
, 0);
356 void usb_desc_init(USBDevice
*dev
)
358 const USBDesc
*desc
= usb_device_get_usb_desc(dev
);
360 assert(desc
!= NULL
);
361 dev
->speed
= USB_SPEED_FULL
;
364 dev
->speedmask
|= USB_SPEED_MASK_FULL
;
367 dev
->speedmask
|= USB_SPEED_MASK_HIGH
;
369 usb_desc_setdefaults(dev
);
372 void usb_desc_attach(USBDevice
*dev
)
374 const USBDesc
*desc
= usb_device_get_usb_desc(dev
);
376 assert(desc
!= NULL
);
377 if (desc
->high
&& (dev
->port
->speedmask
& USB_SPEED_MASK_HIGH
)) {
378 dev
->speed
= USB_SPEED_HIGH
;
379 } else if (desc
->full
&& (dev
->port
->speedmask
& USB_SPEED_MASK_FULL
)) {
380 dev
->speed
= USB_SPEED_FULL
;
382 fprintf(stderr
, "usb: port/device speed mismatch for \"%s\"\n",
383 usb_device_get_product_desc(dev
));
386 usb_desc_setdefaults(dev
);
389 void usb_desc_set_string(USBDevice
*dev
, uint8_t index
, const char *str
)
393 QLIST_FOREACH(s
, &dev
->strings
, next
) {
394 if (s
->index
== index
) {
399 s
= g_malloc0(sizeof(*s
));
401 QLIST_INSERT_HEAD(&dev
->strings
, s
, next
);
404 s
->str
= g_strdup(str
);
407 const char *usb_desc_get_string(USBDevice
*dev
, uint8_t index
)
411 QLIST_FOREACH(s
, &dev
->strings
, next
) {
412 if (s
->index
== index
) {
419 int usb_desc_string(USBDevice
*dev
, int index
, uint8_t *dest
, size_t len
)
421 uint8_t bLength
, pos
, i
;
431 dest
[1] = USB_DT_STRING
;
437 str
= usb_desc_get_string(dev
, index
);
439 str
= usb_device_get_usb_desc(dev
)->str
[index
];
445 bLength
= strlen(str
) * 2 + 2;
447 dest
[1] = USB_DT_STRING
;
449 while (pos
+1 < bLength
&& pos
+1 < len
) {
450 dest
[pos
++] = str
[i
++];
456 int usb_desc_get_descriptor(USBDevice
*dev
, int value
, uint8_t *dest
, size_t len
)
458 const USBDesc
*desc
= usb_device_get_usb_desc(dev
);
459 const USBDescDevice
*other_dev
;
461 uint8_t type
= value
>> 8;
462 uint8_t index
= value
& 0xff;
465 if (dev
->speed
== USB_SPEED_HIGH
) {
466 other_dev
= usb_device_get_usb_desc(dev
)->full
;
468 other_dev
= usb_device_get_usb_desc(dev
)->high
;
473 ret
= usb_desc_device(&desc
->id
, dev
->device
, buf
, sizeof(buf
));
474 trace_usb_desc_device(dev
->addr
, len
, ret
);
477 if (index
< dev
->device
->bNumConfigurations
) {
478 ret
= usb_desc_config(dev
->device
->confs
+ index
, buf
, sizeof(buf
));
480 trace_usb_desc_config(dev
->addr
, index
, len
, ret
);
483 ret
= usb_desc_string(dev
, index
, buf
, sizeof(buf
));
484 trace_usb_desc_string(dev
->addr
, index
, len
, ret
);
487 case USB_DT_DEVICE_QUALIFIER
:
488 if (other_dev
!= NULL
) {
489 ret
= usb_desc_device_qualifier(other_dev
, buf
, sizeof(buf
));
491 trace_usb_desc_device_qualifier(dev
->addr
, len
, ret
);
493 case USB_DT_OTHER_SPEED_CONFIG
:
494 if (other_dev
!= NULL
&& index
< other_dev
->bNumConfigurations
) {
495 ret
= usb_desc_config(other_dev
->confs
+ index
, buf
, sizeof(buf
));
496 buf
[0x01] = USB_DT_OTHER_SPEED_CONFIG
;
498 trace_usb_desc_other_speed_config(dev
->addr
, index
, len
, ret
);
502 /* ignore silently */
506 fprintf(stderr
, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__
,
507 dev
->addr
, type
, len
);
515 memcpy(dest
, buf
, ret
);
520 int usb_desc_handle_control(USBDevice
*dev
, USBPacket
*p
,
521 int request
, int value
, int index
, int length
, uint8_t *data
)
523 const USBDesc
*desc
= usb_device_get_usb_desc(dev
);
526 assert(desc
!= NULL
);
528 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
530 trace_usb_set_addr(dev
->addr
);
534 case DeviceRequest
| USB_REQ_GET_DESCRIPTOR
:
535 ret
= usb_desc_get_descriptor(dev
, value
, data
, length
);
538 case DeviceRequest
| USB_REQ_GET_CONFIGURATION
:
539 data
[0] = dev
->config
->bConfigurationValue
;
542 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
543 ret
= usb_desc_set_config(dev
, value
);
544 trace_usb_set_config(dev
->addr
, value
, ret
);
547 case DeviceRequest
| USB_REQ_GET_STATUS
:
549 if (dev
->config
->bmAttributes
& 0x40) {
550 data
[0] |= 1 << USB_DEVICE_SELF_POWERED
;
552 if (dev
->remote_wakeup
) {
553 data
[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP
;
558 case DeviceOutRequest
| USB_REQ_CLEAR_FEATURE
:
559 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
560 dev
->remote_wakeup
= 0;
563 trace_usb_clear_device_feature(dev
->addr
, value
, ret
);
565 case DeviceOutRequest
| USB_REQ_SET_FEATURE
:
566 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
567 dev
->remote_wakeup
= 1;
570 trace_usb_set_device_feature(dev
->addr
, value
, ret
);
573 case InterfaceRequest
| USB_REQ_GET_INTERFACE
:
574 if (index
< 0 || index
>= dev
->ninterfaces
) {
577 data
[0] = dev
->altsetting
[index
];
580 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
581 ret
= usb_desc_set_interface(dev
, index
, value
);
582 trace_usb_set_interface(dev
->addr
, index
, value
, ret
);