Improved multicore synchronization. Now they exchange signals and protect areas atomically.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2024-08-23 19:24:18 +02:00
parent 90842bb8f7
commit 7a88a2b8e7
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
11 changed files with 238 additions and 110 deletions

View file

@ -195,15 +195,6 @@ if(USB_ITF_HID)
)
endif()
if (USB_ITF_CCID)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/ccid.c
)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid
)
endif()
set(LIBRARIES
pico_stdlib
pico_multicore
@ -259,7 +250,14 @@ if (ENABLE_EMULATION)
${CMAKE_CURRENT_LIST_DIR}/src/usb/emulation
)
else()
if (USB_ITF_CCID)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/ccid.c
)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid
)
endif()
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/usb_descriptors.c
)

View file

@ -22,6 +22,9 @@
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#endif
#ifdef ENABLE_EMULATION
#include "emulation.h"
#endif
uint8_t *rdata_gr = NULL;
uint16_t rdata_bk = 0x0;
@ -179,14 +182,13 @@ uint16_t set_res_sw(uint8_t sw1, uint8_t sw2) {
return make_uint16_t(sw1, sw2);
}
#ifndef ENABLE_EMULATION
void apdu_thread(void) {
card_init_core1();
while (1) {
uint32_t m = 0;
#ifndef ENABLE_EMULATION
queue_remove_blocking(&usb_to_card_q, &m);
#endif
uint32_t flag = m + 1;
queue_add_blocking(&card_to_usb_q, &flag);
if (m == EV_VERIFY_CMD_AVAILABLE || m == EV_MODIFY_CMD_AVAILABLE) {
set_res_sw(0x6f, 0x00);
@ -202,10 +204,8 @@ done: ;
apdu_finish();
finished_data_size = apdu_next();
uint32_t flag = EV_EXEC_FINISHED;
#ifndef ENABLE_EMULATION
flag = EV_EXEC_FINISHED;
queue_add_blocking(&card_to_usb_q, &flag);
#endif
#ifdef ESP_PLATFORM
vTaskDelay(pdMS_TO_TICKS(10));
#endif
@ -219,7 +219,6 @@ done: ;
vTaskDelete(NULL);
#endif
}
#endif
void apdu_finish() {
apdu.rdata[apdu.rlen] = apdu.sw >> 8;

View file

@ -38,7 +38,6 @@
#define mode_t unsigned short
#define lseek _lseek
#include "mman.h"
#include <fcntl.h>
#else
#ifdef ESP_PLATFORM
#include "esp_compat.h"
@ -58,6 +57,7 @@ const esp_partition_t *part0;
#define XIP_BASE 0
int fd_map = 0;
uint8_t *map = NULL;
#include <fcntl.h>
#endif
#include "pico_keys.h"
#include <string.h>

View file

@ -85,14 +85,12 @@ static inline void ws2812_program_init(PIO pio,
}
#endif
#if defined(ENABLE_EMULATION)
#else
#include "usb.h"
#ifndef ESP_PLATFORM
#if !defined(ESP_PLATFORM) && !defined(ENABLE_EMULATION)
#include "hardware/rtc.h"
#include "bsp/board.h"
#endif
#endif
#include "usb.h"
extern void do_flash();
extern void low_flash_init();
@ -427,8 +425,8 @@ int main(void) {
init_rtc();
#ifndef ENABLE_EMULATION
usb_init();
#ifndef ENABLE_EMULATION
#ifdef ESP_PLATFORM
tusb_cfg.string_descriptor[3] = pico_serial_str;
if (enable_wcid) {

View file

@ -92,7 +92,9 @@ typedef struct {
}) ccid_header_t;
uint8_t ccid_status = 1;
#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};
@ -311,12 +313,6 @@ void driver_exec_finished_cont_ccid(uint8_t itf, uint16_t size_next, uint16_t of
}
void ccid_task() {
#ifdef ENABLE_EMULATION
uint16_t rx_len = emul_read(ITF_CCID);
if (rx_len) {
tud_vendor_rx_cb(ITF_CCID);
}
#else
for (int itf = 0; itf < ITF_SC_TOTAL; itf++) {
int status = card_status(sc_itf_to_usb_itf(itf));
if (status == CCID_OK) {
@ -331,7 +327,6 @@ void ccid_task() {
}
}
}
#endif
}
#ifndef ENABLE_EMULATION

View file

@ -54,7 +54,10 @@ extern uint8_t thread_type;
extern const uint8_t *cbor_data;
extern size_t cbor_len;
extern uint8_t cmd;
uint8_t emul_rx[USB_BUFFER_SIZE], emul_tx[USB_BUFFER_SIZE];
uint16_t emul_rx_size = 0, emul_tx_size = 0;
extern int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len);
pthread_t hcore0, hcore1;
#ifndef _MSC_VER
int msleep(long msec) {
@ -178,6 +181,19 @@ socket_t get_sock_itf(uint8_t itf) {
return INVALID_SOCKET;
}
uint32_t tud_vendor_n_write(uint8_t itf, const uint8_t *buffer, uint32_t n) {
uint16_t ret = driver_write_emul(ITF_CCID, buffer, (uint16_t)n);
tud_vendor_tx_cb(itf, ret);
return ret;
}
bool tud_hid_n_report(uint8_t itf, uint8_t report_id, const uint8_t *buffer, uint32_t n) {
(void) itf;
(void) report_id;
uint16_t ret = driver_write_emul(ITF_HID, buffer, (uint16_t)n);
return ret > 0;
}
uint16_t driver_write_emul(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) {
uint16_t size = htons(buffer_size);
socket_t sock = get_sock_itf(itf);
@ -207,14 +223,11 @@ void driver_exec_finished_cont_emul(uint8_t itf, uint16_t size_next, uint16_t of
#endif
#ifdef USB_ITF_CCID
if (itf == ITF_CCID) {
driver_exec_finished_cont_ccid(itf, size_next, offset);
driver_write_emul(itf, emul_tx, size_next);
}
#endif
}
uint8_t emul_rx[USB_BUFFER_SIZE];
uint16_t emul_rx_size = 0, emul_tx_size = 0;
uint16_t emul_read(uint8_t itf) {
/* First we look for a client */
#ifdef USB_ITF_HID
@ -239,14 +252,15 @@ uint16_t emul_read(uint8_t itf) {
if (hid_client_sock > 0) {
close(hid_client_sock);
}
hid_client_sock = accept(hid_server_sock, (struct sockaddr *) &client_sockaddr,
&client_socklen);
printf("hid_client connected!\n");
hid_client_sock = accept(hid_server_sock, (struct sockaddr *) &client_sockaddr, &client_socklen);
if (hid_client_sock != INVALID_SOCKET) {
printf("hid_client connected! %d\n", hid_client_sock);
}
}
if (send_buffer_size > 0) {
/*if (send_buffer_size > 0) {
last_write_result[itf] = WRITE_PENDING;
tud_hid_report_complete_cb(ITF_HID, complete_report, complete_len);
}
}*/
}
#endif
socket_t sock = get_sock_itf(itf);
@ -263,7 +277,8 @@ uint16_t emul_read(uint8_t itf) {
__pragma(warning(pop))
#endif
struct timeval timeout;
timeout.tv_sec = 0;
int valread = 0;
timeout.tv_sec = 0;
timeout.tv_usec = 0 * 1000;
int n = select((int)(sock + 1), &input, NULL, NULL, &timeout);
if (n == -1) {
@ -274,14 +289,42 @@ uint16_t emul_read(uint8_t itf) {
//printf("read timeout [itf:%d]\n", itf);
}
if (FD_ISSET(sock, &input)) {
int valread = recv(sock, (char *)&len, sizeof(len), 0);
valread = recv(sock, (char *)&len, sizeof(len), 0);
len = ntohs(len);
if (len > 0) {
while (true) {
valread = recv(sock, (char *)emul_rx, len, 0);
valread = recv(sock, (char *)emul_rx + emul_rx_size, len, 0);
if (valread > 0) {
emul_rx_size = valread;
return (uint16_t)valread;
if (len == 1) {
uint8_t c = emul_rx[0];
if (c == 4) {
driver_write_emul(itf, ccid_atr ? ccid_atr + 1 : NULL, ccid_atr ? ccid_atr[0] : 0);
}
}
else {
switch(itf) {
#ifdef USB_ITF_CCID
case ITF_CCID: {
uint16_t sent = 0;
DEBUG_PAYLOAD(emul_rx, len);
apdu.rdata = emul_tx;
if ((sent = apdu_process(itf, emul_rx, len)) > 0) {
process_apdu();
apdu_finish();
}
if (sent > 0) {
uint16_t ret = apdu_next();
DEBUG_PAYLOAD(apdu.rdata, ret);
driver_write_emul(itf, apdu.rdata, ret);
}
break;
}
#endif
default:
emul_rx_size += valread;
}
}
return (uint16_t)emul_rx_size;
}
msleep(10);
}
@ -289,5 +332,14 @@ uint16_t emul_read(uint8_t itf) {
}
//else
// printf("no input for sock %d - %d\n", itf, sock);
return 0;
return emul_rx_size;
}
void emul_task() {
#ifdef USB_ITF_CCID
emul_read(ITF_CCID);
#endif
#ifdef USB_ITF_HID
emul_read(ITF_HID);
#endif
}

View file

@ -19,11 +19,12 @@
#define _EMULATION_H_
#include <stdint.h>
#include <stdlib.h>
#include "usb.h"
#include <string.h>
#ifdef _MSC_VER
#include <windows.h>
#endif
#include <stdbool.h>
#define USB_BUFFER_SIZE 2048
extern int emul_init(char *host, uint16_t port);
extern uint8_t emul_rx[USB_BUFFER_SIZE];
extern uint16_t emul_rx_size, emul_tx_size;
@ -49,11 +50,7 @@ static inline uint32_t tud_vendor_n_read(uint8_t itf, uint8_t *buffer, uint32_t
return n;
}
extern void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes);
static inline uint32_t tud_vendor_n_write(uint8_t itf, const uint8_t *buffer, uint32_t n) {
uint16_t ret = driver_write_emul(ITF_CCID, buffer, (uint16_t)n);
tud_vendor_tx_cb(itf, ret);
return ret;
}
extern uint32_t tud_vendor_n_write(uint8_t itf, const uint8_t *buffer, uint32_t n);
static inline uint32_t tud_vendor_n_flush(uint8_t itf) {
(void) itf;
return emul_tx_size;
@ -62,12 +59,101 @@ static inline uint32_t tud_vendor_n_flush(uint8_t itf) {
#ifdef USB_ITF_HID
extern void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len);
static inline bool tud_hid_n_report(uint8_t itf, uint8_t report_id, const uint8_t *buffer, uint32_t n) {
(void) itf;
(void) report_id;
uint16_t ret = driver_write_emul(ITF_HID, buffer, (uint16_t)n);
return ret > 0;
}
extern bool tud_hid_n_report(uint8_t itf, uint8_t report_id, const uint8_t *buffer, uint32_t n);
#endif
#include <pthread.h>
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cnd;
size_t size_elem;
size_t num_elem;
size_t max_elem;
uint8_t buf[1024];
bool is_init;
} queue_t;
static inline void queue_free(queue_t *a) {
pthread_mutex_destroy(&a->mtx);
pthread_cond_destroy(&a->cnd);
a->is_init = false;
}
static inline void queue_init(queue_t *a, size_t size_elem, size_t max_elem) {
if (a->is_init) {
queue_free(a);
}
pthread_mutex_init(&a->mtx, NULL);
pthread_cond_init(&a->cnd, NULL);
a->size_elem = size_elem;
a->max_elem = max_elem;
a->num_elem = 0;
a->is_init = true;
}
static inline void queue_add_blocking(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == a->max_elem) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline void queue_remove_blocking(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == 0) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline int queue_try_add(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == a->max_elem) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_try_remove(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == 0) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_is_empty(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == 0;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline int queue_is_full(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == a->max_elem;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline void queue_clear(queue_t *a) {
pthread_mutex_lock(&a->mtx);
a->num_elem = 0;
pthread_mutex_unlock(&a->mtx);
}
extern pthread_t hcore0, hcore1;
#define multicore_launch_core1(a) pthread_create(&hcore1, NULL, (void *(*) (void *))a, NULL)
#define multicore_reset_core1() pthread_cancel(hcore1)
#endif // _EMULATION_H_

View file

@ -250,7 +250,7 @@ int driver_write_hid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size) {
return 0;
}
#ifdef ENABLE_EMULATION
tud_hid_report_complete_cb(ITF_HID, buffer, buffer_size);
tud_hid_report_complete_cb(ITF_HID_CTAP, buffer, buffer_size);
#endif
return MIN(64, buffer_size);
}
@ -490,10 +490,8 @@ int driver_process_usb_packet_hid(uint16_t read) {
msg_packet.len = msg_packet.current_len = 0;
last_packet_time = 0;
}
else if ((last_cmd == CTAPHID_CBOR ||
last_cmd >= CTAPHID_VENDOR_FIRST) &&
(msg_packet.len == 0 ||
(msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
else if ((last_cmd == CTAPHID_CBOR || last_cmd >= CTAPHID_VENDOR_FIRST) &&
(msg_packet.len == 0 || (msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
thread_type = 2;
select_app(fido_aid + 1, fido_aid[0]);
if (msg_packet.current_len == msg_packet.len && msg_packet.len > 0) {
@ -523,7 +521,6 @@ 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");
#ifndef ENABLE_EMULATION
if (apdu_sent > 0) {
if (apdu_sent == 1) {
card_start(ITF_HID, apdu_thread);
@ -533,7 +530,6 @@ int driver_process_usb_packet_hid(uint16_t read) {
}
usb_send_event(EV_CMD_AVAILABLE);
}
#endif
}
return apdu_sent;
}
@ -584,9 +580,15 @@ void hid_task() {
#ifdef ENABLE_EMULATION
uint16_t rx_len = emul_read(ITF_HID);
if (rx_len) {
tud_hid_set_report_cb(ITF_HID, 0, 0, emul_rx, rx_len);
uint16_t rptr = 0;
while (rx_len > 0) {
tud_hid_set_report_cb(ITF_HID, 0, 0, emul_rx + rptr, 64);
rx_len -= 64;
rptr += 64;
}
emul_rx_size = 0;
}
#else
#endif
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);
@ -606,7 +608,7 @@ void hid_task() {
}
}
#ifndef ENABLE_EMULATION
/* Keyboard ITF */
// Poll every 10ms
const uint32_t interval_ms = 10;

View file

@ -28,6 +28,8 @@
#include "apdu.h"
#ifndef ENABLE_EMULATION
#include "tusb.h"
#else
#include "emulation.h"
#endif
// For memcpy
@ -36,16 +38,15 @@
// Device specific functions
static uint32_t timeout_counter[ITF_TOTAL] = { 0 };
uint8_t card_locked_itf = ITF_TOTAL; // no locked
static uint8_t card_locked_itf = ITF_TOTAL; // no locked
static void (*card_locked_func)(void) = NULL;
void usb_set_timeout_counter(uint8_t itf, uint32_t v) {
timeout_counter[itf] = v;
}
#if !defined(ENABLE_EMULATION)
queue_t usb_to_card_q;
queue_t card_to_usb_q;
#endif
queue_t usb_to_card_q = {0};
queue_t card_to_usb_q = {0};
#ifndef ENABLE_EMULATION
extern tusb_desc_device_t desc_device;
@ -67,10 +68,9 @@ void usb_init() {
desc_device.idProduct = (data[PHY_PID] << 8) | data[PHY_PID+1];
}
}
#endif
queue_init(&card_to_usb_q, sizeof(uint32_t), 64);
queue_init(&usb_to_card_q, sizeof(uint32_t), 64);
#endif
}
uint32_t timeout = 0;
@ -87,12 +87,12 @@ bool is_busy() {
}
void usb_send_event(uint32_t flag) {
#if !defined(ENABLE_EMULATION)
queue_add_blocking(&usb_to_card_q, &flag);
#endif
if (flag == EV_CMD_AVAILABLE) {
timeout_start();
}
uint32_t m;
queue_remove_blocking(&card_to_usb_q , &m);
}
extern void low_flash_init();
@ -106,9 +106,23 @@ uint16_t finished_data_size = 0;
void card_start(uint8_t itf, void (*func)(void)) {
timeout_start();
if (card_locked_itf != itf) {
#ifndef ENABLE_EMULATION
uint32_t m = 0;
if (card_locked_itf != itf || card_locked_func != func) {
if (card_locked_itf != ITF_TOTAL || card_locked_func != NULL) {
card_exit();
}
if (func) {
multicore_launch_core1(func);
}
led_set_blink(BLINK_MOUNTED);
card_locked_itf = itf;
card_locked_func = func;
}
}
void card_exit() {
if (card_locked_itf != ITF_TOTAL || card_locked_func != NULL) {
usb_send_event(EV_EXIT);
uint32_t m;
while (queue_is_empty(&usb_to_card_q) == false) {
if (queue_try_remove(&usb_to_card_q, &m) == false) {
break;
@ -119,37 +133,25 @@ void card_start(uint8_t itf, void (*func)(void)) {
break;
}
}
led_set_blink(BLINK_SUSPENDED);
multicore_reset_core1();
if (func) {
multicore_launch_core1(func);
}
led_set_blink(BLINK_MOUNTED);
#else
(void)func;
#endif
card_locked_itf = itf;
}
}
void card_exit() {
#ifndef ENABLE_EMULATION
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;
hcore1 = NULL;
#endif
}
card_locked_itf = ITF_TOTAL;
#endif
card_locked_func = NULL;
}
extern void hid_task();
extern void ccid_task();
extern void emul_task();
void usb_task() {
#ifndef ENABLE_EMULATION
#ifdef USB_ITF_HID
hid_task();
#endif
#ifdef ENABLE_EMULATION
emul_task();
#else
#ifdef USB_ITF_CCID
ccid_task();
#endif
@ -157,7 +159,6 @@ void usb_task() {
}
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);
@ -167,13 +168,14 @@ int card_status(uint8_t itf) {
if (m == EV_EXEC_FINISHED) {
timeout_stop();
led_set_blink(BLINK_MOUNTED);
card_locked_itf = ITF_TOTAL;
return CCID_OK;
}
#ifndef ENABLE_EMULATION
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);
}
#endif
return CCID_ERR_FILE_NOT_FOUND;
}
else {
@ -185,8 +187,5 @@ int card_status(uint8_t itf) {
}
}
}
#else
(void) itf;
#endif
return CCID_ERR_FILE_NOT_FOUND;
}

View file

@ -19,7 +19,7 @@
#define _USB_H_
#if defined(ENABLE_EMULATION)
#include <stdbool.h>
#include "emulation.h"
#elif defined(ESP_PLATFORM)
#include "esp_compat.h"
#else
@ -77,11 +77,8 @@ enum {
};
extern void usb_task();
#ifndef ENABLE_EMULATION
extern queue_t usb_to_card_q;
extern queue_t card_to_usb_q;
#endif
extern uint8_t card_locked_itf;
extern void card_start(uint8_t, void (*func)(void));
extern void card_exit();

View file

@ -18,6 +18,8 @@
#ifndef USB_DESCRIPTORS_H_
#define USB_DESCRIPTORS_H_
#include "compat.h"
PACK(
struct ccid_class_descriptor {
uint8_t bLength;