Fix USB/CCID writes when APDU is longer than 64 bytes.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2024-08-26 22:41:46 +02:00
parent 23dcc91add
commit c2eda3ca53
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
2 changed files with 35 additions and 38 deletions

View file

@ -92,13 +92,11 @@ typedef struct {
}) ccid_header_t;
uint8_t ccid_status = 1;
static bool tx_finished = true;
#ifndef ENABLE_EMULATION
static uint8_t itf_num;
#endif
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);
@ -114,7 +112,6 @@ void ccid_write(uint8_t itf, uint16_t size) {
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) {
@ -158,42 +155,23 @@ void tud_vendor_rx_cb(uint8_t itf) {
}
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
if (sent_bytes) {
#ifdef ESP_PLATFORM
taskENTER_CRITICAL(&mutex);
#endif
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 += (uint16_t)sent_bytes;
}
if (ccid_tx[itf].r_ptr >= ccid_tx[itf].w_ptr) {
ccid_tx[itf].r_ptr = ccid_tx[itf].w_ptr = 0;
tx_finished = true;
}
}
#ifdef ESP_PLATFORM
taskEXIT_CRITICAL(&mutex);
#endif
}
(void) sent_bytes;
tud_vendor_n_write_flush(itf);
}
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, MIN(buffer_size,64));
}
int r = tud_vendor_n_write(itf, tx_buffer, MIN(buffer_size,64));
last_write_result[itf] = r > 0 ? WRITE_PENDING : WRITE_FAILED;
if (r < buffer_size) {
tx_finished = false;
DEBUG_PAYLOAD(tx_buffer, buffer_size);
}
int r = tud_vendor_n_write(itf, tx_buffer, buffer_size);
if (r > 0) {
r = tud_vendor_n_flush(itf);
tud_vendor_n_flush(itf);
ccid_tx[itf].r_ptr += (uint16_t)buffer_size;
if (ccid_tx[itf].r_ptr >= ccid_tx[itf].w_ptr) {
ccid_tx[itf].r_ptr = ccid_tx[itf].w_ptr = 0;
}
}
#ifdef ENABLE_EMULATION
tud_vendor_tx_cb(itf, r);
@ -202,10 +180,7 @@ int driver_write_ccid(uint8_t itf, const uint8_t *tx_buffer, uint16_t buffer_siz
}
int ccid_write_fast(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) {
if (tx_finished) {
return driver_write_ccid(itf, buffer, buffer_size);
}
return 0;
}
int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) {
@ -333,7 +308,7 @@ void ccid_task() {
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 (ccid_tx[itf].w_ptr > ccid_tx[itf].r_ptr) {
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) {
}

View file

@ -40,6 +40,9 @@
static uint32_t timeout_counter[ITF_TOTAL] = { 0 };
static uint8_t card_locked_itf = ITF_TOTAL; // no locked
static void (*card_locked_func)(void) = NULL;
#ifndef ENABLE_EMULATION
static mutex_t mutex;
#endif
void usb_set_timeout_counter(uint8_t itf, uint32_t v) {
timeout_counter[itf] = v;
@ -68,6 +71,7 @@ void usb_init() {
desc_device.idProduct = (data[PHY_PID] << 8) | data[PHY_PID+1];
}
}
mutex_init(&mutex);
#endif
queue_init(&card_to_usb_q, sizeof(uint32_t), 64);
queue_init(&usb_to_card_q, sizeof(uint32_t), 64);
@ -87,12 +91,18 @@ bool is_busy() {
}
void usb_send_event(uint32_t flag) {
#ifndef ENABLE_EMULATION
mutex_enter_blocking(&mutex);
#endif
queue_add_blocking(&usb_to_card_q, &flag);
if (flag == EV_CMD_AVAILABLE) {
timeout_start();
}
uint32_t m;
queue_remove_blocking(&card_to_usb_q , &m);
#ifndef ENABLE_EMULATION
mutex_exit(&mutex);
#endif
}
extern void low_flash_init();
@ -127,9 +137,15 @@ void card_exit() {
}
}
while (queue_is_empty(&card_to_usb_q) == false) {
#ifndef ENABLE_EMULATION
mutex_enter_blocking(&mutex);
#endif
if (queue_try_remove(&card_to_usb_q, &m) == false) {
break;
}
#ifndef ENABLE_EMULATION
mutex_exit(&mutex);
#endif
}
led_set_blink(BLINK_SUSPENDED);
multicore_reset_core1();
@ -159,7 +175,13 @@ void usb_task() {
int card_status(uint8_t itf) {
if (card_locked_itf == itf) {
uint32_t m = 0x0;
#ifndef ENABLE_EMULATION
mutex_enter_blocking(&mutex);
#endif
bool has_m = queue_try_remove(&card_to_usb_q, &m);
#ifndef ENABLE_EMULATION
mutex_exit(&mutex);
#endif
//if (m != 0)
// printf("\n ------ M = %lu\n",m);
if (has_m) {