USB handling improvement
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 31 May 2016 11:29:31 +0000 (20:29 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 31 May 2016 11:29:31 +0000 (20:29 +0900)
ChangeLog
src/gnuk.h
src/usb-ccid.c
src/usb_ctrl.c

index fbe500c..8f10023 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,11 @@
 2016-05-31  NIIBE Yutaka  <gniibe@fsij.org>
 
+       * src/usb_ctrl.c (usb_cb_interface): call ccid_usb_reset.
+       (usb_cb_handle_event): Likewise.
+
        * src/usb-ccid.c (ccid_thread): Handle RESET->CONFIGURE process
        correctly.
+       (ccid_thread): Handle SET_INTERFACE correctly.
 
        * polarssl/library/aes.c (FT0, FT1, FT2): Add "weak" flag.
 
index 4d774ed..251420e 100644 (file)
@@ -22,14 +22,15 @@ extern struct apdu apdu;
 #define CARD_CHANGE_REMOVE 1
 #define CARD_CHANGE_TOGGLE 2
 void ccid_card_change_signal (int how);
-void ccid_usb_reset (void);
+void ccid_usb_reset (int);
 
 /* CCID thread */
 #define EV_RX_DATA_READY   1 /* USB Rx data available  */
 #define EV_EXEC_FINISHED   2 /* OpenPGP Execution finished */
 #define EV_TX_FINISHED     4 /* CCID Tx finished  */
 #define EV_CARD_CHANGE     8
-#define EV_USB_RESET      16
+#define EV_USB_INTERFACE  16
+#define EV_USB_RESET      32
 
 /* OpenPGPcard thread */
 #define EV_PINPAD_INPUT_DONE      1
@@ -64,7 +65,6 @@ enum ccid_state {
   CCID_STATE_EXEC_REQUESTED,   /* Exec requested */
 };
 
-#define CCID_CARD_INIT CARD_CHANGE_INSERT
 
 extern enum ccid_state *ccid_state_p;
 
index 750d6c2..ceda005 100644 (file)
@@ -258,7 +258,7 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo,
 {
   ccid_state_p = &c->ccid_state;
 
-  c->ccid_state = CCID_STATE_NOCARD;
+  c->ccid_state = CCID_STATE_START;
   c->state = APDU_STATE_WAIT_COMMAND;
   c->p = a->cmd_apdu_data;
   c->len = MAX_CMD_APDU_DATA_SIZE;
@@ -766,7 +766,8 @@ static void ccid_error (struct ccid *c, int offset)
   if (c->ccid_state == CCID_STATE_NOCARD)
     ccid_reply[CCID_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */
   else if (c->ccid_state == CCID_STATE_START)
-    ccid_reply[CCID_MSG_STATUS_OFFSET] = 1; /* 1: ICC present but not activated */
+    /* 1: ICC present but not activated */
+    ccid_reply[CCID_MSG_STATUS_OFFSET] = 1;
   else
     ccid_reply[CCID_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */
   ccid_reply[CCID_MSG_STATUS_OFFSET] |= CCID_CMD_STATUS_ERROR; /* Failed */
@@ -837,7 +838,8 @@ ccid_send_status (struct ccid *c)
   if (c->ccid_state == CCID_STATE_NOCARD)
     ccid_reply[CCID_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */
   else if (c->ccid_state == CCID_STATE_START)
-    ccid_reply[CCID_MSG_STATUS_OFFSET] = 1; /* 1: ICC present but not activated */
+    /* 1: ICC present but not activated */
+    ccid_reply[CCID_MSG_STATUS_OFFSET] = 1;
   else
     ccid_reply[CCID_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */
   ccid_reply[CCID_MSG_ERROR_OFFSET] = 0x00;
@@ -1354,10 +1356,10 @@ ccid_card_change_signal (int how)
 }
 
 void
-ccid_usb_reset (void)
+ccid_usb_reset (int all)
 {
   struct ccid *c = &ccid;
-  eventflag_signal (&c->ccid_comm, EV_USB_RESET);
+  eventflag_signal (&c->ccid_comm, all?EV_USB_RESET:EV_USB_INTERFACE);
 }
 
 
@@ -1375,6 +1377,8 @@ ccid_thread (void *arg)
   extern uint32_t bDeviceState;
   chopstx_intr_t interrupt;
   uint32_t timeout;
+  eventmask_t m;
+  chopstx_poll_cond_t poll_desc;
 
   struct ep_in *epi = &endpoint_in;
   struct ep_out *epo = &endpoint_out;
@@ -1398,18 +1402,22 @@ ccid_thread (void *arg)
 
   while (bDeviceState != CONFIGURED)
     {
-      chopstx_poll (NULL, 1, &interrupt);
-      usb_interrupt_handler ();
+      eventflag_prepare_poll (&c->ccid_comm, &poll_desc);
+      chopstx_poll (NULL, 2, &interrupt, &poll_desc);
+      if (interrupt.ready)
+       {
+         usb_interrupt_handler ();
+         continue;
+       }
+      m = eventflag_get (&c->ccid_comm);
+      /* Ignore event while not-configured.  */
     }
 
-  ccid.ccid_comm.flags = 0;
+ interface:
   timeout = USB_CCID_TIMEOUT;
   ccid_prepare_receive (c);
   while (1)
     {
-      eventmask_t m;
-      chopstx_poll_cond_t poll_desc;
-
       eventflag_prepare_poll (&c->ccid_comm, &poll_desc);
       chopstx_poll (&timeout, 2, &interrupt, &poll_desc);
       if (interrupt.ready)
@@ -1431,6 +1439,11 @@ ccid_thread (void *arg)
            }
          goto reset;
        }
+      else if (m == EV_USB_INTERFACE)
+       /* Upon receivable of SET_INTERFACE, we reset endpoint to RX_NAK.
+        * Thus, we need to prepare receive again.
+        */
+       goto interface;
       else if (m == EV_CARD_CHANGE)
        {
          uint8_t int_msg[2];
index df3755b..aac942c 100644 (file)
@@ -210,7 +210,7 @@ usb_cb_device_reset (void)
     gnuk_setup_endpoints_for_interface (i, 1);
 
   bDeviceState = ATTACHED;
-  ccid_usb_reset ();
+  ccid_usb_reset (1);
 }
 
 #define USB_CCID_REQ_ABORT                     0x01
@@ -439,7 +439,6 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
          usb_lld_set_configuration (value);
          for (i = 0; i < NUM_INTERFACES; i++)
            gnuk_setup_endpoints_for_interface (i, 0);
-         ccid_card_change_signal (CCID_CARD_INIT);
          bDeviceState = CONFIGURED;
        }
       else if (current_conf != value)
@@ -451,6 +450,7 @@ int usb_cb_handle_event (uint8_t event_type, uint16_t value)
          for (i = 0; i < NUM_INTERFACES; i++)
            gnuk_setup_endpoints_for_interface (i, 1);
          bDeviceState = ADDRESSED;
+         ccid_usb_reset (1);
        }
       /* Do nothing when current_conf == value */
       return USB_SUCCESS;
@@ -478,6 +478,7 @@ int usb_cb_interface (uint8_t cmd, struct req_args *arg)
       else
        {
          gnuk_setup_endpoints_for_interface (interface, 0);
+         ccid_usb_reset (0);
          return USB_SUCCESS;
        }