summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xports/stm32/mboot/Makefile1
-rw-r--r--ports/stm32/mboot/main.c68
2 files changed, 64 insertions, 5 deletions
diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile
index 7be5cca69d..389f9f5d0f 100755
--- a/ports/stm32/mboot/Makefile
+++ b/ports/stm32/mboot/Makefile
@@ -76,6 +76,7 @@ CFLAGS += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1
CFLAGS += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -DLFS2_READONLY
CFLAGS += -DBUILDING_MBOOT=$(BUILDING_MBOOT)
CFLAGS += -DMICROPY_HW_STM32WB_FLASH_SYNCRONISATION=0
+CFLAGS += -DUSBD_ENABLE_VENDOR_DEVICE_REQUESTS=1
CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID)
MBOOT_LD_FILES ?= stm32_memory.ld stm32_sections.ld
diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c
index ed5ed1e3ff..d034996afb 100644
--- a/ports/stm32/mboot/main.c
+++ b/ports/stm32/mboot/main.c
@@ -1002,6 +1002,18 @@ typedef struct _pyb_usbdd_obj_t {
#define MBOOT_USB_PID BOOTLOADER_DFU_USB_PID
#endif
+// Special string descriptor value for Microsoft WCID support.
+// If the USB device responds to this string with the correct data (see msft100_str_desc)
+// then the Windows host will request further information about the configuration of
+// the device (see msft100_id). This allows the device to set a Windows USB driver.
+// For more details about WCID see:
+// - https://github.com/pbatard/libwdi/wiki/WCID-Devices
+// - https://github.com/newaetech/naeusb/blob/main/wcid.md
+#define MSFT_WCID_STR_DESC_VALUE (0xee)
+
+// Vendor code, can be anything.
+#define MSFT100_VENDOR_CODE (0x42)
+
#if !MICROPY_HW_USB_IS_MULTI_OTG
STATIC const uint8_t usbd_fifo_size[USBD_PMA_NUM_FIFO] = {
32, 32, // EP0(out), EP0(in)
@@ -1026,14 +1038,14 @@ __ALIGN_BEGIN static const uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __AL
static const uint8_t dev_descr[0x12] = {
0x12, // bLength
0x01, // bDescriptorType: Device
- 0x00, 0x01, // USB version: 1.00
+ 0x00, 0x02, // USB version: 2.00
0x00, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
0x40, // bMaxPacketSize
LOBYTE(MBOOT_USB_VID), HIBYTE(MBOOT_USB_VID),
LOBYTE(MBOOT_USB_PID), HIBYTE(MBOOT_USB_PID),
- 0x00, 0x22, // bcdDevice: 22.00
+ 0x00, 0x03, // bcdDevice: 3.00
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
@@ -1047,6 +1059,32 @@ static uint8_t cfg_descr[9 + 9 + 9] =
"\x09\x21\x0b\xff\x00\x00\x08\x1a\x01" // \x00\x08 goes with USB_XFER_SIZE
;
+__ALIGN_BEGIN static const uint8_t msft100_str_desc[18] __ALIGN_END = {
+ 0x12, 0x03,
+ 'M', 0x00,
+ 'S', 0x00,
+ 'F', 0x00,
+ 'T', 0x00,
+ '1', 0x00,
+ '0', 0x00,
+ '0', 0x00,
+ MSFT100_VENDOR_CODE,
+ 0x00,
+};
+
+__ALIGN_BEGIN static const uint8_t msft100_id[40] __ALIGN_END = {
+ 0x28, 0x00, 0x00, 0x00,
+ 0x00, 0x01, // 1.00
+ 0x04, 0x00,
+ 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ 0x01,
+ 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
static uint8_t *pyb_usbdd_DeviceDescriptor(USBD_HandleTypeDef *pdev, uint16_t *length) {
*length = USB_LEN_DEV_DESC;
return (uint8_t *)dev_descr;
@@ -1131,6 +1169,10 @@ static uint8_t *pyb_usbdd_StrDescriptor(USBD_HandleTypeDef *pdev, uint8_t idx, u
return str_desc;
#endif
+ case MSFT_WCID_STR_DESC_VALUE:
+ *length = sizeof(msft100_str_desc);
+ return (uint8_t *)msft100_str_desc; // the data should only be read from this buf
+
default:
return NULL;
}
@@ -1159,8 +1201,24 @@ static uint8_t pyb_usbdd_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *r
self->bRequest = req->bRequest;
self->wValue = req->wValue;
self->wLength = req->wLength;
- if (req->bmRequest == 0x21) {
- // host-to-device request
+
+ if ((req->bmRequest & 0xe0) == 0xc0) {
+ // device-to-host vendor request
+ if (req->wIndex == 0x04 && req->bRequest == MSFT100_VENDOR_CODE) {
+ // WCID: Compatible ID Feature Descriptor
+ #if USE_USB_POLLING
+ self->tx_pending = true;
+ #endif
+ int len = MIN(req->wLength, 40);
+ memcpy(self->tx_buf, msft100_id, len);
+ USBD_CtlSendData(&self->hUSBDDevice, self->tx_buf, len);
+ return USBD_OK;
+ } else {
+ USBD_CtlError(pdev, req);
+ return USBD_OK;
+ }
+ } else if (req->bmRequest == 0x21) {
+ // host-to-device class request
if (req->wLength == 0) {
// no data, process command straight away
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
USBD_CtlPrepareRx(pdev, self->rx_buf, req->wLength);
}
} else if (req->bmRequest == 0xa1) {
- // device-to-host request
+ // device-to-host class request
int len = dfu_handle_tx(self->bRequest, self->wValue, self->wLength, self->tx_buf, USB_XFER_SIZE);
if (len >= 0) {
#if USE_USB_POLLING