From e055d4cfc9df1a41585ac83d484b903088f3db13 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 13 Mar 2024 17:24:10 +0100 Subject: [PATCH] Added support for WebCCID. Signed-off-by: Pol Henarejos --- src/apdu.c | 18 ++-- src/usb/ccid/ccid.c | 206 ++++++++++++++++++++------------------ src/usb/tusb_config.h | 2 +- src/usb/usb.c | 32 +++--- src/usb/usb.h | 17 ++-- src/usb/usb_descriptors.c | 147 +++++++++++++++++++++++++-- 6 files changed, 280 insertions(+), 142 deletions(-) diff --git a/src/apdu.c b/src/apdu.c index 4efc0f1..fe2961a 100644 --- a/src/apdu.c +++ b/src/apdu.c @@ -111,8 +111,8 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - driver_exec_finished_cont_ccid(apdu.rlen + 2, rdata_gr - usb_get_tx(itf)); + if (itf == ITF_CCID || itf == ITF_WCID) { + driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - usb_get_tx(itf)); } #endif #else @@ -140,8 +140,8 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - driver_exec_finished_cont_ccid(apdu.ne + 2, rdata_gr - apdu.ne - usb_get_tx(itf)); + if (itf == ITF_CCID || itf == ITF_WCID) { + driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - usb_get_tx(itf)); } #endif #else @@ -173,7 +173,6 @@ void apdu_thread() { card_init_core1(); while (1) { uint32_t m = 0; - int proc = 0; queue_remove_blocking(&usb_to_card_q, &m); if (m == EV_VERIFY_CMD_AVAILABLE || m == EV_MODIFY_CMD_AVAILABLE) { @@ -184,12 +183,11 @@ void apdu_thread() { break; } - proc = process_apdu(); + process_apdu(); done: ; - if (proc == 1) { - apdu_finish(); - } + apdu_finish(); + finished_data_size = apdu_next(); uint32_t flag = EV_EXEC_FINISHED; queue_add_blocking(&card_to_usb_q, &flag); @@ -205,7 +203,7 @@ done: ; void apdu_finish() { apdu.rdata[apdu.rlen] = apdu.sw >> 8; apdu.rdata[apdu.rlen + 1] = apdu.sw & 0xff; - //timeout_stop(); + // timeout_stop(); #ifndef ENABLE_EMULATION if ((apdu.rlen + 2 + 10) % 64 == 0) { // FIX for strange behaviour with PSCS and multiple of 64 apdu.ne = apdu.rlen - 2; diff --git a/src/usb/ccid/ccid.c b/src/usb/ccid/ccid.c index 1416ae6..ebf4445 100644 --- a/src/usb/ccid/ccid.c +++ b/src/usb/ccid/ccid.c @@ -103,107 +103,107 @@ uint8_t ccid_status = 1; static uint8_t itf_num; extern tusb_desc_endpoint_t const desc_ep3; -void ccid_write_offset(uint16_t size, uint16_t offset) { - if (*usb_get_tx(ITF_CCID) + offset != 0x81) { - DEBUG_PAYLOAD(usb_get_tx(ITF_CCID) + offset, size + 10); +void ccid_write_offset(uint8_t itf, uint16_t size, uint16_t offset) { + if (*usb_get_tx(itf) + offset != 0x81) { + DEBUG_PAYLOAD(usb_get_tx(itf) + offset, size + 10); } - usb_write_offset(ITF_CCID, size + 10, offset); + usb_write_offset(itf, size + 10, offset); } -void ccid_write(uint16_t size) { - ccid_write_offset(size, 0); +void ccid_write(uint8_t itf, uint16_t size) { + ccid_write_offset(itf, size, 0); } -struct ccid_header *ccid_response; -struct ccid_header *ccid_header; +struct ccid_header *ccid_response[ITF_TOTAL]; +struct ccid_header *ccid_header[ITF_TOTAL]; -int driver_init_ccid() { - ccid_header = (struct ccid_header *) usb_get_rx(ITF_CCID); +int driver_init_ccid(uint8_t itf) { + ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf); // apdu.header = &ccid_header->apdu; - ccid_response = (struct ccid_header *) usb_get_tx(ITF_CCID); + ccid_response[itf] = (struct ccid_header *) usb_get_tx(itf); - usb_set_timeout_counter(ITF_CCID, 1500); + usb_set_timeout_counter(itf, 1500); return CCID_OK; } void tud_vendor_rx_cb(uint8_t itf) { - (void) itf; - - uint32_t len = tud_vendor_available(); - usb_rx(ITF_CCID, NULL, len); + uint32_t len = tud_vendor_n_available(itf); + usb_rx(itf, NULL, len); } void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) { //printf("written %ld\n", sent_bytes); - usb_write_flush(ITF_CCID); + usb_write_flush(itf); } -int driver_write_ccid(const uint8_t *buffer, uint16_t buffer_size) { - int r = tud_vendor_write(buffer, buffer_size); +int driver_write_ccid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) { + int r = tud_vendor_n_write(itf, buffer, buffer_size); if (r > 0) { - return MAX(tud_vendor_flush(), r); + return MAX(tud_vendor_n_flush(itf), r); } return r; } -uint16_t driver_read_ccid(uint8_t *buffer, uint16_t buffer_size) { - return tud_vendor_read(buffer, buffer_size); +uint16_t driver_read_ccid(uint8_t itf, uint8_t *buffer, uint16_t buffer_size) { + return tud_vendor_n_read(itf, buffer, buffer_size); } int driver_process_usb_nopacket_ccid() { return 0; } -int driver_process_usb_packet_ccid(uint16_t rx_read) { +int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) { if (rx_read >= 10) { - driver_init_ccid(); - //printf("%d %d %x\r\n",tccid->dwLength,rx_read-10,tccid->bMessageType); - if (ccid_header->dwLength <= rx_read - 10) { + driver_init_ccid(itf); + //printf("%ld %d %x %x\r\n",ccid_header->dwLength,rx_read-10,ccid_header->bMessageType,ccid_header->bSeq); + if (ccid_header[itf]->dwLength <= rx_read - 10) { size_t apdu_sent = 0; - if (ccid_header->bMessageType != CCID_SLOT_STATUS) { - DEBUG_PAYLOAD(usb_get_rx(ITF_CCID), usb_read_available(ITF_CCID)); + if (ccid_header[itf]->bMessageType != CCID_SLOT_STATUS) { + DEBUG_PAYLOAD(usb_get_rx(itf), usb_read_available(itf)); } - if (ccid_header->bMessageType == CCID_SLOT_STATUS) { - ccid_response->bMessageType = CCID_SLOT_STATUS_RET; - ccid_response->dwLength = 0; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = ccid_status; - ccid_response->abRFU1 = 0; - ccid_write(0); + if (ccid_header[itf]->bMessageType == CCID_SLOT_STATUS) { + ccid_response[itf]->bMessageType = CCID_SLOT_STATUS_RET; + ccid_response[itf]->dwLength = 0; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = ccid_status; + ccid_response[itf]->abRFU1 = 0; + ccid_write(itf, 0); } - else if (ccid_header->bMessageType == CCID_POWER_ON) { + else if (ccid_header[itf]->bMessageType == CCID_POWER_ON) { size_t size_atr = (ccid_atr ? ccid_atr[0] : 0); - ccid_response->bMessageType = CCID_DATA_BLOCK_RET; - ccid_response->dwLength = size_atr; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = 0; - ccid_response->abRFU1 = 0; + ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_response[itf]->dwLength = size_atr; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = 0; + ccid_response[itf]->abRFU1 = 0; //printf("1 %x %x %x || %x %x %x\r\n",ccid_response->apdu,apdu.rdata,ccid_response,ccid_header,ccid_header->apdu,apdu.data); - memcpy(&ccid_response->apdu, ccid_atr + 1, size_atr); - card_start(apdu_thread); + memcpy(&ccid_response[itf]->apdu, ccid_atr + 1, size_atr); + if (ccid_status == 1) { + card_start(apdu_thread); + } ccid_status = 0; - ccid_write(size_atr); + ccid_write(itf, size_atr); } - else if (ccid_header->bMessageType == CCID_POWER_OFF) { + else if (ccid_header[itf]->bMessageType == CCID_POWER_OFF) { if (ccid_status == 0) { card_exit(0); } ccid_status = 1; - ccid_response->bMessageType = CCID_SLOT_STATUS_RET; - ccid_response->dwLength = 0; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = ccid_status; - ccid_response->abRFU1 = 0; - ccid_write(0); + ccid_response[itf]->bMessageType = CCID_SLOT_STATUS_RET; + ccid_response[itf]->dwLength = 0; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = ccid_status; + ccid_response[itf]->abRFU1 = 0; + ccid_write(itf, 0); } - else if (ccid_header->bMessageType == CCID_SET_PARAMS || - ccid_header->bMessageType == CCID_GET_PARAMS || - ccid_header->bMessageType == CCID_RESET_PARAMS) { + else if (ccid_header[itf]->bMessageType == CCID_SET_PARAMS || + ccid_header[itf]->bMessageType == CCID_GET_PARAMS || + ccid_header[itf]->bMessageType == CCID_RESET_PARAMS) { /* Values from gnuk. Not specified in ICCD spec. */ const uint8_t params[] = { 0x11, /* bmFindexDindex */ @@ -214,65 +214,71 @@ int driver_process_usb_packet_ccid(uint16_t rx_read) { 0xFE, /* bIFSC */ 0 /* bNadValue */ }; - ccid_response->bMessageType = CCID_PARAMS_RET; - ccid_response->dwLength = sizeof(params); - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = ccid_status; - ccid_response->abRFU1 = 0x0100; - memcpy(&ccid_response->apdu, params, sizeof(params)); - ccid_write(sizeof(params)); + ccid_response[itf]->bMessageType = CCID_PARAMS_RET; + ccid_response[itf]->dwLength = sizeof(params); + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = ccid_status; + ccid_response[itf]->abRFU1 = 0x0100; + memcpy(&ccid_response[itf]->apdu, params, sizeof(params)); + ccid_write(itf, sizeof(params)); } - else if (ccid_header->bMessageType == CCID_XFR_BLOCK) { - apdu_sent = apdu_process(ITF_CCID, &ccid_header->apdu, ccid_header->dwLength); + else if (ccid_header[itf]->bMessageType == CCID_XFR_BLOCK) { + apdu_sent = apdu_process(itf, &ccid_header[itf]->apdu, ccid_header[itf]->dwLength); } - usb_clear_rx(ITF_CCID); + usb_clear_rx(itf); return apdu_sent; } } return 0; } -bool driver_mounted_ccid() { - return tud_vendor_mounted(); +bool driver_mounted_ccid(uint8_t itf) { + return tud_vendor_n_mounted(itf); } -void driver_exec_timeout_ccid() { - ccid_response->bMessageType = CCID_DATA_BLOCK_RET; - ccid_response->dwLength = 0; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = CCID_CMD_STATUS_TIMEEXT; - ccid_response->abRFU1 = 0; - ccid_write(0); +void driver_exec_timeout_ccid(uint8_t itf) { + ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf); + ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf)); + printf("CCUD_RESPONSE [itf=%d] %p %p\n", itf, ccid_response[itf], usb_get_tx(itf)); + ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_response[itf]->dwLength = 0; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = CCID_CMD_STATUS_TIMEEXT; + ccid_response[itf]->abRFU1 = 0; + ccid_write(itf, 0); } -void driver_exec_finished_ccid(uint16_t size_next) { - ccid_response->bMessageType = CCID_DATA_BLOCK_RET; - ccid_response->dwLength = size_next; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = ccid_status; - ccid_response->abRFU1 = 0; - ccid_write(size_next); +void driver_exec_finished_ccid(uint8_t itf, uint16_t size_next) { + ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf); + ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + 34); + ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_response[itf]->dwLength = size_next; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = ccid_status; + ccid_response[itf]->abRFU1 = 0; + ccid_write_offset(itf, size_next, 34); } -void driver_exec_finished_cont_ccid(uint16_t size_next, uint16_t offset) { - - ccid_response = (struct ccid_header *) (usb_get_tx(ITF_CCID) + offset - 10); - ccid_response->bMessageType = CCID_DATA_BLOCK_RET; - ccid_response->dwLength = size_next; - ccid_response->bSlot = 0; - ccid_response->bSeq = ccid_header->bSeq; - ccid_response->abRFU0 = ccid_status; - ccid_response->abRFU1 = 0; - ccid_write_offset(size_next, offset - 10); +void driver_exec_finished_cont_ccid(uint8_t itf, uint16_t size_next, uint16_t offset) { + ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf); + ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + offset - 10 + 34); + ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_response[itf]->dwLength = size_next; + ccid_response[itf]->bSlot = 0; + ccid_response[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_response[itf]->abRFU0 = ccid_status; + ccid_response[itf]->abRFU1 = 0; + ccid_write_offset(itf, size_next, offset - 10 + 34); } -uint8_t *driver_prepare_response_ccid() { - ccid_response = (struct ccid_header *) usb_get_tx(ITF_CCID); - apdu.rdata = &ccid_response->apdu; - return &ccid_response->apdu; +uint8_t *driver_prepare_response_ccid(uint8_t itf) { + ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + 34); + apdu.rdata = &ccid_response[itf]->apdu; + apdu.rlen = 0; + return &ccid_response[itf]->apdu; } #define USB_CONFIG_ATT_ONE TU_BIT(7) diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h index b256d25..64f419c 100644 --- a/src/usb/tusb_config.h +++ b/src/usb/tusb_config.h @@ -113,7 +113,7 @@ extern "C" { #endif #define CFG_TUD_MIDI 0 #ifdef USB_ITF_CCID -#define CFG_TUD_VENDOR 1 +#define CFG_TUD_VENDOR 2 #else #define CFG_TUD_VENDOR 0 #endif diff --git a/src/usb/usb.c b/src/usb/usb.c index 6b8ab3e..94155ed 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -60,8 +60,8 @@ uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset) { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - w = driver_write_ccid(tx_buffer[itf] + offset, MIN(len, pkt_max)); + if (itf == ITF_CCID || itf == ITF_WCID) { + w = driver_write_ccid(itf, tx_buffer[itf] + offset, MIN(len, pkt_max)); } #endif #else @@ -83,8 +83,8 @@ uint16_t usb_rx(uint8_t itf, const uint8_t *buffer, uint16_t len) { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - size = (uint16_t)driver_read_ccid(rx_buffer[itf] + w_offset[itf], size); + if (itf == ITF_CCID || itf == ITF_WCID) { + size = (uint16_t)driver_read_ccid(itf, rx_buffer[itf] + w_offset[itf], size); } #endif } @@ -107,8 +107,8 @@ uint32_t usb_write_flush(uint8_t itf) { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - w = driver_write_ccid(tx_buffer[itf] + tx_r_offset[itf], MIN(w_len[itf], 64)); + if (itf == ITF_CCID || itf == ITF_WCID) { + w = driver_write_ccid(itf, tx_buffer[itf] + tx_r_offset[itf], MIN(w_len[itf], 64)); } #endif #else @@ -182,8 +182,8 @@ static int usb_event_handle(uint8_t itf) { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - proc_packet = driver_process_usb_packet_ccid(rx_read); + if (itf == ITF_CCID || itf == ITF_WCID) { + proc_packet = driver_process_usb_packet_ccid(itf, rx_read); } #endif #else @@ -267,8 +267,8 @@ void usb_task() { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - mounted = driver_mounted_ccid(); + if (itf == ITF_CCID || itf == ITF_WCID) { + mounted = driver_mounted_ccid(itf); } #endif #endif @@ -293,8 +293,8 @@ void usb_task() { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - driver_exec_finished_ccid(finished_data_size); + if (itf == ITF_CCID || itf == ITF_WCID) { + driver_exec_finished_ccid(itf, finished_data_size); } #endif led_set_blink(BLINK_MOUNTED); @@ -314,8 +314,8 @@ void usb_task() { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - driver_exec_timeout_ccid(); + if (itf == ITF_CCID || itf == ITF_WCID) { + driver_exec_timeout_ccid(itf); } #endif timeout = board_millis(); @@ -342,8 +342,8 @@ uint8_t *usb_prepare_response(uint8_t itf) { } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID) { - return driver_prepare_response_ccid(); + if (itf == ITF_CCID || itf == ITF_WCID) { + return driver_prepare_response_ccid(itf); } #endif return NULL; diff --git a/src/usb/usb.h b/src/usb/usb.h index fd95180..8872468 100644 --- a/src/usb/usb.h +++ b/src/usb/usb.h @@ -48,6 +48,7 @@ enum { #endif #ifdef USB_ITF_CCID ITF_CCID, + ITF_WCID, #endif ITF_TOTAL }; @@ -77,14 +78,14 @@ extern int driver_process_usb_nopacket_hid(); #endif #ifdef USB_ITF_CCID -extern int driver_process_usb_packet_ccid(uint16_t rx_read); -extern void driver_exec_finished_ccid(uint16_t size_next); -extern void driver_exec_finished_cont_ccid(uint16_t size_next, uint16_t offset); -extern void driver_exec_timeout_ccid(); -extern bool driver_mounted_ccid(); -extern uint8_t *driver_prepare_response_ccid(); -extern int driver_write_ccid(const uint8_t *, uint16_t); -extern uint16_t driver_read_ccid(uint8_t *, uint16_t); +extern int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read); +extern void driver_exec_finished_ccid(uint8_t itf, uint16_t size_next); +extern void driver_exec_finished_cont_ccid(uint8_t itf, uint16_t size_next, uint16_t offset); +extern void driver_exec_timeout_ccid(uint8_t itf); +extern bool driver_mounted_ccid(uint8_t itf); +extern uint8_t *driver_prepare_response_ccid(uint8_t itf); +extern int driver_write_ccid(uint8_t, const uint8_t *, uint16_t); +extern uint16_t driver_read_ccid(uint8_t, uint8_t *, uint16_t); extern int driver_process_usb_nopacket_ccid(); #endif diff --git a/src/usb/usb_descriptors.c b/src/usb/usb_descriptors.c index 074c967..0d01607 100644 --- a/src/usb/usb_descriptors.c +++ b/src/usb/usb_descriptors.c @@ -28,7 +28,7 @@ #define USB_PID 0xFCFD #endif -#define USB_BCD 0x0200 +#define USB_BCD 0x0210 #define USB_CONFIG_ATT_ONE TU_BIT(7) @@ -73,8 +73,10 @@ tusb_desc_configuration_t const desc_config = { .bDescriptorType = TUSB_DESC_CONFIGURATION, .wTotalLength = (sizeof(tusb_desc_configuration_t) #ifdef USB_ITF_CCID - + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + - 3 * sizeof(tusb_desc_endpoint_t) + + (sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + + 3 * sizeof(tusb_desc_endpoint_t)) + + (sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + + 2 * sizeof(tusb_desc_endpoint_t)) #endif #ifdef USB_ITF_HID + TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN @@ -127,6 +129,18 @@ tusb_desc_interface_t const desc_interface = { .iInterface = ITF_CCID + 5, }; +tusb_desc_interface_t const desc_interface_wcid = { + .bLength = sizeof(tusb_desc_interface_t), + .bDescriptorType = TUSB_DESC_INTERFACE, + .bInterfaceNumber = ITF_WCID, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = 0xFF, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = ITF_WCID + 5, +}; + tusb_desc_endpoint_t const desc_ep1 = { .bLength = sizeof(tusb_desc_endpoint_t), .bDescriptorType = TUSB_DESC_ENDPOINT, @@ -153,13 +167,33 @@ tusb_desc_endpoint_t const desc_ep3 = { .wMaxPacketSize = (64), .bInterval = 0 }; + +tusb_desc_endpoint_t const desc_ep1_wcid = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = (TUSB_DIR_IN_MASK | 1) + 3, + .bmAttributes.xfer = TUSB_XFER_BULK, + .wMaxPacketSize = (64), + .bInterval = 0 +}; + +tusb_desc_endpoint_t const desc_ep2_wcid = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 1 + 3, + .bmAttributes.xfer = TUSB_XFER_BULK, + .wMaxPacketSize = (64), + .bInterval = 0 +}; #endif static uint8_t desc_config_extended[sizeof(tusb_desc_configuration_t) #ifdef USB_ITF_CCID - + sizeof(tusb_desc_interface_t) + + + (sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 3 * - sizeof(tusb_desc_endpoint_t) + sizeof(tusb_desc_endpoint_t)) + + (sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + + 2 * sizeof(tusb_desc_endpoint_t)) #endif #ifdef USB_ITF_HID + TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN @@ -224,22 +258,120 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { memcpy(p, &desc_ep1, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); memcpy(p, &desc_ep2, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); memcpy(p, &desc_ep3, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); + + memcpy(p, &desc_interface_wcid, sizeof(tusb_desc_interface_t)); + p += sizeof(tusb_desc_interface_t); + memcpy(p, &desc_ccid, sizeof(struct ccid_class_descriptor)); + p += sizeof(struct ccid_class_descriptor); + memcpy(p, &desc_ep1_wcid, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); + memcpy(p, &desc_ep2_wcid, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t); #endif initd = 1; } return (const uint8_t *) desc_config_extended; } -#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN) +#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 + + +enum +{ + VENDOR_REQUEST_WEBUSB = 1, + VENDOR_REQUEST_MICROSOFT = 2 +}; +#define URL "picokeys.com/pki/" +static bool web_serial_connected = false; + +const tusb_desc_webusb_url_t desc_url = +{ + .bLength = 3 + sizeof(URL) - 1, + .bDescriptorType = 3, // WEBUSB URL type + .bScheme = 1, // 0: http, 1: https + .url = 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[] = { + // 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), + + // Configuration subset header: length, type, configuration index, reserved, configuration total length + 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), + + // 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible + + // MS OS 2.0 Registry property descriptor: length, type + U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), + U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16 + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, + 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, + U16_TO_U8S_LE(0x0050), // wPropertyDataLength + //bPropertyData: “{975F44D9-0D08-43FD-8B3E-127CA8AFFF9D}”. + '{', 0x00, '9', 0x00, '7', 0x00, '5', 0x00, 'F', 0x00, '4', 0x00, '4', 0x00, 'D', 0x00, '9', 0x00, '-', 0x00, + '0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00, + '8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00, + '8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 +}; +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) + return true; + + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_VENDOR: + switch (request->bRequest) { + case VENDOR_REQUEST_WEBUSB: + return tud_control_xfer(rhport, request, (void*)(uintptr_t) &desc_url, desc_url.bLength); + + case VENDOR_REQUEST_MICROSOFT: + if (request->wIndex == 7) { + // Get Microsoft OS 2.0 compatible descriptor + uint16_t total_len; + memcpy(&total_len, desc_ms_os_20+8, 2); + return tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_ms_os_20, total_len); + } + else { + return false; + } + default: + break; + } + break; + + case TUSB_REQ_TYPE_CLASS: + if (request->bRequest == 0x22) { + web_serial_connected = (request->wValue != 0); + if (web_serial_connected) { + printf("\r\nWebUSB interface connected\r\n"); + } + return tud_control_status(rhport, request); + } + break; + default: + break; + } + // stall unknown request + return false; +} uint8_t const desc_bos[] = { // total length, number of device caps - TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2) + TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2), + // Vendor Code, iLandingPage + TUD_BOS_WEBUSB_DESCRIPTOR(VENDOR_REQUEST_WEBUSB, 1), + // Microsoft OS 2.0 descriptor + TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, VENDOR_REQUEST_MICROSOFT) }; uint8_t const *tud_descriptor_bos_cb(void) { + printf("!!!!!!!!!!!! tud_descriptor_bos_cb\n"); return desc_bos; } @@ -260,6 +392,7 @@ char const *string_desc_arr [] = { #endif #ifdef USB_ITF_CCID , "Pico Key CCID Interface" + , "Pico Key WebCCID Interface" #endif };