usb: Allow registration of a single non-contiguous string descriptor for WinUSB

Classic WinUSB support is detected by probing for a string descriptor
at index 0xEE with a special string.
usbd_register_extra_string() allows registration of a string at this
index without having to provide 237 other string descriptors

Originally filed as https://github.com/libopencm3/libopencm3/pull/849

WCID reference: https://github.com/pbatard/libwdi/wiki/WCID-Devices
This commit is contained in:
Devan Lai 2020-10-17 17:12:20 +00:00 committed by Karl Palsson
parent ffe8ddfca2
commit c13c2b3b3c
4 changed files with 38 additions and 1 deletions

View File

@ -165,6 +165,9 @@ extern int usbd_register_set_config_callback(usbd_device *usbd_dev,
extern void usbd_register_set_altsetting_callback(usbd_device *usbd_dev,
usbd_set_altsetting_callback callback);
/** Registers a non-contiguous string descriptor */
extern void usbd_register_extra_string(usbd_device *usbd_dev, int index, const char* string);
/* Functions to be provided by the hardware abstraction layer */
extern void usbd_poll(usbd_device *usbd_dev);

View File

@ -54,6 +54,8 @@ usbd_device *usbd_init(const usbd_driver *driver,
usbd_dev->config = conf;
usbd_dev->strings = strings;
usbd_dev->num_strings = num_strings;
usbd_dev->extra_string_idx = 0;
usbd_dev->extra_string = NULL;
usbd_dev->ctrl_buf = control_buffer;
usbd_dev->ctrl_buf_len = control_buffer_size;
@ -94,6 +96,20 @@ void usbd_register_sof_callback(usbd_device *usbd_dev, void (*callback)(void))
usbd_dev->user_callback_sof = callback;
}
void usbd_register_extra_string(usbd_device *usbd_dev, int index, const char* string)
{
/*
* Note: string index 0 is reserved for LANGID requests and cannot
* be overwritten using this functionality.
*/
if (string != NULL && index > 0) {
usbd_dev->extra_string_idx = index;
usbd_dev->extra_string = string;
} else {
usbd_dev->extra_string_idx = 0;
}
}
void _usbd_reset(usbd_device *usbd_dev)
{
usbd_dev->current_address = 0;

View File

@ -92,6 +92,10 @@ struct _usbd_device {
const struct _usbd_driver *driver;
/* Extra, non-contiguous user string descriptor index and value */
int extra_string_idx;
const char* extra_string;
/* private driver data */
uint16_t fifo_mem_top;

View File

@ -179,7 +179,21 @@ usb_standard_get_descriptor(usbd_device *usbd_dev,
sizeof(sd->wData[0]);
*len = MIN(*len, sd->bLength);
} else {
} else if (descr_idx == usbd_dev->extra_string_idx) {
/* This string is returned as UTF16, hence the
* multiplication
*/
sd->bLength = strlen(usbd_dev->extra_string) * 2 +
sizeof(sd->bLength) +
sizeof(sd->bDescriptorType);
*len = MIN(*len, sd->bLength);
for (i = 0; i < (*len / 2) - 1; i++) {
sd->wData[i] =
usbd_dev->extra_string[i];
}
} else {
array_idx = descr_idx - 1;
if (!usbd_dev->strings) {