1#ifndef QEMU_HW_USB_DESC_H
2#define QEMU_HW_USB_DESC_H
3
4#include <wchar.h>
5
6/* binary representation */
7typedef struct USBDescriptor {
8 uint8_t bLength;
9 uint8_t bDescriptorType;
10 union {
11 struct {
12 uint8_t bcdUSB_lo;
13 uint8_t bcdUSB_hi;
14 uint8_t bDeviceClass;
15 uint8_t bDeviceSubClass;
16 uint8_t bDeviceProtocol;
17 uint8_t bMaxPacketSize0;
18 uint8_t idVendor_lo;
19 uint8_t idVendor_hi;
20 uint8_t idProduct_lo;
21 uint8_t idProduct_hi;
22 uint8_t bcdDevice_lo;
23 uint8_t bcdDevice_hi;
24 uint8_t iManufacturer;
25 uint8_t iProduct;
26 uint8_t iSerialNumber;
27 uint8_t bNumConfigurations;
28 } device;
29 struct {
30 uint8_t bcdUSB_lo;
31 uint8_t bcdUSB_hi;
32 uint8_t bDeviceClass;
33 uint8_t bDeviceSubClass;
34 uint8_t bDeviceProtocol;
35 uint8_t bMaxPacketSize0;
36 uint8_t bNumConfigurations;
37 uint8_t bReserved;
38 } device_qualifier;
39 struct {
40 uint8_t wTotalLength_lo;
41 uint8_t wTotalLength_hi;
42 uint8_t bNumInterfaces;
43 uint8_t bConfigurationValue;
44 uint8_t iConfiguration;
45 uint8_t bmAttributes;
46 uint8_t bMaxPower;
47 } config;
48 struct {
49 uint8_t bInterfaceNumber;
50 uint8_t bAlternateSetting;
51 uint8_t bNumEndpoints;
52 uint8_t bInterfaceClass;
53 uint8_t bInterfaceSubClass;
54 uint8_t bInterfaceProtocol;
55 uint8_t iInterface;
56 } interface;
57 struct {
58 uint8_t bEndpointAddress;
59 uint8_t bmAttributes;
60 uint8_t wMaxPacketSize_lo;
61 uint8_t wMaxPacketSize_hi;
62 uint8_t bInterval;
63 uint8_t bRefresh; /* only audio ep */
64 uint8_t bSynchAddress; /* only audio ep */
65 } endpoint;
66 struct {
67 uint8_t bMaxBurst;
68 uint8_t bmAttributes;
69 uint8_t wBytesPerInterval_lo;
70 uint8_t wBytesPerInterval_hi;
71 } super_endpoint;
72 struct {
73 uint8_t wTotalLength_lo;
74 uint8_t wTotalLength_hi;
75 uint8_t bNumDeviceCaps;
76 } bos;
77 struct {
78 uint8_t bDevCapabilityType;
79 union {
80 struct {
81 uint8_t bmAttributes_1;
82 uint8_t bmAttributes_2;
83 uint8_t bmAttributes_3;
84 uint8_t bmAttributes_4;
85 } usb2_ext;
86 struct {
87 uint8_t bmAttributes;
88 uint8_t wSpeedsSupported_lo;
89 uint8_t wSpeedsSupported_hi;
90 uint8_t bFunctionalitySupport;
91 uint8_t bU1DevExitLat;
92 uint8_t wU2DevExitLat_lo;
93 uint8_t wU2DevExitLat_hi;
94 } super;
95 } u;
96 } cap;
97 } u;
98} QEMU_PACKED USBDescriptor;
99
100struct USBDescID {
101 uint16_t idVendor;
102 uint16_t idProduct;
103 uint16_t bcdDevice;
104 uint8_t iManufacturer;
105 uint8_t iProduct;
106 uint8_t iSerialNumber;
107};
108
109struct USBDescDevice {
110 uint16_t bcdUSB;
111 uint8_t bDeviceClass;
112 uint8_t bDeviceSubClass;
113 uint8_t bDeviceProtocol;
114 uint8_t bMaxPacketSize0;
115 uint8_t bNumConfigurations;
116
117 const USBDescConfig *confs;
118};
119
120struct USBDescConfig {
121 uint8_t bNumInterfaces;
122 uint8_t bConfigurationValue;
123 uint8_t iConfiguration;
124 uint8_t bmAttributes;
125 uint8_t bMaxPower;
126
127 /* grouped interfaces */
128 uint8_t nif_groups;
129 const USBDescIfaceAssoc *if_groups;
130
131 /* "normal" interfaces */
132 uint8_t nif;
133 const USBDescIface *ifs;
134};
135
136/* conceptually an Interface Association Descriptor, and releated interfaces */
137struct USBDescIfaceAssoc {
138 uint8_t bFirstInterface;
139 uint8_t bInterfaceCount;
140 uint8_t bFunctionClass;
141 uint8_t bFunctionSubClass;
142 uint8_t bFunctionProtocol;
143 uint8_t iFunction;
144
145 uint8_t nif;
146 const USBDescIface *ifs;
147};
148
149struct USBDescIface {
150 uint8_t bInterfaceNumber;
151 uint8_t bAlternateSetting;
152 uint8_t bNumEndpoints;
153 uint8_t bInterfaceClass;
154 uint8_t bInterfaceSubClass;
155 uint8_t bInterfaceProtocol;
156 uint8_t iInterface;
157
158 uint8_t ndesc;
159 USBDescOther *descs;
160 USBDescEndpoint *eps;
161};
162
163struct USBDescEndpoint {
164 uint8_t bEndpointAddress;
165 uint8_t bmAttributes;
166 uint16_t wMaxPacketSize;
167 uint8_t bInterval;
168 uint8_t bRefresh;
169 uint8_t bSynchAddress;
170
171 uint8_t is_audio; /* has bRefresh + bSynchAddress */
172 uint8_t *extra;
173
174 /* superspeed endpoint companion */
175 uint8_t bMaxBurst;
176 uint8_t bmAttributes_super;
177 uint16_t wBytesPerInterval;
178};
179
180struct USBDescOther {
181 uint8_t length;
182 const uint8_t *data;
183};
184
185struct USBDescMSOS {
186 const char *CompatibleID;
187 const wchar_t *Label;
188 bool SelectiveSuspendEnabled;
189};
190
191typedef const char *USBDescStrings[256];
192
193struct USBDesc {
194 USBDescID id;
195 const USBDescDevice *full;
196 const USBDescDevice *high;
197 const USBDescDevice *super;
198 const char* const *str;
199 const USBDescMSOS *msos;
200};
201
202#define USB_DESC_FLAG_SUPER (1 << 1)
203
204/* little helpers */
205static inline uint8_t usb_lo(uint16_t val)
206{
207 return val & 0xff;
208}
209
210static inline uint8_t usb_hi(uint16_t val)
211{
212 return (val >> 8) & 0xff;
213}
214
215/* generate usb packages from structs */
216int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
217 bool msos, uint8_t *dest, size_t len);
218int usb_desc_device_qualifier(const USBDescDevice *dev,
219 uint8_t *dest, size_t len);
220int usb_desc_config(const USBDescConfig *conf, int flags,
221 uint8_t *dest, size_t len);
222int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
223 uint8_t *dest, size_t len);
224int usb_desc_iface(const USBDescIface *iface, int flags,
225 uint8_t *dest, size_t len);
226int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
227 uint8_t *dest, size_t len);
228int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
229int usb_desc_msos(const USBDesc *desc, USBPacket *p,
230 int index, uint8_t *dest, size_t len);
231
232/* control message emulation helpers */
233void usb_desc_init(USBDevice *dev);
234void usb_desc_attach(USBDevice *dev);
235void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
236void usb_desc_create_serial(USBDevice *dev);
237const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
238int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
239int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p,
240 int value, uint8_t *dest, size_t len);
241int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
242 int request, int value, int index, int length, uint8_t *data);
243
244#endif /* QEMU_HW_USB_DESC_H */
245