summaryrefslogtreecommitdiff
path: root/common/usb_def.h
blob: e3fdd240c04d761dd9bf6e69a0e3e2404c05bd4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
/*
 * Copyright (c) 2022, sakumisu
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#ifndef USB_DEF_H
#define USB_DEF_H

/* Useful define */
#define USB_1_1 0x0110
#define USB_2_0 0x0200
/* Set USB version to 2.1 so that the host will request the BOS descriptor */
#define USB_2_1 0x0210
#define USB_3_0 0x0300
#define USB_3_1 0x0310
#define USB_3_2 0x0320

/* Device speeds */
#define USB_SPEED_UNKNOWN    0 /* Transfer rate not yet set */
#define USB_SPEED_LOW        1 /* USB 1.1 */
#define USB_SPEED_FULL       2 /* USB 1.1 */
#define USB_SPEED_HIGH       3 /* USB 2.0 */
#define USB_SPEED_WIRELESS   4 /* Wireless USB 2.5 */
#define USB_SPEED_SUPER      5 /* USB 3.0 */
#define USB_SPEED_SUPER_PLUS 6 /* USB 3.1 */

/* Maximum number of devices per controller */
#define USB_MAX_DEVICES (127)

/* Default USB control EP, always 0 and 0x80 */
#define USB_CONTROL_OUT_EP0 0
#define USB_CONTROL_IN_EP0  0x80

/**< maximum packet size (MPS) for EP 0 */
#define USB_CTRL_EP_MPS 64

/**< maximum packet size (MPS) for bulk EP */
#define USB_BULK_EP_MPS_HS 512
#define USB_BULK_EP_MPS_FS 64

/* USB PID Types */
#define USB_PID_OUT   (0x01) /* Tokens */
#define USB_PID_IN    (0x09)
#define USB_PID_SOF   (0x05)
#define USB_PID_SETUP (0x0d)

#define USB_PID_DATA0 (0x03) /* Data */
#define USB_PID_DATA1 (0x0b)
#define USB_PID_DATA2 (0x07)
#define USB_PID_MDATA (0x0f)

#define USB_PID_ACK   (0x02) /* Handshake */
#define USB_PID_NAK   (0x0a)
#define USB_PID_STALL (0x0e)
#define USB_PID_NYET  (0x06)

#define USB_PID_PRE      (0x0c) /* Special */
#define USB_PID_ERR      (0x0c)
#define USB_PID_SPLIT    (0x08)
#define USB_PID_PING     (0x04)
#define USB_PID_RESERVED (0x00)

#define USB_REQUEST_DIR_SHIFT 7U                            /* Bits 7: Request dir */
#define USB_REQUEST_DIR_OUT   (0U << USB_REQUEST_DIR_SHIFT) /* Bit 7=0: Host-to-device */
#define USB_REQUEST_DIR_IN    (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Device-to-host */
#define USB_REQUEST_DIR_MASK  (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Direction bit */

#define USB_REQUEST_TYPE_SHIFT 5U /* Bits 5:6: Request type */
#define USB_REQUEST_STANDARD   (0U << USB_REQUEST_TYPE_SHIFT)
#define USB_REQUEST_CLASS      (1U << USB_REQUEST_TYPE_SHIFT)
#define USB_REQUEST_VENDOR     (2U << USB_REQUEST_TYPE_SHIFT)
#define USB_REQUEST_RESERVED   (3U << USB_REQUEST_TYPE_SHIFT)
#define USB_REQUEST_TYPE_MASK  (3U << USB_REQUEST_TYPE_SHIFT)

#define USB_REQUEST_RECIPIENT_SHIFT     0U /* Bits 0:4: Recipient */
#define USB_REQUEST_RECIPIENT_DEVICE    (0U << USB_REQUEST_RECIPIENT_SHIFT)
#define USB_REQUEST_RECIPIENT_INTERFACE (1U << USB_REQUEST_RECIPIENT_SHIFT)
#define USB_REQUEST_RECIPIENT_ENDPOINT  (2U << USB_REQUEST_RECIPIENT_SHIFT)
#define USB_REQUEST_RECIPIENT_OTHER     (3U << USB_REQUEST_RECIPIENT_SHIFT)
#define USB_REQUEST_RECIPIENT_MASK      (3U << USB_REQUEST_RECIPIENT_SHIFT)

/* USB Standard Request Codes */
#define USB_REQUEST_GET_STATUS          0x00
#define USB_REQUEST_CLEAR_FEATURE       0x01
#define USB_REQUEST_SET_FEATURE         0x03
#define USB_REQUEST_SET_ADDRESS         0x05
#define USB_REQUEST_GET_DESCRIPTOR      0x06
#define USB_REQUEST_SET_DESCRIPTOR      0x07
#define USB_REQUEST_GET_CONFIGURATION   0x08
#define USB_REQUEST_SET_CONFIGURATION   0x09
#define USB_REQUEST_GET_INTERFACE       0x0A
#define USB_REQUEST_SET_INTERFACE       0x0B
#define USB_REQUEST_SYNCH_FRAME         0x0C
#define USB_REQUEST_SET_ENCRYPTION      0x0D
#define USB_REQUEST_GET_ENCRYPTION      0x0E
#define USB_REQUEST_RPIPE_ABORT         0x0E
#define USB_REQUEST_SET_HANDSHAKE       0x0F
#define USB_REQUEST_RPIPE_RESET         0x0F
#define USB_REQUEST_GET_HANDSHAKE       0x10
#define USB_REQUEST_SET_CONNECTION      0x11
#define USB_REQUEST_SET_SECURITY_DATA   0x12
#define USB_REQUEST_GET_SECURITY_DATA   0x13
#define USB_REQUEST_SET_WUSB_DATA       0x14
#define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15
#define USB_REQUEST_LOOPBACK_DATA_READ  0x16
#define USB_REQUEST_SET_INTERFACE_DS    0x17

