diff --git a/CMakeLists.txt b/CMakeLists.txt
index 87cdf61..39ecce6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/src/ccid/ccid2040.c b/src/ccid/ccid2040.c
index 76aa668..0b941c1 100644
--- a/src/ccid/ccid2040.c
+++ b/src/ccid/ccid2040.c
@@ -15,20 +15,25 @@
* along with this program. If not, see .
*/
-
#include
// Pico
#include "pico/stdlib.h"
-#include
// For memcpy
#include
-#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) {
@@ -499,8 +445,10 @@ static void ccid_send_status(struct ccid *c) {
/* This is a single packet Bulk-IN transaction */
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);
@@ -1590,11 +1534,10 @@ int main(void) {
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
#endif
#endif
-
led_off_all();
- tusb_init();
+ usb_init();
prepare_ccid();
@@ -1603,6 +1546,8 @@ int main(void) {
low_flash_init();
init_rtc();
+
+ ccid_prepare_receive(&ccid);
while (1) {
execute_tasks();
diff --git a/src/ccid/ccid2040.h b/src/ccid/ccid2040.h
index e9ef919..2fa1d2f 100644
--- a/src/ccid/ccid2040.h
+++ b/src/ccid/ccid2040.h
@@ -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
+
+#include "pico/time.h"
+static inline uint32_t board_millis(void)
+{
+ return to_ms_since_boot(get_absolute_time());
+}
#define USB_REQ_CCID 0xA1
diff --git a/src/fs/file.c b/src/fs/file.c
index ca54ca8..1e082ea 100644
--- a/src/fs/file.c
+++ b/src/fs/file.c
@@ -16,9 +16,9 @@
*/
#include "file.h"
-#include "tusb.h"
#include "ccid2040.h"
#include
+#include
extern const uintptr_t end_data_pool;
extern const uintptr_t start_data_pool;
diff --git a/src/fs/flash.c b/src/fs/flash.c
index e298cb6..f901494 100644
--- a/src/fs/flash.c
+++ b/src/fs/flash.c
@@ -22,7 +22,6 @@
#include "pico/stdlib.h"
#include "hardware/flash.h"
#include "ccid2040.h"
-#include "tusb.h"
#include "file.h"
/*
diff --git a/src/rng/neug.c b/src/rng/neug.c
index 63c731a..df0ade5 100644
--- a/src/rng/neug.c
+++ b/src/rng/neug.c
@@ -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);
diff --git a/src/usb/usb.c b/src/usb/usb.c
index d786adc..f7aa65d 100644
--- a/src/usb/usb.c
+++ b/src/usb/usb.c
@@ -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;
}
+*/
diff --git a/src/usb/usb_common.h b/src/usb/usb_common.h
index 66c8a26..cb53609 100644
--- a/src/usb/usb_common.h
+++ b/src/usb/usb_common.h
@@ -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