From f1b1382300937549fea1e93bffa07aa6b7c7e7c0 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Fri, 21 Mar 2025 15:30:50 +0100 Subject: [PATCH] USB descriptors are now created dynamically. Signed-off-by: Pol Henarejos --- src/usb/ccid/ccid.c | 30 ++++++++++++++--- src/usb/hid/hid.c | 21 ++++++++++-- src/usb/usb.c | 57 ++++++++++++++++++++++++++++++-- src/usb/usb.h | 28 ++++------------ src/usb/usb_descriptors.c | 68 +++++++++++++++++++++++++++++---------- 5 files changed, 157 insertions(+), 47 deletions(-) diff --git a/src/usb/ccid/ccid.c b/src/usb/ccid/ccid.c index b4f46a4..372e1b8 100644 --- a/src/usb/ccid/ccid.c +++ b/src/usb/ccid/ccid.c @@ -94,7 +94,7 @@ uint8_t ccid_status = 1; static uint8_t itf_num; #endif -static usb_buffer_t ccid_rx[ITF_SC_TOTAL] = {0}, ccid_tx[ITF_SC_TOTAL] = {0}; +static usb_buffer_t *ccid_rx = NULL, *ccid_tx = NULL; int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read); @@ -107,9 +107,9 @@ void ccid_write(uint8_t itf, uint16_t size) { ccid_write_offset(itf, size, 0); } -ccid_header_t *ccid_response[ITF_SC_TOTAL]; -ccid_header_t *ccid_resp_fast[ITF_SC_TOTAL]; -ccid_header_t *ccid_header[ITF_SC_TOTAL]; +ccid_header_t **ccid_response = NULL; +ccid_header_t **ccid_resp_fast = NULL; +ccid_header_t **ccid_header = NULL; uint8_t sc_itf_to_usb_itf(uint8_t itf) { if (itf == ITF_SC_CCID) { @@ -121,6 +121,24 @@ uint8_t sc_itf_to_usb_itf(uint8_t itf) { return itf; } +void ccid_init_buffers() { + if (ccid_rx == NULL) { + ccid_rx = (usb_buffer_t *)calloc(ITF_SC_TOTAL, sizeof(usb_buffer_t)); + } + if (ccid_tx == NULL) { + ccid_tx = (usb_buffer_t *)calloc(ITF_SC_TOTAL, sizeof(usb_buffer_t)); + } + if (ccid_header == NULL) { + ccid_header = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *)); + } + if (ccid_response == NULL) { + ccid_response = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *)); + } + if (ccid_resp_fast == NULL) { + ccid_resp_fast = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *)); + } +} + int driver_init_ccid(uint8_t itf) { ccid_header[itf] = (ccid_header_t *) (ccid_rx[itf].buffer + ccid_rx[itf].r_ptr); ccid_resp_fast[itf] = (ccid_header_t *) (ccid_tx[itf].buffer + sizeof(ccid_tx[itf].buffer) - 64); @@ -334,6 +352,10 @@ void ccid_task() { #define MAX_USB_POWER 1 +void ccid_init() { + ccid_init_buffers(); +} + static void ccid_init_cb(void) { vendord_init(); } diff --git a/src/usb/hid/hid.c b/src/usb/hid/hid.c index e3e88f2..ad93013 100644 --- a/src/usb/hid/hid.c +++ b/src/usb/hid/hid.c @@ -37,7 +37,7 @@ bool is_nitrokey = false; uint8_t (*get_version_major)() = NULL; uint8_t (*get_version_minor)() = NULL; -static usb_buffer_t hid_rx[ITF_HID_TOTAL] = {0}, hid_tx[ITF_HID_TOTAL] = {0}; +static usb_buffer_t *hid_rx = NULL, *hid_tx = NULL; PACK( typedef struct msg_packet { @@ -56,8 +56,8 @@ bool driver_mounted_hid() { return mounted; } -static uint16_t send_buffer_size[ITF_HID_TOTAL] = {0}; -static write_status_t last_write_result[ITF_HID_TOTAL] = {0}; +static uint16_t *send_buffer_size = NULL; +static write_status_t *last_write_result = NULL; CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL; void send_keepalive(); @@ -65,6 +65,21 @@ int driver_process_usb_packet_hid(uint16_t read); int driver_write_hid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size); int driver_process_usb_nopacket_hid(); +void hid_init() { + if (send_buffer_size == NULL) { + send_buffer_size = (uint16_t *)calloc(ITF_HID_TOTAL, sizeof(uint16_t)); + } + if (last_write_result == NULL) { + last_write_result = (write_status_t *)calloc(ITF_HID_TOTAL, sizeof(write_status_t)); + } + if (hid_rx == NULL) { + hid_rx = (usb_buffer_t *)calloc(ITF_HID_TOTAL, sizeof(usb_buffer_t)); + } + if (hid_tx == NULL) { + hid_tx = (usb_buffer_t *)calloc(ITF_HID_TOTAL, sizeof(usb_buffer_t)); + } +} + int driver_init_hid() { #ifndef ENABLE_EMULATION static bool _init = false; diff --git a/src/usb/usb.c b/src/usb/usb.c index 86d9fb1..bfebca8 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -37,13 +37,28 @@ #include // Device specific functions -static uint32_t timeout_counter[ITF_TOTAL] = { 0 }; -static uint8_t card_locked_itf = ITF_TOTAL; // no locked +static uint32_t *timeout_counter = NULL; +static uint8_t card_locked_itf = 0; // no locked static void (*card_locked_func)(void) = NULL; #ifndef ENABLE_EMULATION static mutex_t mutex; #endif +#ifdef USB_ITF_HID + uint8_t ITF_HID_CTAP = 0, ITF_HID_KB = 0; + uint8_t ITF_HID = 0, ITF_KEYBOARD = 0; + uint8_t ITF_HID_TOTAL = 0; + extern void hid_init(); +#endif + +#ifdef USB_ITF_CCID + uint8_t ITF_SC_CCID = 0, ITF_SC_WCID = 0; + uint8_t ITF_CCID = 0, ITF_WCID = 0; + uint8_t ITF_SC_TOTAL = 0; + extern void ccid_init(); +#endif +uint8_t ITF_TOTAL = 0; + void usb_set_timeout_counter(uint8_t itf, uint32_t v) { timeout_counter[itf] = v; } @@ -64,6 +79,44 @@ void usb_init() { #endif queue_init(&card_to_usb_q, sizeof(uint32_t), 64); queue_init(&usb_to_card_q, sizeof(uint32_t), 64); + +#ifdef USB_ITF_HID + ITF_HID_TOTAL = 0; +#endif +#ifdef USB_ITF_CCID + ITF_SC_TOTAL = 0; +#endif + ITF_TOTAL = 0; +#ifdef USB_ITF_HID + if (1) { + ITF_HID_CTAP = ITF_HID_TOTAL++; + ITF_HID = ITF_TOTAL++; + } + if (1) { + ITF_HID_KB = ITF_HID_TOTAL++; + ITF_KEYBOARD = ITF_TOTAL++; + } +#endif +#ifdef USB_ITF_CCID + if (1) { + ITF_SC_CCID = ITF_SC_TOTAL++; + ITF_CCID = ITF_TOTAL++; + } + if (1) { + ITF_SC_WCID = ITF_SC_TOTAL++; + ITF_WCID = ITF_TOTAL++; + } +#endif + card_locked_itf = ITF_TOTAL; + if (timeout_counter == NULL) { + timeout_counter = (uint32_t *)calloc(ITF_TOTAL, sizeof(uint32_t)); + } +#ifdef USB_ITF_HID + hid_init(); +#endif +#ifdef USB_ITF_CCID + ccid_init(); +#endif } uint32_t timeout = 0; diff --git a/src/usb/usb.h b/src/usb/usb.h index d63dad5..545f674 100644 --- a/src/usb/usb.h +++ b/src/usb/usb.h @@ -44,32 +44,18 @@ #define EV_BUTTON_TIMEOUT 16 #define EV_BUTTON_PRESSED 32 -enum { #ifdef USB_ITF_HID - ITF_HID_CTAP = 0, - ITF_HID_KB, + extern uint8_t ITF_HID_CTAP, ITF_HID_KB; + extern uint8_t ITF_HID, ITF_KEYBOARD; + extern uint8_t ITF_HID_TOTAL; #endif - ITF_HID_TOTAL -}; -enum { -#ifdef USB_ITF_CCID - ITF_SC_CCID = 0, - ITF_SC_WCID, -#endif - ITF_SC_TOTAL -}; -enum { -#ifdef USB_ITF_HID - ITF_HID = ITF_HID_CTAP, - ITF_KEYBOARD = ITF_HID_KB, -#endif #ifdef USB_ITF_CCID - ITF_CCID = ITF_SC_CCID + ITF_HID_TOTAL, - ITF_WCID = ITF_SC_WCID + ITF_HID_TOTAL, + extern uint8_t ITF_SC_CCID, ITF_SC_WCID; + extern uint8_t ITF_CCID, ITF_WCID; + extern uint8_t ITF_SC_TOTAL; #endif - ITF_TOTAL = ITF_HID_TOTAL + ITF_SC_TOTAL -}; +extern uint8_t ITF_TOTAL; enum { REPORT_ID_KEYBOARD = 0, diff --git a/src/usb/usb_descriptors.c b/src/usb/usb_descriptors.c index 48a5328..d28b66a 100644 --- a/src/usb/usb_descriptors.c +++ b/src/usb/usb_descriptors.c @@ -81,16 +81,16 @@ uint8_t const *tud_descriptor_device_cb(void) { #define TUSB_SMARTCARD_CCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_SMARTCARD_LEN + TUSB_SMARTCARD_CCID_EPS * TUD_ENDPOINT_DESC_LEN) #define TUSB_SMARTCARD_WCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_WSMARTCARD_LEN + 2 * TUD_ENDPOINT_DESC_LEN) +uint16_t TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN; enum { - TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + MAX_TUSB_DESC_TOTAL_LEN = (TUD_CONFIG_DESC_LEN #ifdef USB_ITF_HID - + TUD_HID_INOUT_DESC_LEN - + TUD_HID_DESC_LEN + + TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN #endif #ifdef USB_ITF_CCID - + TUSB_SMARTCARD_CCID_DESC_LEN - + TUSB_SMARTCARD_WCID_DESC_LEN + + TUSB_SMARTCARD_CCID_DESC_LEN + TUSB_SMARTCARD_WCID_DESC_LEN #endif +) }; #ifdef USB_ITF_HID @@ -124,16 +124,8 @@ uint8_t const desc_hid_report_kb[] = { #endif #endif -const uint8_t desc_config[] = { - TUD_CONFIG_DESCRIPTOR(1, ITF_TOTAL, 4, TUSB_DESC_TOTAL_LEN, USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, MAX_USB_POWER), -#ifdef USB_ITF_HID - TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, TUSB_DIR_IN_MASK | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10), - TUD_HID_DESCRIPTOR(ITF_KEYBOARD, ITF_KEYBOARD + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report_kb), TUSB_DIR_IN_MASK | (EPNUM_HID + 1), 16, 5), -#endif -#ifdef USB_ITF_CCID - TUD_SMARTCARD_DESCRIPTOR(ITF_CCID, ITF_CCID+5, 1, TUSB_DIR_IN_MASK | 1, TUSB_DIR_IN_MASK | 2, 64), - TUD_SMARTCARD_DESCRIPTOR_WEB(ITF_WCID, ITF_WCID+5, 3, TUSB_DIR_IN_MASK | 3, 64), -#endif +uint8_t desc_config[MAX_TUSB_DESC_TOTAL_LEN] = { + TUD_CONFIG_DESCRIPTOR(1, 0, 4, 0, USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, MAX_USB_POWER) }; #ifdef USB_ITF_HID @@ -151,6 +143,47 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) { #ifndef ESP_PLATFORM uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations + desc_config[4] = ITF_TOTAL; + TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN; + uint8_t *p = desc_config + TUD_CONFIG_DESC_LEN; +#ifdef USB_ITF_HID + if (1) { + TUSB_DESC_TOTAL_LEN += TUD_HID_INOUT_DESC_LEN; + const uint8_t desc[] = { TUD_HID_INOUT_DESCRIPTOR(0, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, TUSB_DIR_IN_MASK | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) }; + memcpy(p, desc, sizeof(desc)); + p[2] = ITF_HID; + p[8] = ITF_HID + 5; + p += sizeof(desc); + } + if (1) { + TUSB_DESC_TOTAL_LEN += TUD_HID_DESC_LEN; + const uint8_t desc_kb[] = { TUD_HID_DESCRIPTOR(ITF_KEYBOARD, ITF_KEYBOARD + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report_kb), TUSB_DIR_IN_MASK | (EPNUM_HID + 1), 16, 5) }; + memcpy(p, desc_kb, sizeof(desc_kb)); + p[2] = ITF_KEYBOARD; + p[8] = ITF_KEYBOARD + 5; + p += sizeof(desc_kb); + } +#endif +#ifdef USB_ITF_CCID + if (1) { + TUSB_DESC_TOTAL_LEN += TUSB_SMARTCARD_CCID_DESC_LEN; + const uint8_t desc_ccid[] = { TUD_SMARTCARD_DESCRIPTOR(ITF_CCID, ITF_CCID+5, 1, TUSB_DIR_IN_MASK | 1, TUSB_DIR_IN_MASK | 2, 64) }; + memcpy(p, desc_ccid, sizeof(desc_ccid)); + p[2] = ITF_CCID; + p[8] = ITF_CCID + 5; + p += sizeof(desc_ccid); + } + if (1) { + TUSB_DESC_TOTAL_LEN += TUSB_SMARTCARD_WCID_DESC_LEN; + const uint8_t desc_wcid[] = { TUD_SMARTCARD_DESCRIPTOR_WEB(ITF_WCID, ITF_WCID+5, 3, TUSB_DIR_IN_MASK | 3, 64) }; + memcpy(p, desc_wcid, sizeof(desc_wcid)); + p[2] = ITF_WCID; + p[8] = ITF_WCID + 5; + p += sizeof(desc_wcid); + } +#endif + desc_config[2] = TUSB_DESC_TOTAL_LEN & 0xFF; + desc_config[3] = TUSB_DESC_TOTAL_LEN >> 8; return desc_config; } #endif @@ -176,7 +209,7 @@ const tusb_desc_webusb_url_t desc_url = #define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN) #define MS_OS_20_DESC_LEN 0xB2 -uint8_t const desc_ms_os_20[] = { +uint8_t desc_ms_os_20[] = { // Set header: length, type, windows version, total length U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN), @@ -184,7 +217,7 @@ uint8_t const desc_ms_os_20[] = { U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A), // Function Subset header: length, type, first interface, reserved, subset length - U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_WCID, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08), + U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), 0/*ITF_WCID*/, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08), // MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, @@ -217,6 +250,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ if (request->wIndex == 7) { // Get Microsoft OS 2.0 compatible descriptor uint16_t total_len; + desc_ms_os_20[22] = ITF_WCID; memcpy(&total_len, desc_ms_os_20+8, 2); return tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_ms_os_20, total_len); }