/* USB Standard Feature selectors */
#define USB_FEATURE_ENDPOINT_HALT  0
#define USB_FEATURE_SELF_POWERED   0
#define USB_FEATURE_REMOTE_WAKEUP  1
#define USB_FEATURE_TEST_MODE      2
#define USB_FEATURE_BATTERY        2
#define USB_FEATURE_BHNPENABLE     3
#define USB_FEATURE_WUSBDEVICE     3
#define USB_FEATURE_AHNPSUPPORT    4
#define USB_FEATURE_AALTHNPSUPPORT 5
#define USB_FEATURE_DEBUGMODE      6

/* USB GET_STATUS Bit Values */
#define USB_GETSTATUS_ENDPOINT_HALT 0x01
#define USB_GETSTATUS_SELF_POWERED  0x01
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02

/* USB Descriptor Types */
#define USB_DESCRIPTOR_TYPE_DEVICE                0x01U
#define USB_DESCRIPTOR_TYPE_CONFIGURATION         0x02U
#define USB_DESCRIPTOR_TYPE_STRING                0x03U
#define USB_DESCRIPTOR_TYPE_INTERFACE             0x04U
#define USB_DESCRIPTOR_TYPE_ENDPOINT              0x05U
#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER      0x06U
#define USB_DESCRIPTOR_TYPE_OTHER_SPEED           0x07U
#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER       0x08U
#define USB_DESCRIPTOR_TYPE_OTG                   0x09U
#define USB_DESCRIPTOR_TYPE_DEBUG                 0x0AU
#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU
#define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE   0x0FU
#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY     0x10U
#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINTCOMP 0x11U

/* Class Specific Descriptor */
#define USB_CS_DESCRIPTOR_TYPE_DEVICE        0x21U
#define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U
#define USB_CS_DESCRIPTOR_TYPE_STRING        0x23U
#define USB_CS_DESCRIPTOR_TYPE_INTERFACE     0x24U
#define USB_CS_DESCRIPTOR_TYPE_ENDPOINT      0x25U

#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION     0x30U
#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U

/* USB Device Classes */
#define USB_DEVICE_CLASS_RESERVED      0x00
#define USB_DEVICE_CLASS_AUDIO         0x01
#define USB_DEVICE_CLASS_CDC           0x02
#define USB_DEVICE_CLASS_HID           0x03
#define USB_DEVICE_CLASS_MONITOR       0x04
#define USB_DEVICE_CLASS_PHYSICAL      0x05
#define USB_DEVICE_CLASS_IMAGE         0x06
#define USB_DEVICE_CLASS_PRINTER       0x07
#define USB_DEVICE_CLASS_MASS_STORAGE  0x08
#define USB_DEVICE_CLASS_HUB           0x09
#define USB_DEVICE_CLASS_CDC_DATA      0x0a
#define USB_DEVICE_CLASS_SMART_CARD    0x0b
#define USB_DEVICE_CLASS_SECURITY      0x0d
#define USB_DEVICE_CLASS_VIDEO         0x0e
#define USB_DEVICE_CLASS_HEALTHCARE    0x0f
#define USB_DEVICE_CLASS_DIAG_DEVICE   0xdc
#define USB_DEVICE_CLASS_WIRELESS      0xe0
#define USB_DEVICE_CLASS_MISC          0xef
#define USB_DEVICE_CLASS_APP_SPECIFIC  0xfe
#define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff

/* usb string index define */
#define USB_STRING_LANGID_INDEX    0x00
#define USB_STRING_MFC_INDEX       0x01
#define USB_STRING_PRODUCT_INDEX   0x02
#define USB_STRING_SERIAL_INDEX    0x03
#define USB_STRING_CONFIG_INDEX    0x04
#define USB_STRING_INTERFACE_INDEX 0x05
#define USB_STRING_OS_INDEX        0x06
#define USB_STRING_MAX             USB_STRING_OS_INDEX
/*
 * Devices supporting Microsoft OS Descriptors store special string
 * descriptor at fixed index (0xEE). It is read when a new device is
 * attached to a computer for the first time.
 */
#define USB_OSDESC_STRING_DESC_INDEX 0xEE

/* bmAttributes in Configuration Descriptor */
#define USB_CONFIG_REMOTE_WAKEUP 0x20
#define USB_CONFIG_POWERED_MASK  0x40
#define USB_CONFIG_BUS_POWERED   0x80
#define USB_CONFIG_SELF_POWERED  0xC0

