@@ -1002,6 +1002,18 @@ typedef struct _pyb_usbdd_obj_t {
10021002#define MBOOT_USB_PID BOOTLOADER_DFU_USB_PID
10031003#endif
10041004
1005+ // Special string descriptor value for Microsoft WCID support.
1006+ // If the USB device responds to this string with the correct data (see msft100_str_desc)
1007+ // then the Windows host will request further information about the configuration of
1008+ // the device (see msft100_id). This allows the device to set a Windows USB driver.
1009+ // For more details about WCID see:
1010+ // - https://github.com/pbatard/libwdi/wiki/WCID-Devices
1011+ // - https://github.com/newaetech/naeusb/blob/main/wcid.md
1012+ #define MSFT_WCID_STR_DESC_VALUE (0xee)
1013+
1014+ // Vendor code, can be anything.
1015+ #define MSFT100_VENDOR_CODE (0x42)
1016+
10051017#if !MICROPY_HW_USB_IS_MULTI_OTG
10061018STATIC const uint8_t usbd_fifo_size [USBD_PMA_NUM_FIFO ] = {
10071019 32 , 32 , // EP0(out), EP0(in)
@@ -1026,14 +1038,14 @@ __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __AL
10261038static const uint8_t dev_descr [0x12 ] = {
10271039 0x12 , // bLength
10281040 0x01 , // bDescriptorType: Device
1029- 0x00 , 0x01 , // USB version: 1 .00
1041+ 0x00 , 0x02 , // USB version: 2 .00
10301042 0x00 , // bDeviceClass
10311043 0x00 , // bDeviceSubClass
10321044 0x00 , // bDeviceProtocol
10331045 0x40 , // bMaxPacketSize
10341046 LOBYTE (MBOOT_USB_VID ), HIBYTE (MBOOT_USB_VID ),
10351047 LOBYTE (MBOOT_USB_PID ), HIBYTE (MBOOT_USB_PID ),
1036- 0x00 , 0x22 , // bcdDevice: 22 .00
1048+ 0x00 , 0x03 , // bcdDevice: 3 .00
10371049 0x01 , // iManufacturer
10381050 0x02 , // iProduct
10391051 0x03 , // iSerialNumber
@@ -1047,6 +1059,32 @@ static uint8_t cfg_descr[9 + 9 + 9] =
10471059 "\x09\x21\x0b\xff\x00\x00\x08\x1a\x01" // \x00\x08 goes with USB_XFER_SIZE
10481060;
10491061
1062+ __ALIGN_BEGIN static const uint8_t msft100_str_desc [18 ] __ALIGN_END = {
1063+ 0x12 , 0x03 ,
1064+ 'M' , 0x00 ,
1065+ 'S' , 0x00 ,
1066+ 'F' , 0x00 ,
1067+ 'T' , 0x00 ,
1068+ '1' , 0x00 ,
1069+ '0' , 0x00 ,
1070+ '0' , 0x00 ,
1071+ MSFT100_VENDOR_CODE ,
1072+ 0x00 ,
1073+ };
1074+
1075+ __ALIGN_BEGIN static const uint8_t msft100_id [40 ] __ALIGN_END = {
1076+ 0x28 , 0x00 , 0x00 , 0x00 ,
1077+ 0x00 , 0x01 , // 1.00
1078+ 0x04 , 0x00 ,
1079+ 0x01 ,
1080+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
1081+ 0x00 ,
1082+ 0x01 ,
1083+ 'W' , 'I' , 'N' , 'U' , 'S' , 'B' , 0x00 , 0x00 ,
1084+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
1085+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
1086+ };
1087+
10501088static uint8_t * pyb_usbdd_DeviceDescriptor (USBD_HandleTypeDef * pdev , uint16_t * length ) {
10511089 * length = USB_LEN_DEV_DESC ;
10521090 return (uint8_t * )dev_descr ;
@@ -1131,6 +1169,10 @@ static uint8_t *pyb_usbdd_StrDescriptor(USBD_HandleTypeDef *pdev, uint8_t idx, u
11311169 return str_desc ;
11321170 #endif
11331171
1172+ case MSFT_WCID_STR_DESC_VALUE :
1173+ * length = sizeof (msft100_str_desc );
1174+ return (uint8_t * )msft100_str_desc ; // the data should only be read from this buf
1175+
11341176 default :
11351177 return NULL ;
11361178 }
@@ -1159,8 +1201,24 @@ static uint8_t pyb_usbdd_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *r
11591201 self -> bRequest = req -> bRequest ;
11601202 self -> wValue = req -> wValue ;
11611203 self -> wLength = req -> wLength ;
1162- if (req -> bmRequest == 0x21 ) {
1163- // host-to-device request
1204+
1205+ if ((req -> bmRequest & 0xe0 ) == 0xc0 ) {
1206+ // device-to-host vendor request
1207+ if (req -> wIndex == 0x04 && req -> bRequest == MSFT100_VENDOR_CODE ) {
1208+ // WCID: Compatible ID Feature Descriptor
1209+ #if USE_USB_POLLING
1210+ self -> tx_pending = true;
1211+ #endif
1212+ int len = MIN (req -> wLength , 40 );
1213+ memcpy (self -> tx_buf , msft100_id , len );
1214+ USBD_CtlSendData (& self -> hUSBDDevice , self -> tx_buf , len );
1215+ return USBD_OK ;
1216+ } else {
1217+ USBD_CtlError (pdev , req );
1218+ return USBD_OK ;
1219+ }
1220+ } else if (req -> bmRequest == 0x21 ) {
1221+ // host-to-device class request
11641222 if (req -> wLength == 0 ) {
11651223 // no data, process command straight away
11661224 dfu_handle_rx (self -> bRequest , self -> wValue , 0 , NULL );
@@ -1169,7 +1227,7 @@ static uint8_t pyb_usbdd_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *r
11691227 USBD_CtlPrepareRx (pdev , self -> rx_buf , req -> wLength );
11701228 }
11711229 } else if (req -> bmRequest == 0xa1 ) {
1172- // device-to-host request
1230+ // device-to-host class request
11731231 int len = dfu_handle_tx (self -> bRequest , self -> wValue , self -> wLength , self -> tx_buf , USB_XFER_SIZE );
11741232 if (len >= 0 ) {
11751233 #if USE_USB_POLLING
0 commit comments