aboutsummaryrefslogtreecommitdiff
path: root/example-cdc
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2016-06-08 12:04:05 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2016-06-08 15:40:55 +0900
commit5f1c26ff176ee46f846f74ab361d62305a34c01a (patch)
treea2d93fad1511ce37967afc81aa9bb824b396c89c /example-cdc
parent78718e57df6f55c0670cdb6b70337204dd045dba (diff)
USB API major change
Diffstat (limited to 'example-cdc')
-rw-r--r--example-cdc/sample.c2
-rw-r--r--example-cdc/tty.h4
-rw-r--r--example-cdc/usb-cdc.c334
3 files changed, 227 insertions, 113 deletions
diff --git a/example-cdc/sample.c b/example-cdc/sample.c
index 0acd6a8..d5f45b3 100644
--- a/example-cdc/sample.c
+++ b/example-cdc/sample.c
@@ -117,7 +117,7 @@ main (int argc, const char *argv[])
m = 50;
while (1)
{
- uint8_t s[LINEBUFSIZE];
+ char s[LINEBUFSIZE];
u = 1;
tty_wait_connection (tty);
diff --git a/example-cdc/tty.h b/example-cdc/tty.h
index bd0f070..77e7f46 100644
--- a/example-cdc/tty.h
+++ b/example-cdc/tty.h
@@ -5,5 +5,5 @@ struct tty;
struct tty *tty_open (void);
void tty_wait_configured (struct tty *tty);
void tty_wait_connection (struct tty *tty);
-int tty_send (struct tty *tty, uint8_t *buf, int count);
-int tty_recv (struct tty *tty, uint8_t *buf, uint32_t *timeout);
+int tty_send (struct tty *tty, const char *buf, int count);
+int tty_recv (struct tty *tty, char *buf, uint32_t *timeout);
diff --git a/example-cdc/usb-cdc.c b/example-cdc/usb-cdc.c
index b132d8d..e9abcac 100644
--- a/example-cdc/usb-cdc.c
+++ b/example-cdc/usb-cdc.c
@@ -30,7 +30,7 @@ static const struct line_coding line_coding0 = {
*
* In that case, add argument to TTY_OPEN function and
* modify TTY_GET function to get the TTY structure. Functions which
- * directy accesses TTY0 (usb_cb_device_reset and usb_cb_handle_event)
+ * directy accesses TTY0 (usb_device_reset and usb_set_configuration)
* should be modified, too.
*
* Modification of TTY_MAIN thread will be also needed to echo back
@@ -234,10 +234,10 @@ static const uint8_t vcom_string3[28] = {
#define NUM_INTERFACES 2
-void
-usb_cb_device_reset (void)
+static void
+usb_device_reset (struct usb_dev *dev)
{
- usb_lld_reset (VCOM_FEATURE_BUS_POWERED);
+ usb_lld_reset (dev, VCOM_FEATURE_BUS_POWERED);
/* Initialize Endpoint 0 */
usb_lld_setup_endpoint (ENDP0, EP_CONTROL, 0, ENDP0_RXADDR, ENDP0_TXADDR, 64);
@@ -256,13 +256,15 @@ usb_cb_device_reset (void)
#define CDC_CTRL_DTR 0x0001
-void
-usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
+static void
+usb_ctrl_write_finish (struct usb_dev *dev)
{
- uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
+ struct device_req *arg = &dev->dev_req;
+ uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0
- && USB_SETUP_SET (req) && req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
+ && USB_SETUP_SET (arg->type)
+ && arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
{
struct tty *t = tty_get (arg->index, 0);
@@ -272,63 +274,74 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
chopstx_cond_signal (&t->cnd);
chopstx_mutex_unlock (&t->mtx);
}
+
+ /*
+ * The transaction was already finished. So, it is no use to call
+ * usb_lld_ctrl_error when the condition does not match.
+ */
}
static int
-vcom_port_data_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
+vcom_port_data_setup (struct usb_dev *dev)
{
- if (USB_SETUP_GET (req))
+ struct device_req *arg = &dev->dev_req;
+
+ if (USB_SETUP_GET (arg->type))
{
struct tty *t = tty_get (arg->index, 0);
- if (req_no == USB_CDC_REQ_GET_LINE_CODING)
- return usb_lld_reply_request (&t->line_coding,
- sizeof (struct line_coding), arg);
+ if (arg->request == USB_CDC_REQ_GET_LINE_CODING)
+ return usb_lld_reply_request (dev, &t->line_coding,
+ sizeof (struct line_coding));
}
else /* USB_SETUP_SET (req) */
{
- if (req_no == USB_CDC_REQ_SET_LINE_CODING
+ if (arg->request == USB_CDC_REQ_SET_LINE_CODING
&& arg->len == sizeof (struct line_coding))
{
struct tty *t = tty_get (arg->index, 0);
- usb_lld_set_data_to_recv (&t->line_coding,
- sizeof (struct line_coding));
- return USB_SUCCESS;
+ return usb_lld_set_data_to_recv (dev, &t->line_coding,
+ sizeof (struct line_coding));
}
- else if (req_no == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
- return USB_SUCCESS;
+ else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
+ return 0;
}
- return USB_UNSUPPORT;
+ return -1;
}
-int
-usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg)
+static int
+usb_setup (struct usb_dev *dev)
{
- uint8_t type_rcp = req & (REQUEST_TYPE|RECIPIENT);
+ struct device_req *arg = &dev->dev_req;
+ uint8_t type_rcp = arg->type & (REQUEST_TYPE|RECIPIENT);
if (type_rcp == (CLASS_REQUEST | INTERFACE_RECIPIENT) && arg->index == 0)
- return vcom_port_data_setup (req, req_no, arg);
+ return vcom_port_data_setup (dev);
- return USB_UNSUPPORT;
+ return -1;
}
-int
-usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
- struct req_args *arg)
+static int
+usb_get_descriptor (struct usb_dev *dev)
{
+ struct device_req *arg = &dev->dev_req;
+ uint8_t rcp = arg->type & RECIPIENT;
+ uint8_t desc_type = (arg->value >> 8);
+ uint8_t desc_index = (arg->value & 0xff);
+
if (rcp != DEVICE_RECIPIENT)
- return USB_UNSUPPORT;
+ return -1;
if (desc_type == DEVICE_DESCRIPTOR)
- return usb_lld_reply_request (vcom_device_desc, sizeof (vcom_device_desc),
- arg);
+ return usb_lld_reply_request (dev,
+ vcom_device_desc, sizeof (vcom_device_desc));
else if (desc_type == CONFIG_DESCRIPTOR)
- return usb_lld_reply_request (vcom_config_desc, sizeof (vcom_config_desc),
- arg);
+ return usb_lld_reply_request (dev,
+ vcom_config_desc, sizeof (vcom_config_desc));
else if (desc_type == STRING_DESCRIPTOR)
{
const uint8_t *str;
@@ -353,13 +366,13 @@ usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index,
size = sizeof (vcom_string3);
break;
default:
- return USB_UNSUPPORT;
+ return -1;
}
- return usb_lld_reply_request (str, size, arg);
+ return usb_lld_reply_request (dev, str, size);
}
- return USB_UNSUPPORT;
+ return -1;
}
static void
@@ -388,83 +401,85 @@ vcom_setup_endpoints_for_interface (uint16_t interface, int stop)
}
}
-int
-usb_cb_handle_event (uint8_t event_type, uint16_t value)
+static int
+usb_set_configuration (struct usb_dev *dev)
{
int i;
uint8_t current_conf;
- switch (event_type)
+ current_conf = usb_lld_current_configuration (dev);
+ if (current_conf == 0)
{
- case USB_EVENT_ADDRESS:
+ if (dev->dev_req.value != 1)
+ return -1;
+
+ usb_lld_set_configuration (dev, 1);
+ for (i = 0; i < NUM_INTERFACES; i++)
+ vcom_setup_endpoints_for_interface (i, 0);
+ chopstx_mutex_lock (&tty0.mtx);
+ tty0.device_state = CONFIGURED;
+ chopstx_cond_signal (&tty0.cnd);
+ chopstx_mutex_unlock (&tty0.mtx);
+ }
+ else if (current_conf != dev->dev_req.value)
+ {
+ if (dev->dev_req.value != 0)
+ return -1;
+
+ usb_lld_set_configuration (dev, 0);
+ for (i = 0; i < NUM_INTERFACES; i++)
+ vcom_setup_endpoints_for_interface (i, 1);
chopstx_mutex_lock (&tty0.mtx);
tty0.device_state = ADDRESSED;
+ chopstx_cond_signal (&tty0.cnd);
chopstx_mutex_unlock (&tty0.mtx);
- return USB_SUCCESS;
- case USB_EVENT_CONFIG:
- current_conf = usb_lld_current_configuration ();
- if (current_conf == 0)
- {
- if (value != 1)
- return USB_UNSUPPORT;
-
- usb_lld_set_configuration (1);
- for (i = 0; i < NUM_INTERFACES; i++)
- vcom_setup_endpoints_for_interface (i, 0);
- chopstx_mutex_lock (&tty0.mtx);
- tty0.device_state = CONFIGURED;
- chopstx_mutex_unlock (&tty0.mtx);
- }
- else if (current_conf != value)
- {
- if (value != 0)
- return USB_UNSUPPORT;
-
- usb_lld_set_configuration (0);
- for (i = 0; i < NUM_INTERFACES; i++)
- vcom_setup_endpoints_for_interface (i, 1);
- chopstx_mutex_lock (&tty0.mtx);
- tty0.device_state = ADDRESSED;
- chopstx_mutex_unlock (&tty0.mtx);
- }
- /* Do nothing when current_conf == value */
- return USB_SUCCESS;
- default:
- break;
}
- return USB_UNSUPPORT;
+ return 0;
}
-int
-usb_cb_interface (uint8_t cmd, struct req_args *arg)
+static int
+usb_set_interface (struct usb_dev *dev)
{
- const uint8_t zero = 0;
- uint16_t interface = arg->index;
- uint16_t alt = arg->value;
+ uint16_t interface = dev->dev_req.index;
+ uint16_t alt = dev->dev_req.value;
if (interface >= NUM_INTERFACES)
- return USB_UNSUPPORT;
+ return -1;
- switch (cmd)
+ if (alt != 0)
+ return -1;
+ else
{
- case USB_SET_INTERFACE:
- if (alt != 0)
- return USB_UNSUPPORT;
- else
- {
- vcom_setup_endpoints_for_interface (interface, 0);
- return USB_SUCCESS;
- }
+ vcom_setup_endpoints_for_interface (interface, 0);
+ return 0;
+ }
+}
- case USB_GET_INTERFACE:
- return usb_lld_reply_request (&zero, 1, arg);
+static int
+usb_get_interface (struct usb_dev *dev)
+{
+ const uint8_t zero = 0;
+ uint16_t interface = dev->dev_req.index;
- default:
- case USB_QUERY_INTERFACE:
- return USB_SUCCESS;
- }
+ if (interface >= NUM_INTERFACES)
+ return -1;
+
+ /* We don't have alternate interface, so, always return 0. */
+ return usb_lld_reply_request (dev, &zero, 1);
+}
+
+static int
+usb_get_status_interface (struct usb_dev *dev)
+{
+ const uint16_t status_info = 0;
+ uint16_t interface = dev->dev_req.index;
+
+ if (interface >= NUM_INTERFACES)
+ return -1;
+
+ return usb_lld_reply_request (dev, &status_info, 2);
}
@@ -515,8 +530,8 @@ tty_echo_char (struct tty *t, int c)
}
-void
-usb_cb_tx_done (uint8_t ep_num, uint32_t len)
+static void
+usb_tx_done (uint8_t ep_num, uint16_t len)
{
struct tty *t = tty_get (-1, ep_num);
@@ -598,19 +613,18 @@ tty_input_char (struct tty *t, int c)
return r;
}
-void
-usb_cb_rx_ready (uint8_t ep_num)
+static void
+usb_rx_ready (uint8_t ep_num, uint16_t len)
{
uint8_t recv_buf[64];
struct tty *t = tty_get (-1, ep_num);
if (ep_num == ENDP3)
{
- int i, r;
+ int i;
- r = usb_lld_rx_data_len (ENDP3);
- usb_lld_rxcpy (recv_buf, ep_num, 0, r);
- for (i = 0; i < r; i++)
+ usb_lld_rxcpy (recv_buf, ep_num, 0, len);
+ for (i = 0; i < len; i++)
if (tty_input_char (t, recv_buf[i]))
break;
@@ -652,6 +666,8 @@ static void *
tty_main (void *arg)
{
struct tty *t = arg;
+ struct usb_dev dev;
+ int e;
#if defined(OLDER_SYS_H)
/*
@@ -660,9 +676,9 @@ tty_main (void *arg)
*
* When USB interrupt occurs between usb_lld_init (which assumes
* ISR) and chopstx_claim_irq (which clears pending interrupt),
- * invocation of usb_interrupt_handler won't occur.
+ * invocation of usb_lld_event_handler won't occur.
*
- * Calling usb_interrupt_handler is no harm even if there were no
+ * Calling usb_lld_event_handler is no harm even if there were no
* interrupts, thus, we call it unconditionally here, just in case
* if there is a request.
*
@@ -671,19 +687,117 @@ tty_main (void *arg)
* chopstx_claim_irq after usb_lld_init overrides that.
*
*/
- usb_lld_init (VCOM_FEATURE_BUS_POWERED);
+ usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
- usb_interrupt_handler ();
+ goto event_handle;
#else
chopstx_claim_irq (&usb_intr, INTR_REQ_USB);
- usb_lld_init (VCOM_FEATURE_BUS_POWERED);
+ usb_lld_init (&dev, VCOM_FEATURE_BUS_POWERED);
#endif
while (1)
{
chopstx_poll (NULL, 1, &usb_intr);
if (usb_intr.ready)
- usb_interrupt_handler ();
+ {
+ uint8_t ep_num;
+#if defined(OLDER_SYS_H)
+ event_handle:
+#endif
+ /*
+ * When interrupt is detected, call usb_lld_event_handler.
+ * The event may be one of following:
+ * (1) Transfer to endpoint (bulk or interrupt)
+ * In this case EP_NUM is encoded in the variable E.
+ * (2) "NONE" event: some trasfer was done, but all was
+ * done by lower layer, no other work is needed in
+ * upper layer.
+ * (3) Device events: Reset or Suspend
+ * (4) Device requests to the endpoint zero.
+ *
+ */
+ e = usb_lld_event_handler (&dev);
+ ep_num = USB_EVENT_ENDP (e);
+
+ 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));
+ }
+ else
+ switch (USB_EVENT_ID (e))
+ {
+ case USB_EVENT_DEVICE_RESET:
+ usb_device_reset (&dev);
+ continue;
+
+ case USB_EVENT_GET_DESCRIPTOR:
+ if (usb_get_descriptor (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ continue;
+
+ /* The addres is assigned to the device. We don't
+ * need to do anything for this actually, but in this
+ * application, we maintain the USB status of the
+ * device. Usually, just "continue" as EVENT_NONE is
+ * OK.
+ */
+ case USB_EVENT_DEVICE_ADDRESSED:
+ chopstx_mutex_lock (&tty0.mtx);
+ tty0.device_state = ADDRESSED;
+ chopstx_cond_signal (&tty0.cnd);
+ chopstx_mutex_unlock (&tty0.mtx);
+ continue;
+
+ case USB_EVENT_SET_CONFIGURATION:
+ if (usb_set_configuration (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ else
+ usb_lld_ctrl_good (&dev);
+ continue;
+
+ case USB_EVENT_SET_INTERFACE:
+ if (usb_set_interface (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ else
+ usb_lld_ctrl_good (&dev);
+ continue;
+
+ /* Non standard device request. */
+ case USB_EVENT_CTRL_REQUEST:
+ if (usb_setup (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ else
+ usb_lld_ctrl_good (&dev);
+ continue;
+
+ /* Control WRITE transfer finished. */
+ case USB_EVENT_CTRL_WRITE_FINISH:
+ usb_ctrl_write_finish (&dev);
+ continue;
+
+ case USB_EVENT_GET_STATUS_INTERFACE:
+ if (usb_get_status_interface (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ continue;
+
+ case USB_EVENT_GET_INTERFACE:
+ if (usb_get_interface (&dev) < 0)
+ usb_lld_ctrl_error (&dev);
+ continue;
+
+ case USB_EVENT_NONE:
+ case USB_EVENT_SET_FEATURE_DEVICE:
+ case USB_EVENT_SET_FEATURE_ENDPOINT:
+ case USB_EVENT_CLEAR_FEATURE_DEVICE:
+ case USB_EVENT_CLEAR_FEATURE_ENDPOINT:
+ case USB_EVENT_DEVICE_SUSPEND:
+ default:
+ continue;
+ }
+ }
chopstx_mutex_lock (&t->mtx);
if (t->device_state == CONFIGURED && t->flag_connected
@@ -743,10 +857,10 @@ check_tx (struct tty *t)
}
int
-tty_send (struct tty *t, uint8_t *buf, int len)
+tty_send (struct tty *t, const char *buf, int len)
{
int r;
- uint8_t *p;
+ const char *p;
int count;
p = buf;
@@ -801,7 +915,7 @@ check_rx (void *arg)
*
*/
int
-tty_recv (struct tty *t, uint8_t *buf, uint32_t *timeout)
+tty_recv (struct tty *t, char *buf, uint32_t *timeout)
{
int r;
chopstx_poll_cond_t poll_desc;