USB suspend/resume change.
This commit is contained in:
25
ChangeLog
25
ChangeLog
@@ -1,3 +1,28 @@
|
||||
2017-11-14 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb-ccid.c (ccid_usb_reset): Remove
|
||||
(usb_event_handle): Return value change to notify
|
||||
caller about needs for going out of the loop.
|
||||
Support USB suspend/resume.
|
||||
(ccid_thread): Supporting USB suspend, sleep forever with
|
||||
timeout_p = NULL.
|
||||
|
||||
* src/main.c (main): Add USB_DEVICE_STATE_ prefix.
|
||||
* src/usb_ctrl.c: Likewise.
|
||||
(usb_device_reset): Don't call ccid_usb_reset.
|
||||
(usb_set_configuration, usb_set_interface): Likewise.
|
||||
|
||||
* src/usb_desc.c (device_desc): bcdUSB = 2.0, supporting
|
||||
suspend/resume.
|
||||
|
||||
2017-11-13 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/usb_ctrl.c: Use new const USB_DEVICE_STATE_*
|
||||
* src/main.c (main): Likewise.
|
||||
* src/usb-ccid.c: Likewise.
|
||||
(INTR_REQ_USB): Remove. Use the definition
|
||||
in usb-lld.h.
|
||||
|
||||
2017-11-08 NIIBE Yutaka <gniibe@fsij.org>
|
||||
|
||||
* src/openpgp-do.c (gpg_do_kdf_check): New.
|
||||
|
||||
2
chopstx
2
chopstx
Submodule chopstx updated: 96d2a81331...5ac8a1f251
@@ -22,15 +22,12 @@ 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 (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_SET_INTERFACE 16
|
||||
#define EV_USB_DEVICE_RESET 32
|
||||
#define EV_CARD_CHANGE 8
|
||||
|
||||
/* OpenPGPcard thread */
|
||||
#define EV_PINPAD_INPUT_DONE 1
|
||||
|
||||
@@ -329,7 +329,7 @@ main (int argc, const char *argv[])
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (bDeviceState != UNCONNECTED)
|
||||
if (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
|
||||
break;
|
||||
|
||||
chopstx_usec_wait (250*1000);
|
||||
|
||||
203
src/usb-ccid.c
203
src/usb-ccid.c
@@ -1513,14 +1513,6 @@ ccid_card_change_signal (int how)
|
||||
eventflag_signal (&c->ccid_comm, EV_CARD_CHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
ccid_usb_reset (int full)
|
||||
{
|
||||
struct ccid *c = &ccid;
|
||||
|
||||
eventflag_signal (&c->ccid_comm,
|
||||
full ? EV_USB_DEVICE_RESET : EV_USB_SET_INTERFACE);
|
||||
}
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
static uint8_t endp2_tx_buf[2];
|
||||
@@ -1555,13 +1547,6 @@ ccid_notify_slot_change (struct ccid *c)
|
||||
#define GPG_THREAD_TERMINATED 0xffff
|
||||
|
||||
|
||||
#ifdef GNU_LINUX_EMULATION
|
||||
#include <signal.h>
|
||||
#define INTR_REQ_USB SIGUSR1
|
||||
#else
|
||||
#define INTR_REQ_USB 20
|
||||
#endif
|
||||
|
||||
extern uint32_t bDeviceState;
|
||||
extern void usb_device_reset (struct usb_dev *dev);
|
||||
extern int usb_setup (struct usb_dev *dev);
|
||||
@@ -1573,7 +1558,12 @@ extern int usb_get_status_interface (struct usb_dev *dev);
|
||||
|
||||
extern int usb_get_descriptor (struct usb_dev *dev);
|
||||
|
||||
static void
|
||||
/*
|
||||
* Return 0 for normal USB event
|
||||
* -1 for USB reset
|
||||
* 1 for SET_INTERFACE or SET_CONFIGURATION
|
||||
*/
|
||||
static int
|
||||
usb_event_handle (struct usb_dev *dev)
|
||||
{
|
||||
uint8_t ep_num;
|
||||
@@ -1582,76 +1572,100 @@ usb_event_handle (struct usb_dev *dev)
|
||||
e = usb_lld_event_handler (dev);
|
||||
ep_num = USB_EVENT_ENDP (e);
|
||||
|
||||
/* Transfer to endpoint (not control endpoint) */
|
||||
if (ep_num != 0)
|
||||
{
|
||||
if (USB_EVENT_TXRX (e))
|
||||
usb_tx_done (ep_num, USB_EVENT_LEN (e));
|
||||
else
|
||||
usb_rx_ready (ep_num, USB_EVENT_LEN (e));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
switch (USB_EVENT_ID (e))
|
||||
{
|
||||
case USB_EVENT_DEVICE_RESET:
|
||||
usb_device_reset (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_DEVICE_ADDRESSED:
|
||||
bDeviceState = ADDRESSED;
|
||||
break;
|
||||
/* Control endpoint */
|
||||
switch (USB_EVENT_ID (e))
|
||||
{
|
||||
case USB_EVENT_DEVICE_RESET:
|
||||
usb_device_reset (dev);
|
||||
return -1;
|
||||
|
||||
case USB_EVENT_GET_DESCRIPTOR:
|
||||
if (usb_get_descriptor (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_DEVICE_ADDRESSED:
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
break;
|
||||
|
||||
case USB_EVENT_SET_CONFIGURATION:
|
||||
if (usb_set_configuration (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_GET_DESCRIPTOR:
|
||||
if (usb_get_descriptor (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_SET_INTERFACE:
|
||||
if (usb_set_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_SET_CONFIGURATION:
|
||||
if (usb_set_configuration (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
else
|
||||
{
|
||||
if (bDeviceState == USB_DEVICE_STATE_ADDRESSED)
|
||||
/* de-Configured */
|
||||
return -1;
|
||||
else
|
||||
/* Configured */
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_EVENT_CTRL_REQUEST:
|
||||
/* Device specific device request. */
|
||||
if (usb_setup (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_SET_INTERFACE:
|
||||
if (usb_set_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
else
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case USB_EVENT_GET_STATUS_INTERFACE:
|
||||
if (usb_get_status_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_CTRL_REQUEST:
|
||||
/* Device specific device request. */
|
||||
if (usb_setup (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_GET_INTERFACE:
|
||||
if (usb_get_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
case USB_EVENT_GET_STATUS_INTERFACE:
|
||||
if (usb_get_status_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_SET_FEATURE_DEVICE:
|
||||
case USB_EVENT_SET_FEATURE_ENDPOINT:
|
||||
case USB_EVENT_CLEAR_FEATURE_DEVICE:
|
||||
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
|
||||
usb_lld_ctrl_ack (dev);
|
||||
break;
|
||||
case USB_EVENT_GET_INTERFACE:
|
||||
if (usb_get_interface (dev) < 0)
|
||||
usb_lld_ctrl_error (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_CTRL_WRITE_FINISH:
|
||||
/* Control WRITE transfer finished. */
|
||||
usb_ctrl_write_finish (dev);
|
||||
break;
|
||||
case USB_EVENT_SET_FEATURE_DEVICE:
|
||||
case USB_EVENT_SET_FEATURE_ENDPOINT:
|
||||
case USB_EVENT_CLEAR_FEATURE_DEVICE:
|
||||
case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
|
||||
usb_lld_ctrl_ack (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_OK:
|
||||
case USB_EVENT_DEVICE_SUSPEND:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case USB_EVENT_CTRL_WRITE_FINISH:
|
||||
/* Control WRITE transfer finished. */
|
||||
usb_ctrl_write_finish (dev);
|
||||
break;
|
||||
|
||||
case USB_EVENT_DEVICE_SUSPEND:
|
||||
bDeviceState |= USB_DEVICE_STATE_SUSPEND;
|
||||
break;
|
||||
|
||||
case USB_EVENT_DEVICE_WAKEUP:
|
||||
bDeviceState &= ~USB_DEVICE_STATE_SUSPEND;
|
||||
break;
|
||||
|
||||
case USB_EVENT_OK:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
poll_event_intr (uint32_t *timeout, struct eventflag *ev, chopstx_intr_t *intr)
|
||||
poll_event_intr (uint32_t *timeout_p,
|
||||
struct eventflag *ev, chopstx_intr_t *intr)
|
||||
{
|
||||
chopstx_poll_cond_t poll_desc;
|
||||
struct chx_poll_head *pd_array[2] = {
|
||||
@@ -1660,7 +1674,7 @@ poll_event_intr (uint32_t *timeout, struct eventflag *ev, chopstx_intr_t *intr)
|
||||
};
|
||||
|
||||
eventflag_prepare_poll (ev, &poll_desc);
|
||||
chopstx_poll (timeout, 2, pd_array);
|
||||
chopstx_poll (timeout_p, 2, pd_array);
|
||||
}
|
||||
|
||||
void *
|
||||
@@ -1670,6 +1684,7 @@ ccid_thread (void *arg)
|
||||
uint32_t timeout;
|
||||
struct usb_dev dev;
|
||||
struct ccid *c = &ccid;
|
||||
uint32_t *timeout_p;
|
||||
|
||||
(void)arg;
|
||||
|
||||
@@ -1680,7 +1695,7 @@ ccid_thread (void *arg)
|
||||
chopstx_claim_irq (&interrupt, INTR_REQ_USB);
|
||||
usb_event_handle (&dev); /* For old SYS < 3.0 */
|
||||
|
||||
device_reset:
|
||||
reset:
|
||||
{
|
||||
struct ep_in *epi = &endpoint_in;
|
||||
struct ep_out *epo = &endpoint_out;
|
||||
@@ -1692,50 +1707,46 @@ ccid_thread (void *arg)
|
||||
ccid_init (c, epi, epo, a);
|
||||
}
|
||||
|
||||
while (bDeviceState != CONFIGURED)
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
if (bDeviceState == USB_DEVICE_STATE_CONFIGURED)
|
||||
{
|
||||
poll_event_intr (NULL, &c->ccid_comm, &interrupt);
|
||||
if (interrupt.ready)
|
||||
usb_event_handle (&dev);
|
||||
|
||||
eventflag_get (&c->ccid_comm);
|
||||
/* Ignore event while not-configured. */
|
||||
ccid_prepare_receive (c);
|
||||
ccid_notify_slot_change (c);
|
||||
}
|
||||
|
||||
interface_reset:
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
ccid_prepare_receive (c);
|
||||
ccid_notify_slot_change (c);
|
||||
while (1)
|
||||
{
|
||||
eventmask_t m;
|
||||
|
||||
poll_event_intr (&timeout, &c->ccid_comm, &interrupt);
|
||||
if (bDeviceState == USB_DEVICE_STATE_CONFIGURED)
|
||||
timeout_p = &timeout;
|
||||
else
|
||||
timeout_p = NULL;
|
||||
|
||||
poll_event_intr (timeout_p, &c->ccid_comm, &interrupt);
|
||||
if (interrupt.ready)
|
||||
{
|
||||
usb_event_handle (&dev);
|
||||
continue;
|
||||
}
|
||||
if (usb_event_handle (&dev) == 0)
|
||||
continue;
|
||||
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
m = eventflag_get (&c->ccid_comm);
|
||||
|
||||
if (m == EV_USB_DEVICE_RESET)
|
||||
{
|
||||
/* RESET handling:
|
||||
* (1) After DEVICE_RESET, it needs to re-start out of the loop.
|
||||
* (2) After SET_INTERFACE, the endpoint is reset to RX_NAK.
|
||||
* It needs to prepare receive again.
|
||||
*/
|
||||
if (c->application)
|
||||
{
|
||||
chopstx_cancel (c->application);
|
||||
chopstx_join (c->application, NULL);
|
||||
c->application = 0;
|
||||
}
|
||||
goto device_reset;
|
||||
goto reset;
|
||||
}
|
||||
else if (m == EV_USB_SET_INTERFACE)
|
||||
/* Upon receival of SET_INTERFACE, the endpoint is reset to RX_NAK.
|
||||
* Thus, we need to prepare receive again.
|
||||
*/
|
||||
goto interface_reset;
|
||||
else if (m == EV_CARD_CHANGE)
|
||||
|
||||
timeout = USB_CCID_TIMEOUT;
|
||||
m = eventflag_get (&c->ccid_comm);
|
||||
|
||||
if (m == EV_CARD_CHANGE)
|
||||
{
|
||||
if (c->ccid_state == CCID_STATE_NOCARD)
|
||||
/* Inserted! */
|
||||
@@ -1820,7 +1831,7 @@ ccid_thread (void *arg)
|
||||
}
|
||||
|
||||
/* Loading reGNUal. */
|
||||
while (bDeviceState != UNCONNECTED)
|
||||
while (bDeviceState != USB_DEVICE_STATE_UNCONNECTED)
|
||||
{
|
||||
chopstx_intr_wait (&interrupt);
|
||||
usb_event_handle (&dev);
|
||||
|
||||
@@ -87,7 +87,7 @@ vcom_port_data_setup (struct usb_dev *dev)
|
||||
#include "usb-msc.h"
|
||||
#endif
|
||||
|
||||
uint32_t bDeviceState = UNCONNECTED; /* USB device status */
|
||||
uint32_t bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
|
||||
#define USB_HID_REQ_GET_REPORT 1
|
||||
#define USB_HID_REQ_GET_IDLE 2
|
||||
@@ -218,8 +218,7 @@ usb_device_reset (struct usb_dev *dev)
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 1);
|
||||
|
||||
bDeviceState = ATTACHED;
|
||||
ccid_usb_reset (1);
|
||||
bDeviceState = USB_DEVICE_STATE_ATTACHED;
|
||||
}
|
||||
|
||||
#define USB_CCID_REQ_ABORT 0x01
|
||||
@@ -414,7 +413,7 @@ usb_ctrl_write_finish (struct usb_dev *dev)
|
||||
if (*ccid_state_p != CCID_STATE_EXITED)
|
||||
return;
|
||||
|
||||
bDeviceState = UNCONNECTED;
|
||||
bDeviceState = USB_DEVICE_STATE_UNCONNECTED;
|
||||
usb_lld_prepare_shutdown (); /* No further USB communication */
|
||||
led_blink (LED_GNUK_EXEC); /* Notify the main. */
|
||||
}
|
||||
@@ -476,7 +475,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
usb_lld_set_configuration (dev, 1);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 0);
|
||||
bDeviceState = CONFIGURED;
|
||||
bDeviceState = USB_DEVICE_STATE_CONFIGURED;
|
||||
}
|
||||
else if (current_conf != dev->dev_req.value)
|
||||
{
|
||||
@@ -486,8 +485,7 @@ usb_set_configuration (struct usb_dev *dev)
|
||||
usb_lld_set_configuration (dev, 0);
|
||||
for (i = 0; i < NUM_INTERFACES; i++)
|
||||
gnuk_setup_endpoints_for_interface (dev, i, 1);
|
||||
bDeviceState = ADDRESSED;
|
||||
ccid_usb_reset (1);
|
||||
bDeviceState = USB_DEVICE_STATE_ADDRESSED;
|
||||
}
|
||||
|
||||
/* Do nothing when current_conf == value */
|
||||
@@ -509,7 +507,6 @@ usb_set_interface (struct usb_dev *dev)
|
||||
else
|
||||
{
|
||||
gnuk_setup_endpoints_for_interface (dev, interface, 0);
|
||||
ccid_usb_reset (0);
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ static const
|
||||
uint8_t device_desc[] = {
|
||||
18, /* bLength */
|
||||
DEVICE_DESCRIPTOR, /* bDescriptorType */
|
||||
0x10, 0x01, /* bcdUSB = 1.1 */
|
||||
0x00, 0x02, /* bcdUSB = 2.0 */
|
||||
0x00, /* bDeviceClass: 0 means deferred to interface */
|
||||
0x00, /* bDeviceSubClass */
|
||||
0x00, /* bDeviceProtocol */
|
||||
|
||||
Reference in New Issue
Block a user