/* bMaxPower in Configuration Descriptor */
#define USB_CONFIG_POWER_MA(mA) ((mA) / 2)

/* bEndpointAddress in Endpoint Descriptor */
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr)      ((addr) | 0x00)
#define USB_ENDPOINT_IN(addr)       ((addr) | 0x80)

/**
 * USB endpoint direction and number.
 */
#define USB_EP_DIR_MASK 0x80U
#define USB_EP_DIR_IN   0x80U
#define USB_EP_DIR_OUT  0x00U

/** Get endpoint index (number) from endpoint address */
#define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK)
/** Get direction from endpoint address */
#define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK)
/** Get endpoint address from endpoint index and direction */
#define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK))
/** True if the endpoint is an IN endpoint */
#define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN)
/** True if the endpoint is an OUT endpoint */
#define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT)

/* bmAttributes in Endpoint Descriptor */
#define USB_ENDPOINT_TYPE_SHIFT       0
#define USB_ENDPOINT_TYPE_CONTROL     (0 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_ISOCHRONOUS (1 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_BULK        (2 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_INTERRUPT   (3 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_ENDPOINT_TYPE_MASK        (3 << USB_ENDPOINT_TYPE_SHIFT)
#define USB_GET_ENDPOINT_TYPE(x)      ((x & USB_ENDPOINT_TYPE_MASK) >> USB_ENDPOINT_TYPE_SHIFT)

#define USB_ENDPOINT_SYNC_SHIFT              2
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS       (1 << USB_ENDPOINT_SYNC_SHIFT)
#define USB_ENDPOINT_SYNC_ADAPTIVE           (2 << USB_ENDPOINT_SYNC_SHIFT)
#define USB_ENDPOINT_SYNC_SYNCHRONOUS        (3 << USB_ENDPOINT_SYNC_SHIFT)
#define USB_ENDPOINT_SYNC_MASK               (3 << USB_ENDPOINT_SYNC_SHIFT)

#define USB_ENDPOINT_USAGE_SHIFT             4
#define USB_ENDPOINT_USAGE_DATA              (0 << USB_ENDPOINT_USAGE_SHIFT)
#define USB_ENDPOINT_USAGE_FEEDBACK          (1 << USB_ENDPOINT_USAGE_SHIFT)
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << USB_ENDPOINT_USAGE_SHIFT)
#define USB_ENDPOINT_USAGE_MASK              (3 << USB_ENDPOINT_USAGE_SHIFT)

#define USB_ENDPOINT_MAX_ADJUSTABLE (1 << 7)

