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_config(const USBDescConfig
*conf
, uint8_t *dest
, size_t len
)
53 uint8_t bLength
= 0x09;
54 uint16_t wTotalLength
= 0;
62 dest
[0x01] = USB_DT_CONFIG
;
63 dest
[0x04] = conf
->bNumInterfaces
;
64 dest
[0x05] = conf
->bConfigurationValue
;
65 dest
[0x06] = conf
->iConfiguration
;
66 dest
[0x07] = conf
->bmAttributes
;
67 dest
[0x08] = conf
->bMaxPower
;
68 wTotalLength
+= bLength
;
70 count
= conf
->nif
? conf
->nif
: conf
->bNumInterfaces
;
71 for (i
= 0; i
< count
; i
++) {
72 rc
= usb_desc_iface(conf
->ifs
+ i
, dest
+ wTotalLength
, len
- wTotalLength
);
79 dest
[0x02] = usb_lo(wTotalLength
);
80 dest
[0x03] = usb_hi(wTotalLength
);
84 int usb_desc_iface(const USBDescIface
*iface
, uint8_t *dest
, size_t len
)
86 uint8_t bLength
= 0x09;
94 dest
[0x01] = USB_DT_INTERFACE
;
95 dest
[0x02] = iface
->bInterfaceNumber
;
96 dest
[0x03] = iface
->bAlternateSetting
;
97 dest
[0x04] = iface
->bNumEndpoints
;
98 dest
[0x05] = iface
->bInterfaceClass
;
99 dest
[0x06] = iface
->bInterfaceSubClass
;
100 dest
[0x07] = iface
->bInterfaceProtocol
;
101 dest
[0x08] = iface
->iInterface
;
104 for (i
= 0; i
< iface
->ndesc
; i
++) {
105 rc
= usb_desc_other(iface
->descs
+ i
, dest
+ pos
, len
- pos
);
112 for (i
= 0; i
< iface
->bNumEndpoints
; i
++) {
113 rc
= usb_desc_endpoint(iface
->eps
+ i
, dest
+ pos
, len
- pos
);
123 int usb_desc_endpoint(const USBDescEndpoint
*ep
, uint8_t *dest
, size_t len
)
125 uint8_t bLength
= 0x07;
131 dest
[0x00] = bLength
;
132 dest
[0x01] = USB_DT_ENDPOINT
;
133 dest
[0x02] = ep
->bEndpointAddress
;
134 dest
[0x03] = ep
->bmAttributes
;
135 dest
[0x04] = usb_lo(ep
->wMaxPacketSize
);
136 dest
[0x05] = usb_hi(ep
->wMaxPacketSize
);
137 dest
[0x06] = ep
->bInterval
;
142 int usb_desc_other(const USBDescOther
*desc
, uint8_t *dest
, size_t len
)
144 int bLength
= desc
->length
? desc
->length
: desc
->data
[0];
150 memcpy(dest
, desc
->data
, bLength
);
154 /* ------------------------------------------------------------------ */
156 void usb_desc_set_string(USBDevice
*dev
, uint8_t index
, const char *str
)
160 QLIST_FOREACH(s
, &dev
->strings
, next
) {
161 if (s
->index
== index
) {
166 s
= qemu_mallocz(sizeof(*s
));
168 QLIST_INSERT_HEAD(&dev
->strings
, s
, next
);
171 s
->str
= qemu_strdup(str
);
174 const char *usb_desc_get_string(USBDevice
*dev
, uint8_t index
)
178 QLIST_FOREACH(s
, &dev
->strings
, next
) {
179 if (s
->index
== index
) {
186 int usb_desc_string(USBDevice
*dev
, int index
, uint8_t *dest
, size_t len
)
188 uint8_t bLength
, pos
, i
;
198 dest
[1] = USB_DT_STRING
;
204 str
= usb_desc_get_string(dev
, index
);
206 str
= dev
->info
->usb_desc
->str
[index
];
212 bLength
= strlen(str
) * 2 + 2;
214 dest
[1] = USB_DT_STRING
;
216 while (pos
+1 < bLength
&& pos
+1 < len
) {
217 dest
[pos
++] = str
[i
++];
223 int usb_desc_get_descriptor(USBDevice
*dev
, int value
, uint8_t *dest
, size_t len
)
225 const USBDesc
*desc
= dev
->info
->usb_desc
;
227 uint8_t type
= value
>> 8;
228 uint8_t index
= value
& 0xff;
233 ret
= usb_desc_device(&desc
->id
, desc
->full
, buf
, sizeof(buf
));
234 trace_usb_desc_device(dev
->addr
, len
, ret
);
237 if (index
< desc
->full
->bNumConfigurations
) {
238 ret
= usb_desc_config(desc
->full
->confs
+ index
, buf
, sizeof(buf
));
240 trace_usb_desc_config(dev
->addr
, index
, len
, ret
);
243 ret
= usb_desc_string(dev
, index
, buf
, sizeof(buf
));
244 trace_usb_desc_string(dev
->addr
, index
, len
, ret
);
247 fprintf(stderr
, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__
,
248 dev
->addr
, type
, len
);
256 memcpy(dest
, buf
, ret
);
261 int usb_desc_handle_control(USBDevice
*dev
, int request
, int value
,
262 int index
, int length
, uint8_t *data
)
264 const USBDesc
*desc
= dev
->info
->usb_desc
;
267 assert(desc
!= NULL
);
269 case DeviceRequest
| USB_REQ_GET_DESCRIPTOR
:
270 ret
= usb_desc_get_descriptor(dev
, value
, data
, length
);