USB suspend/resume change.

This commit is contained in:
NIIBE Yutaka
2017-11-14 12:59:18 +09:00
parent bd58997dc9
commit e85527d302
7 changed files with 141 additions and 111 deletions

View File

@@ -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.

Submodule chopstx updated: 96d2a81331...5ac8a1f251

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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 */