Skip to content

Commit

Permalink
Merge pull request dmitrystu#40 from dzarda/wcid
Browse files Browse the repository at this point in the history
Add WCID mechanism
  • Loading branch information
dmitrystu authored Sep 29, 2021
2 parents 2d8ae1c + e1ac8d5 commit fc74c3b
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 2 deletions.
9 changes: 7 additions & 2 deletions CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ You can find configuration parameters in the following tables. Defaults marked *
|DFU_BOOTSTRAP_PULL | Bootstrap pin pullup control | _DISABLE/**_AUTO**/_LOW/_HIGH | |
|DFU_DBLRESET_MS | Doublereset activation time (ms) | TIMEOUT/_DISABLE | **300** |
|DFU_APP_START | Start address for user code | ROM ADDRESS/**_AUTO** | must be page aligned |
|DFU_APP_SIZE | User application max size | AMMOUNT/**_AUTO** | up to the ROM end |
|DFU_APP_SIZE | User application max size | AMOUNT/**_AUTO** | up to the ROM end |
|DFU_WCID | Enables Microsoft OS Descriptors | _ENABLE/**_DISABLE** | Aut. Win. driver assign.|
|DFU_CIPHER | Type of ciper | See Table 3 | **DFU_CIPHER_RC5** |
|DFU_CIPHER_MODE | Cipher mode of operation | See Table 4 | **DFU_CIPHER_CBC** |
|DFU_AES_KEY_128 | 128-bit cipher key | Comma separated bytes | |
Expand Down Expand Up @@ -92,4 +93,8 @@ You can find configuration parameters in the following tables. Defaults marked *
|DFU_CIPHER_PCBC | Propagating Cipher Block Chaining (PCBC) |
|DFU_CIPHER_CFB | Cipher Feedback (CFB) |
|DFU_CIPHER_OFB | Output Feedback (OFB) |
|DFU_CIPHER_CTR | Counter (CTR) (simply IV increment) |
|DFU_CIPHER_CTR | Counter (CTR) (simply IV increment) |


### WCID
DFU_WCID can be enabled to obtain a Microsoft-defined mechanism called WCID which is used by Windows to automatically assign a USB driver upon device connection. You probably want this as it enhances Windows user experience massively. See https://github.com/pbatard/libwdi/wiki/WCID-Devices
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_ */
5 changes: 5 additions & 0 deletions src/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,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
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 fc74c3b

Please sign in to comment.