Skip to content

Commit

Permalink
Add WCID mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
dzarda committed Sep 28, 2021
1 parent 2d8ae1c commit 605879c
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 1 deletion.
5 changes: 5 additions & 0 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@
#ifndef DFU_APP_SIZE
#define DFU_APP_SIZE _AUTO
#endif
/* Microsoft WCID allows automatic driver (WinUSB) installation on device
* connection. Use _ENABLE to make your device likeable by Windows. */
#ifndef DFU_WCID
#define DFU_WCID _DISABLE
#endif
/* Cipher to use. set _DISABLE or choose from implemented ciphers */
#ifndef DFU_CIPHER
#define DFU_CIPHER DFU_CIPHER_RC5
Expand Down
3 changes: 3 additions & 0 deletions inc/descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

usbd_respond dfu_get_descriptor(usbd_ctlreq *req, void **address, uint16_t *len);

#if (DFU_WCID != _DISABLE)
usbd_respond dfu_get_vendor_descriptor(usbd_ctlreq *req, void**address, uint16_t *len);
#endif

#if defined (__cplusplus)
}
Expand Down
41 changes: 41 additions & 0 deletions inc/usb_msft.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef _USB_MSFT_H_
#define _USB_MSFT_H_
#if defined(__cplusplus)
extern "C" {
#endif

#include <stdint.h>

/* Microsoft OS 1.0 descriptors */

/* Extended Compat ID OS Feature Descriptor Specification */
#define USB_MSFT_REQ_GET_COMPAT_ID_FEATURE_DESCRIPTOR 0x04

/* Table 2. Function Section */
struct usb_msft_compat_id_func_section {
uint8_t bInterfaceNumber;
uint8_t reserved0[1];
const char compatibleId[8];
const char subCompatibleId[8];
uint8_t reserved1[6];
} __attribute__((packed));

#define USB_MSFT_COMPAT_ID_FUNCTION_SECTION_SIZE 24

/* Table 1. Header Section */
struct usb_msft_compat_id_desc {
uint32_t dwLength;
uint16_t bcdVersion;
uint16_t wIndex;
uint8_t bNumSections;
uint8_t reserved[7];
struct usb_msft_compat_id_func_section functions[];
} __attribute__((packed));

#define USB_MSFT_COMPAT_ID_HEADER_SIZE 16

#if defined(__cplusplus)
}
#endif

#endif /* _USB_MSFT_H_ */
16 changes: 15 additions & 1 deletion src/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "bootloader.h"
#include "config.h"
#include "stm32.h"
#include "usb.h"
Expand All @@ -25,7 +26,7 @@
#include "crypto.h"

/* Checking for the EEPROM */
#if defined(DATA_EEPROM_BASE)
#if defined(DATA_EEPROM_BASE) && defined(DATA_EEPROM_END)
#define _EE_START DATA_EEPROM_BASE
#define _EE_LENGTH (DATA_EEPROM_END - DATA_EEPROM_BASE + 1)
#elif defined(FLASH_EEPROM_BASE)
Expand Down Expand Up @@ -272,6 +273,11 @@ static usbd_respond dfu_control (usbd_device *dev, usbd_ctlreq *req, usbd_rqc_ca
}
return dfu_err_badreq();
}
#if (DFU_WCID != _DISABLE)
if ((req->bmRequestType & USB_REQ_TYPE) == USB_REQ_VENDOR) {
return dfu_get_vendor_descriptor(req, &dev->status.data_ptr, &dev->status.data_count);
}
#endif
return usbd_fail;
}

Expand Down Expand Up @@ -301,9 +307,17 @@ static void dfu_init (void) {
usbd_connect(&dfu, 1);
}

void __attribute__ ((weak)) user_init() {
}

void __attribute__ ((weak)) user_poll() {
}

int main (void) {
dfu_init();
user_init();
while(1) {
usbd_poll(&dfu);
user_poll();
}
}
45 changes: 45 additions & 0 deletions src/descriptors.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "config.h"
#include "usb.h"
#include "usb_dfu.h"
#include "usb_msft.h"

/* Checking for the EEPROM */
#if (defined(DATA_EEPROM_BASE) || defined(FLASH_EEPROM_BASE)) && (DFU_INTF_EEPROM != _DISABLE)
Expand Down Expand Up @@ -136,6 +137,7 @@ static const struct usb_string_descriptor dfu_flash_sdesc = USB_STRING_DESC(DF
#if (_EEPROM_IDX != NO_DESCRIPTOR)
static const struct usb_string_descriptor dfu_eeprom_sdesc = USB_STRING_DESC(DFU_STR_EEPROM);
#endif

static const struct usb_string_descriptor * const dtable[] = {
&dfu_lang_sdesc,
&dfu_manuf_sdesc,
Expand All @@ -151,6 +153,32 @@ static const struct usb_string_descriptor * const dtable[] = {
#endif
};

#if (DFU_WCID != _DISABLE)
static const struct usb_string_descriptor dfu_msft_sdesc = {
.bLength = 18,
.bDescriptorType = USB_DTYPE_STRING,
.wString = u"MSFT100\x00\x00"
};

static const struct usb_msft_compat_id_desc dfu_msft_compat_id_desc = {
.dwLength = (USB_MSFT_COMPAT_ID_HEADER_SIZE +
1*USB_MSFT_COMPAT_ID_FUNCTION_SECTION_SIZE),
.bcdVersion = 0x0100,
.wIndex = 0x0004,
.bNumSections = 1,
.reserved = { 0, 0, 0, 0, 0, 0, 0 },
.functions = {
{
.bInterfaceNumber = 0,
.reserved0 = { 1 },
.compatibleId = "WINUSB",
.subCompatibleId = "",
.reserved1 = { 0, 0, 0, 0, 0, 0}
},
}
};
#endif

usbd_respond dfu_get_descriptor(usbd_ctlreq *req, void **address, uint16_t *len) {
const uint8_t dtype = req->wValue >> 8;
const uint8_t dindx = req->wValue & 0xFF;
Expand All @@ -169,6 +197,10 @@ usbd_respond dfu_get_descriptor(usbd_ctlreq *req, void **address, uint16_t *len)
case USB_DTYPE_STRING:
if (dindx < _countof(dtable)) {
desc = dtable[dindx];
#if (DFU_WCID != _DISABLE)
} else if (dindx == 0xEE) {
desc = &dfu_msft_sdesc;
#endif
} else {
return usbd_fail;
}
Expand All @@ -181,3 +213,16 @@ usbd_respond dfu_get_descriptor(usbd_ctlreq *req, void **address, uint16_t *len)
*address = (void*)desc;
return usbd_ack;
}

#if (DFU_WCID != _DISABLE)
usbd_respond dfu_get_vendor_descriptor(usbd_ctlreq *req, void**address, uint16_t *len) {
if ((req->bmRequestType & USB_REQ_RECIPIENT) == USB_REQ_DEVICE) {
if (req->wIndex == USB_MSFT_REQ_GET_COMPAT_ID_FEATURE_DESCRIPTOR) {
*len = dfu_msft_compat_id_desc.dwLength;
*address = (struct usb_msft_compat_id_desc*)&dfu_msft_compat_id_desc;
return usbd_ack;
}
}
return usbd_fail;
}
#endif

0 comments on commit 605879c

Please sign in to comment.