/* wMaxPacketSize in Endpoint Descriptor */
#define USB_MAXPACKETSIZE_SHIFT                        0
#define USB_MAXPACKETSIZE_MASK                         (0x7ff << USB_MAXPACKETSIZE_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT 11
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_NONE  (0 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE   (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO   (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK  (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
#define USB_GET_MAXPACKETSIZE(x)                       ((x & USB_MAXPACKETSIZE_MASK) >> USB_MAXPACKETSIZE_SHIFT)
#define USB_GET_MULT(x)                                ((x & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)

/* bDevCapabilityType in Device Capability Descriptor */
#define USB_DEVICE_CAPABILITY_WIRELESS_USB                1
#define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION           2
#define USB_DEVICE_CAPABILITY_SUPERSPEED_USB              3
#define USB_DEVICE_CAPABILITY_CONTAINER_ID                4
#define USB_DEVICE_CAPABILITY_PLATFORM                    5
#define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY   6
#define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY     7
#define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8
#define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9
#define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS             10
#define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT  11
#define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT            12

#define USB_BOS_CAPABILITY_EXTENSION 0x02
#define USB_BOS_CAPABILITY_PLATFORM  0x05

/* OTG SET FEATURE Constants */
#define USB_OTG_FEATURE_B_HNP_ENABLE      3 /* Enable B device to perform HNP */
#define USB_OTG_FEATURE_A_HNP_SUPPORT     4 /* A device supports HNP */
#define USB_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */

/* WinUSB Microsoft OS 2.0 descriptor request codes */
#define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07
#define WINUSB_REQUEST_SET_ALT_ENUM       0x08

/* WinUSB Microsoft OS 2.0 descriptor sizes */
#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE  10
#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE  20

/* WinUSB Microsoft OS 2.0 Descriptor Types */
#define WINUSB_SET_HEADER_DESCRIPTOR_TYPE       0x00
#define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01
#define WINUSB_SUBSET_HEADER_FUNCTION_TYPE      0x02
#define WINUSB_FEATURE_COMPATIBLE_ID_TYPE       0x03
#define WINUSB_FEATURE_REG_PROPERTY_TYPE        0x04
#define WINUSB_FEATURE_MIN_RESUME_TIME_TYPE     0x05
#define WINUSB_FEATURE_MODEL_ID_TYPE            0x06
#define WINUSB_FEATURE_CCGP_DEVICE_TYPE         0x07

#define WINUSB_PROP_DATA_TYPE_REG_SZ       0x01
#define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07

/* WebUSB Descriptor Types */
#define WEBUSB_DESCRIPTOR_SET_HEADER_TYPE       0x00
#define WEBUSB_CONFIGURATION_SUBSET_HEADER_TYPE 0x01
#define WEBUSB_FUNCTION_SUBSET_HEADER_TYPE      0x02
#define WEBUSB_URL_TYPE                         0x03

/* WebUSB Request Codes */
#define WEBUSB_REQUEST_GET_URL 0x02

/* bScheme in URL descriptor */
#define WEBUSB_URL_SCHEME_HTTP  0x00
#define WEBUSB_URL_SCHEME_HTTPS 0x01

/* WebUSB Descriptor sizes */
#define WEBUSB_DESCRIPTOR_SET_HEADER_SIZE       5
#define WEBUSB_CONFIGURATION_SUBSET_HEADER_SIZE 4
#define WEBUSB_FUNCTION_SUBSET_HEADER_SIZE      3

/* Setup packet definition used to read raw data from USB line */
struct usb_setup_packet {
    /** Request type. Bits 0:4 determine recipient, see
     * \ref usb_request_recipient. Bits 5:6 determine type, see
     * \ref usb_request_type. Bit 7 determines data transfer direction, see
     * \ref usb_endpoint_direction.
     */
    uint8_t bmRequestType;

    /** Request. If the type bits of bmRequestType are equal to
     * \ref usb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
     * "USB_REQUEST_TYPE_STANDARD" then this field refers to
     * \ref usb_standard_request. For other cases, use of this field is
     * application-specific. */
    uint8_t bRequest;

    /** Value. Varies according to request */
    uint16_t wValue;

    /** Index. Varies according to request, typically used to pass an index
     * or offset */
    uint16_t wIndex;

    /** Number of bytes to transfer */
    uint16_t wLength;
} __PACKED;

#define USB_SIZEOF_SETUP_PACKET 8

/** Standard Device Descriptor */
struct usb_device_descriptor {
    uint8_t bLength;            /* Descriptor size in bytes = 18 */
    uint8_t bDescriptorType;    /* DEVICE descriptor type = 1 */
    uint16_t bcdUSB;            /* USB spec in BCD, e.g. 0x0200 */
    uint8_t bDeviceClass;       /* Class code, if 0 see interface */
    uint8_t bDeviceSubClass;    /* Sub-Class code, 0 if class = 0 */
    uint8_t bDeviceProtocol;    /* Protocol, if 0 see interface */
    uint8_t bMaxPacketSize0;    /* Endpoint 0 max. size */
    uint16_t idVendor;          /* Vendor ID per USB-IF */
    uint16_t idProduct;         /* Product ID per manufacturer */
    uint16_t bcdDevice;         /* Device release # in BCD */
    uint8_t iManufacturer;      /* Index to manufacturer string */
    uint8_t iProduct;           /* Index to product string */
    uint8_t iSerialNumber;      /* Index to serial number string */
    uint8_t bNumConfigurations; /* Number of possible configurations */
} __PACKED;

#define USB_SIZEOF_DEVICE_DESC 18

/** Standard Configuration Descriptor */
struct usb_configuration_descriptor {
    uint8_t bLength;             /* Descriptor size in bytes = 9 */
    uint8_t bDescriptorType;     /* CONFIGURATION type = 2 or 7 */
    uint16_t wTotalLength;       /* Length of concatenated descriptors */
    uint8_t bNumInterfaces;      /* Number of interfaces, this config. */
    uint8_t bConfigurationValue; /* Value to set this config. */
    uint8_t iConfiguration;      /* Index to configuration string */
    uint8_t bmAttributes;        /* Config. characteristics */
    uint8_t bMaxPower;           /* Max.power from bus, 2mA units */
} __PACKED;

#define USB_SIZEOF_CONFIG_DESC 9

/** Standard Interface Descriptor */
struct usb_interface_descriptor {
    uint8_t bLength;            /* Descriptor size in bytes = 9 */
    uint8_t bDescriptorType;    /* INTERFACE descriptor type = 4 */
    uint8_t bInterfaceNumber;   /* Interface no.*/
    uint8_t bAlternateSetting;  /* Value to select this IF */
    uint8_t bNumEndpoints;      /* Number of endpoints excluding 0 */
    uint8_t bInterfaceClass;    /* Class code, 0xFF = vendor */
    uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */
    uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */
    uint8_t iInterface;         /* Index to interface string */
} __PACKED;

#define USB_SIZEOF_INTERFACE_DESC 9

/** Standard Endpoint Descriptor */
struct usb_endpoint_descriptor {
    uint8_t bLength;          /* Descriptor size in bytes = 7 */
    uint8_t bDescriptorType;  /* ENDPOINT descriptor type = 5 */
    uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
    uint8_t bmAttributes;     /* Transfer type */
    uint16_t wMaxPacketSize;  /* Bits 10:0 = max. packet size */
    uint8_t bInterval;        /* Polling interval in (micro) frames */
} __PACKED;

#define USB_SIZEOF_ENDPOINT_DESC 7

/** Unicode (UTF16LE) String Descriptor */
struct usb_string_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint16_t bString;
} __PACKED;

#define USB_SIZEOF_STRING_LANGID_DESC 4

/* USB Interface Association Descriptor */
struct usb_interface_association_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint8_t bFirstInterface;
    uint8_t bInterfaceCount;
    uint8_t bFunctionClass;
    uint8_t bFunctionSubClass;
    uint8_t bFunctionProtocol;
    uint8_t iFunction;
} __PACKED;

#define USB_SIZEOF_IAD_DESC 8

/** USB device_qualifier descriptor */
struct usb_device_qualifier_descriptor {
    uint8_t bLength;            /* Descriptor size in bytes = 10 */
    uint8_t bDescriptorType;    /* DEVICE QUALIFIER type = 6 */
    uint16_t bcdUSB;            /* USB spec in BCD, e.g. 0x0200 */
    uint8_t bDeviceClass;       /* Class code, if 0 see interface */
    uint8_t bDeviceSubClass;    /* Sub-Class code, 0 if class = 0 */
    uint8_t bDeviceProtocol;    /* Protocol, if 0 see interface */
    uint8_t bMaxPacketSize;     /* Endpoint 0 max. size */
    uint8_t bNumConfigurations; /* Number of possible configurations */
    uint8_t bReserved;          /* Reserved = 0 */
} __PACKED;

#define USB_SIZEOF_DEVICE_QUALIFIER_DESC 10

/* Microsoft OS function descriptor.
 * This can be used to request a specific driver (such as WINUSB) to be
 * loaded on Windows. Unlike other descriptors, it is requested by a special
 * request USB_REQ_GETMSFTOSDESCRIPTOR.
 * More details:
 *       https://msdn.microsoft.com/en-us/windows/hardware/gg463179
 * And excellent explanation:
 *       https://github.com/pbatard/libwdi/wiki/WCID-Devices
 *
 * The device will have exactly one "Extended Compat ID Feature Descriptor",
 * which may contain multiple "Function Descriptors" associated with
 * different interfaces.
 */

/* MS OS 1.0 string descriptor */
struct usb_msosv1_string_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint8_t bString[14];
    uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */
    uint8_t bPad;           /* Padding byte for VendorCode look as UTF16 */
} __PACKED;

/* MS OS 1.0 Header descriptor */
struct usb_msosv1_compat_id_header_descriptor {
    uint32_t dwLength;
    uint16_t bcdVersion;
    uint16_t wIndex;
    uint8_t bCount;
    uint8_t reserved[7];
} __PACKED;

/* MS OS 1.0 Function descriptor */
struct usb_msosv1_comp_id_function_descriptor {
    uint8_t bFirstInterfaceNumber;
    uint8_t reserved1;
    uint8_t compatibleID[8];
    uint8_t subCompatibleID[8];
    uint8_t reserved2[6];
} __PACKED;

#define usb_msosv1_comp_id_create(x)                                         \
    struct usb_msosv1_comp_id {                                              \
        struct usb_msosv1_compat_id_header_descriptor compat_id_header;      \
        struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \
    };

struct usb_msosv1_descriptor {
    const uint8_t *string;
    uint8_t vendor_code;
    const uint8_t *compat_id;
    const uint8_t **comp_id_property;
};

/* MS OS 2.0 Header descriptor */
struct usb_msosv2_header_descriptor {
    uint32_t dwLength;
    uint16_t bcdVersion;
    uint16_t wIndex;
    uint8_t bCount;
} __PACKED;

/*Microsoft OS 2.0 set header descriptor*/
struct usb_msosv2_set_header_descriptor {
    uint16_t wLength;
    uint16_t wDescriptorType;
    uint32_t dwWindowsVersion;
    uint16_t wDescriptorSetTotalLength;
} __PACKED;

/* Microsoft OS 2.0 compatibleID descriptor*/
struct usb_msosv2_comp_id_descriptor {
    uint16_t wLength;
    uint16_t wDescriptorType;
    uint8_t compatibleID[8];
    uint8_t subCompatibleID[8];
} __PACKED;

/* MS OS 2.0 property descriptor */
struct usb_msosv2_property_descriptor {
    uint16_t wLength;
    uint16_t wDescriptorType;
    uint32_t dwPropertyDataType;
    uint16_t wPropertyNameLength;
    const char *bPropertyName;
    uint32_t dwPropertyDataLength;
    const char *bPropertyData;
};

/* Microsoft OS 2.0 subset function descriptor  */
struct usb_msosv2_subset_function_descriptor {
    uint16_t wLength;
    uint16_t wDescriptorType;
    uint8_t bFirstInterface;
    uint8_t bReserved;
    uint16_t wSubsetLength;
} __PACKED;

struct usb_msosv2_descriptor {
    const uint8_t *compat_id;
    uint16_t compat_id_len;
    uint8_t vendor_code;
};

/* BOS header Descriptor */
struct usb_bos_header_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint16_t wTotalLength;
    uint8_t bNumDeviceCaps;
} __PACKED;

