More fixes

This commit is contained in:
Pol Henarejos 2022-05-26 14:15:16 +02:00
parent 77ce276b59
commit d4b0978d50
8 changed files with 159 additions and 164 deletions

View file

@ -44,7 +44,6 @@ set_source_files_properties(
target_sources(pico_ccid PUBLIC
${CMAKE_CURRENT_LIST_DIR}/src/usb/usb.c
${CMAKE_CURRENT_LIST_DIR}/src/usb/usb_descriptors.c
${CMAKE_CURRENT_LIST_DIR}/src/fs/file.c
${CMAKE_CURRENT_LIST_DIR}/src/fs/flash.c
${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c
@ -67,4 +66,4 @@ pico_add_extra_outputs(pico_ccid)
#target_compile_definitions(pico_ccid PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
target_link_libraries(pico_ccid PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc)
target_link_libraries(pico_ccid PRIVATE pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc)

View file

@ -15,20 +15,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
// Pico
#include "pico/stdlib.h"
#include <stdlib.h>
// For memcpy
#include <string.h>
#include "bsp/board.h"
#include "tusb.h"
#include "usb_descriptors.h"
#include "device/usbd_pvt.h"
// Include descriptor struct definitions
#include "usb_common.h"
// USB register definitions from pico-sdk
#include "hardware/regs/usb.h"
// USB hardware struct definitions from pico-sdk
#include "hardware/structs/usb.h"
// For interrupt enable and numbers
#include "hardware/irq.h"
// For resetting the USB controller
#include "hardware/resets.h"
#include "pico/multicore.h"
#include "random.h"
#include "ccid2040.h"
@ -271,105 +276,8 @@ static void ccid_notify_slot_change(struct ccid *c)
#define USB_CCID_TIMEOUT (50)
#define GPG_THREAD_TERMINATED 0xffff
#define GPG_ACK_TIMEOUT 0x6600
static void ccid_init_cb(void) {
struct ccid *c = &ccid;
TU_LOG1("-------- CCID INIT\r\n");
vendord_init();
//ccid_notify_slot_change(c);
}
static void ccid_reset_cb(uint8_t rhport) {
TU_LOG1("-------- CCID RESET\r\n");
itf_num = 0;
vendord_reset(rhport);
}
static uint16_t ccid_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
uint8_t *itf_vendor = (uint8_t *)malloc(sizeof(uint8_t)*max_len);
TU_LOG1("-------- CCID OPEN\r\n");
TU_VERIFY(itf_desc->bInterfaceClass == TUSB_CLASS_SMART_CARD && itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0, 0);
//vendord_open expects a CLASS_VENDOR interface class
memcpy(itf_vendor, itf_desc, sizeof(uint8_t)*max_len);
((tusb_desc_interface_t *)itf_vendor)->bInterfaceClass = TUSB_CLASS_VENDOR_SPECIFIC;
vendord_open(rhport, (tusb_desc_interface_t *)itf_vendor, max_len);
free(itf_vendor);
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t);
TU_VERIFY(max_len >= drv_len, 0);
itf_num = itf_desc->bInterfaceNumber;
return drv_len;
}
// Support for parameterized reset via vendor interface control request
static bool ccid_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const * request) {
// nothing to do with DATA & ACK stage
TU_LOG2("-------- CCID CTRL XFER\r\n");
if (stage != CONTROL_STAGE_SETUP) return true;
if (request->wIndex == itf_num)
{
TU_LOG2("-------- bmRequestType %x, bRequest %x, wValue %x, wLength %x\r\n",request->bmRequestType,request->bRequest, request->wValue, request->wLength);
/*
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL
if (request->bRequest == RESET_REQUEST_BOOTSEL) {
#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
#else
uint gpio_mask = 0u;
#endif
#if !PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
if (request->wValue & 0x100) {
gpio_mask = 1u << (request->wValue >> 9u);
}
#endif
reset_usb_boot(gpio_mask, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
// does not return, otherwise we'd return true
}
#endif
#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT
if (request->bRequest == RESET_REQUEST_FLASH) {
watchdog_reboot(0, 0, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS);
return true;
}
#endif
*/
return true;
}
return false;
}
static bool ccid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
//TU_LOG2("------ CALLED XFER_CB\r\n");
return vendord_xfer_cb(rhport, ep_addr, result, xferred_bytes);
//return true;
}
static usbd_class_driver_t const ccid_driver = {
#if CFG_TUSB_DEBUG >= 2
.name = "CCID",
#endif
.init = ccid_init_cb,
.reset = ccid_reset_cb,
.open = ccid_open,
.control_xfer_cb = ccid_control_xfer_cb,
.xfer_cb = ccid_xfer_cb,
.sof = NULL
};
// Implement callback to add our custom driver
usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
*driver_count = 1;
return &ccid_driver;
}
#define CCID_THREAD_TERMINATED 0xffff
#define CCID_ACK_TIMEOUT 0x6600
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
@ -379,6 +287,44 @@ void led_set_blink(uint32_t mode) {
void execute_tasks();
#include "hardware/structs/ioqspi.h"
#define BUTTON_STATE_ACTIVE 0
bool __no_inline_not_in_flash_func(get_bootsel_button)() {
const uint CS_PIN_INDEX = 1;
// Must disable interrupts, as interrupt handlers may be in flash, and we
// are about to temporarily disable flash access!
uint32_t flags = save_and_disable_interrupts();
// Set chip select to Hi-Z
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
// Note we can't call into any sleep functions in flash right now
for (volatile int i = 0; i < 1000; ++i);
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
// Note the button pulls the pin *low* when pressed.
bool button_state = (sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX));
// Need to restore the state of chip select, else we are going to have a
// bad time when we return to code in flash!
hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
restore_interrupts(flags);
return button_state;
}
static uint32_t board_button_read(void)
{
return BUTTON_STATE_ACTIVE == get_bootsel_button();
}
static bool wait_button() {
uint32_t start_button = board_millis();
bool timeout = false;
@ -406,12 +352,12 @@ static bool wait_button() {
return timeout;
}
void usb_tx_enable(const uint8_t *buf, uint32_t len) {
void usb_tx_enable(const uint8_t *wbuf, uint32_t len) {
if (len > 0) {
if (buf[0] != 0x81)
DEBUG_PAYLOAD(buf,len);
//DEBUG_PAYLOAD(buf,len);
tud_vendor_write(buf, len);
//if (wbuf[0] != 0x81)
DEBUG_PAYLOAD(wbuf,len);
//DEBUG_PAYLOAD(wbuf,len);
usb_write(wbuf, len);
}
}
@ -439,7 +385,7 @@ static const uint8_t ATR_head[] = {
/* Send back ATR (Answer To Reset) */
static enum ccid_state ccid_power_on(struct ccid *c) {
TU_LOG1("!!! CCID POWER ON %d\r\n",c->application);
printf("!!! CCID POWER ON %d\r\n",c->application);
uint8_t p[CCID_MSG_HEADER_SIZE+1]; /* >= size of historical_bytes -1 */
size_t size_atr = (ccid_atr ? ccid_atr[0] : 0);
if (c->application == 0) {
@ -500,7 +446,9 @@ static void ccid_send_status(struct ccid *c) {
c->epi->buf = NULL;
c->epi->tx_done = 1;
memcpy(endp1_tx_buf, ccid_reply, CCID_MSG_HEADER_SIZE);
usb_tx_enable(endp1_tx_buf, CCID_MSG_HEADER_SIZE);
c->tx_busy = 1;
}
@ -786,7 +734,7 @@ static enum ccid_state ccid_handle_data(struct ccid *c)
{
enum ccid_state next_state = c->ccid_state;
TU_LOG3("---- CCID STATE %d,msg_type %x,start %d\r\n",c->ccid_state,c->ccid_header.msg_type,CCID_STATE_START);
printf("---- CCID STATE %d,msg_type %x,start %d\r\n",c->ccid_state,c->ccid_header.msg_type,CCID_STATE_START);
if (c->err != 0) {
ccid_reset(c);
ccid_error(c, CCID_OFFSET_DATA_LEN);
@ -952,7 +900,7 @@ static int end_abdata(struct ep_out *epo, size_t orig_len) {
if (orig_len == USB_LL_BUF_SIZE && len < c->ccid_header.data_len)
/* more packet comes */
return 1;
printf("!!end_abdata len %d %d\r\n",len,c->ccid_header.data_len);
if (len != c->ccid_header.data_len)
epo->err = 1;
@ -963,7 +911,7 @@ static int end_cmd_apdu_head(struct ep_out *epo, size_t orig_len) {
struct ccid *c = (struct ccid *)epo->priv;
(void)orig_len;
printf("!!end_cmd_apdu_head len %d %d %d\r\n",epo->cnt,c->ccid_header.data_len,epo->cnt);
if (epo->cnt < 4 || epo->cnt != c->ccid_header.data_len) {
epo->err = 1;
return 0;
@ -1173,6 +1121,7 @@ static void ccid_rx_ready(uint16_t len) {
int offset = 0;
int cont;
size_t orig_len = len;
printf("epo buf_len %d\r\n",epo->buf_len);
while (epo->err == 0) {
if (len == 0)
break;
@ -1257,13 +1206,13 @@ static void ccid_tx_done () {
}
static int usb_event_handle(struct ccid *c) {
TU_LOG3("!!! tx %d, vendor %d, cfg %d, rx %d\r\n",c->tx_busy,tud_vendor_n_write_available(0),CFG_TUD_VENDOR_TX_BUFSIZE,tud_vendor_available());
if (c->tx_busy == 1 && tud_vendor_n_write_available(0) == CFG_TUD_VENDOR_TX_BUFSIZE) {
//printf("!!! tx %d, rx %d\r\n",c->tx_busy,usb_read_available());
//if (c->tx_busy == 1 && tud_vendor_n_write_available(0) == CFG_TUD_VENDOR_TX_BUFSIZE) {
if (c->tx_busy == 1)
ccid_tx_done ();
}
if (tud_vendor_available() && c->epo->ready) {
uint32_t count = tud_vendor_read(endp1_rx_buf, sizeof(endp1_rx_buf));
if (endp1_rx_buf[0] != 0x65)
if (usb_read_available() && c->epo->ready) {
uint32_t count = usb_read(endp1_rx_buf, sizeof(endp1_rx_buf));
//if (endp1_rx_buf[0] != 0x65)
DEBUG_PAYLOAD(endp1_rx_buf, count);
//DEBUG_PAYLOAD(endp1_rx_buf, count);
ccid_rx_ready(count);
@ -1349,9 +1298,9 @@ void card_thread() {
void ccid_task(void) {
struct ccid *c = &ccid;
if (tud_vendor_mounted()) {
if (usb_is_configured()) {
// connected and there are data available
if ((c->epo->ready && tud_vendor_available()) || (tud_vendor_n_write_available(0) == CFG_TUD_VENDOR_TX_BUFSIZE && c->tx_busy == 1)) {
if ((c->epo->ready && usb_read_available()) || (c->tx_busy == 1)) {
if (usb_event_handle (c) != 0) {
if (c->application) {
uint32_t flag = EV_EXIT;
@ -1369,7 +1318,7 @@ void ccid_task(void) {
uint32_t m = 0x0;
bool has_m = queue_try_remove(&c->ccid_comm, &m);
if (m != 0)
TU_LOG3("\r\n ------ M = %d\r\n",m);
printf("\r\n ------ M = %d\r\n",m);
if (has_m) {
if (m == EV_CARD_CHANGE) {
if (c->ccid_state == CCID_STATE_NOCARD)
@ -1393,7 +1342,7 @@ void ccid_task(void) {
else if (m == EV_EXEC_FINISHED) {
if (c->ccid_state == CCID_STATE_EXECUTE) {
exec_done:
if (c->a->sw == GPG_THREAD_TERMINATED) {
if (c->a->sw == CCID_THREAD_TERMINATED) {
c->sw1sw2[0] = 0x90;
c->sw1sw2[1] = 0x00;
c->state = APDU_STATE_RESULT;
@ -1441,9 +1390,7 @@ void ccid_task(void) {
timeout -= MIN(board_millis()-prev_millis,timeout);
if (timeout == 0) {
if (c->timeout_cnt == 7 && c->ccid_state == CCID_STATE_ACK_REQUIRED_1) {
c->a->sw = GPG_ACK_TIMEOUT;
c->a->res_apdu_data_len = 0;
c->a->sw = GPG_ACK_TIMEOUT;
c->a->sw = CCID_ACK_TIMEOUT;
c->a->res_apdu_data_len = 0;
goto exec_done;
@ -1455,10 +1402,6 @@ void ccid_task(void) {
}
}
void tud_mount_cb() {
ccid_prepare_receive (&ccid);
}
void led_blinking_task() {
#ifdef PICO_DEFAULT_LED_PIN
static uint32_t start_ms = 0;
@ -1567,7 +1510,7 @@ pico_unique_board_id_t unique_id;
void execute_tasks() {
prev_millis = board_millis();
ccid_task();
tud_task(); // tinyusb device task
//tud_task(); // tinyusb device task
led_blinking_task();
}
@ -1575,7 +1518,8 @@ int main(void) {
struct apdu *a = &apdu;
struct ccid *c = &ccid;
board_init();
//board_init();
stdio_init_all();
#ifdef PIMORONI_TINY2040
gpio_init(TINY2040_LED_R_PIN);
@ -1591,10 +1535,9 @@ int main(void) {
#endif
#endif
led_off_all();
tusb_init();
usb_init();
prepare_ccid();
@ -1604,6 +1547,8 @@ int main(void) {
init_rtc();
ccid_prepare_receive(&ccid);
while (1) {
execute_tasks();
neug_task();

View file

@ -18,11 +18,16 @@
#ifndef _CCID2040_H_
#define _CCID2040_H_
#include "ccid.h"
#include "tusb.h"
#include "file.h"
#include "pico/unique_id.h"
#include "pico/util/queue.h"
#include <string.h>
#include "pico/time.h"
static inline uint32_t board_millis(void)
{
return to_ms_since_boot(get_absolute_time());
}
#define USB_REQ_CCID 0xA1

View file

@ -16,9 +16,9 @@
*/
#include "file.h"
#include "tusb.h"
#include "ccid2040.h"
#include <string.h>
#include <stdio.h>
extern const uintptr_t end_data_pool;
extern const uintptr_t start_data_pool;

View file

@ -22,7 +22,6 @@
#include "pico/stdlib.h"
#include "hardware/flash.h"
#include "ccid2040.h"
#include "tusb.h"
#include "file.h"
/*

View file

@ -27,9 +27,14 @@
#include "hardware/structs/rosc.h"
#include "hardware/gpio.h"
#include "hardware/adc.h"
#include "bsp/board.h"
#include "pico/unique_id.h"
#include "pico/time.h"
static inline uint32_t board_millis(void)
{
return to_ms_since_boot(get_absolute_time());
}
void adc_start() {
adc_init();
adc_gpio_init(27);

View file

@ -23,7 +23,7 @@
// For resetting the USB controller
#include "hardware/resets.h"
extern void led_blinking_task();
// Device descriptors
@ -327,6 +327,27 @@ void usb_bus_reset(void) {
configured = false;
}
bool usb_is_configured(void) {
return configured;
}
uint32_t usb_write(uint8_t *buffer, size_t buffer_size) {
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
usb_start_transfer(ep, buffer, MIN(buffer_size, 64));
return MIN(buffer_size, 64);
}
void usb_init() {
usb_device_init();
// Wait until configured
while (!usb_is_configured()) {
tight_loop_contents();
led_blinking_task();
}
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
}
/**
* @brief Send the requested string descriptor to the host.
*
@ -564,30 +585,45 @@ void ep0_out_handler(uint8_t *buf, uint16_t len) {
;
}
#define DEBUG_PAYLOAD(p,s) { \
printf("Payload %s (%d bytes):\r\n", #p,s);\
for (int i = 0; i < s; i += 16) {\
printf("%07Xh : ",i+p);\
for (int j = 0; j < 16; j++) {\
if (j < s-i) printf("%02X ",(p)[i+j]);\
else printf(" ");\
if (j == 7) printf(" ");\
} printf(": "); \
for (int j = 0; j < MIN(16,s-i); j++) {\
printf("%c",(p)[i+j] == 0x0a || (p)[i+j] == 0x0d ? '\\' : (p)[i+j]);\
if (j == 7) printf(" ");\
}\
printf("\r\n");\
} printf("\r\n"); \
}
// Device specific functions
static uint8_t rx_buffer[4096];
static uint16_t w_offset = 0, r_offset = 0;
void ep1_out_handler(uint8_t *buf, uint16_t len) {
printf("RX %d bytes from host\n", len);
// Send data back to host
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
DEBUG_PAYLOAD(buf,len);
uint16_t size = MIN(sizeof(rx_buffer)-w_offset,len);
if (size > 0) {
memcpy(rx_buffer+w_offset, buf, size);
w_offset += size;
}
/*
do {
uint16_t size = MIN(sizeof(rx_buffer)-w_offset,len);
memcpy(rx_buffer+w_offset, buf, size);
len -= size;
w_offset += size;
if (w_offset == sizeof(rx_buffer))
w_offset = 0;
buf += size;
} while (len > 0);
*/
}
uint16_t usb_read_available() {
return w_offset - r_offset;
}
uint16_t usb_read(uint8_t *buffer, size_t buffer_size) {
if (w_offset-r_offset > 0) {
uint16_t size = MIN(buffer_size, w_offset-r_offset);
memcpy(buffer, rx_buffer+r_offset, size);
r_offset += size;
if (r_offset == w_offset) {
r_offset = w_offset = 0;
}
return size;
}
return 0;
}
void ep2_in_handler(uint8_t *buf, uint16_t len) {
@ -595,7 +631,7 @@ void ep2_in_handler(uint8_t *buf, uint16_t len) {
// Get ready to rx again from host
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
}
/*
int main(void) {
stdio_init_all();
printf("USB Device Low-Level hardware example\n");
@ -639,3 +675,4 @@ int main(void) {
return 0;
}
*/

View file

@ -315,6 +315,11 @@ static const unsigned char *descriptor_strings[] = {
#define USB_REQ_CCID 0xA1
extern uint16_t usb_read(uint8_t *buffer, size_t buffer_size);
extern uint16_t usb_read_available();
extern uint32_t usb_write(uint8_t *buffer, size_t buffer_size);
extern bool usb_is_configured();
extern void usb_init();
#endif