From becf8fabc5c21a52b65d28f51cea46443229e848 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Fri, 9 Nov 2018 20:50:35 +0900 Subject: [PATCH] Fix synchronous sending. --- ChangeLog | 15 ++++++---- chopstx | 2 +- src/gnuk.h | 2 +- src/main.c | 2 +- src/usb-ccid.c | 74 ++++++++++++++++++++++++++++++-------------------- src/usb_ctrl.c | 6 ++-- 6 files changed, 59 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index a35d60f..6bb650a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,14 +3,17 @@ * src/openpgp.c (cmd_pso, cmd_internal_authenticate): Use ccid_comm. - * src/usb-ccid.c (wait_for_tx_finish): New. + * src/usb-ccid.c (struct ccid): New field tx_busy. (ccid_error, ccid_power_on, ccid_send_status, ccid_power_off) (ccid_send_data_block_internal, ccid_send_data_block_0x9000) - (ccid_send_data_block_gr, ccid_send_params): Add call of - wait_for_tx_finish. - (ccid_handle_data): Move c->state change before - ccid_send_datablock_gr, because of wait_for_tx_finish. - (ccid_thread): Don't handle EV_TX_FINISHED. + (ccid_send_data_block_gr, ccid_send_params): Set c->tx_busy. + (ccid_state_p): Remove. + (ccid_get_ccid_state): New. + (ccid_thread): Only handle EV_TX_FINISHED event when c->tx_busy. + + * src/usb_ctrl.c (usb_setup, usb_ctrl_write_finish): Use + ccid_get_ccid_state. + * src/main.c (display_status_code): Likewise. 2018-11-09 NIIBE Yutaka diff --git a/chopstx b/chopstx index 2992b89..1369361 160000 --- a/chopstx +++ b/chopstx @@ -1 +1 @@ -Subproject commit 2992b894e04df8c84a5cccb803566ebd5bafb91d +Subproject commit 1369361e5934e0aa4701b17d1b53811afc453f7a diff --git a/src/gnuk.h b/src/gnuk.h index a03f4b4..383241b 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -64,7 +64,7 @@ enum ccid_state { }; -extern enum ccid_state *const ccid_state_p; +enum ccid_state ccid_get_ccid_state (void); extern volatile uint8_t auth_status; #define AC_NONE_AUTHORIZED 0x00 diff --git a/src/main.c b/src/main.c index 950c87b..05c5f11 100644 --- a/src/main.c +++ b/src/main.c @@ -146,7 +146,7 @@ emit_led (uint32_t on_time, uint32_t off_time) static void display_status_code (void) { - enum ccid_state ccid_state = *ccid_state_p; + enum ccid_state ccid_state = ccid_get_ccid_state (); uint32_t usec; if (ccid_state == CCID_STATE_START) diff --git a/src/usb-ccid.c b/src/usb-ccid.c index 26a5e53..01d37a0 100644 --- a/src/usb-ccid.c +++ b/src/usb-ccid.c @@ -186,9 +186,10 @@ struct ccid_header { /* Data structure handled by CCID layer */ struct ccid { - enum ccid_state ccid_state; - uint8_t state; - uint8_t err; + uint32_t ccid_state : 4; + uint32_t state : 4; + uint32_t err : 1; + uint32_t tx_busy : 1; uint8_t *p; size_t len; @@ -245,6 +246,7 @@ struct ccid { static void ccid_reset (struct ccid *c) { c->err = 0; + c->tx_busy = 0; c->state = APDU_STATE_WAIT_COMMAND; c->p = c->a->cmd_apdu_data; c->len = MAX_CMD_APDU_DATA_SIZE; @@ -256,10 +258,11 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, struct apdu *a) { c->ccid_state = CCID_STATE_START; + c->err = 0; + c->tx_busy = 0; c->state = APDU_STATE_WAIT_COMMAND; c->p = a->cmd_apdu_data; c->len = MAX_CMD_APDU_DATA_SIZE; - c->err = 0; memset (&c->ccid_header, 0, sizeof (struct ccid_header)); c->sw1sw2[0] = 0x90; c->sw1sw2[1] = 0x00; @@ -769,18 +772,6 @@ usb_tx_done (uint8_t ep_num, uint16_t len) #endif } -static void wait_for_tx_finish (struct ccid *c) -{ - eventflag_wait_all (&c->ccid_comm, EV_TX_FINISHED); - - if (c->state == APDU_STATE_RESULT) - ccid_reset (c); - - if (c->state == APDU_STATE_WAIT_COMMAND - || c->state == APDU_STATE_COMMAND_CHAINING - || c->state == APDU_STATE_RESULT_GET_RESPONSE) - ccid_prepare_receive (c); -} /* * ATR (Answer To Reset) string @@ -837,7 +828,7 @@ static void ccid_error (struct ccid *c, int offset) #else usb_lld_write (c->epi->ep_num, ccid_reply, CCID_MSG_HEADER_SIZE); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } extern void *openpgp_card_thread (void *arg); @@ -911,8 +902,7 @@ ccid_power_on (struct ccid *c) usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE + size_atr); #endif DEBUG_INFO ("ON\r\n"); - wait_for_tx_finish (c); - + c->tx_busy = 1; return CCID_STATE_WAIT; } @@ -953,7 +943,7 @@ ccid_send_status (struct ccid *c) #ifdef DEBUG_MORE DEBUG_INFO ("St\r\n"); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } static enum ccid_state @@ -969,7 +959,7 @@ ccid_power_off (struct ccid *c) c->ccid_state = CCID_STATE_START; /* This status change should be here */ ccid_send_status (c); DEBUG_INFO ("OFF\r\n"); - wait_for_tx_finish (c); + c->tx_busy = 1; return CCID_STATE_START; } @@ -1012,7 +1002,7 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error) #else usb_lld_tx_enable (c->epi->ep_num, CCID_MSG_HEADER_SIZE); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; return; } @@ -1090,7 +1080,7 @@ ccid_send_data_block_internal (struct ccid *c, uint8_t status, uint8_t error) #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } static void @@ -1142,7 +1132,7 @@ ccid_send_data_block_0x9000 (struct ccid *c) #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } /* @@ -1239,7 +1229,7 @@ ccid_send_data_block_gr (struct ccid *c, size_t chunk_len) #ifdef DEBUG_MORE DEBUG_INFO ("DATA\r\n"); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } @@ -1288,7 +1278,7 @@ ccid_send_params (struct ccid *c) #ifdef DEBUG_MORE DEBUG_INFO ("PARAMS\r\n"); #endif - wait_for_tx_finish (c); + c->tx_busy = 1; } @@ -1369,9 +1359,9 @@ ccid_handle_data (struct ccid *c) if (c->len <= c->a->expected_res_size) len = c->len; + ccid_send_data_block_gr (c, len); if (c->len == 0) c->state = APDU_STATE_RESULT; - ccid_send_data_block_gr (c, len); c->ccid_state = CCID_STATE_WAIT; DEBUG_INFO ("GET Response.\r\n"); } @@ -1536,7 +1526,13 @@ ccid_handle_timeout (struct ccid *c) } static struct ccid ccid; -enum ccid_state *const ccid_state_p = &ccid.ccid_state; + +enum ccid_state +ccid_get_ccid_state (void) +{ + return ccid.ccid_state; +} + void ccid_card_change_signal (int how) @@ -1717,11 +1713,11 @@ usb_event_handle (struct usb_dev *dev) static chopstx_poll_cond_t ccid_event_poll_desc; static struct chx_poll_head *const ccid_poll[] = { + (struct chx_poll_head *const)&usb_intr, + (struct chx_poll_head *const)&ccid_event_poll_desc #ifdef ACKBTN_SUPPORT (struct chx_poll_head *const)&ack_intr, #endif - (struct chx_poll_head *const)&usb_intr, - (struct chx_poll_head *const)&ccid_event_poll_desc }; #define CCID_POLL_NUM (sizeof (ccid_poll)/sizeof (struct chx_poll_head *)) @@ -1775,7 +1771,13 @@ ccid_thread (void *arg) else timeout_p = NULL; + eventflag_set_mask (&c->ccid_comm, c->tx_busy ? EV_TX_FINISHED : ~0); + +#ifdef ACKBTN_SUPPORT + chopstx_poll (timeout_p, CCID_POLL_NUM - c->tx_busy, ccid_poll); +#else chopstx_poll (timeout_p, CCID_POLL_NUM, ccid_poll); +#endif if (usb_intr.ready) { @@ -1892,6 +1894,18 @@ ccid_thread (void *arg) DEBUG_INFO ("ERR06\r\n"); } #endif + else if (m == EV_TX_FINISHED) + { + if (c->state == APDU_STATE_RESULT) + ccid_reset (c); + else + c->tx_busy = 0; + + if (c->state == APDU_STATE_WAIT_COMMAND + || c->state == APDU_STATE_COMMAND_CHAINING + || c->state == APDU_STATE_RESULT_GET_RESPONSE) + ccid_prepare_receive (c); + } else /* Timeout */ c->ccid_state = ccid_handle_timeout (c); } diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index c494b97..559906c 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -281,7 +281,7 @@ usb_setup (struct usb_dev *dev) if (arg->request == USB_FSIJ_GNUK_DOWNLOAD) { #ifdef FLASH_UPGRADE_SUPPORT - if (*ccid_state_p != CCID_STATE_EXITED) + if (ccid_get_ccid_state () != CCID_STATE_EXITED) return -1; if (addr < &_regnual_start || addr + arg->len > __heap_end__) @@ -299,7 +299,7 @@ usb_setup (struct usb_dev *dev) else if (arg->request == USB_FSIJ_GNUK_EXEC && arg->len == 0) { #ifdef FLASH_UPGRADE_SUPPORT - if (*ccid_state_p != CCID_STATE_EXITED) + if (ccid_get_ccid_state () != CCID_STATE_EXITED) return -1; if (((uintptr_t)addr & 0x03)) @@ -404,7 +404,7 @@ usb_ctrl_write_finish (struct usb_dev *dev) { if (USB_SETUP_SET (arg->type) && arg->request == USB_FSIJ_GNUK_EXEC) { - if (*ccid_state_p != CCID_STATE_EXITED) + if (ccid_get_ccid_state () != CCID_STATE_EXITED) return; bDeviceState = USB_DEVICE_STATE_UNCONNECTED;