/* BOS Capability platform Descriptor */
struct usb_bos_capability_platform_common_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint8_t bDevCapabilityType;
    uint8_t bReserved;
    uint8_t PlatformCapabilityUUID[16];
} __PACKED;

/* Microsoft OS 2.0 Platform Capability Descriptor
* See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
* microsoft-defined-usb-descriptors
* Adapted from the source:
* https://github.com/sowbug/weblight/blob/master/firmware/webusb.c
* (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c
*/
struct usb_bos_capability_platform_winusb_descriptor {
    struct usb_bos_capability_platform_common_descriptor common;
    uint32_t dwWindowsVersion;
    uint16_t wMSOSDescriptorSetTotalLength;
    uint8_t bVendorCode;
    uint8_t bAltEnumCode;
} __PACKED;

/* WebUSB Platform Capability Descriptor:
* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
*/
struct usb_bos_capability_platform_webusb_descriptor {
    struct usb_bos_capability_platform_common_descriptor common;
    uint16_t bcdVersion;
    uint8_t bVendorCode;
    uint8_t iLandingPage;
} __PACKED;

/* BOS Capability extension Descriptor*/
struct usb_bos_capability_extension_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint8_t bDevCapabilityType;
    uint32_t bmAttributes;
} __PACKED;

struct usb_webusb_url_descriptor {
    uint8_t bLength;
    uint8_t bDescriptorType;
    uint8_t bScheme;
    char URL[];
} __PACKED;

