From fa6292118d32990be0bcfc8cb60bbbecaa99b57a Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Fri, 23 Aug 2024 10:02:19 +0200 Subject: [PATCH] Major refactor of USB CCID and USB HID interfaces. All interfaces are rewritten. With this new scheme we ensure that: - memcpy's are reduced. - no race conditions are performed. - critical areas are protected. - callbacks are executed immediately. - write's are executed after the positive report is received. - no usb middle interface anymore. - CCID and HID are totally independent. Signed-off-by: Pol Henarejos --- src/apdu.c | 23 ++- src/apdu.h | 4 +- src/esp_compat.h | 8 +- src/main.c | 24 +-- src/pico_keys.h | 3 - src/usb/ccid/ccid.c | 248 +++++++++++++++++------------ src/usb/hid/ctap_hid.h | 12 +- src/usb/hid/hid.c | 219 ++++++++++++++------------ src/usb/usb.c | 349 +++++++++-------------------------------- src/usb/usb.h | 106 ++++++------- 10 files changed, 420 insertions(+), 576 deletions(-) diff --git a/src/apdu.c b/src/apdu.c index c38fa0d..9c1dda5 100644 --- a/src/apdu.c +++ b/src/apdu.c @@ -118,22 +118,22 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) if (apdu.rlen <= apdu.ne) { #ifndef ENABLE_EMULATION #ifdef USB_ITF_HID - if (itf == ITF_HID) { - driver_exec_finished_cont_hid(itf, apdu.rlen + 2, rdata_gr - (usb_get_tx(itf))); + if (itf == ITF_HID_CTAP) { + driver_exec_finished_cont_hid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata); } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - (usb_get_tx(itf) + 34)); + if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) { + driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata); } #endif #else - driver_exec_finished_cont_emul(itf, apdu.rlen + 2, (uint16_t)(rdata_gr - (usb_get_tx(itf)))); + driver_exec_finished_cont_emul(itf, apdu.rlen + 2, (uint16_t)(rdata_gr - apdu.rdata)); #endif //Prepare next RAPDU apdu.sw = 0; apdu.rlen = 0; - usb_prepare_response(itf); + rdata_gr = apdu.rdata; } else { rdata_gr += apdu.ne; @@ -147,17 +147,17 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) } #ifndef ENABLE_EMULATION #ifdef USB_ITF_HID - if (itf == ITF_HID) { - driver_exec_finished_cont_hid(itf, apdu.ne + 2, rdata_gr - apdu.ne - (usb_get_tx(itf))); + if (itf == ITF_HID_CTAP) { + driver_exec_finished_cont_hid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata); } #endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - (usb_get_tx(itf) + 34)); + if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) { + driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata); } #endif #else - driver_exec_finished_cont_emul(itf, (uint16_t)(apdu.ne + 2), (uint16_t)(rdata_gr - apdu.ne - (usb_get_tx(itf)))); + driver_exec_finished_cont_emul(itf, (uint16_t)(apdu.ne + 2), (uint16_t)(rdata_gr - apdu.ne - apdu.rdata)); #endif apdu.rlen -= (uint16_t)apdu.ne; } @@ -165,7 +165,6 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) else { apdu.sw = 0; apdu.rlen = 0; - apdu.rdata = usb_prepare_response(itf); rdata_gr = apdu.rdata; return 1; } diff --git a/src/apdu.h b/src/apdu.h index ab141a9..89c04b5 100644 --- a/src/apdu.h +++ b/src/apdu.h @@ -29,11 +29,11 @@ typedef struct app { const uint8_t *aid; int (*process_apdu)(); - int (*select_aid)(struct app *); + int (*select_aid)(struct app *, uint8_t); int (*unload)(); } app_t; -extern int register_app(int (*)(app_t *), const uint8_t *); +extern int register_app(int (*)(app_t *, uint8_t), const uint8_t *); extern int select_app(const uint8_t *aid, size_t aid_len); typedef struct cmd { diff --git a/src/esp_compat.h b/src/esp_compat.h index 3966f72..0379c13 100644 --- a/src/esp_compat.h +++ b/src/esp_compat.h @@ -30,7 +30,7 @@ typedef QueueHandle_t queue_t; #define queue_is_empty(a) (uxQueueMessagesWaiting(*(a)) == 0) #define queue_try_remove(a,b) xQueueReceive(*(a), b, 0) extern TaskHandle_t hcore0, hcore1; -#define multicore_launch_core1(a) xTaskCreate((void(*)(void *))a, "core1", 4096*ITF_TOTAL, NULL, CONFIG_TINYUSB_TASK_PRIORITY + 2, &hcore1) +#define multicore_launch_core1(a) xTaskCreatePinnedToCore((void(*)(void *))a, "core1", 4096*5, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 2, &hcore1, 1) #define multicore_reset_core1() do { if (hcore1) { eTaskState e = eTaskGetState(hcore1); if (e <= eSuspended) { vTaskDelete(hcore1); }} }while(0) #define sleep_ms(a) vTaskDelay(a / portTICK_PERIOD_MS) static inline uint32_t board_millis(void) { @@ -46,10 +46,8 @@ typedef SemaphoreHandle_t semaphore_t; #define sem_release(a) xSemaphoreGive(*(a)) #define sem_acquire_blocking(a) xSemaphoreTake(*(a), portMAX_DELAY) #define multicore_lockout_victim_init() (void)0 -static inline bool multicore_lockout_start_timeout_us(int a) { - vTaskSuspend(hcore1); return true; } -static inline bool multicore_lockout_end_timeout_us(int a) { - vTaskResume(hcore1); return true; } +static inline bool multicore_lockout_start_timeout_us(int a) { if (hcore1) { vTaskSuspend(hcore1); } return true; } +static inline bool multicore_lockout_end_timeout_us(int a) { if (hcore1) { vTaskResume(hcore1); } return true; } #endif diff --git a/src/main.c b/src/main.c index 8147c92..1ac1a3f 100644 --- a/src/main.c +++ b/src/main.c @@ -104,7 +104,7 @@ app_t *current_app = NULL; const uint8_t *ccid_atr = NULL; -int register_app(int (*select_aid)(app_t *), const uint8_t *aid) { +int register_app(int (*select_aid)(app_t *, uint8_t), const uint8_t *aid) { if (num_apps < sizeof(apps) / sizeof(app_t)) { apps[num_apps].select_aid = select_aid; apps[num_apps].aid = aid; @@ -116,13 +116,14 @@ int register_app(int (*select_aid)(app_t *), const uint8_t *aid) { int select_app(const uint8_t *aid, size_t aid_len) { if (current_app && current_app->aid && (current_app->aid + 1 == aid || !memcmp(current_app->aid + 1, aid, aid_len))) { + current_app->select_aid(current_app, 0); return CCID_OK; } for (int a = 0; a < num_apps; a++) { if (!memcmp(apps[a].aid + 1, aid, MIN(aid_len, apps[a].aid[0]))) { if (current_app) { if (current_app->aid && !memcmp(current_app->aid + 1, aid, aid_len)) { - current_app->select_aid(current_app); + current_app->select_aid(current_app, 1); return CCID_OK; } if (current_app->unload) { @@ -130,7 +131,7 @@ int select_app(const uint8_t *aid, size_t aid_len) { } } current_app = &apps[a]; - if (current_app->select_aid(current_app) == CCID_OK) { + if (current_app->select_aid(current_app, 1) == CCID_OK) { return CCID_OK; } } @@ -146,19 +147,6 @@ void led_set_blink(uint32_t mode) { blink_interval_ms = mode; } -uint32_t timeout = 0; -void timeout_stop() { - timeout = 0; -} - -void timeout_start() { - timeout = board_millis(); -} - -bool is_busy() { - return timeout > 0; -} - void execute_tasks(); static bool req_button_pending = false; @@ -344,10 +332,10 @@ extern void neug_task(); extern void usb_task(); void execute_tasks() { - usb_task(); #if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM) tud_task(); // tinyusb device task #endif + usb_task(); led_blinking_task(); } @@ -464,7 +452,7 @@ int main(void) { #endif #ifdef ESP_PLATFORM - xTaskCreate(core0_loop, "core0", 4096*ITF_TOTAL, NULL, CONFIG_TINYUSB_TASK_PRIORITY + 1, &hcore0); + xTaskCreatePinnedToCore(core0_loop, "core0", 4096*5, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 1, &hcore0, 0); #else core0_loop(); #endif diff --git a/src/pico_keys.h b/src/pico_keys.h index 8f5675f..458af2e 100644 --- a/src/pico_keys.h +++ b/src/pico_keys.h @@ -75,9 +75,6 @@ static inline void put_uint16_t(uint16_t n, uint8_t *b) { extern void low_flash_available(); extern int flash_clear_file(file_t *file); -extern void timeout_stop(); -extern void timeout_start(); - extern int (*button_pressed_cb)(uint8_t); enum { diff --git a/src/usb/ccid/ccid.c b/src/usb/ccid/ccid.c index 8f6d6fc..d3ab2a5 100644 --- a/src/usb/ccid/ccid.c +++ b/src/usb/ccid/ccid.c @@ -20,6 +20,11 @@ #if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM) #include "hardware/rtc.h" #endif +#ifndef ESP_PLATFORM +#include "bsp/board.h" +#else +static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED; +#endif #include "tusb.h" #include "ccid.h" #include "device/usbd_pvt.h" @@ -72,7 +77,7 @@ #define CCID_THREAD_TERMINATED 0xffff #define CCID_ACK_TIMEOUT 0x6600 -struct ccid_header { +typedef struct { uint8_t bMessageType; uint32_t dwLength; uint8_t bSlot; @@ -80,119 +85,159 @@ struct ccid_header { uint8_t abRFU0; uint16_t abRFU1; uint8_t apdu; //Actually it is an array -} __attribute__((__packed__)); +} __attribute__((__packed__)) ccid_header_t; uint8_t ccid_status = 1; static uint8_t itf_num; +static usb_buffer_t ccid_rx[ITF_SC_TOTAL] = {0}, ccid_tx[ITF_SC_TOTAL] = {0}; +static write_status_t last_write_result[ITF_SC_TOTAL] = {0}; + +int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read); + 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, size + 10, offset); + ccid_tx[itf].w_ptr += size + offset; + ccid_tx[itf].r_ptr += offset; } void ccid_write(uint8_t itf, uint16_t size) { ccid_write_offset(itf, size, 0); } -struct ccid_header *ccid_response[ITF_TOTAL]; -struct ccid_header *ccid_header[ITF_TOTAL]; +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_last[ITF_SC_TOTAL]; + +uint8_t sc_itf_to_usb_itf(uint8_t itf) { + if (itf == ITF_SC_CCID) { + return ITF_CCID; + } + else if (itf == ITF_SC_WCID) { + return ITF_WCID; + } + return itf; +} int driver_init_ccid(uint8_t itf) { - ccid_header[itf] = (struct ccid_header *) usb_get_rx(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); // apdu.header = &ccid_header->apdu; - ccid_response[itf] = (struct ccid_header *) usb_get_tx(itf); + ccid_response[itf] = (ccid_header_t *) (ccid_tx[itf].buffer + ccid_tx[itf].w_ptr); - usb_set_timeout_counter(itf, 1500); + usb_set_timeout_counter(sc_itf_to_usb_itf(itf), 1500); + + //ccid_tx[itf].w_ptr = ccid_tx[itf].r_ptr = 0; return CCID_OK; } void tud_vendor_rx_cb(uint8_t itf) { uint32_t len = tud_vendor_n_available(itf); -#ifdef USB_ITF_HID - itf += 2; -#endif - usb_rx(itf, NULL, len); + do { + uint16_t tlen = 0; + if (len > 0xFFFF) { + tlen = 0xFFFF; + } + else { + tlen = len; + } + tlen = tud_vendor_n_read(itf, ccid_rx[itf].buffer + ccid_rx[itf].w_ptr, tlen); + ccid_rx[itf].w_ptr += tlen; + driver_process_usb_packet_ccid(itf, tlen); + len -= tlen; + } while (len > 0); } void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) { -#ifdef USB_ITF_HID - itf += 2; + if (sent_bytes) { +#ifdef ESP_PLATFORM + taskENTER_CRITICAL(&mutex); #endif - usb_write_flush(itf); + if (last_write_result[itf] == WRITE_PENDING) { + last_write_result[itf] = WRITE_SUCCESS; + ccid_header_t *lresp = &ccid_response_last[itf]; + if (lresp->bMessageType != CCID_DATA_BLOCK_RET || lresp->dwLength != 0 || lresp->bSlot != 0 || lresp->abRFU0 != CCID_CMD_STATUS_TIMEEXT) { + ccid_tx[itf].r_ptr += sent_bytes; + } + } + if (ccid_tx[itf].r_ptr >= ccid_tx[itf].w_ptr) { + ccid_tx[itf].r_ptr = ccid_tx[itf].w_ptr = 0; + } +#ifdef ESP_PLATFORM + taskEXIT_CRITICAL(&mutex); +#endif + } } -int driver_write_ccid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) { -#ifdef USB_ITF_HID - itf -= 2; -#endif - int r = tud_vendor_n_write(itf, buffer, buffer_size); - if (r > 0) { - return MAX(tud_vendor_n_flush(itf), r); +int driver_write_ccid(uint8_t itf, const uint8_t *tx_buffer, uint16_t buffer_size) { + if (last_write_result[itf] == WRITE_PENDING) { + return 0; + } + memcpy(&ccid_response_last[itf], tx_buffer, 10); + if (*tx_buffer != 0x81) { + DEBUG_PAYLOAD(tx_buffer, buffer_size); + } + int r = tud_vendor_n_write(itf, tx_buffer, buffer_size); + last_write_result[itf] = r == buffer_size ? WRITE_PENDING : WRITE_FAILED; + if (r == buffer_size) { + r = tud_vendor_n_flush(itf); } return r; } -uint16_t driver_read_ccid(uint8_t itf, uint8_t *buffer, uint16_t buffer_size) { -#ifdef USB_ITF_HID - itf -= 2; -#endif - return tud_vendor_n_read(itf, buffer, buffer_size); -} - -int driver_process_usb_nopacket_ccid() { - return 0; -} - int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) { - if (rx_read >= 10) { + if (ccid_rx[itf].w_ptr - ccid_rx[itf].r_ptr >= 10) { driver_init_ccid(itf); - //printf("%ld %d %x %x\n",ccid_header->dwLength,rx_read-10,ccid_header->bMessageType,ccid_header->bSeq); - if (ccid_header[itf]->dwLength <= rx_read - 10) { + //printf("ccid_process %ld %d %x %x %d\n",ccid_header[itf]->dwLength,rx_read-10,ccid_header[itf]->bMessageType,ccid_header[itf]->bSeq,ccid_rx[itf].w_ptr - ccid_rx[itf].r_ptr - 10); + if (ccid_header[itf]->dwLength <= ccid_rx[itf].w_ptr - ccid_rx[itf].r_ptr - 10){ + ccid_rx[itf].r_ptr += ccid_header[itf]->dwLength + 10; + if (ccid_rx[itf].r_ptr >= ccid_rx[itf].w_ptr) { + ccid_rx[itf].r_ptr = ccid_rx[itf].w_ptr = 0; + } + size_t apdu_sent = 0; if (ccid_header[itf]->bMessageType != CCID_SLOT_STATUS) { - DEBUG_PAYLOAD(usb_get_rx(itf), usb_read_available(itf)); + DEBUG_PAYLOAD((uint8_t *)ccid_header[itf], ccid_header[itf]->dwLength + 10); } 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); + ccid_resp_fast[itf]->bMessageType = CCID_SLOT_STATUS_RET; + ccid_resp_fast[itf]->dwLength = 0; + ccid_resp_fast[itf]->bSlot = 0; + ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_resp_fast[itf]->abRFU0 = ccid_status; + ccid_resp_fast[itf]->abRFU1 = 0; + driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10); } else if (ccid_header[itf]->bMessageType == CCID_POWER_ON) { size_t size_atr = (ccid_atr ? ccid_atr[0] : 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\n",ccid_response->apdu,apdu.rdata,ccid_response,ccid_header,ccid_header->apdu,apdu.data); - memcpy(&ccid_response[itf]->apdu, ccid_atr + 1, size_atr); + ccid_resp_fast[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_resp_fast[itf]->dwLength = size_atr; + ccid_resp_fast[itf]->bSlot = 0; + ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_resp_fast[itf]->abRFU0 = 0; + ccid_resp_fast[itf]->abRFU1 = 0; + //printf("1 %x %x %x || %x %x %x\n",ccid_resp_fast->apdu,apdu.rdata,ccid_resp_fast,ccid_header,ccid_header->apdu,apdu.data); + memcpy(&ccid_resp_fast[itf]->apdu, ccid_atr + 1, size_atr); if (ccid_status == 1) { //card_start(apdu_thread); } ccid_status = 0; - ccid_write(itf, size_atr); + driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], size_atr + 10); } else if (ccid_header[itf]->bMessageType == CCID_POWER_OFF) { if (ccid_status == 0) { //card_exit(0); } ccid_status = 1; - 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); + ccid_resp_fast[itf]->bMessageType = CCID_SLOT_STATUS_RET; + ccid_resp_fast[itf]->dwLength = 0; + ccid_resp_fast[itf]->bSlot = 0; + ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_resp_fast[itf]->abRFU0 = ccid_status; + ccid_resp_fast[itf]->abRFU1 = 0; + driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10); } else if (ccid_header[itf]->bMessageType == CCID_SET_PARAMS || ccid_header[itf]->bMessageType == CCID_GET_PARAMS || @@ -207,19 +252,23 @@ int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) { 0xFE, /* bIFSC */ 0 /* bNadValue */ }; - 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)); + ccid_resp_fast[itf]->bMessageType = CCID_PARAMS_RET; + ccid_resp_fast[itf]->dwLength = sizeof(params); + ccid_resp_fast[itf]->bSlot = 0; + ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_resp_fast[itf]->abRFU0 = ccid_status; + ccid_resp_fast[itf]->abRFU1 = 0x0100; + memcpy(&ccid_resp_fast[itf]->apdu, params, sizeof(params)); + driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], sizeof(params) + 10); } else if (ccid_header[itf]->bMessageType == CCID_XFR_BLOCK) { + apdu.rdata = &ccid_response[itf]->apdu; apdu_sent = apdu_process(itf, &ccid_header[itf]->apdu, ccid_header[itf]->dwLength); + if (apdu_sent > 0) { + card_start(sc_itf_to_usb_itf(itf), apdu_thread); + usb_send_event(EV_CMD_AVAILABLE); + } } - usb_clear_rx(itf); return apdu_sent; } } @@ -227,54 +276,51 @@ int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) { } bool driver_mounted_ccid(uint8_t itf) { -#ifdef USB_ITF_HID - itf -= 2; -#endif return tud_vendor_n_mounted(itf); } 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)); - 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); + ccid_resp_fast[itf]->bMessageType = CCID_DATA_BLOCK_RET; + ccid_resp_fast[itf]->dwLength = 0; + ccid_resp_fast[itf]->bSlot = 0; + ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq; + ccid_resp_fast[itf]->abRFU0 = CCID_CMD_STATUS_TIMEEXT; + ccid_resp_fast[itf]->abRFU1 = 0; + driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10); } 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); + driver_exec_finished_cont_ccid(itf, size_next, 0); } 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] = (ccid_header_t *) (ccid_tx[itf].buffer + ccid_tx[itf].w_ptr + offset); 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); + ccid_write_offset(itf, size_next+10, offset); } -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; +void ccid_task() { + for (int itf = 0; itf < ITF_SC_TOTAL; itf++) { + int status = card_status(sc_itf_to_usb_itf(itf)); + if (status == CCID_OK) { + driver_exec_finished_ccid(itf, finished_data_size); + } + else if (status == CCID_ERR_BLOCKED) { + driver_exec_timeout_ccid(itf); + } + if (ccid_tx[itf].w_ptr > ccid_tx[itf].r_ptr && last_write_result[itf] != WRITE_PENDING) { + if (driver_write_ccid(itf, ccid_tx[itf].buffer + ccid_tx[itf].r_ptr, ccid_tx[itf].w_ptr - ccid_tx[itf].r_ptr) > 0) { + + } + } + } } + #define USB_CONFIG_ATT_ONE TU_BIT(7) #define MAX_USB_POWER 1 diff --git a/src/usb/hid/ctap_hid.h b/src/usb/hid/ctap_hid.h index 9828ef5..0d662d1 100644 --- a/src/usb/hid/ctap_hid.h +++ b/src/usb/hid/ctap_hid.h @@ -33,6 +33,8 @@ typedef unsigned long int uint64_t; extern "C" { #endif +#include "usb.h" + // Size of HID reports #define HID_RPT_SIZE 64 // Default size of raw HID report @@ -144,7 +146,8 @@ typedef struct { // Low-level error codes. Return as negatives. -#define CTAP_MAX_PACKET_SIZE (64 - 7 + 128 * (64 - 5)) +#define CTAP_MAX_PACKET_SIZE (64 - 7 + 128 * (64 - 5)) +#define CTAP_MAX_CBOR_PAYLOAD (USB_BUFFER_SIZE - 64 - 7 - 1) #define CTAP1_ERR_NONE 0x00 // No error #define CTAP1_ERR_INVALID_CMD 0x01 // Invalid command @@ -162,13 +165,6 @@ extern void append_keyboard_buffer(const uint8_t *data, size_t data_len); extern bool is_nitrokey; -typedef enum { - WRITE_UNKNOWN = 0, - WRITE_PENDING, - WRITE_FAILED, - WRITE_SUCCESS, -} write_status_t; - #ifdef __cplusplus } #endif diff --git a/src/usb/hid/hid.c b/src/usb/hid/hid.c index 90acf57..5a06113 100644 --- a/src/usb/hid/hid.c +++ b/src/usb/hid/hid.c @@ -19,6 +19,8 @@ #include "tusb.h" #ifndef ESP_PLATFORM #include "bsp/board.h" +#else +static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED; #endif #endif #include "ctap_hid.h" @@ -28,11 +30,12 @@ #include "usb.h" static bool mounted = false; -void (*init_fido_cb)() = NULL; +extern void init_fido(); bool is_nitrokey = false; uint8_t (*get_version_major)() = NULL; uint8_t (*get_version_minor)() = NULL; -int (*cbor_process_cb)(uint8_t, const uint8_t *, size_t) = NULL; + +static usb_buffer_t hid_rx[ITF_HID_TOTAL] = {0}, hid_tx[ITF_HID_TOTAL] = {0}; typedef struct msg_packet { uint16_t len; @@ -50,8 +53,15 @@ 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}; + CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL; void send_keepalive(); +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(); + int driver_init_hid() { #ifndef ENABLE_EMULATION static bool _init = false; @@ -60,21 +70,22 @@ int driver_init_hid() { _init = true; } #endif - ctap_req = (CTAPHID_FRAME *) (usb_get_rx(ITF_HID) + usb_get_r_offset(ITF_HID)); + ctap_req = (CTAPHID_FRAME *) (hid_rx[ITF_HID_CTAP].buffer + hid_rx[ITF_HID_CTAP].r_ptr); apdu.header = ctap_req->init.data; - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); + ctap_resp = (CTAPHID_FRAME *) (hid_tx[ITF_HID_CTAP].buffer); apdu.rdata = ctap_resp->init.data; + //memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); usb_set_timeout_counter(ITF_HID, 200); is_nitrokey = false; + + hid_tx[ITF_HID_CTAP].w_ptr = hid_tx[ITF_HID_CTAP].r_ptr = 0; + send_buffer_size[ITF_HID_CTAP] = 0; return 0; } -uint16_t send_buffer_size[ITF_TOTAL] = {0}; -write_status_t last_write_result[ITF_TOTAL] = {0}; - uint16_t *get_send_buffer_size(uint8_t itf) { return &send_buffer_size[itf]; } @@ -111,10 +122,12 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, #endif uint32_t hid_write_offset(uint16_t size, uint16_t offset) { - if (*usb_get_tx(ITF_HID) != 0x81) { - DEBUG_PAYLOAD(usb_get_tx(ITF_HID) + offset, size); + if (hid_tx[ITF_HID_CTAP].buffer[offset] != 0x81) { + DEBUG_PAYLOAD(&hid_tx[ITF_HID_CTAP].buffer[offset], size); } - return usb_write_offset(ITF_HID, size, offset); + hid_tx[ITF_HID_CTAP].w_ptr += size + offset; + hid_tx[ITF_HID_CTAP].r_ptr += offset; + return size; } uint32_t hid_write(uint16_t size) { @@ -166,14 +179,12 @@ static void send_hid_report(uint8_t report_id) { } keycode[0] = chr & 0x7f; } - if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, modifier, - keycode) == true) { + if (tud_hid_n_keyboard_report(ITF_HID_KB, REPORT_ID_KEYBOARD, modifier, keycode) == true) { sent_key = true; } } else { - if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, 0, - NULL) == true) { + if (tud_hid_n_keyboard_report(ITF_HID_KB, REPORT_ID_KEYBOARD, 0, NULL) == true) { keyboard_w++; sent_key = false; @@ -190,7 +201,27 @@ static void send_hid_report(uint8_t report_id) { } } -void hid_task(void) { +void hid_task() { + int proc_pkt = 0; + if (hid_rx[ITF_HID_CTAP].w_ptr - hid_rx[ITF_HID_CTAP].r_ptr >= 64) { + //proc_pkt = driver_process_usb_packet_hid(64); + } + if (proc_pkt == 0) { + driver_process_usb_nopacket_hid(); + } + int status = card_status(ITF_HID); + if (status == CCID_OK) { + driver_exec_finished_hid(finished_data_size); + } + else if (status == CCID_ERR_BLOCKED) { + send_keepalive(); + } + if (hid_tx[ITF_HID_CTAP].w_ptr > hid_tx[ITF_HID_CTAP].r_ptr && last_write_result[ITF_HID_CTAP] != WRITE_PENDING) { + if (driver_write_hid(ITF_HID_CTAP, hid_tx[ITF_HID_CTAP].buffer + hid_tx[ITF_HID_CTAP].r_ptr, 64) > 0) { + + } + } + /* Keyboard ITF */ // Poll every 10ms const uint32_t interval_ms = 10; static uint32_t start_ms = 0; @@ -211,7 +242,11 @@ void hid_task(void) { #endif void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { - if (instance == ITF_HID && len > 0) { + printf("report_complete %d %d %d\n", instance, len, send_buffer_size[instance]); + if (instance == ITF_HID_CTAP && len > 0) { +#ifdef ESP_PLATFORM + taskENTER_CRITICAL(&mutex); +#endif CTAPHID_FRAME *ctap_req = (CTAPHID_FRAME *) report; if (last_write_result[instance] == WRITE_PENDING) { last_write_result[instance] = WRITE_SUCCESS; @@ -224,18 +259,27 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_ send_buffer_size[instance] -= MIN(64 - 5, send_buffer_size[instance]); } } - if (send_buffer_size[instance] > 0) { - if (last_write_result[instance] == WRITE_SUCCESS) { - if (FRAME_TYPE(ctap_req) != TYPE_INIT || ctap_req->init.cmd != CTAPHID_KEEPALIVE) { + if (last_write_result[instance] == WRITE_SUCCESS) { + if (FRAME_TYPE(ctap_req) != TYPE_INIT || ctap_req->init.cmd != CTAPHID_KEEPALIVE) { + if (send_buffer_size[instance] > 0) { ctap_resp = (CTAPHID_FRAME *) ((uint8_t *) ctap_resp + 64 - 5); + uint8_t seq = FRAME_TYPE(ctap_req) == TYPE_INIT ? 0 : FRAME_SEQ(ctap_req) + 1; + ctap_resp->cid = ctap_req->cid; + ctap_resp->cont.seq = seq; + + hid_tx[ITF_HID_CTAP].r_ptr += 64 - 5; + } + else { + hid_tx[ITF_HID_CTAP].r_ptr += 64; } - uint8_t seq = FRAME_TYPE(ctap_req) == TYPE_INIT ? 0 : FRAME_SEQ(ctap_req) + 1; - ctap_resp->cid = ctap_req->cid; - ctap_resp->cont.seq = seq; - } - if (hid_write_offset(64, (uint8_t *) ctap_resp - (usb_get_tx(ITF_HID))) > 0) { } } + if (hid_tx[ITF_HID_CTAP].r_ptr >= hid_tx[ITF_HID_CTAP].w_ptr) { + hid_tx[ITF_HID_CTAP].r_ptr = hid_tx[ITF_HID_CTAP].w_ptr = 0; + } +#ifdef ESP_PLATFORM + taskEXIT_CRITICAL(&mutex); +#endif } } @@ -253,43 +297,38 @@ int driver_write_hid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) { } #endif -uint16_t driver_read_hid(uint8_t *buffer, uint16_t buffer_size) { - return 0; -} - #ifndef ENABLE_EMULATION int (*hid_set_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t) = NULL; // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t itf, - uint8_t report_id, - hid_report_type_t report_type, - uint8_t const *buffer, - uint16_t bufsize) -{ +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { // This example doesn't use multiple report and report ID (void) itf; (void) report_id; (void) report_type; printf("set_report %d %d %d\n", itf, report_id, report_type); if (!hid_set_report_cb || hid_set_report_cb(itf, report_id, report_type, buffer, bufsize) == 0) { - usb_rx(itf, buffer, bufsize); + //usb_rx(itf, buffer, bufsize); + memcpy(hid_rx[itf].buffer + hid_rx[itf].w_ptr, buffer, bufsize); + hid_rx[itf].w_ptr += bufsize; + int proc_pkt = driver_process_usb_packet_hid(64); + if (proc_pkt == 0) { + driver_process_usb_nopacket_hid(); + } } } #endif uint32_t last_cmd_time = 0, last_packet_time = 0; int ctap_error(uint8_t error) { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); + memset((uint8_t *)ctap_resp, 0, sizeof(CTAPHID_FRAME)); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = CTAPHID_ERROR; ctap_resp->init.bcntl = 1; ctap_resp->init.data[0] = error; hid_write(64); - usb_clear_rx(ITF_HID); last_packet_time = 0; return 0; } @@ -301,6 +340,7 @@ uint32_t lock = 0; uint8_t thread_type = 0; //1 is APDU, 2 is CBOR extern bool cancel_button; +extern int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len); int driver_process_usb_nopacket_hid() { if (last_packet_time > 0 && last_packet_time + 500 < board_millis()) { @@ -312,16 +352,21 @@ int driver_process_usb_nopacket_hid() { } extern const uint8_t fido_aid[], u2f_aid[]; +extern void apdu_thread(), cbor_thread(); int driver_process_usb_packet_hid(uint16_t read) { int apdu_sent = 0; if (read >= 5) { driver_init_hid(); + + hid_rx[ITF_HID_CTAP].r_ptr += 64; + if (hid_rx[ITF_HID_CTAP].r_ptr >= hid_rx[ITF_HID_CTAP].w_ptr) { + hid_rx[ITF_HID_CTAP].r_ptr = hid_rx[ITF_HID_CTAP].w_ptr = 0; + } last_packet_time = board_millis(); - DEBUG_PAYLOAD(usb_get_rx(ITF_HID) + usb_get_r_offset(ITF_HID), 64); - memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); + DEBUG_PAYLOAD((uint8_t *)ctap_req, 64); if (ctap_req->cid == 0x0 || - (ctap_req->cid == CID_BROADCAST && ctap_req->init.cmd != CTAPHID_INIT)) { + (ctap_req->cid == CID_BROADCAST && (FRAME_TYPE(ctap_req) != TYPE_INIT || ctap_req->init.cmd != CTAPHID_INIT))) { return ctap_error(CTAP1_ERR_INVALID_CHANNEL); } if (board_millis() < lock && ctap_req->cid != last_req.cid && @@ -371,15 +416,11 @@ int driver_process_usb_packet_hid(uint16_t read) { else if (last_cmd_time + 100 > board_millis()) { return ctap_error(CTAP1_ERR_CHANNEL_BUSY); } - } - if (ctap_req->init.cmd == CTAPHID_INIT) { - if (init_fido_cb) { - init_fido_cb(); - } - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, 64); + card_exit(); + hid_tx[ITF_HID_CTAP].r_ptr = hid_tx[ITF_HID_CTAP].w_ptr = 0; + init_fido(); CTAPHID_INIT_REQ *req = (CTAPHID_INIT_REQ *) ctap_req->init.data; CTAPHID_INIT_RESP *resp = (CTAPHID_INIT_RESP *) ctap_resp->init.data; memcpy(resp->nonce, req->nonce, sizeof(resp->nonce)); @@ -393,7 +434,7 @@ int driver_process_usb_packet_hid(uint16_t read) { ctap_resp->init.cmd = CTAPHID_INIT; ctap_resp->init.bcntl = 17; ctap_resp->init.bcnth = 0; - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } @@ -401,19 +442,17 @@ int driver_process_usb_packet_hid(uint16_t read) { if (MSG_LEN(ctap_req) != 0) { return ctap_error(CTAP1_ERR_INVALID_LEN); } - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); + last_packet_time = 0; memcpy(ctap_resp, ctap_req, sizeof(CTAPHID_FRAME)); #ifndef ENABLE_EMULATION sleep_ms(1000); //For blinking the device during 1 seg #endif - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; - last_packet_time = 0; } else if ((last_cmd == CTAPHID_PING || last_cmd == CTAPHID_SYNC) && (msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) { memcpy(ctap_resp->init.data, msg_packet.data, msg_packet.len); driver_exec_finished_hid(msg_packet.len); @@ -424,7 +463,7 @@ int driver_process_usb_packet_hid(uint16_t read) { ctap_resp->init.cmd = last_cmd; ctap_resp->init.bcnth = MSG_LEN(ctap_req) >> 8; ctap_resp->init.bcntl = MSG_LEN(ctap_req) & 0xff; - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); } msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; @@ -437,47 +476,39 @@ int driver_process_usb_packet_hid(uint16_t read) { return ctap_error(CTAP1_ERR_INVALID_PARAMETER); } lock = board_millis() + ctap_req->init.data[0] * 1000; - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, 64); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = ctap_req->init.cmd; - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } else if (ctap_req->init.cmd == CTAPHID_UUID) { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, 64); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = ctap_req->init.cmd; memcpy(ctap_resp->init.data, pico_serial.id, sizeof(pico_serial.id)); ctap_resp->init.bcntl = 16; - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } else if (ctap_req->init.cmd == CTAPHID_VERSION) { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, 64); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = ctap_req->init.cmd; ctap_resp->init.data[0] = PICO_KEYS_SDK_VERSION_MAJOR; ctap_resp->init.data[1] = PICO_KEYS_SDK_VERSION_MINOR; ctap_resp->init.bcntl = 4; - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } else if (ctap_req->init.cmd == CTAPHID_ADMIN) { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - memset(ctap_resp, 0, 64); ctap_resp->cid = ctap_req->cid; ctap_resp->init.cmd = ctap_req->init.cmd; if (ctap_req->init.data[0] == 0x80) { // Status memcpy(ctap_resp->init.data, "\x00\xff\xff\xff\x00", 5); ctap_resp->init.bcntl = 5; } - hid_write(64); + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64); msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; } @@ -497,10 +528,10 @@ int driver_process_usb_packet_hid(uint16_t read) { thread_type = 1; if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) { - apdu_sent = apdu_process(ITF_HID, msg_packet.data, msg_packet.len); + apdu_sent = apdu_process(ITF_HID_CTAP, msg_packet.data, msg_packet.len); } else { - apdu_sent = apdu_process(ITF_HID, ctap_req->init.data, MSG_LEN(ctap_req)); + apdu_sent = apdu_process(ITF_HID_CTAP, ctap_req->init.data, MSG_LEN(ctap_req)); } DEBUG_PAYLOAD(apdu.data, (int) apdu.nc); msg_packet.len = msg_packet.current_len = 0; @@ -512,13 +543,11 @@ int driver_process_usb_packet_hid(uint16_t read) { (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) { thread_type = 2; select_app(fido_aid + 1, fido_aid[0]); - if (cbor_process_cb) { - if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) { - apdu_sent = cbor_process_cb(last_cmd, msg_packet.data, msg_packet.len); - } - else { - apdu_sent = cbor_process_cb(last_cmd, ctap_req->init.data, MSG_LEN(ctap_req)); - } + if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) { + apdu_sent = cbor_process(last_cmd, msg_packet.data, msg_packet.len); + } + else { + apdu_sent = cbor_process(last_cmd, ctap_req->init.data, MSG_LEN(ctap_req)); } msg_packet.len = msg_packet.current_len = 0; last_packet_time = 0; @@ -541,34 +570,28 @@ int driver_process_usb_packet_hid(uint16_t read) { // echo back anything we received from host //tud_hid_report(0, buffer, bufsize); //printf("END\n"); - usb_more_rx(ITF_HID, 64); + if (apdu_sent > 0) { + if (apdu_sent == 1) { + card_start(ITF_HID, apdu_thread); + } + else if (apdu_sent == 2) { + card_start(ITF_HID, cbor_thread); + } + usb_send_event(EV_CMD_AVAILABLE); + } } return apdu_sent; } void send_keepalive() { - CTAPHID_FRAME *resp = (CTAPHID_FRAME *) (usb_get_tx(ITF_HID) + 4096); + CTAPHID_FRAME *resp = (CTAPHID_FRAME *) (hid_tx[ITF_HID_CTAP].buffer + sizeof(hid_tx[ITF_HID_CTAP].buffer) - 64); //memset(ctap_resp, 0, sizeof(CTAPHID_FRAME)); resp->cid = ctap_req->cid; resp->init.cmd = CTAPHID_KEEPALIVE; resp->init.bcntl = 1; resp->init.data[0] = is_req_button_pending() ? 2 : 1; - //send_buffer_size[ITF_HID] = 0; - hid_write_offset(64, 4096); -} - -void driver_exec_timeout_hid() { - if (thread_type == 2) { - send_keepalive(); - } -} - -uint8_t *driver_prepare_response_hid() { - ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID); - apdu.rdata = ctap_resp->init.data; - send_buffer_size[ITF_HID] = 0; - memset(usb_get_tx(ITF_HID), 0, 4096); - return ctap_resp->init.data; + //send_buffer_size[ITF_HID_CTAP] = 0; + driver_write_hid(ITF_HID_CTAP, (const uint8_t *)resp, 64); } void driver_exec_finished_hid(uint16_t size_next) { @@ -582,7 +605,7 @@ void driver_exec_finished_hid(uint16_t size_next) { apdu.rdata[0] = apdu.sw >> 8; apdu.rdata[1] = apdu.sw & 0xff; } - driver_exec_finished_cont_hid(ITF_HID, size_next, 7); + driver_exec_finished_cont_hid(ITF_HID_CTAP, size_next, 7); } } apdu.sw = 0; @@ -590,14 +613,14 @@ void driver_exec_finished_hid(uint16_t size_next) { void driver_exec_finished_cont_hid(uint8_t itf, uint16_t size_next, uint16_t offset) { offset -= 7; - ctap_resp = (CTAPHID_FRAME *) (usb_get_tx(itf) + offset); + ctap_resp = (CTAPHID_FRAME *) (hid_tx[itf].buffer + offset); ctap_resp->cid = ctap_req->cid; - ctap_resp->init.cmd = last_cmd; ctap_resp->init.bcnth = size_next >> 8; ctap_resp->init.bcntl = size_next & 0xff; send_buffer_size[itf] = size_next; - if (hid_write_offset(64, offset) > 0) { + ctap_resp->init.cmd = last_cmd; + if (hid_write_offset(size_next+7, offset) > 0) { //ctap_resp = (CTAPHID_FRAME *) ((uint8_t *) ctap_resp + 64 - 5); - //send_buffer_size[ITF_HID] -= MIN(64 - 7, send_buffer_size[ITF_HID]); + //send_buffer_size[ITF_HID_CTAP] -= MIN(64 - 7, send_buffer_size[ITF_HID_CTAP]); } } diff --git a/src/usb/usb.c b/src/usb/usb.c index 7ddb03c..5a5d90a 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -35,138 +35,13 @@ #include // Device specific functions -static uint8_t rx_buffer[ITF_TOTAL][4096] = { 0 }, tx_buffer[ITF_TOTAL][4096 + 64] = { 0 }; -static uint16_t w_offset[ITF_TOTAL] = { 0 }, r_offset[ITF_TOTAL] = { 0 }; -static uint16_t w_len[ITF_TOTAL] = { 0 }, tx_r_offset[ITF_TOTAL] = { 0 }; static uint32_t timeout_counter[ITF_TOTAL] = { 0 }; uint8_t card_locked_itf = ITF_TOTAL; // no locked -#ifndef ENABLE_EMULATION -static uint8_t proc_locked = 0; -#endif - -void (*cbor_thread_func)() = NULL; void usb_set_timeout_counter(uint8_t itf, uint32_t v) { timeout_counter[itf] = v; } -uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset) { -#ifndef ENABLE_EMULATION - uint8_t pkt_max = 64; -#endif - uint16_t w = 0; - if (len > sizeof(tx_buffer[itf])) { - len = sizeof(tx_buffer[itf]); - } - w_len[itf] = len; - tx_r_offset[itf] = offset; -#ifndef ENABLE_EMULATION -#ifdef USB_ITF_HID - if (itf == ITF_HID || itf == ITF_KEYBOARD) { - w = driver_write_hid(itf, tx_buffer[itf] + offset, MIN(len, pkt_max)); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - w = driver_write_ccid(itf, tx_buffer[itf] + offset, MIN(len, pkt_max)); - } -#endif -#else - w = driver_write_emul(itf, tx_buffer[itf] + offset, len); -#endif - w_len[itf] -= w; - tx_r_offset[itf] += w; - return w; -} - -#ifndef ENABLE_EMULATION -uint16_t usb_rx(uint8_t itf, const uint8_t *buffer, uint16_t len) { - uint16_t size = MIN((uint16_t)sizeof(rx_buffer[itf]) - w_offset[itf], (uint16_t)len); - if (size > 0) { - if (buffer == NULL) { -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - size = driver_read_hid(rx_buffer[itf] + w_offset[itf], size); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - size = (uint16_t)driver_read_ccid(itf, rx_buffer[itf] + w_offset[itf], size); - } -#endif - } - else { - memcpy(rx_buffer[itf] + w_offset[itf], buffer, size); - } - w_offset[itf] += size; - } - return size; -} -#endif - -uint32_t usb_write_flush(uint8_t itf) { - uint16_t w = 0; - if (w_len[itf] > 0) { -#ifndef ENABLE_EMULATION -#ifdef USB_ITF_HID - if (itf == ITF_HID || itf == ITF_KEYBOARD) { - w = driver_write_hid(itf, tx_buffer[itf] + tx_r_offset[itf], MIN(w_len[itf], 64)); - } -#endif -#ifdef USB_ITF_CCID - 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 - w = driver_write_emul(itf, tx_buffer[itf] + tx_r_offset[itf], w_len[itf]); -#endif - tx_r_offset[itf] += w; - w_len[itf] -= w; - } - return w; -} - -uint32_t usb_write(uint8_t itf, uint16_t len) { - return usb_write_offset(itf, len, 0); -} - -uint16_t usb_read_available(uint8_t itf) { - return w_offset[itf] - r_offset[itf]; -} - -uint16_t usb_write_available(uint8_t itf) { - return w_len[itf] > 0; -} - -uint8_t *usb_get_rx(uint8_t itf) { - return rx_buffer[itf]; -} - -uint8_t *usb_get_tx(uint8_t itf) { - return tx_buffer[itf]; -} - -void usb_clear_rx(uint8_t itf) { - w_offset[itf] = r_offset[itf] = 0; -} - -uint16_t usb_get_r_offset(uint8_t itf) { - return r_offset[itf]; -} - -uint16_t usb_more_rx(uint8_t itf, uint16_t len) { - if (len > w_offset[itf] - r_offset[itf]) { - len = w_offset[itf] - r_offset[itf]; - } - r_offset[itf] += len; - if (r_offset[itf] == w_offset[itf]) { - r_offset[itf] = w_offset[itf] = 0; - return 0; - } - return usb_read_available(itf); -} - #if !defined(ENABLE_EMULATION) queue_t usb_to_card_q; queue_t card_to_usb_q; @@ -198,62 +73,24 @@ void usb_init() { #endif } -extern int driver_process_usb_nopacket(); -extern uint32_t timeout; +uint32_t timeout = 0; +void timeout_stop() { + timeout = 0; +} -static int usb_event_handle(uint8_t itf) { -#ifndef ENABLE_EMULATION - uint16_t rx_read = usb_read_available(itf); -#else - uint16_t rx_read = emul_read(itf); -#endif - int proc_packet = 0; -#ifndef ENABLE_EMULATION -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - proc_packet = driver_process_usb_packet_hid(rx_read); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - proc_packet = driver_process_usb_packet_ccid(itf, rx_read); - } -#endif -#else - proc_packet = driver_process_usb_packet_emul(itf, rx_read); -#endif - if (proc_packet > 0) { - card_locked_itf = itf; +void timeout_start() { + timeout = board_millis(); +} + +bool is_busy() { + return timeout > 0; +} + +void usb_send_event(uint32_t flag) { + queue_add_blocking(&usb_to_card_q, &flag); + if (flag == EV_CMD_AVAILABLE) { timeout_start(); -#ifndef ENABLE_EMULATION - if (proc_locked != proc_packet) { - if (proc_packet == 1) { - card_start(apdu_thread); - } - else if (proc_packet == 2) { - if (cbor_thread_func) { - card_start(cbor_thread_func); - } - } - proc_locked = proc_packet; - } - uint32_t flag = EV_CMD_AVAILABLE; - queue_add_blocking(&usb_to_card_q, &flag); -#endif } - else { -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - driver_process_usb_nopacket_hid(); - } -#endif -#ifdef USB_ITF_CCID - //if (itf == ITF_CCID) { - // driver_process_usb_nopacket_ccid(); - //} -#endif - } - return 0; } extern void low_flash_init(); @@ -265,27 +102,31 @@ void card_init_core1() { uint16_t finished_data_size = 0; -void card_start(void (*func)(void)) { +void card_start(uint8_t itf, void (*func)(void)) { + timeout_start(); + if (card_locked_itf != itf) { #ifndef ENABLE_EMULATION - uint32_t m = 0; - while (queue_is_empty(&usb_to_card_q) == false) { - if (queue_try_remove(&usb_to_card_q, &m) == false) { - break; + uint32_t m = 0; + while (queue_is_empty(&usb_to_card_q) == false) { + if (queue_try_remove(&usb_to_card_q, &m) == false) { + break; + } } - } - while (queue_is_empty(&card_to_usb_q) == false) { - if (queue_try_remove(&card_to_usb_q, &m) == false) { - break; + while (queue_is_empty(&card_to_usb_q) == false) { + if (queue_try_remove(&card_to_usb_q, &m) == false) { + break; + } } - } - multicore_reset_core1(); - if (func) { - multicore_launch_core1(func); - } - led_set_blink(BLINK_MOUNTED); + multicore_reset_core1(); + if (func) { + multicore_launch_core1(func); + } + led_set_blink(BLINK_MOUNTED); #else - (void)func; + (void)func; #endif + card_locked_itf = itf; + } } void card_exit() { @@ -293,102 +134,62 @@ void card_exit() { uint32_t flag = EV_EXIT; queue_try_add(&usb_to_card_q, &flag); led_set_blink(BLINK_SUSPENDED); + multicore_reset_core1(); +#ifdef ESP_PLATFORM + hcore1 = NULL; #endif card_locked_itf = ITF_TOTAL; +#endif } extern void hid_task(); +extern void ccid_task(); void usb_task() { -#ifndef ENABLE_EMULATION - bool mounted = false; -#else - bool mounted = true; -#endif - for (uint8_t itf = 0; itf < ITF_TOTAL; itf++) { -#ifndef ENABLE_EMULATION -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - mounted = driver_mounted_hid(); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - mounted = driver_mounted_ccid(itf); - } -#endif -#endif - - if (mounted == true) { - if (usb_event_handle(itf) != 0) { - - } - usb_write_flush(itf); -#ifndef ENABLE_EMULATION - if (card_locked_itf == itf) { - uint32_t m = 0x0; - bool has_m = queue_try_remove(&card_to_usb_q, &m); - //if (m != 0) - // printf("\n ------ M = %lu\n",m); - if (has_m) { - if (m == EV_EXEC_FINISHED) { - timeout_stop(); -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - driver_exec_finished_hid(finished_data_size); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - driver_exec_finished_ccid(itf, finished_data_size); - } -#endif - led_set_blink(BLINK_MOUNTED); - card_locked_itf = ITF_TOTAL; - } - else if (m == EV_PRESS_BUTTON) { - uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED; - queue_try_add(&usb_to_card_q, &flag); - } - } - else { - if (timeout > 0) { - if (timeout + timeout_counter[itf] < board_millis()) { -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - driver_exec_timeout_hid(); - } -#endif -#ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - driver_exec_timeout_ccid(itf); - } -#endif - timeout = board_millis(); - } - } - } - } -#endif - } - } #ifndef ENABLE_EMULATION #ifdef USB_ITF_HID hid_task(); #endif +#ifdef USB_ITF_CCID + ccid_task(); +#endif #endif } +int card_status(uint8_t itf) { +#ifndef ENABLE_EMULATION + if (card_locked_itf == itf) { + uint32_t m = 0x0; + bool has_m = queue_try_remove(&card_to_usb_q, &m); + //if (m != 0) + // printf("\n ------ M = %lu\n",m); + if (has_m) { + if (m == EV_EXEC_FINISHED) { + timeout_stop(); + led_set_blink(BLINK_MOUNTED); + card_locked_itf = ITF_TOTAL; + return CCID_OK; + } + else if (m == EV_PRESS_BUTTON) { + uint32_t flag = wait_button() ? EV_BUTTON_TIMEOUT : EV_BUTTON_PRESSED; + queue_try_add(&usb_to_card_q, &flag); + } + return CCID_ERR_FILE_NOT_FOUND; + } + else { + if (timeout > 0) { + if (timeout + timeout_counter[itf] < board_millis()) { + timeout = board_millis(); + return CCID_ERR_BLOCKED; + } + } + } + } +#endif + return CCID_ERR_FILE_NOT_FOUND; +} uint8_t *usb_prepare_response(uint8_t itf) { #ifndef ENABLE_EMULATION -#ifdef USB_ITF_HID - if (itf == ITF_HID) { - return driver_prepare_response_hid(); - } -#endif #ifdef USB_ITF_CCID - if (itf == ITF_CCID || itf == ITF_WCID) { - return driver_prepare_response_ccid(itf); - } #endif return NULL; #else diff --git a/src/usb/usb.h b/src/usb/usb.h index 818972f..e59ddf3 100644 --- a/src/usb/usb.h +++ b/src/usb/usb.h @@ -45,17 +45,31 @@ #define EV_BUTTON_TIMEOUT 16 #define EV_BUTTON_PRESSED 32 +enum { +#ifdef USB_ITF_HID + ITF_HID_CTAP = 0, + ITF_HID_KB, +#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 = 0, - ITF_KEYBOARD, + ITF_HID = ITF_HID_CTAP, + ITF_KEYBOARD = ITF_HID_KB, #endif #ifdef USB_ITF_CCID - ITF_CCID, - ITF_WCID, + ITF_CCID = ITF_SC_CCID + ITF_HID_TOTAL, + ITF_WCID = ITF_SC_WCID + ITF_HID_TOTAL, #endif - ITF_TOTAL + ITF_TOTAL = ITF_HID_TOTAL + ITF_SC_TOTAL }; enum { @@ -70,60 +84,42 @@ extern queue_t card_to_usb_q; #endif extern uint8_t card_locked_itf; -#ifdef USB_ITF_HID -extern int driver_process_usb_packet_hid(uint16_t rx_read); -extern void driver_exec_finished_hid(uint16_t size_next); -extern void driver_exec_finished_cont_hid(uint8_t itf, uint16_t size_next, uint16_t offset); -extern void driver_exec_timeout_hid(); -extern bool driver_mounted_hid(); -extern uint8_t *driver_prepare_response_hid(); -extern int driver_write_hid(uint8_t, const uint8_t *, uint16_t); -extern uint16_t driver_read_hid(uint8_t *, uint16_t); -extern int driver_process_usb_nopacket_hid(); -#endif - -#ifdef USB_ITF_CCID -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 - -#ifdef ENABLE_EMULATION -extern int driver_process_usb_packet_emul(uint8_t, uint16_t rx_read); -extern void driver_exec_finished_emul(uint8_t, uint16_t size_next); -extern void driver_exec_finished_cont_emul(uint8_t, uint16_t size_next, uint16_t offset); -extern void driver_exec_timeout_emul(uint8_t); -extern bool driver_mounted_emul(uint8_t); -extern uint8_t *driver_prepare_response_emul(uint8_t); -extern uint16_t driver_write_emul(uint8_t, const uint8_t *, uint16_t); -extern uint16_t driver_read_emul(uint8_t, uint8_t *, uint16_t); -extern int driver_process_usb_nopacket_emul(uint8_t); -extern uint16_t emul_read(uint8_t); -#else -extern uint16_t usb_rx(uint8_t itf, const uint8_t *buffer, uint16_t len); -#endif - -extern void card_start(void (*func)(void)); +extern void card_start(uint8_t, void (*func)(void)); extern void card_exit(); +extern int card_status(uint8_t itf); extern void usb_init(); -extern uint8_t *usb_prepare_response(uint8_t itf); -extern uint8_t *usb_get_rx(uint8_t itf); -extern uint8_t *usb_get_tx(uint8_t itf); -extern uint32_t usb_write_offset(uint8_t itf, uint16_t len, uint16_t offset); -extern void usb_clear_rx(uint8_t itf); -extern uint16_t usb_more_rx(uint8_t itf, uint16_t len); -extern uint16_t usb_get_r_offset(uint8_t itf); + extern uint16_t finished_data_size; extern void usb_set_timeout_counter(uint8_t itf, uint32_t v); extern void card_init_core1(); -extern uint32_t usb_write_flush(uint8_t itf); -extern uint16_t usb_read_available(uint8_t itf); -extern uint16_t usb_write_available(uint8_t itf); + +extern void usb_send_event(uint32_t flag); +extern void timeout_stop(); +extern void timeout_start(); +extern bool is_busy(); + +#ifdef USB_ITF_HID +extern void driver_exec_finished_hid(uint16_t size_next); +extern void driver_exec_finished_cont_hid(uint8_t itf, uint16_t size_next, uint16_t offset); +#endif + +#ifdef USB_ITF_CCID +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); +#endif + +#define USB_BUFFER_SIZE 2048 // Size of USB buffer + +typedef struct { + uint8_t buffer[USB_BUFFER_SIZE]; + uint16_t r_ptr, w_ptr; +} __attribute__((__packed__)) usb_buffer_t; + +typedef enum { + WRITE_UNKNOWN = 0, + WRITE_PENDING, + WRITE_FAILED, + WRITE_SUCCESS, +} write_status_t; #endif