1 /*
2  * Copyright (c) 2022, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef USB_DEF_H
7 #define USB_DEF_H
8 
9 /* Useful define */
10 #define USB_1_1 0x0110
11 #define USB_2_0 0x0200
12 /* Set USB version to 2.1 so that the host will request the BOS descriptor */
13 #define USB_2_1 0x0210
14 #define USB_3_0 0x0300
15 #define USB_3_1 0x0310
16 #define USB_3_2 0x0320
17 
18 /* Device speeds */
19 #define USB_SPEED_UNKNOWN    0 /* Transfer rate not yet set */
20 #define USB_SPEED_LOW        1 /* USB 1.1 */
21 #define USB_SPEED_FULL       2 /* USB 1.1 */
22 #define USB_SPEED_HIGH       3 /* USB 2.0 */
23 #define USB_SPEED_WIRELESS   4 /* Wireless USB 2.5 */
24 #define USB_SPEED_SUPER      5 /* USB 3.0 */
25 #define USB_SPEED_SUPER_PLUS 6 /* USB 3.1 */
26 
27 /* Maximum number of devices per controller */
28 #define USB_MAX_DEVICES (127)
29 
30 /* Default USB control EP, always 0 and 0x80 */
31 #define USB_CONTROL_OUT_EP0 0
32 #define USB_CONTROL_IN_EP0  0x80
33 
34 /**< maximum packet size (MPS) for EP 0 */
35 #define USB_CTRL_EP_MPS 64
36 
37 /**< maximum packet size (MPS) for bulk EP */
38 #define USB_BULK_EP_MPS_HS 512
39 #define USB_BULK_EP_MPS_FS 64
40 
41 /* USB PID Types */
42 #define USB_PID_OUT   (0x01) /* Tokens */
43 #define USB_PID_IN    (0x09)
44 #define USB_PID_SOF   (0x05)
45 #define USB_PID_SETUP (0x0d)
46 
47 #define USB_PID_DATA0 (0x03) /* Data */
48 #define USB_PID_DATA1 (0x0b)
49 #define USB_PID_DATA2 (0x07)
50 #define USB_PID_MDATA (0x0f)
51 
52 #define USB_PID_ACK   (0x02) /* Handshake */
53 #define USB_PID_NAK   (0x0a)
54 #define USB_PID_STALL (0x0e)
55 #define USB_PID_NYET  (0x06)
56 
57 #define USB_PID_PRE      (0x0c) /* Special */
58 #define USB_PID_ERR      (0x0c)
59 #define USB_PID_SPLIT    (0x08)
60 #define USB_PID_PING     (0x04)
61 #define USB_PID_RESERVED (0x00)
62 
63 #define USB_REQUEST_DIR_SHIFT 7U                            /* Bits 7: Request dir */
64 #define USB_REQUEST_DIR_OUT   (0U << USB_REQUEST_DIR_SHIFT) /* Bit 7=0: Host-to-device */
65 #define USB_REQUEST_DIR_IN    (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Device-to-host */
66 #define USB_REQUEST_DIR_MASK  (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Direction bit */
67 
68 #define USB_REQUEST_TYPE_SHIFT 5U /* Bits 5:6: Request type */
69 #define USB_REQUEST_STANDARD   (0U << USB_REQUEST_TYPE_SHIFT)
70 #define USB_REQUEST_CLASS      (1U << USB_REQUEST_TYPE_SHIFT)
71 #define USB_REQUEST_VENDOR     (2U << USB_REQUEST_TYPE_SHIFT)
72 #define USB_REQUEST_RESERVED   (3U << USB_REQUEST_TYPE_SHIFT)
73 #define USB_REQUEST_TYPE_MASK  (3U << USB_REQUEST_TYPE_SHIFT)
74 
75 #define USB_REQUEST_RECIPIENT_SHIFT     0U /* Bits 0:4: Recipient */
76 #define USB_REQUEST_RECIPIENT_DEVICE    (0U << USB_REQUEST_RECIPIENT_SHIFT)
77 #define USB_REQUEST_RECIPIENT_INTERFACE (1U << USB_REQUEST_RECIPIENT_SHIFT)
78 #define USB_REQUEST_RECIPIENT_ENDPOINT  (2U << USB_REQUEST_RECIPIENT_SHIFT)
79 #define USB_REQUEST_RECIPIENT_OTHER     (3U << USB_REQUEST_RECIPIENT_SHIFT)
80 #define USB_REQUEST_RECIPIENT_MASK      (3U << USB_REQUEST_RECIPIENT_SHIFT)
81 
82 /* USB Standard Request Codes */
83 #define USB_REQUEST_GET_STATUS          0x00
84 #define USB_REQUEST_CLEAR_FEATURE       0x01
85 #define USB_REQUEST_SET_FEATURE         0x03
86 #define USB_REQUEST_SET_ADDRESS         0x05
87 #define USB_REQUEST_GET_DESCRIPTOR      0x06
88 #define USB_REQUEST_SET_DESCRIPTOR      0x07
89 #define USB_REQUEST_GET_CONFIGURATION   0x08
90 #define USB_REQUEST_SET_CONFIGURATION   0x09
91 #define USB_REQUEST_GET_INTERFACE       0x0A
92 #define USB_REQUEST_SET_INTERFACE       0x0B
93 #define USB_REQUEST_SYNCH_FRAME         0x0C
94 #define USB_REQUEST_SET_ENCRYPTION      0x0D
95 #define USB_REQUEST_GET_ENCRYPTION      0x0E
96 #define USB_REQUEST_RPIPE_ABORT         0x0E
97 #define USB_REQUEST_SET_HANDSHAKE       0x0F
98 #define USB_REQUEST_RPIPE_RESET         0x0F
99 #define USB_REQUEST_GET_HANDSHAKE       0x10
100 #define USB_REQUEST_SET_CONNECTION      0x11
101 #define USB_REQUEST_SET_SECURITY_DATA   0x12
102 #define USB_REQUEST_GET_SECURITY_DATA   0x13
103 #define USB_REQUEST_SET_WUSB_DATA       0x14
104 #define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15
105 #define USB_REQUEST_LOOPBACK_DATA_READ  0x16
106 #define USB_REQUEST_SET_INTERFACE_DS    0x17
107 
108 /* USB Standard Feature selectors */
109 #define USB_FEATURE_ENDPOINT_HALT  0
110 #define USB_FEATURE_SELF_POWERED   0
111 #define USB_FEATURE_REMOTE_WAKEUP  1
112 #define USB_FEATURE_TEST_MODE      2
113 #define USB_FEATURE_BATTERY        2
114 #define USB_FEATURE_BHNPENABLE     3
115 #define USB_FEATURE_WUSBDEVICE     3
116 #define USB_FEATURE_AHNPSUPPORT    4
117 #define USB_FEATURE_AALTHNPSUPPORT 5
118 #define USB_FEATURE_DEBUGMODE      6
119 
120 /* USB GET_STATUS Bit Values */
121 #define USB_GETSTATUS_ENDPOINT_HALT 0x01
122 #define USB_GETSTATUS_SELF_POWERED  0x01
123 #define USB_GETSTATUS_REMOTE_WAKEUP 0x02
124 
125 /* USB Descriptor Types */
126 #define USB_DESCRIPTOR_TYPE_DEVICE                0x01U
127 #define USB_DESCRIPTOR_TYPE_CONFIGURATION         0x02U
128 #define USB_DESCRIPTOR_TYPE_STRING                0x03U
129 #define USB_DESCRIPTOR_TYPE_INTERFACE             0x04U
130 #define USB_DESCRIPTOR_TYPE_ENDPOINT              0x05U
131 #define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER      0x06U
132 #define USB_DESCRIPTOR_TYPE_OTHER_SPEED           0x07U
133 #define USB_DESCRIPTOR_TYPE_INTERFACE_POWER       0x08U
134 #define USB_DESCRIPTOR_TYPE_OTG                   0x09U
135 #define USB_DESCRIPTOR_TYPE_DEBUG                 0x0AU
136 #define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU
137 #define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE   0x0FU
138 #define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY     0x10U
139 #define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINTCOMP 0x11U
140 
141 /* Class Specific Descriptor */
142 #define USB_CS_DESCRIPTOR_TYPE_DEVICE        0x21U
143 #define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U
144 #define USB_CS_DESCRIPTOR_TYPE_STRING        0x23U
145 #define USB_CS_DESCRIPTOR_TYPE_INTERFACE     0x24U
146 #define USB_CS_DESCRIPTOR_TYPE_ENDPOINT      0x25U
147 
148 #define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION     0x30U
149 #define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U
150 
151 /* USB Device Classes */
152 #define USB_DEVICE_CLASS_RESERVED      0x00
153 #define USB_DEVICE_CLASS_AUDIO         0x01
154 #define USB_DEVICE_CLASS_CDC           0x02
155 #define USB_DEVICE_CLASS_HID           0x03
156 #define USB_DEVICE_CLASS_MONITOR       0x04
157 #define USB_DEVICE_CLASS_PHYSICAL      0x05
158 #define USB_DEVICE_CLASS_IMAGE         0x06
159 #define USB_DEVICE_CLASS_PRINTER       0x07
160 #define USB_DEVICE_CLASS_MASS_STORAGE  0x08
161 #define USB_DEVICE_CLASS_HUB           0x09
162 #define USB_DEVICE_CLASS_CDC_DATA      0x0a
163 #define USB_DEVICE_CLASS_SMART_CARD    0x0b
164 #define USB_DEVICE_CLASS_SECURITY      0x0d
165 #define USB_DEVICE_CLASS_VIDEO         0x0e
166 #define USB_DEVICE_CLASS_HEALTHCARE    0x0f
167 #define USB_DEVICE_CLASS_DIAG_DEVICE   0xdc
168 #define USB_DEVICE_CLASS_WIRELESS      0xe0
169 #define USB_DEVICE_CLASS_MISC          0xef
170 #define USB_DEVICE_CLASS_APP_SPECIFIC  0xfe
171 #define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff
172 
173 /* usb string index define */
174 #define USB_STRING_LANGID_INDEX    0x00
175 #define USB_STRING_MFC_INDEX       0x01
176 #define USB_STRING_PRODUCT_INDEX   0x02
177 #define USB_STRING_SERIAL_INDEX    0x03
178 #define USB_STRING_CONFIG_INDEX    0x04
179 #define USB_STRING_INTERFACE_INDEX 0x05
180 #define USB_STRING_OS_INDEX        0x06
181 #define USB_STRING_MAX             USB_STRING_OS_INDEX
182 /*
183  * Devices supporting Microsoft OS Descriptors store special string
184  * descriptor at fixed index (0xEE). It is read when a new device is
185  * attached to a computer for the first time.
186  */
187 #define USB_OSDESC_STRING_DESC_INDEX 0xEE
188 
189 /* bmAttributes in Configuration Descriptor */
190 #define USB_CONFIG_REMOTE_WAKEUP 0x20
191 #define USB_CONFIG_POWERED_MASK  0x40
192 #define USB_CONFIG_BUS_POWERED   0x80
193 #define USB_CONFIG_SELF_POWERED  0xC0
194 
195 /* bMaxPower in Configuration Descriptor */
196 #define USB_CONFIG_POWER_MA(mA) ((mA) / 2)
197 
198 /* bEndpointAddress in Endpoint Descriptor */
199 #define USB_ENDPOINT_DIRECTION_MASK 0x80
200 #define USB_ENDPOINT_OUT(addr)      ((addr) | 0x00)
201 #define USB_ENDPOINT_IN(addr)       ((addr) | 0x80)
202 
203 /**
204  * USB endpoint direction and number.
205  */
206 #define USB_EP_DIR_MASK 0x80U
207 #define USB_EP_DIR_IN   0x80U
208 #define USB_EP_DIR_OUT  0x00U
209 
210 /** Get endpoint index (number) from endpoint address */
211 #define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK)
212 /** Get direction from endpoint address */
213 #define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK)
214 /** Get endpoint address from endpoint index and direction */
215 #define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK))
216 /** True if the endpoint is an IN endpoint */
217 #define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN)
218 /** True if the endpoint is an OUT endpoint */
219 #define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT)
220 
221 /* bmAttributes in Endpoint Descriptor */
222 #define USB_ENDPOINT_TYPE_SHIFT       0
223 #define USB_ENDPOINT_TYPE_CONTROL     (0 << USB_ENDPOINT_TYPE_SHIFT)
224 #define USB_ENDPOINT_TYPE_ISOCHRONOUS (1 << USB_ENDPOINT_TYPE_SHIFT)
225 #define USB_ENDPOINT_TYPE_BULK        (2 << USB_ENDPOINT_TYPE_SHIFT)
226 #define USB_ENDPOINT_TYPE_INTERRUPT   (3 << USB_ENDPOINT_TYPE_SHIFT)
227 #define USB_ENDPOINT_TYPE_MASK        (3 << USB_ENDPOINT_TYPE_SHIFT)
228 #define USB_GET_ENDPOINT_TYPE(x)      ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT)
229 
230 #define USB_ENDPOINT_SYNC_SHIFT              2
231 #define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
232 #define USB_ENDPOINT_SYNC_ASYNCHRONOUS       (1 << USB_ENDPOINT_SYNC_SHIFT)
233 #define USB_ENDPOINT_SYNC_ADAPTIVE           (2 << USB_ENDPOINT_SYNC_SHIFT)
234 #define USB_ENDPOINT_SYNC_SYNCHRONOUS        (3 << USB_ENDPOINT_SYNC_SHIFT)
235 #define USB_ENDPOINT_SYNC_MASK               (3 << USB_ENDPOINT_SYNC_SHIFT)
236 
237 #define USB_ENDPOINT_USAGE_SHIFT             4
238 #define USB_ENDPOINT_USAGE_DATA              (0 << USB_ENDPOINT_USAGE_SHIFT)
239 #define USB_ENDPOINT_USAGE_FEEDBACK          (1 << USB_ENDPOINT_USAGE_SHIFT)
240 #define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << USB_ENDPOINT_USAGE_SHIFT)
241 #define USB_ENDPOINT_USAGE_MASK              (3 << USB_ENDPOINT_USAGE_SHIFT)
242 
243 #define USB_ENDPOINT_MAX_ADJUSTABLE (1 << 7)
244 
245 /* wMaxPacketSize in Endpoint Descriptor */
246 #define USB_MAXPACKETSIZE_SHIFT                        0
247 #define USB_MAXPACKETSIZE_MASK                         (0x7ff << USB_MAXPACKETSIZE_SHIFT)
248 #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT 11
249 #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_NONE  (0 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
250 #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE   (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
251 #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO   (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
252 #define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK  (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
253 #define USB_GET_MAXPACKETSIZE(x)                       ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT)
254 #define USB_GET_MULT(x)                                ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
255 
256 /* bDevCapabilityType in Device Capability Descriptor */
257 #define USB_DEVICE_CAPABILITY_WIRELESS_USB                1
258 #define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION           2
259 #define USB_DEVICE_CAPABILITY_SUPERSPEED_USB              3
260 #define USB_DEVICE_CAPABILITY_CONTAINER_ID                4
261 #define USB_DEVICE_CAPABILITY_PLATFORM                    5
262 #define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY   6
263 #define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY     7
264 #define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8
265 #define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9
266 #define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS             10
267 #define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT  11
268 #define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT            12
269 
270 #define USB_BOS_CAPABILITY_EXTENSION 0x02
271 #define USB_BOS_CAPABILITY_PLATFORM  0x05
272 
273 /* OTG SET FEATURE Constants */
274 #define USB_OTG_FEATURE_B_HNP_ENABLE      3 /* Enable B device to perform HNP */
275 #define USB_OTG_FEATURE_A_HNP_SUPPORT     4 /* A device supports HNP */
276 #define USB_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */
277 
278 /* WinUSB Microsoft OS 2.0 descriptor request codes */
279 #define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07
280 #define WINUSB_REQUEST_SET_ALT_ENUM       0x08
281 
282 /* WinUSB Microsoft OS 2.0 descriptor sizes */
283 #define WINUSB_DESCRIPTOR_SET_HEADER_SIZE  10
284 #define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
285 #define WINUSB_FEATURE_COMPATIBLE_ID_SIZE  20
286 
287 /* WinUSB Microsoft OS 2.0 Descriptor Types */
288 #define WINUSB_SET_HEADER_DESCRIPTOR_TYPE       0x00
289 #define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01
290 #define WINUSB_SUBSET_HEADER_FUNCTION_TYPE      0x02
291 #define WINUSB_FEATURE_COMPATIBLE_ID_TYPE       0x03
292 #define WINUSB_FEATURE_REG_PROPERTY_TYPE        0x04
293 #define WINUSB_FEATURE_MIN_RESUME_TIME_TYPE     0x05
294 #define WINUSB_FEATURE_MODEL_ID_TYPE            0x06
295 #define WINUSB_FEATURE_CCGP_DEVICE_TYPE         0x07
296 
297 #define WINUSB_PROP_DATA_TYPE_REG_SZ       0x01
298 #define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07
299 
300 /* WebUSB Descriptor Types */
301 #define WEBUSB_DESCRIPTOR_SET_HEADER_TYPE       0x00
302 #define WEBUSB_CONFIGURATION_SUBSET_HEADER_TYPE 0x01
303 #define WEBUSB_FUNCTION_SUBSET_HEADER_TYPE      0x02
304 #define WEBUSB_URL_TYPE                         0x03
305 
306 /* WebUSB Request Codes */
307 #define WEBUSB_REQUEST_GET_URL 0x02
308 
309 /* bScheme in URL descriptor */
310 #define WEBUSB_URL_SCHEME_HTTP  0x00
311 #define WEBUSB_URL_SCHEME_HTTPS 0x01
312 
313 /* WebUSB Descriptor sizes */
314 #define WEBUSB_DESCRIPTOR_SET_HEADER_SIZE       5
315 #define WEBUSB_CONFIGURATION_SUBSET_HEADER_SIZE 4
316 #define WEBUSB_FUNCTION_SUBSET_HEADER_SIZE      3
317 
318 /* Setup packet definition used to read raw data from USB line */
319 struct usb_setup_packet {
320     /** Request type. Bits 0:4 determine recipient, see
321 	 * \ref usb_request_recipient. Bits 5:6 determine type, see
322 	 * \ref usb_request_type. Bit 7 determines data transfer direction, see
323 	 * \ref usb_endpoint_direction.
324 	 */
325     uint8_t bmRequestType;
326 
327     /** Request. If the type bits of bmRequestType are equal to
328 	 * \ref usb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
329 	 * "USB_REQUEST_TYPE_STANDARD" then this field refers to
330 	 * \ref usb_standard_request. For other cases, use of this field is
331 	 * application-specific. */
332     uint8_t bRequest;
333 
334     /** Value. Varies according to request */
335     uint16_t wValue;
336 
337     /** Index. Varies according to request, typically used to pass an index
338 	 * or offset */
339     uint16_t wIndex;
340 
341     /** Number of bytes to transfer */
342     uint16_t wLength;
343 } __PACKED;
344 
345 #define USB_SIZEOF_SETUP_PACKET 8
346 
347 /** Standard Device Descriptor */
348 struct usb_device_descriptor {
349     uint8_t bLength;            /* Descriptor size in bytes = 18 */
350     uint8_t bDescriptorType;    /* DEVICE descriptor type = 1 */
351     uint16_t bcdUSB;            /* USB spec in BCD, e.g. 0x0200 */
352     uint8_t bDeviceClass;       /* Class code, if 0 see interface */
353     uint8_t bDeviceSubClass;    /* Sub-Class code, 0 if class = 0 */
354     uint8_t bDeviceProtocol;    /* Protocol, if 0 see interface */
355     uint8_t bMaxPacketSize0;    /* Endpoint 0 max. size */
356     uint16_t idVendor;          /* Vendor ID per USB-IF */
357     uint16_t idProduct;         /* Product ID per manufacturer */
358     uint16_t bcdDevice;         /* Device release # in BCD */
359     uint8_t iManufacturer;      /* Index to manufacturer string */
360     uint8_t iProduct;           /* Index to product string */
361     uint8_t iSerialNumber;      /* Index to serial number string */
362     uint8_t bNumConfigurations; /* Number of possible configurations */
363 } __PACKED;
364 
365 #define USB_SIZEOF_DEVICE_DESC 18
366 
367 /** Standard Configuration Descriptor */
368 struct usb_configuration_descriptor {
369     uint8_t bLength;             /* Descriptor size in bytes = 9 */
370     uint8_t bDescriptorType;     /* CONFIGURATION type = 2 or 7 */
371     uint16_t wTotalLength;       /* Length of concatenated descriptors */
372     uint8_t bNumInterfaces;      /* Number of interfaces, this config. */
373     uint8_t bConfigurationValue; /* Value to set this config. */
374     uint8_t iConfiguration;      /* Index to configuration string */
375     uint8_t bmAttributes;        /* Config. characteristics */
376     uint8_t bMaxPower;           /* Max.power from bus, 2mA units */
377 } __PACKED;
378 
379 #define USB_SIZEOF_CONFIG_DESC 9
380 
381 /** Standard Interface Descriptor */
382 struct usb_interface_descriptor {
383     uint8_t bLength;            /* Descriptor size in bytes = 9 */
384     uint8_t bDescriptorType;    /* INTERFACE descriptor type = 4 */
385     uint8_t bInterfaceNumber;   /* Interface no.*/
386     uint8_t bAlternateSetting;  /* Value to select this IF */
387     uint8_t bNumEndpoints;      /* Number of endpoints excluding 0 */
388     uint8_t bInterfaceClass;    /* Class code, 0xFF = vendor */
389     uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */
390     uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */
391     uint8_t iInterface;         /* Index to interface string */
392 } __PACKED;
393 
394 #define USB_SIZEOF_INTERFACE_DESC 9
395 
396 /** Standard Endpoint Descriptor */
397 struct usb_endpoint_descriptor {
398     uint8_t bLength;          /* Descriptor size in bytes = 7 */
399     uint8_t bDescriptorType;  /* ENDPOINT descriptor type = 5 */
400     uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
401     uint8_t bmAttributes;     /* Transfer type */
402     uint16_t wMaxPacketSize;  /* Bits 10:0 = max. packet size */
403     uint8_t bInterval;        /* Polling interval in (micro) frames */
404 } __PACKED;
405 
406 #define USB_SIZEOF_ENDPOINT_DESC 7
407 
408 /** Unicode (UTF16LE) String Descriptor */
409 struct usb_string_descriptor {
410     uint8_t bLength;
411     uint8_t bDescriptorType;
412     uint16_t bString;
413 } __PACKED;
414 
415 #define USB_SIZEOF_STRING_LANGID_DESC 4
416 
417 /* USB Interface Association Descriptor */
418 struct usb_interface_association_descriptor {
419     uint8_t bLength;
420     uint8_t bDescriptorType;
421     uint8_t bFirstInterface;
422     uint8_t bInterfaceCount;
423     uint8_t bFunctionClass;
424     uint8_t bFunctionSubClass;
425     uint8_t bFunctionProtocol;
426     uint8_t iFunction;
427 } __PACKED;
428 
429 #define USB_SIZEOF_IAD_DESC 8
430 
431 /** USB device_qualifier descriptor */
432 struct usb_device_qualifier_descriptor {
433     uint8_t bLength;            /* Descriptor size in bytes = 10 */
434     uint8_t bDescriptorType;    /* DEVICE QUALIFIER type = 6 */
435     uint16_t bcdUSB;            /* USB spec in BCD, e.g. 0x0200 */
436     uint8_t bDeviceClass;       /* Class code, if 0 see interface */
437     uint8_t bDeviceSubClass;    /* Sub-Class code, 0 if class = 0 */
438     uint8_t bDeviceProtocol;    /* Protocol, if 0 see interface */
439     uint8_t bMaxPacketSize;     /* Endpoint 0 max. size */
440     uint8_t bNumConfigurations; /* Number of possible configurations */
441     uint8_t bReserved;          /* Reserved = 0 */
442 } __PACKED;
443 
444 #define USB_SIZEOF_DEVICE_QUALIFIER_DESC 10
445 
446 /* Microsoft OS function descriptor.
447  * This can be used to request a specific driver (such as WINUSB) to be
448  * loaded on Windows. Unlike other descriptors, it is requested by a special
449  * request USB_REQ_GETMSFTOSDESCRIPTOR.
450  * More details:
451  *       https://msdn.microsoft.com/en-us/windows/hardware/gg463179
452  * And excellent explanation:
453  *       https://github.com/pbatard/libwdi/wiki/WCID-Devices
454  *
455  * The device will have exactly one "Extended Compat ID Feature Descriptor",
456  * which may contain multiple "Function Descriptors" associated with
457  * different interfaces.
458  */
459 
460 /* MS OS 1.0 string descriptor */
461 struct usb_msosv1_string_descriptor {
462     uint8_t bLength;
463     uint8_t bDescriptorType;
464     uint8_t bString[14];
465     uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */
466     uint8_t bPad;           /* Padding byte for VendorCode look as UTF16 */
467 } __PACKED;
468 
469 /* MS OS 1.0 Header descriptor */
470 struct usb_msosv1_compat_id_header_descriptor {
471     uint32_t dwLength;
472     uint16_t bcdVersion;
473     uint16_t wIndex;
474     uint8_t bCount;
475     uint8_t reserved[7];
476 } __PACKED;
477 
478 /* MS OS 1.0 Function descriptor */
479 struct usb_msosv1_comp_id_function_descriptor {
480     uint8_t bFirstInterfaceNumber;
481     uint8_t reserved1;
482     uint8_t compatibleID[8];
483     uint8_t subCompatibleID[8];
484     uint8_t reserved2[6];
485 } __PACKED;
486 
487 #define usb_msosv1_comp_id_create(x)                                         \
488     struct usb_msosv1_comp_id {                                              \
489         struct usb_msosv1_compat_id_header_descriptor compat_id_header;      \
490         struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \
491     };
492 
493 struct usb_msosv1_descriptor {
494     const uint8_t *string;
495     uint8_t vendor_code;
496     const uint8_t *compat_id;
497     const uint8_t **comp_id_property;
498 };
499 
500 /* MS OS 2.0 Header descriptor */
501 struct usb_msosv2_header_descriptor {
502     uint32_t dwLength;
503     uint16_t bcdVersion;
504     uint16_t wIndex;
505     uint8_t bCount;
506 } __PACKED;
507 
508 /*Microsoft OS 2.0 set header descriptor*/
509 struct usb_msosv2_set_header_descriptor {
510     uint16_t wLength;
511     uint16_t wDescriptorType;
512     uint32_t dwWindowsVersion;
513     uint16_t wDescriptorSetTotalLength;
514 } __PACKED;
515 
516 /* Microsoft OS 2.0 compatibleID descriptor*/
517 struct usb_msosv2_comp_id_descriptor {
518     uint16_t wLength;
519     uint16_t wDescriptorType;
520     uint8_t compatibleID[8];
521     uint8_t subCompatibleID[8];
522 } __PACKED;
523 
524 /* MS OS 2.0 property descriptor */
525 struct usb_msosv2_property_descriptor {
526     uint16_t wLength;
527     uint16_t wDescriptorType;
528     uint32_t dwPropertyDataType;
529     uint16_t wPropertyNameLength;
530     const char *bPropertyName;
531     uint32_t dwPropertyDataLength;
532     const char *bPropertyData;
533 };
534 
535 /* Microsoft OS 2.0 subset function descriptor  */
536 struct usb_msosv2_subset_function_descriptor {
537     uint16_t wLength;
538     uint16_t wDescriptorType;
539     uint8_t bFirstInterface;
540     uint8_t bReserved;
541     uint16_t wSubsetLength;
542 } __PACKED;
543 
544 struct usb_msosv2_descriptor {
545     const uint8_t *compat_id;
546     uint16_t compat_id_len;
547     uint8_t vendor_code;
548 };
549 
550 /* BOS header Descriptor */
551 struct usb_bos_header_descriptor {
552     uint8_t bLength;
553     uint8_t bDescriptorType;
554     uint16_t wTotalLength;
555     uint8_t bNumDeviceCaps;
556 } __PACKED;
557 
558 /* BOS Capability platform Descriptor */
559 struct usb_bos_capability_platform_descriptor {
560     uint8_t bLength;
561     uint8_t bDescriptorType;
562     uint8_t bDevCapabilityType;
563     uint8_t bReserved;
564     uint8_t PlatformCapabilityUUID[16];
565 } __PACKED;
566 
567 /* BOS Capability MS OS Descriptors version 2 */
568 struct usb_bos_capability_msosv2_descriptor {
569     uint32_t dwWindowsVersion;
570     uint16_t wMSOSDescriptorSetTotalLength;
571     uint8_t bVendorCode;
572     uint8_t bAltEnumCode;
573 } __PACKED;
574 
575 /* BOS Capability webusb */
576 struct usb_bos_capability_webusb_descriptor {
577     uint16_t bcdVersion;
578     uint8_t bVendorCode;
579     uint8_t iLandingPage;
580 } __PACKED;
581 
582 /* BOS Capability extension Descriptor*/
583 struct usb_bos_capability_extension_descriptor {
584     uint8_t bLength;
585     uint8_t bDescriptorType;
586     uint8_t bDevCapabilityType;
587     uint32_t bmAttributes;
588 } __PACKED;
589 
590 /* Microsoft OS 2.0 Platform Capability Descriptor
591 * See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
592 * microsoft-defined-usb-descriptors
593 * Adapted from the source:
594 * https://github.com/sowbug/weblight/blob/master/firmware/webusb.c
595 * (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c
596 */
597 struct usb_bos_capability_platform_msosv2_descriptor {
598     struct usb_bos_capability_platform_descriptor platform_msos;
599     struct usb_bos_capability_msosv2_descriptor data_msosv2;
600 } __PACKED;
601 
602 /* WebUSB Platform Capability Descriptor:
603 * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
604 */
605 struct usb_bos_capability_platform_webusb_descriptor {
606     struct usb_bos_capability_platform_descriptor platform_webusb;
607     struct usb_bos_capability_webusb_descriptor data_webusb;
608 } __PACKED;
609 
610 struct usb_webusb_url_descriptor {
611     uint8_t bLength;
612     uint8_t bDescriptorType;
613     uint8_t bScheme;
614     char URL[];
615 } __PACKED;
616 
617 struct usb_webusb_descriptor {
618     uint8_t vendor_code;
619     const uint8_t *string;
620     uint32_t string_len;
621 } __PACKED;
622 
623 struct usb_bos_descriptor {
624     const uint8_t *string;
625     uint32_t string_len;
626 };
627 
628 /* USB Device Capability Descriptor */
629 struct usb_device_capability_descriptor {
630     uint8_t bLength;
631     uint8_t bDescriptorType;
632     uint8_t bDevCapabilityType;
633 } __PACKED;
634 
635 /** USB descriptor header */
636 struct usb_desc_header {
637     uint8_t bLength;         /**< descriptor length */
638     uint8_t bDescriptorType; /**< descriptor type */
639 };
640 // clang-format off
641 #define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \
642     0x12,                       /* bLength */                                                                                              \
643     USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */                                                                                      \
644     WBVAL(bcdUSB),              /* bcdUSB */                                                                                               \
645     bDeviceClass,               /* bDeviceClass */                                                                                         \
646     bDeviceSubClass,            /* bDeviceSubClass */                                                                                      \
647     bDeviceProtocol,            /* bDeviceProtocol */                                                                                      \
648     0x40,                       /* bMaxPacketSize */                                                                                       \
649     WBVAL(idVendor),            /* idVendor */                                                                                             \
650     WBVAL(idProduct),           /* idProduct */                                                                                            \
651     WBVAL(bcdDevice),           /* bcdDevice */                                                                                            \
652     USB_STRING_MFC_INDEX,       /* iManufacturer */                                                                                        \
653     USB_STRING_PRODUCT_INDEX,   /* iProduct */                                                                                             \
654     USB_STRING_SERIAL_INDEX,    /* iSerial */                                                                                              \
655     bNumConfigurations          /* bNumConfigurations */
656 
657 #define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
658     0x09,                              /* bLength */                                                       \
659     USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */                                               \
660     WBVAL(wTotalLength),               /* wTotalLength */                                                  \
661     bNumInterfaces,                    /* bNumInterfaces */                                                \
662     bConfigurationValue,               /* bConfigurationValue */                                           \
663     0x00,                              /* iConfiguration */                                                \
664     bmAttributes,                      /* bmAttributes */                                                  \
665     USB_CONFIG_POWER_MA(bMaxPower)     /* bMaxPower */
666 
667 #define USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bNumConfigurations) \
668     0x0A,                                 /* bLength */                                                    \
669     USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */                                            \
670     WBVAL(bcdUSB),              /* bcdUSB */                                                               \
671     bDeviceClass,               /* bDeviceClass */                                                         \
672     bDeviceSubClass,            /* bDeviceSubClass */                                                      \
673     bDeviceProtocol,            /* bDeviceProtocol */                                                      \
674     0x40,                       /* bMaxPacketSize */                                                       \
675     bNumConfigurations,         /* bNumConfigurations */                                                   \
676     0x00                        /* bReserved */
677 
678 #define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
679     0x09,                              /* bLength */                                                       \
680     USB_DESCRIPTOR_TYPE_OTHER_SPEED,   /* bDescriptorType */                                               \
681     WBVAL(wTotalLength),               /* wTotalLength */                                                  \
682     bNumInterfaces,                    /* bNumInterfaces */                                                \
683     bConfigurationValue,               /* bConfigurationValue */                                           \
684     0x00,                              /* iConfiguration */                                                \
685     bmAttributes,                      /* bmAttributes */                                                  \
686     USB_CONFIG_POWER_MA(bMaxPower)     /* bMaxPower */
687 
688 #define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints,                  \
689                                       bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
690     0x09,                          /* bLength */                                                       \
691     USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */                                               \
692     bInterfaceNumber,              /* bInterfaceNumber */                                              \
693     bAlternateSetting,             /* bAlternateSetting */                                             \
694     bNumEndpoints,                 /* bNumEndpoints */                                                 \
695     bInterfaceClass,               /* bInterfaceClass */                                               \
696     bInterfaceSubClass,            /* bInterfaceSubClass */                                            \
697     bInterfaceProtocol,            /* bInterfaceProtocol */                                            \
698     iInterface                     /* iInterface */
699 
700 #define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
701     0x07,                         /* bLength */                                             \
702     USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */                                     \
703     bEndpointAddress,             /* bEndpointAddress */                                    \
704     bmAttributes,                 /* bmAttributes */                                        \
705     WBVAL(wMaxPacketSize),        /* wMaxPacketSize */                                      \
706     bInterval                     /* bInterval */
707 
708 #define USB_IAD_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \
709     0x08,                                      /* bLength */                                             \
710     USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */                                     \
711     bFirstInterface,                           /* bFirstInterface */                                     \
712     bInterfaceCount,                           /* bInterfaceCount */                                     \
713     bFunctionClass,                            /* bFunctionClass */                                      \
714     bFunctionSubClass,                         /* bFunctionSubClass */                                   \
715     bFunctionProtocol,                         /* bFunctionProtocol */                                   \
716     0x00                                       /* iFunction */
717 
718 #define USB_LANGID_INIT(id)                           \
719     0x04,                           /* bLength */     \
720     USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \
721     WBVAL(id)                   /* wLangID0 */
722 // clang-format on
723 
724 #endif /* USB_DEF_H */
725