struct usb_webusb_descriptor {
    uint8_t vendor_code;
    const uint8_t *string;
    uint32_t string_len;
} __PACKED;

struct usb_bos_descriptor {
    const uint8_t *string;
    uint32_t string_len;
};

/** USB descriptor header */
struct usb_desc_header {
    uint8_t bLength;         /**< descriptor length */
    uint8_t bDescriptorType; /**< descriptor type */
};

// clang-format off
#define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \
    0x12,                       /* bLength */                                                                                              \
    USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */                                                                                      \
    WBVAL(bcdUSB),              /* bcdUSB */                                                                                               \
    bDeviceClass,               /* bDeviceClass */                                                                                         \
    bDeviceSubClass,            /* bDeviceSubClass */                                                                                      \
    bDeviceProtocol,            /* bDeviceProtocol */                                                                                      \
    0x40,                       /* bMaxPacketSize */                                                                                       \
    WBVAL(idVendor),            /* idVendor */                                                                                             \
    WBVAL(idProduct),           /* idProduct */                                                                                            \
    WBVAL(bcdDevice),           /* bcdDevice */                                                                                            \
    USB_STRING_MFC_INDEX,       /* iManufacturer */                                                                                        \
    USB_STRING_PRODUCT_INDEX,   /* iProduct */                                                                                             \
    USB_STRING_SERIAL_INDEX,    /* iSerial */                                                                                              \
    bNumConfigurations          /* bNumConfigurations */

#define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
    0x09,                              /* bLength */                                                       \
    USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */                                               \
    WBVAL(wTotalLength),               /* wTotalLength */                                                  \
    bNumInterfaces,                    /* bNumInterfaces */                                                \
    bConfigurationValue,               /* bConfigurationValue */                                           \
    0x00,                              /* iConfiguration */                                                \
    bmAttributes,                      /* bmAttributes */                                                  \
    USB_CONFIG_POWER_MA(bMaxPower)     /* bMaxPower */

#define USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bNumConfigurations) \
    0x0A,                                 /* bLength */                                                    \
    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, /* bDescriptorType */                                            \
    WBVAL(bcdUSB),              /* bcdUSB */                                                               \
    bDeviceClass,               /* bDeviceClass */                                                         \
    bDeviceSubClass,            /* bDeviceSubClass */                                                      \
    bDeviceProtocol,            /* bDeviceProtocol */                                                      \
    0x40,                       /* bMaxPacketSize */                                                       \
    bNumConfigurations,         /* bNumConfigurations */                                                   \
    0x00                        /* bReserved */

#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
    0x09,                              /* bLength */                                                       \
    USB_DESCRIPTOR_TYPE_OTHER_SPEED,   /* bDescriptorType */                                               \
    WBVAL(wTotalLength),               /* wTotalLength */                                                  \
    bNumInterfaces,                    /* bNumInterfaces */                                                \
    bConfigurationValue,               /* bConfigurationValue */                                           \
    0x00,                              /* iConfiguration */                                                \
    bmAttributes,                      /* bmAttributes */                                                  \
    USB_CONFIG_POWER_MA(bMaxPower)     /* bMaxPower */

#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints,                  \
                                      bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
    0x09,                          /* bLength */                                                       \
    USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */                                               \
    bInterfaceNumber,              /* bInterfaceNumber */                                              \
    bAlternateSetting,             /* bAlternateSetting */                                             \
    bNumEndpoints,                 /* bNumEndpoints */                                                 \
    bInterfaceClass,               /* bInterfaceClass */                                               \
    bInterfaceSubClass,            /* bInterfaceSubClass */                                            \
    bInterfaceProtocol,            /* bInterfaceProtocol */                                            \
    iInterface                     /* iInterface */

