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 <pol.henarejos@cttc.es>
This commit is contained in:
parent
0745838e3f
commit
fa6292118d
10 changed files with 420 additions and 576 deletions
23
src/apdu.c
23
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
24
src/main.c
24
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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -145,6 +147,7 @@ typedef struct {
|
|||
// Low-level error codes. Return as negatives.
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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,19 +259,28 @@ 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 (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;
|
||||
}
|
||||
if (hid_write_offset(64, (uint8_t *) ctap_resp - (usb_get_tx(ITF_HID))) > 0) {
|
||||
else {
|
||||
hid_tx[ITF_HID_CTAP].r_ptr += 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ENABLE_EMULATION
|
||||
|
|
@ -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);
|
||||
apdu_sent = cbor_process(last_cmd, msg_packet.data, msg_packet.len);
|
||||
}
|
||||
else {
|
||||
apdu_sent = cbor_process_cb(last_cmd, ctap_req->init.data, MSG_LEN(ctap_req));
|
||||
}
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
265
src/usb/usb.c
265
src/usb/usb.c
|
|
@ -35,138 +35,13 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
// 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;
|
||||
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;
|
||||
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);
|
||||
#endif
|
||||
if (flag == EV_CMD_AVAILABLE) {
|
||||
timeout_start();
|
||||
}
|
||||
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,7 +102,9 @@ 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) {
|
||||
|
|
@ -286,6 +125,8 @@ void card_start(void (*func)(void)) {
|
|||
#else
|
||||
(void)func;
|
||||
#endif
|
||||
card_locked_itf = itf;
|
||||
}
|
||||
}
|
||||
|
||||
void card_exit() {
|
||||
|
|
@ -293,35 +134,27 @@ 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();
|
||||
}
|
||||
hid_task();
|
||||
#endif
|
||||
#ifdef USB_ITF_CCID
|
||||
if (itf == ITF_CCID || itf == ITF_WCID) {
|
||||
mounted = driver_mounted_ccid(itf);
|
||||
}
|
||||
ccid_task();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mounted == true) {
|
||||
if (usb_event_handle(itf) != 0) {
|
||||
|
||||
}
|
||||
usb_write_flush(itf);
|
||||
int card_status(uint8_t itf) {
|
||||
#ifndef ENABLE_EMULATION
|
||||
if (card_locked_itf == itf) {
|
||||
uint32_t m = 0x0;
|
||||
|
|
@ -331,64 +164,32 @@ void usb_task() {
|
|||
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;
|
||||
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()) {
|
||||
#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();
|
||||
return CCID_ERR_BLOCKED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifndef ENABLE_EMULATION
|
||||
#ifdef USB_ITF_HID
|
||||
hid_task();
|
||||
#endif
|
||||
#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
|
||||
|
|
|
|||
106
src/usb/usb.h
106
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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue