mirror of
https://github.com/polhenarejos/pico-keys-sdk
synced 2026-05-28 00:51:25 +02:00
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:
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) {
|
if (apdu.rlen <= apdu.ne) {
|
||||||
#ifndef ENABLE_EMULATION
|
#ifndef ENABLE_EMULATION
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
if (itf == ITF_HID) {
|
if (itf == ITF_HID_CTAP) {
|
||||||
driver_exec_finished_cont_hid(itf, apdu.rlen + 2, rdata_gr - (usb_get_tx(itf)));
|
driver_exec_finished_cont_hid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
if (itf == ITF_CCID || itf == ITF_WCID) {
|
if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) {
|
||||||
driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - (usb_get_tx(itf) + 34));
|
driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#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
|
#endif
|
||||||
//Prepare next RAPDU
|
//Prepare next RAPDU
|
||||||
apdu.sw = 0;
|
apdu.sw = 0;
|
||||||
apdu.rlen = 0;
|
apdu.rlen = 0;
|
||||||
usb_prepare_response(itf);
|
rdata_gr = apdu.rdata;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rdata_gr += apdu.ne;
|
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
|
#ifndef ENABLE_EMULATION
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
if (itf == ITF_HID) {
|
if (itf == ITF_HID_CTAP) {
|
||||||
driver_exec_finished_cont_hid(itf, apdu.ne + 2, rdata_gr - apdu.ne - (usb_get_tx(itf)));
|
driver_exec_finished_cont_hid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
if (itf == ITF_CCID || itf == ITF_WCID) {
|
if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) {
|
||||||
driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - (usb_get_tx(itf) + 34));
|
driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#else
|
#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
|
#endif
|
||||||
apdu.rlen -= (uint16_t)apdu.ne;
|
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 {
|
else {
|
||||||
apdu.sw = 0;
|
apdu.sw = 0;
|
||||||
apdu.rlen = 0;
|
apdu.rlen = 0;
|
||||||
apdu.rdata = usb_prepare_response(itf);
|
|
||||||
rdata_gr = apdu.rdata;
|
rdata_gr = apdu.rdata;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
typedef struct app {
|
typedef struct app {
|
||||||
const uint8_t *aid;
|
const uint8_t *aid;
|
||||||
int (*process_apdu)();
|
int (*process_apdu)();
|
||||||
int (*select_aid)(struct app *);
|
int (*select_aid)(struct app *, uint8_t);
|
||||||
int (*unload)();
|
int (*unload)();
|
||||||
} app_t;
|
} 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);
|
extern int select_app(const uint8_t *aid, size_t aid_len);
|
||||||
|
|
||||||
typedef struct cmd {
|
typedef struct cmd {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ typedef QueueHandle_t queue_t;
|
|||||||
#define queue_is_empty(a) (uxQueueMessagesWaiting(*(a)) == 0)
|
#define queue_is_empty(a) (uxQueueMessagesWaiting(*(a)) == 0)
|
||||||
#define queue_try_remove(a,b) xQueueReceive(*(a), b, 0)
|
#define queue_try_remove(a,b) xQueueReceive(*(a), b, 0)
|
||||||
extern TaskHandle_t hcore0, hcore1;
|
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 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)
|
#define sleep_ms(a) vTaskDelay(a / portTICK_PERIOD_MS)
|
||||||
static inline uint32_t board_millis(void) {
|
static inline uint32_t board_millis(void) {
|
||||||
@@ -46,10 +46,8 @@ typedef SemaphoreHandle_t semaphore_t;
|
|||||||
#define sem_release(a) xSemaphoreGive(*(a))
|
#define sem_release(a) xSemaphoreGive(*(a))
|
||||||
#define sem_acquire_blocking(a) xSemaphoreTake(*(a), portMAX_DELAY)
|
#define sem_acquire_blocking(a) xSemaphoreTake(*(a), portMAX_DELAY)
|
||||||
#define multicore_lockout_victim_init() (void)0
|
#define multicore_lockout_victim_init() (void)0
|
||||||
static inline bool multicore_lockout_start_timeout_us(int a) {
|
static inline bool multicore_lockout_start_timeout_us(int a) { if (hcore1) { vTaskSuspend(hcore1); } return true; }
|
||||||
vTaskSuspend(hcore1); return true; }
|
static inline bool multicore_lockout_end_timeout_us(int a) { if (hcore1) { vTaskResume(hcore1); } return true; }
|
||||||
static inline bool multicore_lockout_end_timeout_us(int a) {
|
|
||||||
vTaskResume(hcore1); return true; }
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
24
src/main.c
24
src/main.c
@@ -104,7 +104,7 @@ app_t *current_app = NULL;
|
|||||||
|
|
||||||
const uint8_t *ccid_atr = 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)) {
|
if (num_apps < sizeof(apps) / sizeof(app_t)) {
|
||||||
apps[num_apps].select_aid = select_aid;
|
apps[num_apps].select_aid = select_aid;
|
||||||
apps[num_apps].aid = 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) {
|
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))) {
|
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;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
for (int a = 0; a < num_apps; a++) {
|
for (int a = 0; a < num_apps; a++) {
|
||||||
if (!memcmp(apps[a].aid + 1, aid, MIN(aid_len, apps[a].aid[0]))) {
|
if (!memcmp(apps[a].aid + 1, aid, MIN(aid_len, apps[a].aid[0]))) {
|
||||||
if (current_app) {
|
if (current_app) {
|
||||||
if (current_app->aid && !memcmp(current_app->aid + 1, aid, aid_len)) {
|
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;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
if (current_app->unload) {
|
if (current_app->unload) {
|
||||||
@@ -130,7 +131,7 @@ int select_app(const uint8_t *aid, size_t aid_len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_app = &apps[a];
|
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;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,19 +147,6 @@ void led_set_blink(uint32_t mode) {
|
|||||||
blink_interval_ms = 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();
|
void execute_tasks();
|
||||||
|
|
||||||
static bool req_button_pending = false;
|
static bool req_button_pending = false;
|
||||||
@@ -344,10 +332,10 @@ extern void neug_task();
|
|||||||
extern void usb_task();
|
extern void usb_task();
|
||||||
void execute_tasks()
|
void execute_tasks()
|
||||||
{
|
{
|
||||||
usb_task();
|
|
||||||
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||||
tud_task(); // tinyusb device task
|
tud_task(); // tinyusb device task
|
||||||
#endif
|
#endif
|
||||||
|
usb_task();
|
||||||
led_blinking_task();
|
led_blinking_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +452,7 @@ int main(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#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
|
#else
|
||||||
core0_loop();
|
core0_loop();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ static inline void put_uint16_t(uint16_t n, uint8_t *b) {
|
|||||||
extern void low_flash_available();
|
extern void low_flash_available();
|
||||||
extern int flash_clear_file(file_t *file);
|
extern int flash_clear_file(file_t *file);
|
||||||
|
|
||||||
extern void timeout_stop();
|
|
||||||
extern void timeout_start();
|
|
||||||
|
|
||||||
extern int (*button_pressed_cb)(uint8_t);
|
extern int (*button_pressed_cb)(uint8_t);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||||
#include "hardware/rtc.h"
|
#include "hardware/rtc.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef ESP_PLATFORM
|
||||||
|
#include "bsp/board.h"
|
||||||
|
#else
|
||||||
|
static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
#endif
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "ccid.h"
|
#include "ccid.h"
|
||||||
#include "device/usbd_pvt.h"
|
#include "device/usbd_pvt.h"
|
||||||
@@ -72,7 +77,7 @@
|
|||||||
#define CCID_THREAD_TERMINATED 0xffff
|
#define CCID_THREAD_TERMINATED 0xffff
|
||||||
#define CCID_ACK_TIMEOUT 0x6600
|
#define CCID_ACK_TIMEOUT 0x6600
|
||||||
|
|
||||||
struct ccid_header {
|
typedef struct {
|
||||||
uint8_t bMessageType;
|
uint8_t bMessageType;
|
||||||
uint32_t dwLength;
|
uint32_t dwLength;
|
||||||
uint8_t bSlot;
|
uint8_t bSlot;
|
||||||
@@ -80,119 +85,159 @@ struct ccid_header {
|
|||||||
uint8_t abRFU0;
|
uint8_t abRFU0;
|
||||||
uint16_t abRFU1;
|
uint16_t abRFU1;
|
||||||
uint8_t apdu; //Actually it is an array
|
uint8_t apdu; //Actually it is an array
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__)) ccid_header_t;
|
||||||
|
|
||||||
uint8_t ccid_status = 1;
|
uint8_t ccid_status = 1;
|
||||||
static uint8_t itf_num;
|
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) {
|
void ccid_write_offset(uint8_t itf, uint16_t size, uint16_t offset) {
|
||||||
if (*usb_get_tx(itf) + offset != 0x81) {
|
ccid_tx[itf].w_ptr += size + offset;
|
||||||
DEBUG_PAYLOAD(usb_get_tx(itf) + offset, size + 10);
|
ccid_tx[itf].r_ptr += offset;
|
||||||
}
|
|
||||||
usb_write_offset(itf, size + 10, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ccid_write(uint8_t itf, uint16_t size) {
|
void ccid_write(uint8_t itf, uint16_t size) {
|
||||||
ccid_write_offset(itf, size, 0);
|
ccid_write_offset(itf, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ccid_header *ccid_response[ITF_TOTAL];
|
ccid_header_t *ccid_response[ITF_SC_TOTAL];
|
||||||
struct ccid_header *ccid_header[ITF_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) {
|
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;
|
// 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;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tud_vendor_rx_cb(uint8_t itf) {
|
void tud_vendor_rx_cb(uint8_t itf) {
|
||||||
uint32_t len = tud_vendor_n_available(itf);
|
uint32_t len = tud_vendor_n_available(itf);
|
||||||
#ifdef USB_ITF_HID
|
do {
|
||||||
itf += 2;
|
uint16_t tlen = 0;
|
||||||
#endif
|
if (len > 0xFFFF) {
|
||||||
usb_rx(itf, NULL, len);
|
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) {
|
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
|
||||||
#ifdef USB_ITF_HID
|
if (sent_bytes) {
|
||||||
itf += 2;
|
#ifdef ESP_PLATFORM
|
||||||
|
taskENTER_CRITICAL(&mutex);
|
||||||
#endif
|
#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) {
|
int driver_write_ccid(uint8_t itf, const uint8_t *tx_buffer, uint16_t buffer_size) {
|
||||||
#ifdef USB_ITF_HID
|
if (last_write_result[itf] == WRITE_PENDING) {
|
||||||
itf -= 2;
|
return 0;
|
||||||
#endif
|
}
|
||||||
int r = tud_vendor_n_write(itf, buffer, buffer_size);
|
memcpy(&ccid_response_last[itf], tx_buffer, 10);
|
||||||
if (r > 0) {
|
if (*tx_buffer != 0x81) {
|
||||||
return MAX(tud_vendor_n_flush(itf), r);
|
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;
|
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) {
|
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);
|
driver_init_ccid(itf);
|
||||||
//printf("%ld %d %x %x\n",ccid_header->dwLength,rx_read-10,ccid_header->bMessageType,ccid_header->bSeq);
|
//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 <= rx_read - 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;
|
size_t apdu_sent = 0;
|
||||||
if (ccid_header[itf]->bMessageType != CCID_SLOT_STATUS) {
|
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) {
|
if (ccid_header[itf]->bMessageType == CCID_SLOT_STATUS) {
|
||||||
ccid_response[itf]->bMessageType = CCID_SLOT_STATUS_RET;
|
ccid_resp_fast[itf]->bMessageType = CCID_SLOT_STATUS_RET;
|
||||||
ccid_response[itf]->dwLength = 0;
|
ccid_resp_fast[itf]->dwLength = 0;
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_resp_fast[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->abRFU0 = ccid_status;
|
ccid_resp_fast[itf]->abRFU0 = ccid_status;
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
ccid_resp_fast[itf]->abRFU1 = 0;
|
||||||
ccid_write(itf, 0);
|
driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10);
|
||||||
}
|
}
|
||||||
else if (ccid_header[itf]->bMessageType == CCID_POWER_ON) {
|
else if (ccid_header[itf]->bMessageType == CCID_POWER_ON) {
|
||||||
size_t size_atr = (ccid_atr ? ccid_atr[0] : 0);
|
size_t size_atr = (ccid_atr ? ccid_atr[0] : 0);
|
||||||
ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
ccid_resp_fast[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
||||||
ccid_response[itf]->dwLength = size_atr;
|
ccid_resp_fast[itf]->dwLength = size_atr;
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_resp_fast[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->abRFU0 = 0;
|
ccid_resp_fast[itf]->abRFU0 = 0;
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
ccid_resp_fast[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);
|
//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_response[itf]->apdu, ccid_atr + 1, size_atr);
|
memcpy(&ccid_resp_fast[itf]->apdu, ccid_atr + 1, size_atr);
|
||||||
if (ccid_status == 1) {
|
if (ccid_status == 1) {
|
||||||
//card_start(apdu_thread);
|
//card_start(apdu_thread);
|
||||||
}
|
}
|
||||||
ccid_status = 0;
|
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) {
|
else if (ccid_header[itf]->bMessageType == CCID_POWER_OFF) {
|
||||||
if (ccid_status == 0) {
|
if (ccid_status == 0) {
|
||||||
//card_exit(0);
|
//card_exit(0);
|
||||||
}
|
}
|
||||||
ccid_status = 1;
|
ccid_status = 1;
|
||||||
ccid_response[itf]->bMessageType = CCID_SLOT_STATUS_RET;
|
ccid_resp_fast[itf]->bMessageType = CCID_SLOT_STATUS_RET;
|
||||||
ccid_response[itf]->dwLength = 0;
|
ccid_resp_fast[itf]->dwLength = 0;
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_resp_fast[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->abRFU0 = ccid_status;
|
ccid_resp_fast[itf]->abRFU0 = ccid_status;
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
ccid_resp_fast[itf]->abRFU1 = 0;
|
||||||
ccid_write(itf, 0);
|
driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10);
|
||||||
}
|
}
|
||||||
else if (ccid_header[itf]->bMessageType == CCID_SET_PARAMS ||
|
else if (ccid_header[itf]->bMessageType == CCID_SET_PARAMS ||
|
||||||
ccid_header[itf]->bMessageType == CCID_GET_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 */
|
0xFE, /* bIFSC */
|
||||||
0 /* bNadValue */
|
0 /* bNadValue */
|
||||||
};
|
};
|
||||||
ccid_response[itf]->bMessageType = CCID_PARAMS_RET;
|
ccid_resp_fast[itf]->bMessageType = CCID_PARAMS_RET;
|
||||||
ccid_response[itf]->dwLength = sizeof(params);
|
ccid_resp_fast[itf]->dwLength = sizeof(params);
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_resp_fast[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->abRFU0 = ccid_status;
|
ccid_resp_fast[itf]->abRFU0 = ccid_status;
|
||||||
ccid_response[itf]->abRFU1 = 0x0100;
|
ccid_resp_fast[itf]->abRFU1 = 0x0100;
|
||||||
memcpy(&ccid_response[itf]->apdu, params, sizeof(params));
|
memcpy(&ccid_resp_fast[itf]->apdu, params, sizeof(params));
|
||||||
ccid_write(itf, 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) {
|
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);
|
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;
|
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) {
|
bool driver_mounted_ccid(uint8_t itf) {
|
||||||
#ifdef USB_ITF_HID
|
|
||||||
itf -= 2;
|
|
||||||
#endif
|
|
||||||
return tud_vendor_n_mounted(itf);
|
return tud_vendor_n_mounted(itf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_timeout_ccid(uint8_t itf) {
|
void driver_exec_timeout_ccid(uint8_t itf) {
|
||||||
ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf);
|
ccid_resp_fast[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
||||||
ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf));
|
ccid_resp_fast[itf]->dwLength = 0;
|
||||||
ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
ccid_resp_fast[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->dwLength = 0;
|
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_resp_fast[itf]->abRFU0 = CCID_CMD_STATUS_TIMEEXT;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_resp_fast[itf]->abRFU1 = 0;
|
||||||
ccid_response[itf]->abRFU0 = CCID_CMD_STATUS_TIMEEXT;
|
driver_write_ccid(itf, (const uint8_t *)ccid_resp_fast[itf], 10);
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
|
||||||
ccid_write(itf, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_finished_ccid(uint8_t itf, uint16_t size_next) {
|
void driver_exec_finished_ccid(uint8_t itf, uint16_t size_next) {
|
||||||
ccid_header[itf] = (struct ccid_header *) usb_get_rx(itf);
|
driver_exec_finished_cont_ccid(itf, size_next, 0);
|
||||||
ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + 34);
|
|
||||||
ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
|
||||||
ccid_response[itf]->dwLength = size_next;
|
|
||||||
ccid_response[itf]->bSlot = 0;
|
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
|
||||||
ccid_response[itf]->abRFU0 = ccid_status;
|
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
|
||||||
ccid_write_offset(itf, size_next, 34);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_finished_cont_ccid(uint8_t itf, uint16_t size_next, uint16_t offset) {
|
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] = (ccid_header_t *) (ccid_tx[itf].buffer + ccid_tx[itf].w_ptr + offset);
|
||||||
ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + offset - 10 + 34);
|
|
||||||
ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
ccid_response[itf]->bMessageType = CCID_DATA_BLOCK_RET;
|
||||||
ccid_response[itf]->dwLength = size_next;
|
ccid_response[itf]->dwLength = size_next;
|
||||||
ccid_response[itf]->bSlot = 0;
|
ccid_response[itf]->bSlot = 0;
|
||||||
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
ccid_response[itf]->bSeq = ccid_header[itf]->bSeq;
|
||||||
ccid_response[itf]->abRFU0 = ccid_status;
|
ccid_response[itf]->abRFU0 = ccid_status;
|
||||||
ccid_response[itf]->abRFU1 = 0;
|
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) {
|
void ccid_task() {
|
||||||
ccid_response[itf] = (struct ccid_header *) (usb_get_tx(itf) + 34);
|
for (int itf = 0; itf < ITF_SC_TOTAL; itf++) {
|
||||||
apdu.rdata = &ccid_response[itf]->apdu;
|
int status = card_status(sc_itf_to_usb_itf(itf));
|
||||||
apdu.rlen = 0;
|
if (status == CCID_OK) {
|
||||||
return &ccid_response[itf]->apdu;
|
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 USB_CONFIG_ATT_ONE TU_BIT(7)
|
||||||
|
|
||||||
#define MAX_USB_POWER 1
|
#define MAX_USB_POWER 1
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ typedef unsigned long int uint64_t;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
// Size of HID reports
|
// Size of HID reports
|
||||||
|
|
||||||
#define HID_RPT_SIZE 64 // Default size of raw HID report
|
#define HID_RPT_SIZE 64 // Default size of raw HID report
|
||||||
@@ -144,7 +146,8 @@ typedef struct {
|
|||||||
|
|
||||||
// Low-level error codes. Return as negatives.
|
// 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_NONE 0x00 // No error
|
||||||
#define CTAP1_ERR_INVALID_CMD 0x01 // Invalid command
|
#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;
|
extern bool is_nitrokey;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
WRITE_UNKNOWN = 0,
|
|
||||||
WRITE_PENDING,
|
|
||||||
WRITE_FAILED,
|
|
||||||
WRITE_SUCCESS,
|
|
||||||
} write_status_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#ifndef ESP_PLATFORM
|
#ifndef ESP_PLATFORM
|
||||||
#include "bsp/board.h"
|
#include "bsp/board.h"
|
||||||
|
#else
|
||||||
|
static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include "ctap_hid.h"
|
#include "ctap_hid.h"
|
||||||
@@ -28,11 +30,12 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
static bool mounted = false;
|
static bool mounted = false;
|
||||||
void (*init_fido_cb)() = NULL;
|
extern void init_fido();
|
||||||
bool is_nitrokey = false;
|
bool is_nitrokey = false;
|
||||||
uint8_t (*get_version_major)() = NULL;
|
uint8_t (*get_version_major)() = NULL;
|
||||||
uint8_t (*get_version_minor)() = 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 {
|
typedef struct msg_packet {
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
@@ -50,8 +53,15 @@ bool driver_mounted_hid() {
|
|||||||
return mounted;
|
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;
|
CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL;
|
||||||
void send_keepalive();
|
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() {
|
int driver_init_hid() {
|
||||||
#ifndef ENABLE_EMULATION
|
#ifndef ENABLE_EMULATION
|
||||||
static bool _init = false;
|
static bool _init = false;
|
||||||
@@ -60,21 +70,22 @@ int driver_init_hid() {
|
|||||||
_init = true;
|
_init = true;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
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;
|
apdu.rdata = ctap_resp->init.data;
|
||||||
|
//memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
|
|
||||||
usb_set_timeout_counter(ITF_HID, 200);
|
usb_set_timeout_counter(ITF_HID, 200);
|
||||||
|
|
||||||
is_nitrokey = false;
|
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;
|
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) {
|
uint16_t *get_send_buffer_size(uint8_t itf) {
|
||||||
return &send_buffer_size[itf];
|
return &send_buffer_size[itf];
|
||||||
}
|
}
|
||||||
@@ -111,10 +122,12 @@ uint16_t tud_hid_get_report_cb(uint8_t itf,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t hid_write_offset(uint16_t size, uint16_t offset) {
|
uint32_t hid_write_offset(uint16_t size, uint16_t offset) {
|
||||||
if (*usb_get_tx(ITF_HID) != 0x81) {
|
if (hid_tx[ITF_HID_CTAP].buffer[offset] != 0x81) {
|
||||||
DEBUG_PAYLOAD(usb_get_tx(ITF_HID) + offset, size);
|
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) {
|
uint32_t hid_write(uint16_t size) {
|
||||||
@@ -166,14 +179,12 @@ static void send_hid_report(uint8_t report_id) {
|
|||||||
}
|
}
|
||||||
keycode[0] = chr & 0x7f;
|
keycode[0] = chr & 0x7f;
|
||||||
}
|
}
|
||||||
if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, modifier,
|
if (tud_hid_n_keyboard_report(ITF_HID_KB, REPORT_ID_KEYBOARD, modifier, keycode) == true) {
|
||||||
keycode) == true) {
|
|
||||||
sent_key = true;
|
sent_key = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (tud_hid_n_keyboard_report(ITF_KEYBOARD, REPORT_ID_KEYBOARD, 0,
|
if (tud_hid_n_keyboard_report(ITF_HID_KB, REPORT_ID_KEYBOARD, 0, NULL) == true) {
|
||||||
NULL) == true) {
|
|
||||||
keyboard_w++;
|
keyboard_w++;
|
||||||
sent_key = false;
|
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
|
// Poll every 10ms
|
||||||
const uint32_t interval_ms = 10;
|
const uint32_t interval_ms = 10;
|
||||||
static uint32_t start_ms = 0;
|
static uint32_t start_ms = 0;
|
||||||
@@ -211,7 +242,11 @@ void hid_task(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) {
|
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;
|
CTAPHID_FRAME *ctap_req = (CTAPHID_FRAME *) report;
|
||||||
if (last_write_result[instance] == WRITE_PENDING) {
|
if (last_write_result[instance] == WRITE_PENDING) {
|
||||||
last_write_result[instance] = WRITE_SUCCESS;
|
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]);
|
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 (last_write_result[instance] == WRITE_SUCCESS) {
|
if (FRAME_TYPE(ctap_req) != TYPE_INIT || ctap_req->init.cmd != CTAPHID_KEEPALIVE) {
|
||||||
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);
|
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
|
#endif
|
||||||
|
|
||||||
uint16_t driver_read_hid(uint8_t *buffer, uint16_t buffer_size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ENABLE_EMULATION
|
#ifndef ENABLE_EMULATION
|
||||||
|
|
||||||
int (*hid_set_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t) = NULL;
|
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
|
// Invoked when received SET_REPORT control request or
|
||||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||||
|
|
||||||
void tud_hid_set_report_cb(uint8_t itf,
|
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) {
|
||||||
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
|
// This example doesn't use multiple report and report ID
|
||||||
(void) itf;
|
(void) itf;
|
||||||
(void) report_id;
|
(void) report_id;
|
||||||
(void) report_type;
|
(void) report_type;
|
||||||
printf("set_report %d %d %d\n", itf, report_id, 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) {
|
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
|
#endif
|
||||||
|
|
||||||
uint32_t last_cmd_time = 0, last_packet_time = 0;
|
uint32_t last_cmd_time = 0, last_packet_time = 0;
|
||||||
int ctap_error(uint8_t error) {
|
int ctap_error(uint8_t error) {
|
||||||
ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID);
|
memset((uint8_t *)ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
|
||||||
ctap_resp->cid = ctap_req->cid;
|
ctap_resp->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = CTAPHID_ERROR;
|
ctap_resp->init.cmd = CTAPHID_ERROR;
|
||||||
ctap_resp->init.bcntl = 1;
|
ctap_resp->init.bcntl = 1;
|
||||||
ctap_resp->init.data[0] = error;
|
ctap_resp->init.data[0] = error;
|
||||||
hid_write(64);
|
hid_write(64);
|
||||||
usb_clear_rx(ITF_HID);
|
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -301,6 +340,7 @@ uint32_t lock = 0;
|
|||||||
|
|
||||||
uint8_t thread_type = 0; //1 is APDU, 2 is CBOR
|
uint8_t thread_type = 0; //1 is APDU, 2 is CBOR
|
||||||
extern bool cancel_button;
|
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() {
|
int driver_process_usb_nopacket_hid() {
|
||||||
if (last_packet_time > 0 && last_packet_time + 500 < board_millis()) {
|
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 const uint8_t fido_aid[], u2f_aid[];
|
||||||
|
extern void apdu_thread(), cbor_thread();
|
||||||
|
|
||||||
int driver_process_usb_packet_hid(uint16_t read) {
|
int driver_process_usb_packet_hid(uint16_t read) {
|
||||||
int apdu_sent = 0;
|
int apdu_sent = 0;
|
||||||
if (read >= 5) {
|
if (read >= 5) {
|
||||||
driver_init_hid();
|
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();
|
last_packet_time = board_millis();
|
||||||
DEBUG_PAYLOAD(usb_get_rx(ITF_HID) + usb_get_r_offset(ITF_HID), 64);
|
DEBUG_PAYLOAD((uint8_t *)ctap_req, 64);
|
||||||
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
|
||||||
if (ctap_req->cid == 0x0 ||
|
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);
|
return ctap_error(CTAP1_ERR_INVALID_CHANNEL);
|
||||||
}
|
}
|
||||||
if (board_millis() < lock && ctap_req->cid != last_req.cid &&
|
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()) {
|
else if (last_cmd_time + 100 > board_millis()) {
|
||||||
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
|
return ctap_error(CTAP1_ERR_CHANNEL_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctap_req->init.cmd == CTAPHID_INIT) {
|
if (ctap_req->init.cmd == CTAPHID_INIT) {
|
||||||
if (init_fido_cb) {
|
card_exit();
|
||||||
init_fido_cb();
|
hid_tx[ITF_HID_CTAP].r_ptr = hid_tx[ITF_HID_CTAP].w_ptr = 0;
|
||||||
}
|
init_fido();
|
||||||
ctap_resp = (CTAPHID_FRAME *) usb_get_tx(ITF_HID);
|
|
||||||
memset(ctap_resp, 0, 64);
|
|
||||||
CTAPHID_INIT_REQ *req = (CTAPHID_INIT_REQ *) ctap_req->init.data;
|
CTAPHID_INIT_REQ *req = (CTAPHID_INIT_REQ *) ctap_req->init.data;
|
||||||
CTAPHID_INIT_RESP *resp = (CTAPHID_INIT_RESP *) ctap_resp->init.data;
|
CTAPHID_INIT_RESP *resp = (CTAPHID_INIT_RESP *) ctap_resp->init.data;
|
||||||
memcpy(resp->nonce, req->nonce, sizeof(resp->nonce));
|
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.cmd = CTAPHID_INIT;
|
||||||
ctap_resp->init.bcntl = 17;
|
ctap_resp->init.bcntl = 17;
|
||||||
ctap_resp->init.bcnth = 0;
|
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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
}
|
}
|
||||||
@@ -401,19 +442,17 @@ int driver_process_usb_packet_hid(uint16_t read) {
|
|||||||
if (MSG_LEN(ctap_req) != 0) {
|
if (MSG_LEN(ctap_req) != 0) {
|
||||||
return ctap_error(CTAP1_ERR_INVALID_LEN);
|
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));
|
memcpy(ctap_resp, ctap_req, sizeof(CTAPHID_FRAME));
|
||||||
#ifndef ENABLE_EMULATION
|
#ifndef ENABLE_EMULATION
|
||||||
sleep_ms(1000); //For blinking the device during 1 seg
|
sleep_ms(1000); //For blinking the device during 1 seg
|
||||||
#endif
|
#endif
|
||||||
hid_write(64);
|
driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64);
|
||||||
msg_packet.len = msg_packet.current_len = 0;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
|
||||||
}
|
}
|
||||||
else if ((last_cmd == CTAPHID_PING || last_cmd == CTAPHID_SYNC) &&
|
else if ((last_cmd == CTAPHID_PING || last_cmd == CTAPHID_SYNC) &&
|
||||||
(msg_packet.len == 0 ||
|
(msg_packet.len == 0 ||
|
||||||
(msg_packet.len == msg_packet.current_len && 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) {
|
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
|
||||||
memcpy(ctap_resp->init.data, msg_packet.data, msg_packet.len);
|
memcpy(ctap_resp->init.data, msg_packet.data, msg_packet.len);
|
||||||
driver_exec_finished_hid(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.cmd = last_cmd;
|
||||||
ctap_resp->init.bcnth = MSG_LEN(ctap_req) >> 8;
|
ctap_resp->init.bcnth = MSG_LEN(ctap_req) >> 8;
|
||||||
ctap_resp->init.bcntl = MSG_LEN(ctap_req) & 0xff;
|
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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 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);
|
return ctap_error(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
lock = board_millis() + ctap_req->init.data[0] * 1000;
|
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->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = ctap_req->init.cmd;
|
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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
}
|
}
|
||||||
else if (ctap_req->init.cmd == CTAPHID_UUID) {
|
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->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = ctap_req->init.cmd;
|
ctap_resp->init.cmd = ctap_req->init.cmd;
|
||||||
memcpy(ctap_resp->init.data, pico_serial.id, sizeof(pico_serial.id));
|
memcpy(ctap_resp->init.data, pico_serial.id, sizeof(pico_serial.id));
|
||||||
ctap_resp->init.bcntl = 16;
|
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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
}
|
}
|
||||||
else if (ctap_req->init.cmd == CTAPHID_VERSION) {
|
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->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = ctap_req->init.cmd;
|
ctap_resp->init.cmd = ctap_req->init.cmd;
|
||||||
ctap_resp->init.data[0] = PICO_KEYS_SDK_VERSION_MAJOR;
|
ctap_resp->init.data[0] = PICO_KEYS_SDK_VERSION_MAJOR;
|
||||||
ctap_resp->init.data[1] = PICO_KEYS_SDK_VERSION_MINOR;
|
ctap_resp->init.data[1] = PICO_KEYS_SDK_VERSION_MINOR;
|
||||||
ctap_resp->init.bcntl = 4;
|
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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
}
|
}
|
||||||
else if (ctap_req->init.cmd == CTAPHID_ADMIN) {
|
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->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = ctap_req->init.cmd;
|
ctap_resp->init.cmd = ctap_req->init.cmd;
|
||||||
if (ctap_req->init.data[0] == 0x80) { // Status
|
if (ctap_req->init.data[0] == 0x80) { // Status
|
||||||
memcpy(ctap_resp->init.data, "\x00\xff\xff\xff\x00", 5);
|
memcpy(ctap_resp->init.data, "\x00\xff\xff\xff\x00", 5);
|
||||||
ctap_resp->init.bcntl = 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;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 0;
|
last_packet_time = 0;
|
||||||
}
|
}
|
||||||
@@ -497,10 +528,10 @@ int driver_process_usb_packet_hid(uint16_t read) {
|
|||||||
thread_type = 1;
|
thread_type = 1;
|
||||||
|
|
||||||
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
|
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 {
|
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);
|
DEBUG_PAYLOAD(apdu.data, (int) apdu.nc);
|
||||||
msg_packet.len = msg_packet.current_len = 0;
|
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))) {
|
(msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
|
||||||
thread_type = 2;
|
thread_type = 2;
|
||||||
select_app(fido_aid + 1, fido_aid[0]);
|
select_app(fido_aid + 1, fido_aid[0]);
|
||||||
if (cbor_process_cb) {
|
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
|
||||||
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
|
apdu_sent = cbor_process(last_cmd, msg_packet.data, msg_packet.len);
|
||||||
apdu_sent = cbor_process_cb(last_cmd, msg_packet.data, msg_packet.len);
|
}
|
||||||
}
|
else {
|
||||||
else {
|
apdu_sent = cbor_process(last_cmd, ctap_req->init.data, MSG_LEN(ctap_req));
|
||||||
apdu_sent = cbor_process_cb(last_cmd, ctap_req->init.data, MSG_LEN(ctap_req));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
msg_packet.len = msg_packet.current_len = 0;
|
msg_packet.len = msg_packet.current_len = 0;
|
||||||
last_packet_time = 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
|
// echo back anything we received from host
|
||||||
//tud_hid_report(0, buffer, bufsize);
|
//tud_hid_report(0, buffer, bufsize);
|
||||||
//printf("END\n");
|
//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;
|
return apdu_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_keepalive() {
|
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));
|
//memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
|
||||||
resp->cid = ctap_req->cid;
|
resp->cid = ctap_req->cid;
|
||||||
resp->init.cmd = CTAPHID_KEEPALIVE;
|
resp->init.cmd = CTAPHID_KEEPALIVE;
|
||||||
resp->init.bcntl = 1;
|
resp->init.bcntl = 1;
|
||||||
resp->init.data[0] = is_req_button_pending() ? 2 : 1;
|
resp->init.data[0] = is_req_button_pending() ? 2 : 1;
|
||||||
//send_buffer_size[ITF_HID] = 0;
|
//send_buffer_size[ITF_HID_CTAP] = 0;
|
||||||
hid_write_offset(64, 4096);
|
driver_write_hid(ITF_HID_CTAP, (const uint8_t *)resp, 64);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_exec_finished_hid(uint16_t size_next) {
|
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[0] = apdu.sw >> 8;
|
||||||
apdu.rdata[1] = apdu.sw & 0xff;
|
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;
|
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) {
|
void driver_exec_finished_cont_hid(uint8_t itf, uint16_t size_next, uint16_t offset) {
|
||||||
offset -= 7;
|
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->cid = ctap_req->cid;
|
||||||
ctap_resp->init.cmd = last_cmd;
|
|
||||||
ctap_resp->init.bcnth = size_next >> 8;
|
ctap_resp->init.bcnth = size_next >> 8;
|
||||||
ctap_resp->init.bcntl = size_next & 0xff;
|
ctap_resp->init.bcntl = size_next & 0xff;
|
||||||
send_buffer_size[itf] = size_next;
|
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);
|
//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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
349
src/usb/usb.c
349
src/usb/usb.c
@@ -35,138 +35,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
// Device specific functions
|
// 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 };
|
static uint32_t timeout_counter[ITF_TOTAL] = { 0 };
|
||||||
uint8_t card_locked_itf = ITF_TOTAL; // no locked
|
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) {
|
void usb_set_timeout_counter(uint8_t itf, uint32_t v) {
|
||||||
timeout_counter[itf] = 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)
|
#if !defined(ENABLE_EMULATION)
|
||||||
queue_t usb_to_card_q;
|
queue_t usb_to_card_q;
|
||||||
queue_t card_to_usb_q;
|
queue_t card_to_usb_q;
|
||||||
@@ -198,62 +73,24 @@ void usb_init() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int driver_process_usb_nopacket();
|
uint32_t timeout = 0;
|
||||||
extern uint32_t timeout;
|
void timeout_stop() {
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int usb_event_handle(uint8_t itf) {
|
void timeout_start() {
|
||||||
#ifndef ENABLE_EMULATION
|
timeout = board_millis();
|
||||||
uint16_t rx_read = usb_read_available(itf);
|
}
|
||||||
#else
|
|
||||||
uint16_t rx_read = emul_read(itf);
|
bool is_busy() {
|
||||||
#endif
|
return timeout > 0;
|
||||||
int proc_packet = 0;
|
}
|
||||||
#ifndef ENABLE_EMULATION
|
|
||||||
#ifdef USB_ITF_HID
|
void usb_send_event(uint32_t flag) {
|
||||||
if (itf == ITF_HID) {
|
queue_add_blocking(&usb_to_card_q, &flag);
|
||||||
proc_packet = driver_process_usb_packet_hid(rx_read);
|
if (flag == EV_CMD_AVAILABLE) {
|
||||||
}
|
|
||||||
#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();
|
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();
|
extern void low_flash_init();
|
||||||
@@ -265,27 +102,31 @@ void card_init_core1() {
|
|||||||
|
|
||||||
uint16_t finished_data_size = 0;
|
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
|
#ifndef ENABLE_EMULATION
|
||||||
uint32_t m = 0;
|
uint32_t m = 0;
|
||||||
while (queue_is_empty(&usb_to_card_q) == false) {
|
while (queue_is_empty(&usb_to_card_q) == false) {
|
||||||
if (queue_try_remove(&usb_to_card_q, &m) == false) {
|
if (queue_try_remove(&usb_to_card_q, &m) == false) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
while (queue_is_empty(&card_to_usb_q) == false) {
|
||||||
while (queue_is_empty(&card_to_usb_q) == false) {
|
if (queue_try_remove(&card_to_usb_q, &m) == false) {
|
||||||
if (queue_try_remove(&card_to_usb_q, &m) == false) {
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
multicore_reset_core1();
|
||||||
multicore_reset_core1();
|
if (func) {
|
||||||
if (func) {
|
multicore_launch_core1(func);
|
||||||
multicore_launch_core1(func);
|
}
|
||||||
}
|
led_set_blink(BLINK_MOUNTED);
|
||||||
led_set_blink(BLINK_MOUNTED);
|
|
||||||
#else
|
#else
|
||||||
(void)func;
|
(void)func;
|
||||||
#endif
|
#endif
|
||||||
|
card_locked_itf = itf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void card_exit() {
|
void card_exit() {
|
||||||
@@ -293,102 +134,62 @@ void card_exit() {
|
|||||||
uint32_t flag = EV_EXIT;
|
uint32_t flag = EV_EXIT;
|
||||||
queue_try_add(&usb_to_card_q, &flag);
|
queue_try_add(&usb_to_card_q, &flag);
|
||||||
led_set_blink(BLINK_SUSPENDED);
|
led_set_blink(BLINK_SUSPENDED);
|
||||||
|
multicore_reset_core1();
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
hcore1 = NULL;
|
||||||
#endif
|
#endif
|
||||||
card_locked_itf = ITF_TOTAL;
|
card_locked_itf = ITF_TOTAL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
extern void hid_task();
|
extern void hid_task();
|
||||||
|
extern void ccid_task();
|
||||||
void usb_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
|
#ifndef ENABLE_EMULATION
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
hid_task();
|
hid_task();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USB_ITF_CCID
|
||||||
|
ccid_task();
|
||||||
|
#endif
|
||||||
#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) {
|
uint8_t *usb_prepare_response(uint8_t itf) {
|
||||||
#ifndef ENABLE_EMULATION
|
#ifndef ENABLE_EMULATION
|
||||||
#ifdef USB_ITF_HID
|
|
||||||
if (itf == ITF_HID) {
|
|
||||||
return driver_prepare_response_hid();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
if (itf == ITF_CCID || itf == ITF_WCID) {
|
|
||||||
return driver_prepare_response_ccid(itf);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
|
|||||||
106
src/usb/usb.h
106
src/usb/usb.h
@@ -45,17 +45,31 @@
|
|||||||
#define EV_BUTTON_TIMEOUT 16
|
#define EV_BUTTON_TIMEOUT 16
|
||||||
#define EV_BUTTON_PRESSED 32
|
#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 {
|
enum {
|
||||||
#ifdef USB_ITF_HID
|
#ifdef USB_ITF_HID
|
||||||
ITF_HID = 0,
|
ITF_HID = ITF_HID_CTAP,
|
||||||
ITF_KEYBOARD,
|
ITF_KEYBOARD = ITF_HID_KB,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USB_ITF_CCID
|
#ifdef USB_ITF_CCID
|
||||||
ITF_CCID,
|
ITF_CCID = ITF_SC_CCID + ITF_HID_TOTAL,
|
||||||
ITF_WCID,
|
ITF_WCID = ITF_SC_WCID + ITF_HID_TOTAL,
|
||||||
#endif
|
#endif
|
||||||
ITF_TOTAL
|
ITF_TOTAL = ITF_HID_TOTAL + ITF_SC_TOTAL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -70,60 +84,42 @@ extern queue_t card_to_usb_q;
|
|||||||
#endif
|
#endif
|
||||||
extern uint8_t card_locked_itf;
|
extern uint8_t card_locked_itf;
|
||||||
|
|
||||||
#ifdef USB_ITF_HID
|
extern void card_start(uint8_t, void (*func)(void));
|
||||||
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_exit();
|
extern void card_exit();
|
||||||
|
extern int card_status(uint8_t itf);
|
||||||
extern void usb_init();
|
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 uint16_t finished_data_size;
|
||||||
extern void usb_set_timeout_counter(uint8_t itf, uint32_t v);
|
extern void usb_set_timeout_counter(uint8_t itf, uint32_t v);
|
||||||
extern void card_init_core1();
|
extern void card_init_core1();
|
||||||
extern uint32_t usb_write_flush(uint8_t itf);
|
|
||||||
extern uint16_t usb_read_available(uint8_t itf);
|
extern void usb_send_event(uint32_t flag);
|
||||||
extern uint16_t usb_write_available(uint8_t itf);
|
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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user