#define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
    0x07,                         /* bLength */                                             \
    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */                                     \
    bEndpointAddress,             /* bEndpointAddress */                                    \
    bmAttributes,                 /* bmAttributes */                                        \
    WBVAL(wMaxPacketSize),        /* wMaxPacketSize */                                      \
    bInterval                     /* bInterval */

#define USB_IAD_DESCRIPTOR_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \
    0x08,                                      /* bLength */                                             \
    USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */                                     \
    bFirstInterface,                           /* bFirstInterface */                                     \
    bInterfaceCount,                           /* bInterfaceCount */                                     \
    bFunctionClass,                            /* bFunctionClass */                                      \
    bFunctionSubClass,                         /* bFunctionSubClass */                                   \
    bFunctionProtocol,                         /* bFunctionProtocol */                                   \
    0x00                                       /* iFunction */

#define USB_LANGID_INIT(id)                           \
    0x04,                       /* bLength */         \
    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \
    WBVAL(id)                   /* wLangID0 */

#define USB_BOS_HEADER_DESCRIPTOR_INIT(wTotalLength, bNumDeviceCaps) \
    0x05,                       /* bLength */                        \
    USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE,    /* bDescriptorType */\
    WBVAL(wTotalLength),        /* wTotalLength */                   \
    bNumDeviceCaps              /* bNumDeviceCaps */

#define USB_BOS_CAP_PLATFORM_WEBUSB_DESCRIPTOR_INIT(bVendorCode, iLandingPage)   \
    0x18,                                           /* bLength */                \
    USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY,          /* bDescriptorType */        \
    USB_DEVICE_CAPABILITY_PLATFORM,                 /* bDevCapabilityType */     \
    0x00,                                           /* bReserved */              \
    0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47, /* PlatformCapabilityUUID */ \
    0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65,                              \
    WBVAL(0x0100),                                  /* bcdVersion */             \
    bVendorCode,                                    /* bVendorCode */            \
    iLandingPage                                    /* iLandingPage */

#define USB_BOS_CAP_PLATFORM_WINUSB_DESCRIPTOR_INIT(bVendorCode, wMSOSDescriptorSetTotalLength) \
    0x1C,                                           /* bLength */                \
    USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY,          /* bDescriptorType */        \
    USB_DEVICE_CAPABILITY_PLATFORM,                 /* bDevCapabilityType */     \
    0x00,                                           /* bReserved */              \
    0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, /* PlatformCapabilityUUID */ \
    0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,                              \
    DBVAL(0x06030000),                              /* dwWindowsVersion */       \
    WBVAL(wMSOSDescriptorSetTotalLength),           /* wMSOSDescriptorSetTotalLength */ \
    bVendorCode,                                    /* bVendorCode */            \
    0x00                                            /* bAltEnumCode */

#define USB_BOS_CAP_PLATFORM_WEBUSB_DESCRIPTOR_LEN 24
#define USB_BOS_CAP_PLATFORM_WINUSB_DESCRIPTOR_LEN 28

#define USB_MSOSV1_STRING_DESCRIPTOR_INIT(vendor_code) \
    0x12,                       /* bLength */                             \
    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */                     \
    'M', 0,                     /* bString[0] */                          \
    'S', 0,                     /* bString[1] */                          \
    'F', 0,                     /* bString[2] */                          \
    'T', 0,                     /* bString[3] */                          \
    '1', 0,                     /* bString[4] */                          \
    '0', 0,                     /* bString[5] */                          \
    '0', 0,                     /* bString[6] */                          \
    vendor_code,                /* bMS_VendorCode */                      \
    0x00                        /* bPad */

#define USB_MSOSV1_COMP_ID_HEADER_DESCRIPTOR_INIT(bCount) \
    DBVAL((sizeof(struct usb_msosv1_compat_id_header_descriptor) + sizeof(struct usb_msosv1_comp_id_function_descriptor) * bCount)), /* dwLength */ \
    WBVAL(0x0100),            /* bcdVersion */                     \
    WBVAL(0x0004),            /* wIndex */                         \
    bCount,                   /* bCount */                         \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* reserved[7] */

#define USB_MSOSV1_COMP_ID_FUNCTION_WINUSB_DESCRIPTOR_INIT(bFirstInterfaceNumber) \
    bFirstInterfaceNumber,                          /* bFirstInterfaceNumber */\
    0x01,                                           /* reserved1 */            \
    'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,       /* compatibleID[8] */      \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* subCompatibleID[8] */   \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* reserved2[6] */

#define USB_MSOSV1_COMP_ID_FUNCTION_MTP_DESCRIPTOR_INIT(bFirstInterfaceNumber)\
    bFirstInterfaceNumber,                          /* bFirstInterfaceNumber */\
    0x01,                                           /* reserved1 */            \
    'M', 'T', 'P', 0x00, 0x00, 0x00, 0x00, 0x00,    /* compatibleID[8] */      \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* subCompatibleID[8] */   \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* reserved2[6] */

#define USB_MSOSV1_COMP_ID_FUNCTION_ADB_DESCRIPTOR_INIT(bFirstInterfaceNumber)\
    bFirstInterfaceNumber,                          /* bFirstInterfaceNumber */\
    0x01,                                           /* reserved1 */            \
    'A', 'D', 'B', 0x00, 0x00, 0x00, 0x00, 0x00,    /* compatibleID[8] */      \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* subCompatibleID[8] */   \
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* reserved2[6] */

#define USB_MSOSV1_COMP_ID_DESCRIPTOR_LEN(bCount) \
    (sizeof(struct usb_msosv1_compat_id_header_descriptor) + sizeof(struct usb_msosv1_comp_id_function_descriptor) * (bCount))

#define USB_MSOSV2_COMP_ID_SET_HEADER_DESCRIPTOR_INIT(wDescriptorSetTotalLength)   \
    WBVAL(WINUSB_DESCRIPTOR_SET_HEADER_SIZE),               /* wLength */          \
    WBVAL(WINUSB_SET_HEADER_DESCRIPTOR_TYPE),               /* wDescriptorType */  \
    DBVAL(0x06030000),                                      /* dwWindowsVersion */ \
    WBVAL(wDescriptorSetTotalLength)                        /* wDescriptorSetTotalLength */

#define USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_SINGLE_DESCRIPTOR_INIT()                                           \
    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  /* wLength */                                                  \
    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  /* wDescriptorType */                                          \
    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        /* CompatibleId*/                                              \
    0, 0, 0, 0, 0, 0, 0, 0,                    /* SubCompatibleId*/                                           \
    WBVAL(132),                                /* wLength */                                                  \
    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   /* wDescriptorType */                                          \
    WBVAL(WINUSB_PROP_DATA_TYPE_REG_SZ),       /* wPropertyDataType */                                        \
    WBVAL(42),                                 /* wPropertyNameLength bPropertyName: "DeviceInterfaceGUID" */ \
    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,                                                           \
    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,                                   \
    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,                                                             \
    WBVAL(80), /* wPropertyDataLength */                                                                      \
    '{', 0,                                                                                                   \
    'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,                                   \
    '2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,                                                                   \
    '4', 0, '6', 0, '6', 0, '3', 0, '-', 0,                                                                   \
    'A', 0, 'A', 0, '3', 0, '6', 0, '-',                                                                      \
    0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,        \
    '}', 0, 0, 0, 0, 0

#define USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_SINGLE_DESCRIPTOR_LEN \
    (WINUSB_FEATURE_COMPATIBLE_ID_SIZE + 132)

#define USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_MULTI_DESCRIPTOR_INIT(bFirstInterfaceNumber)                       \
    WBVAL(WINUSB_FUNCTION_SUBSET_HEADER_SIZE), /* wLength */                                                  \
    WBVAL(WINUSB_SUBSET_HEADER_FUNCTION_TYPE), /* wDescriptorType */                                          \
    bFirstInterfaceNumber,                     /* bFirstInterface*/                                           \
    0,                                         /* bReserved */                                                \
    WBVAL((WINUSB_FUNCTION_SUBSET_HEADER_SIZE + WINUSB_FEATURE_COMPATIBLE_ID_SIZE + 132)), /* wSubsetLength */\
    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_SIZE),  /* wLength */                                                  \
    WBVAL(WINUSB_FEATURE_COMPATIBLE_ID_TYPE),  /* wDescriptorType */                                          \
    'W', 'I', 'N', 'U', 'S', 'B', 0, 0,        /* CompatibleId*/                                              \
    0, 0, 0, 0, 0, 0, 0, 0,                    /* SubCompatibleId*/                                           \
    WBVAL(132),                                /* wLength */                                                  \
    WBVAL(WINUSB_FEATURE_REG_PROPERTY_TYPE),   /* wDescriptorType */                                          \
    WBVAL(WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ), /* wPropertyDataType */                                        \
    WBVAL(42),                                 /* wPropertyNameLength bPropertyName: "DeviceInterfaceGUID" */ \
    'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,                                                           \
    'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,                                   \
    'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,                                                             \
    WBVAL(80), /* wPropertyDataLength */                                                                      \
    '{', 0,                                                                                                   \
    'C', 0, 'D', 0, 'B', 0, '3', 0, 'B', 0, '5', 0, 'A', 0, 'D', 0, '-', 0,                                   \
    '2', 0, '9', 0, '3', 0, 'B', 0, '-', 0,                                                                   \
    '4', 0, '6', 0, '6', 0, '3', 0, '-', 0,                                                                   \
    'A', 0, 'A', 0, '3', 0, '6', 0, '-',                                                                      \
    0, '1', 0, 'A', 0, 'A', 0, 'E', 0, '4', 0, '6', 0, '4', 0, '6', 0, '3', 0, '7', 0, '7', 0, '6', 0,        \
    '}', 0, 0, 0, 0, 0

#define USB_MSOSV2_COMP_ID_FUNCTION_WINUSB_MULTI_DESCRIPTOR_LEN \
    (WINUSB_FUNCTION_SUBSET_HEADER_SIZE + WINUSB_FEATURE_COMPATIBLE_ID_SIZE + 132)

// clang-format on

#endif /* USB_DEF_H */