diff --git a/src/gnuk.h b/src/gnuk.h index ef88753..811ad84 100644 --- a/src/gnuk.h +++ b/src/gnuk.h @@ -17,6 +17,7 @@ struct apdu { }; extern struct apdu apdu; +void ccid_card_change_signal (void); /* CCID thread */ #define EV_RX_DATA_READY (1) /* USB Rx data available */ diff --git a/src/usb-icc.c b/src/usb-icc.c index 3aa5aca..58d061e 100644 --- a/src/usb-icc.c +++ b/src/usb-icc.c @@ -252,7 +252,7 @@ static void ccid_init (struct ccid *c, struct ep_in *epi, struct ep_out *epo, { icc_state_p = &c->icc_state; - c->icc_state = ICC_STATE_START; + c->icc_state = ICC_STATE_NOCARD; /* Default should be _START ?? */ c->state = APDU_STATE_WAIT_COMMAND; /* * Note: a is not yet initialized yet, we can't use c->a->cmd_apdu_data here. @@ -722,12 +722,12 @@ static void icc_error (struct ccid *c, int offset) icc_reply[4] = 0x00; icc_reply[5] = 0x00; /* Slot */ icc_reply[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; - if (c->icc_state == ICC_STATE_START) - /* 1: ICC present but not activated 2: No ICC present */ - icc_reply[ICC_MSG_STATUS_OFFSET] = 1; + if (c->icc_state == ICC_STATE_NOCARD) + icc_reply[ICC_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */ + else if (c->icc_state == ICC_STATE_START) + icc_reply[ICC_MSG_STATUS_OFFSET] = 1; /* 1: ICC present but not activated */ else - /* An ICC is present and active */ - icc_reply[ICC_MSG_STATUS_OFFSET] = 0; + icc_reply[ICC_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */ icc_reply[ICC_MSG_STATUS_OFFSET] |= ICC_CMD_STATUS_ERROR; /* Failed */ icc_reply[ICC_MSG_ERROR_OFFSET] = offset; icc_reply[ICC_MSG_CHAIN_OFFSET] = 0x00; @@ -793,12 +793,12 @@ icc_send_status (struct ccid *c) icc_reply[4] = 0x00; icc_reply[5] = 0x00; /* Slot */ icc_reply[ICC_MSG_SEQ_OFFSET] = c->icc_header.seq; - if (c->icc_state == ICC_STATE_START) - /* 1: ICC present but not activated 2: No ICC present */ - icc_reply[ICC_MSG_STATUS_OFFSET] = 1; + if (c->icc_state == ICC_STATE_NOCARD) + icc_reply[ICC_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */ + else if (c->icc_state == ICC_STATE_START) + icc_reply[ICC_MSG_STATUS_OFFSET] = 1; /* 1: ICC present but not activated */ else - /* An ICC is present and active */ - icc_reply[ICC_MSG_STATUS_OFFSET] = 0; + icc_reply[ICC_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */ icc_reply[ICC_MSG_ERROR_OFFSET] = 0x00; icc_reply[ICC_MSG_CHAIN_OFFSET] = 0x00; @@ -1075,6 +1075,15 @@ icc_handle_data (struct ccid *c) switch (c->icc_state) { + case ICC_STATE_NOCARD: + if (c->icc_header.msg_type == ICC_SLOT_STATUS) + icc_send_status (c); + else + { + DEBUG_INFO ("ERR00\r\n"); + icc_error (c, ICC_OFFSET_CMD_NOT_SUPPORTED); + } + break; case ICC_STATE_START: if (c->icc_header.msg_type == ICC_POWER_ON) { @@ -1307,6 +1316,15 @@ USBthread (void *arg) return ccid_thread (thd); } +void +ccid_card_change_signal (void) +{ + struct ccid *c = &ccid; + + eventflag_signal (&c->ccid_comm, EV_CARD_CHANGE); +} + + static void * ccid_thread (chopstx_t thd) { @@ -1314,6 +1332,7 @@ ccid_thread (chopstx_t thd) struct ep_out *epo = &endpoint_out; struct ccid *c = &ccid; struct apdu *a = &apdu; + int card_change_requested = 0; epi_init (epi, ENDP1, notify_tx, c); epo_init (epo, ENDP1, notify_icc, c); @@ -1327,7 +1346,33 @@ ccid_thread (chopstx_t thd) m = eventflag_wait_timeout (&c->ccid_comm, USB_ICC_TIMEOUT); - if (m == EV_RX_DATA_READY) + if (m == EV_CARD_CHANGE) + { + if (card_change_requested) + { + led_blink (LED_TWOSHOTS); + + if (c->icc_state == ICC_STATE_NOCARD) + /* Inserted! */ + c->icc_state = ICC_STATE_START; + else + { + if (c->application) + { + eventflag_signal (&c->openpgp_comm, EV_EXIT); + chopstx_join (c->application, NULL); + c->application = 0; + } + + c->icc_state = ICC_STATE_NOCARD; + } + + card_change_requested = 0; + } + else + card_change_requested = 1; + } + else if (m == EV_RX_DATA_READY) c->icc_state = icc_handle_data (c); else if (m == EV_EXEC_FINISHED) if (c->icc_state == ICC_STATE_EXECUTE) @@ -1383,7 +1428,10 @@ ccid_thread (chopstx_t thd) icc_prepare_receive (c); } else /* Timeout */ - c->icc_state = icc_handle_timeout (c); + { + c->icc_state = icc_handle_timeout (c); + card_change_requested = 0; + } } return NULL; diff --git a/src/usb_ctrl.c b/src/usb_ctrl.c index 2fa1e98..cd610ad 100644 --- a/src/usb_ctrl.c +++ b/src/usb_ctrl.c @@ -130,7 +130,11 @@ uint32_t bDeviceState = UNCONNECTED; /* USB device status */ #define USB_HID_REQ_SET_IDLE 10 #define USB_HID_REQ_SET_PROTOCOL 11 +#define HID_LED_STATUS_NUMLOCK 0x01 + static uint8_t hid_idle_rate; /* in 4ms */ +static uint8_t hid_report_saved; +static uint16_t hid_report; static void gnuk_setup_endpoints_for_interface (uint16_t interface, int stop) @@ -346,11 +350,14 @@ usb_cb_setup (uint8_t req, uint8_t req_no, return USB_SUCCESS; case USB_HID_REQ_GET_REPORT: - usb_lld_set_data_to_send (&zero, 2); + /* Request of LED status and key press */ + usb_lld_set_data_to_send (&hid_report, 2); return USB_SUCCESS; case USB_HID_REQ_SET_REPORT: - /* Received LED set request! */ + /* Received LED set request */ + if (len == 1) + usb_lld_set_data_to_recv (&hid_report, len); return USB_SUCCESS; case USB_HID_REQ_GET_PROTOCOL: @@ -388,20 +395,34 @@ usb_cb_setup (uint8_t req, uint8_t req_no, return USB_UNSUPPORT; } -void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, - uint16_t index, uint16_t len) + +void +usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, uint16_t value, + uint16_t index, uint16_t len) { uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT); - if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT) - && USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC && len == 0) + if (type_rcp == (VENDOR_REQUEST | DEVICE_RECIPIENT)) { - if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) - return; + if (USB_SETUP_SET (req) && req_no == USB_FSIJ_GNUK_EXEC && len == 0) + { + if (icc_state_p == NULL || *icc_state_p != ICC_STATE_EXITED) + return; - (void)value; (void)index; - usb_lld_prepare_shutdown (); /* No further USB communication */ - *icc_state_p = ICC_STATE_EXEC_REQUESTED; + (void)value; (void)index; + usb_lld_prepare_shutdown (); /* No further USB communication */ + *icc_state_p = ICC_STATE_EXEC_REQUESTED; + } + } + else if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + { + if (index == 1 && req_no == USB_HID_REQ_SET_REPORT) + { + if ((hid_report ^ hid_report_saved) & HID_LED_STATUS_NUMLOCK) + ccid_card_change_signal (); + + hid_report_saved = hid_report; + } } } diff --git a/src/usb_desc.c b/src/usb_desc.c index 497b5cd..e0d250b 100644 --- a/src/usb_desc.c +++ b/src/usb_desc.c @@ -18,7 +18,7 @@ static const uint8_t hid_report_desc[] = { 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x06, /* USAGE (Keyboard) */ + 0x09, 0x07, /* USAGE (Keypad) */ 0xa1, 0x01, /* COLLECTION (Application) */ 0x05, 0x07, /* USAGE_PAGE (Key Codes) */ 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ @@ -29,16 +29,16 @@ static const uint8_t hid_report_desc[] = { 0x95, 0x08, /* REPORT_COUNT (8) */ 0x81, 0x02, /* INPUT (Data,Var,Abs); Modifier byte */ - /* NumLock, CapsLock, ScrollLock, Compose, Kana */ + /* + * NumLock, CapsLock, ScrollLock, Compose, Kana, Power, Shift, + * Do Not Disturb + */ 0x05, 0x08, /* USAGE_PAGE (LEDs) */ 0x19, 0x01, /* USAGE_MINIMUM (1) */ - 0x29, 0x05, /* USAGE_MAXIMUM (5) */ - 0x95, 0x05, /* REPORT_COUNT (5) */ + 0x29, 0x08, /* USAGE_MAXIMUM (8) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ 0x75, 0x01, /* REPORT_SIZE (1) */ 0x91, 0x02, /* OUTPUT (Data,Var,Abs); LED report */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x01, /* OUTPUT (Constant); LED report padding */ 0x05, 0x07, /* USAGE_PAGE (Key Codes) */ 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ @@ -73,7 +73,7 @@ static const uint8_t gnukDeviceDescriptor[] = { 0x01 /* bNumConfigurations */ }; -#define ICC_TOTAL_LENGTH (9+9+54+7+7) +#define ICC_TOTAL_LENGTH (9+9+54+7+7+7) #define ICC_NUM_INTERFACES 1 #define HID_TOTAL_LENGTH (9+9+7) @@ -126,7 +126,7 @@ static const uint8_t gnukConfigDescriptor[] = { USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType: Interface */ 0, /* bInterfaceNumber: Index of this interface */ 0, /* Alternate setting for this interface */ - 2, /* bNumEndpoints: Bulk-IN, Bulk-OUT */ + 3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */ USB_ICC_INTERFACE_CLASS, USB_ICC_INTERFACE_SUBCLASS, USB_ICC_INTERFACE_BULK_PROTOCOL, @@ -197,6 +197,13 @@ static const uint8_t gnukConfigDescriptor[] = { 0x02, /* bmAttributes: Bulk */ USB_ICC_DATA_SIZE, 0x00, /* wMaxPacketSize: */ 0x00, /* bInterval */ + /*Endpoint IN2 Descriptor*/ + 7, /* bLength: Endpoint Descriptor size */ + USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: Endpoint */ + 0x82, /* bEndpointAddress: (IN2) */ + 0x03, /* bmAttributes: Interrupt */ + 4, 0x00, /* wMaxPacketSize: */ + 0x20, /* bInterval (32ms) */ /* Interface Descriptor */ 9, /* bLength: Interface Descriptor size */