From 5f1c26ff176ee46f846f74ab361d62305a34c01a Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka <gniibe@fsij.org> Date: Wed, 8 Jun 2016 12:04:05 +0900 Subject: USB API major change --- ChangeLog | 8 + NEWS | 9 + example-cdc/sample.c | 2 +- example-cdc/tty.h | 4 +- example-cdc/usb-cdc.c | 334 +++++++++++++++++++---------- mcu/usb-stm32f103.c | 565 +++++++++++++++++++++++++------------------------- usb_lld.h | 99 +++++---- 7 files changed, 581 insertions(+), 440 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c7188f..c524c7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-06-08 NIIBE Yutaka <gniibe@fsij.org> + + * mcu/usb-stm32f103.c: Rewrite to be event driven API. + + * example-cdc/usb-cdc.c: Update to new USB API. + * example-cdc/tty.h: Change tty API to be C string (char*) + friendly. + 2016-06-02 Niibe Yutaka <gniibe@fsij.org> * contrib/adc-mkl27z.c: Move from mcu. diff --git a/NEWS b/NEWS index e3c0838..83f9a85 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,15 @@ NEWS - Noteworthy changes +* Major changes in Chopstx 0.13 + + Released 2016-06-xx + +** New USB API +Since USB driver is included, it should be good one. It used to be +interrupt based API with callbacks. Now, it's event driven API. + + * Major changes in Chopstx 0.12 Released 2016-05-31 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; diff --git a/mcu/usb-stm32f103.c b/mcu/usb-stm32f103.c index d41c960..3a0ce48 100644 --- a/mcu/usb-stm32f103.c +++ b/mcu/usb-stm32f103.c @@ -56,50 +56,20 @@ enum STANDARD_REQUESTS enum CONTROL_STATE { WAIT_SETUP, - SETTING_UP, IN_DATA, OUT_DATA, LAST_IN_DATA, WAIT_STATUS_IN, WAIT_STATUS_OUT, STALLED, - PAUSE }; enum FEATURE_SELECTOR { - ENDPOINT_STALL, - DEVICE_REMOTE_WAKEUP + FEATURE_ENDPOINT_HALT=0, + FEATURE_DEVICE_REMOTE_WAKEUP=1 }; -struct DATA_INFO -{ - uint8_t *addr; - uint16_t len; - uint8_t require_zlp; -}; - - -struct DEVICE_INFO -{ - uint8_t current_configuration; - uint8_t current_feature; - uint8_t state; - /**/ - uint8_t bmRequestType; - uint8_t bRequest; - /**/ - uint16_t value; - uint16_t index; - uint16_t len; -}; - -static struct DEVICE_INFO device_info; -static struct DATA_INFO data_info; - -static struct DEVICE_INFO *const dev_p = &device_info; -static struct DATA_INFO *const data_p = &data_info; - #define REG_BASE (0x40005C00UL) /* USB_IP Peripheral Registers base address */ #define PMA_ADDR (0x40006000UL) /* USB_IP Packet Memory Area base address */ @@ -181,7 +151,7 @@ static struct DATA_INFO *const data_p = &data_info; #define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ #define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ -static void usb_handle_transfer (uint16_t istr_value); +static int usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value); static void st103_set_btable (void) { @@ -376,14 +346,31 @@ static void st103_ep_clear_dtog_tx (uint8_t ep_num) } } -void usb_lld_init (uint8_t feature) +void +usb_lld_ctrl_error (struct usb_dev *dev) { - usb_lld_sys_init (); + dev->state = STALLED; + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL); +} - dev_p->state = IN_DATA; +void +usb_lld_ctrl_good (struct usb_dev *dev) +{ + if (dev->dev_req.len == 0) + { + dev->state = WAIT_STATUS_IN; + st103_set_tx_count (ENDP0, 0); + st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID); + } +} - usb_lld_set_configuration (0); - dev_p->current_feature = feature; +void usb_lld_init (struct usb_dev *dev, uint8_t feature) +{ + usb_lld_sys_init (); + + dev->configuration = 0; + dev->feature = feature; + dev->state = WAIT_SETUP; /* Reset USB */ st103_set_cntr (CNTR_FRES); @@ -406,15 +393,18 @@ void usb_lld_shutdown (void) usb_lld_sys_shutdown (); } -void -usb_interrupt_handler (void) +#define USB_MAKE_EV(event) (event<<24) +#define USB_MAKE_TXRX(ep_num,txrx,len) ((txrx? (1<<23):0)|(ep_num<<16)|len) + +int +usb_lld_event_handler (struct usb_dev *dev) { uint16_t istr_value = st103_get_istr (); if ((istr_value & ISTR_RESET)) { st103_set_istr (CLR_RESET); - usb_cb_device_reset (); + return USB_MAKE_EV (USB_EVENT_DEVICE_RESET); } else { @@ -425,42 +415,45 @@ usb_interrupt_handler (void) st103_set_istr (CLR_ERR); if ((istr_value & ISTR_CTR)) - usb_handle_transfer (istr_value); + return usb_handle_transfer (dev, istr_value); } + + return 0; } -static void handle_datastage_out (void) +static void handle_datastage_out (struct usb_dev *dev) { - if (data_p->addr && data_p->len) + if (dev->ctrl_data.addr && dev->ctrl_data.len) { uint32_t len = st103_get_rx_count (ENDP0); - if (len > data_p->len) - len = data_p->len; + if (len > dev->ctrl_data.len) + len = dev->ctrl_data.len; - usb_lld_from_pmabuf (data_p->addr, st103_get_rx_addr (ENDP0), len); - data_p->len -= len; - data_p->addr += len; + usb_lld_from_pmabuf (dev->ctrl_data.addr, st103_get_rx_addr (ENDP0), len); + dev->ctrl_data.len -= len; + dev->ctrl_data.addr += len; } - if (data_p->len == 0) + if (dev->ctrl_data.len == 0) { - dev_p->state = WAIT_STATUS_IN; + dev->state = WAIT_STATUS_IN; st103_set_tx_count (ENDP0, 0); - st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); } else { - dev_p->state = OUT_DATA; + dev->state = OUT_DATA; st103_ep_set_rx_status (ENDP0, EP_RX_VALID); } } -static void handle_datastage_in (void) +static void handle_datastage_in (struct usb_dev *dev) { uint32_t len = USB_MAX_PACKET_SIZE;; + struct ctrl_data *data_p = &dev->ctrl_data; - if ((data_p->len == 0) && (dev_p->state == LAST_IN_DATA)) + if ((data_p->len == 0) && (dev->state == LAST_IN_DATA)) { if (data_p->require_zlp) { @@ -468,19 +461,19 @@ static void handle_datastage_in (void) /* No more data to send. Send empty packet */ st103_set_tx_count (ENDP0, 0); - st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_VALID); + st103_ep_set_tx_status (ENDP0, EP_TX_VALID); } else { - /* No more data to send, proceed to receive OUT acknowledge.*/ - dev_p->state = WAIT_STATUS_OUT; - st103_ep_set_rxtx_status (ENDP0, EP_RX_VALID, EP_TX_STALL); + /* No more data to send, proceed to receive OUT acknowledge. */ + dev->state = WAIT_STATUS_OUT; + st103_ep_set_rx_status (ENDP0, EP_RX_VALID); } return; } - dev_p->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA; + dev->state = (data_p->len <= len) ? LAST_IN_DATA : IN_DATA; if (len > data_p->len) len = data_p->len; @@ -492,29 +485,30 @@ static void handle_datastage_in (void) st103_ep_set_tx_status (ENDP0, EP_TX_VALID); } -typedef int (*HANDLER) (uint8_t req, struct req_args *arg); +typedef int (*HANDLER) (struct usb_dev *dev); -static int std_none (uint8_t req, struct req_args *arg) +static int std_none (struct usb_dev *dev) { - (void)req; (void)arg; - return USB_UNSUPPORT; + (void)dev; + return -1; } -static int std_get_status (uint8_t req, struct req_args *arg) +static int std_get_status (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = (arg->type & RECIPIENT); uint16_t status_info = 0; if (arg->value != 0 || arg->len != 2 || (arg->index >> 8) != 0 - || USB_SETUP_SET (req)) - return USB_UNSUPPORT; + || USB_SETUP_SET (arg->type)) + return -1; if (rcp == DEVICE_RECIPIENT) { if (arg->index == 0) { /* Get Device Status */ - uint8_t feature = dev_p->current_feature; + uint8_t feature = dev->feature; /* Remote Wakeup enabled */ if ((feature & (1 << 5))) @@ -528,21 +522,15 @@ static int std_get_status (uint8_t req, struct req_args *arg) else /* Self-powered */ status_info &= ~1; - return usb_lld_reply_request (&status_info, 2, arg); + return usb_lld_reply_request (dev, &status_info, 2); } } else if (rcp == INTERFACE_RECIPIENT) { - int r; - - if (dev_p->current_configuration == 0) - return USB_UNSUPPORT; - - r = usb_cb_interface (USB_QUERY_INTERFACE, arg); - if (r != USB_SUCCESS) - return USB_UNSUPPORT; + if (dev->configuration == 0) + return -1; - return usb_lld_reply_request (&status_info, 2, arg); + return USB_EVENT_GET_STATUS_INTERFACE; } else if (rcp == ENDPOINT_RECIPIENT) { @@ -550,13 +538,13 @@ static int std_get_status (uint8_t req, struct req_args *arg) uint16_t status; if ((arg->index & 0x70) || endpoint == ENDP0) - return USB_UNSUPPORT; + return -1; if ((arg->index & 0x80)) { status = st103_ep_get_tx_status (endpoint); if (status == 0) /* Disabled */ - return USB_UNSUPPORT; + return -1; else if (status == EP_TX_STALL) status_info |= 1; /* IN Endpoint stalled */ } @@ -564,33 +552,34 @@ static int std_get_status (uint8_t req, struct req_args *arg) { status = st103_ep_get_rx_status (endpoint); if (status == 0) /* Disabled */ - return USB_UNSUPPORT; + return -1; else if (status == EP_RX_STALL) status_info |= 1; /* OUT Endpoint stalled */ } - return usb_lld_reply_request (&status_info, 2, arg); + return usb_lld_reply_request (dev, &status_info, 2); } - return USB_UNSUPPORT; + return -1; } -static int std_clear_feature (uint8_t req, struct req_args *arg) +static int std_clear_feature (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_GET (req)) - return USB_UNSUPPORT; + if (USB_SETUP_GET (arg->type)) + return -1; if (rcp == DEVICE_RECIPIENT) { if (arg->len != 0 || arg->index != 0) - return USB_UNSUPPORT; + return -1; - if (arg->value == DEVICE_REMOTE_WAKEUP) + if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP) { - dev_p->current_feature &= ~(1 << 5); - return USB_SUCCESS; + dev->feature &= ~(1 << 5); + return USB_EVENT_CLEAR_FEATURE_DEVICE; } } else if (rcp == ENDPOINT_RECIPIENT) @@ -598,50 +587,49 @@ static int std_clear_feature (uint8_t req, struct req_args *arg) uint8_t endpoint = (arg->index & 0x0f); uint16_t status; - if (dev_p->current_configuration == 0) - return USB_UNSUPPORT; + if (dev->configuration == 0) + return -1; if (arg->len != 0 || (arg->index >> 8) != 0 - || arg->value != ENDPOINT_STALL || endpoint == ENDP0) - return USB_UNSUPPORT; + || arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0) + return -1; if ((arg->index & 0x80)) status = st103_ep_get_tx_status (endpoint); else status = st103_ep_get_rx_status (endpoint); - if (status == 0) /* Disabled */ - return USB_UNSUPPORT; + if (status == 0) /* It's disabled endpoint. */ + return -1; - if (arg->index & 0x80) /* IN endpoint */ + if (arg->index & 0x80) /* IN endpoint */ st103_ep_clear_dtog_tx (endpoint); else /* OUT endpoint */ st103_ep_clear_dtog_rx (endpoint); - // event?? - return USB_SUCCESS; + return USB_EVENT_CLEAR_FEATURE_ENDPOINT; } - return USB_UNSUPPORT; + return -1; } -static int std_set_feature (uint8_t req, struct req_args *arg) +static int std_set_feature (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_GET (req)) - return USB_UNSUPPORT; + if (USB_SETUP_GET (arg->type)) + return -1; if (rcp == DEVICE_RECIPIENT) { if (arg->len != 0 || arg->index != 0) - return USB_UNSUPPORT; + return -1; - if (arg->value == DEVICE_REMOTE_WAKEUP) + if (arg->value == FEATURE_DEVICE_REMOTE_WAKEUP) { - dev_p->current_feature |= 1 << 5; - // event?? - return USB_SUCCESS; + dev->feature |= 1 << 5; + return USB_EVENT_SET_FEATURE_DEVICE; } } else if (rcp == ENDPOINT_RECIPIENT) @@ -649,282 +637,290 @@ static int std_set_feature (uint8_t req, struct req_args *arg) uint8_t endpoint = (arg->index & 0x0f); uint32_t status; - if (dev_p->current_configuration == 0) - return USB_UNSUPPORT; + if (dev->configuration == 0) + return -1; if (arg->len != 0 || (arg->index >> 8) != 0 - || arg->value != 0 || endpoint == ENDP0) - return USB_UNSUPPORT; + || arg->value != FEATURE_ENDPOINT_HALT || endpoint == ENDP0) + return -1; if ((arg->index & 0x80)) status = st103_ep_get_tx_status (endpoint); else status = st103_ep_get_rx_status (endpoint); - if (status == 0) /* Disabled */ - return USB_UNSUPPORT; + if (status == 0) /* It's disabled endpoint. */ + return -1; - if (arg->index & 0x80) - /* IN endpoint */ + if (arg->index & 0x80) /* IN endpoint */ st103_ep_set_tx_status (endpoint, EP_TX_STALL); - else - /* OUT endpoint */ + else /* OUT endpoint */ st103_ep_set_rx_status (endpoint, EP_RX_STALL); - // event?? - return USB_SUCCESS; + return USB_EVENT_SET_FEATURE_ENDPOINT; } - return USB_UNSUPPORT; + return -1; } -static int std_set_address (uint8_t req, struct req_args *arg) +static int std_set_address (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_GET (req)) - return USB_UNSUPPORT; + if (USB_SETUP_GET (arg->type)) + return -1; if (rcp == DEVICE_RECIPIENT && arg->len == 0 && arg->value <= 127 - && arg->index == 0 && dev_p->current_configuration == 0) - return USB_SUCCESS; + && arg->index == 0 && dev->configuration == 0) + return USB_EVENT_NONE; - return USB_UNSUPPORT; + return -1; } -static int std_get_descriptor (uint8_t req, struct req_args *arg) +static int std_get_descriptor (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; - - if (USB_SETUP_SET (req)) - return USB_UNSUPPORT; + struct device_req *arg = &dev->dev_req; + if (USB_SETUP_SET (arg->type)) + return -1; - return usb_cb_get_descriptor (rcp, (arg->value >> 8), - (arg->value & 0xff), arg); + return USB_EVENT_GET_DESCRIPTOR; } -static int std_get_configuration (uint8_t req, struct req_args *arg) +static int std_get_configuration (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_SET (req)) - return USB_UNSUPPORT; + if (USB_SETUP_SET (arg->type)) + return -1; + + if (arg->value != 0 || arg->index != 0 || arg->len != 1) + return -1; if (rcp == DEVICE_RECIPIENT) - return usb_lld_reply_request (&dev_p->current_configuration, 1, arg); + return usb_lld_reply_request (dev, &dev->configuration, 1); - return USB_UNSUPPORT; + return -1; } -static int std_set_configuration (uint8_t req, struct req_args *arg) +static int std_set_configuration (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; + + if (USB_SETUP_GET (arg->type)) + return -1; - if (USB_SETUP_GET (req)) - return USB_UNSUPPORT; + if (arg->index != 0 || arg->len != 0) + return -1; - if (rcp == DEVICE_RECIPIENT && arg->index == 0 && arg->len == 0) - return usb_cb_handle_event (USB_EVENT_CONFIG, arg->value); + if (rcp == DEVICE_RECIPIENT) + return USB_EVENT_SET_CONFIGURATION; - return USB_UNSUPPORT; + return -1; } -static int std_get_interface (uint8_t req, struct req_args *arg) +static int std_get_interface (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_SET (req)) - return USB_UNSUPPORT; + if (USB_SETUP_SET (arg->type)) + return -1; - if (rcp == INTERFACE_RECIPIENT) - { - if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1) - return USB_UNSUPPORT; + if (arg->value != 0 || (arg->index >> 8) != 0 || arg->len != 1) + return -1; - if (dev_p->current_configuration == 0) - return USB_UNSUPPORT; + if (dev->configuration == 0) + return -1; - return usb_cb_interface (USB_GET_INTERFACE, arg); - } + if (rcp == INTERFACE_RECIPIENT) + return USB_EVENT_GET_INTERFACE; - return USB_UNSUPPORT; + return -1; } -static int std_set_interface (uint8_t req, struct req_args *arg) +static int std_set_interface (struct usb_dev *dev) { - uint8_t rcp = req & RECIPIENT; + struct device_req *arg = &dev->dev_req; + uint8_t rcp = arg->type & RECIPIENT; - if (USB_SETUP_GET (req) || rcp != INTERFACE_RECIPIENT + if (USB_SETUP_GET (arg->type) || rcp != INTERFACE_RECIPIENT || arg->len != 0 || (arg->index >> 8) != 0 - || (arg->value >> 8) != 0 || dev_p->current_configuration == 0) - return USB_UNSUPPORT; + || (arg->value >> 8) != 0 || dev->configuration == 0) + return -1; - return usb_cb_interface (USB_SET_INTERFACE, arg); + return USB_EVENT_SET_INTERFACE; } -static void handle_setup0 (void) +static int handle_setup0 (struct usb_dev *dev) { const uint16_t *pw; uint16_t w; uint8_t req_no; - int r = USB_UNSUPPORT; HANDLER handler; pw = (uint16_t *)(PMA_ADDR + (uint8_t *)(st103_get_rx_addr (ENDP0) * 2)); w = *pw++; - dev_p->bmRequestType = w & 0xff; - dev_p->bRequest = req_no = w >> 8; + dev->dev_req.type = (w & 0xff); + dev->dev_req.request = req_no = (w >> 8); pw++; - dev_p->value = *pw++; + dev->dev_req.value = *pw++; pw++; - dev_p->index = *pw++; + dev->dev_req.index = *pw++; pw++; - dev_p->len = *pw; + dev->dev_req.len = *pw; - data_p->addr = NULL; - data_p->len = 0; - data_p->require_zlp = 0; + dev->ctrl_data.addr = NULL; + dev->ctrl_data.len = 0; + dev->ctrl_data.require_zlp = 0; - if ((dev_p->bmRequestType & REQUEST_TYPE) == STANDARD_REQUEST) + if ((dev->dev_req.type & REQUEST_TYPE) == STANDARD_REQUEST) { - if (req_no < TOTAL_REQUEST) - { - switch (req_no) - { - case 0: handler = std_get_status; break; - case 1: handler = std_clear_feature; break; - case 3: handler = std_set_feature; break; - case 5: handler = std_set_address; break; - case 6: handler = std_get_descriptor; break; - case 8: handler = std_get_configuration; break; - case 9: handler = std_set_configuration; break; - case 10: handler = std_get_interface; break; - case 11: handler = std_set_interface; break; - default: handler = std_none; break; - } + int r; - r = (*handler) (dev_p->bmRequestType, - (struct req_args *)&dev_p->value); + switch (req_no) + { + case 0: handler = std_get_status; break; + case 1: handler = std_clear_feature; break; + case 3: handler = std_set_feature; break; + case 5: handler = std_set_address; break; + case 6: handler = std_get_descriptor; break; + case 8: handler = std_get_configuration; break; + case 9: handler = std_set_configuration; break; + case 10: handler = std_get_interface; break; + case 11: handler = std_set_interface; break; + default: handler = std_none; break; } - } - else - r = usb_cb_setup (dev_p->bmRequestType, req_no, - (struct req_args *)&dev_p->value); - if (r != USB_SUCCESS) - dev_p->state = STALLED; - else - { - if (USB_SETUP_SET (dev_p->bmRequestType)) + if ((r = (*handler) (dev)) <= 0) { - if (dev_p->len == 0) - { - dev_p->state = WAIT_STATUS_IN; - st103_set_tx_count (ENDP0, 0); - st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_VALID); - } + /* Handling finished in standard way. */ + if (r == 0) + usb_lld_ctrl_good (dev); else - { - dev_p->state = OUT_DATA; - st103_ep_set_rx_status (ENDP0, EP_RX_VALID); - } + usb_lld_ctrl_error (dev); + return 0; } + else + return r; } + else + return USB_EVENT_CTRL_REQUEST; } -static void handle_in0 (void) +static int handle_in0 (struct usb_dev *dev) { - if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA) - handle_datastage_in (); - else if (dev_p->state == WAIT_STATUS_IN) + int r = 0; + + if (dev->state == IN_DATA || dev->state == LAST_IN_DATA) + handle_datastage_in (dev); + else if (dev->state == WAIT_STATUS_IN) { - if ((dev_p->bRequest == SET_ADDRESS) && - ((dev_p->bmRequestType & (REQUEST_TYPE | RECIPIENT)) + dev->state = WAIT_SETUP; + + if ((dev->dev_req.request == SET_ADDRESS) && + ((dev->dev_req.type & (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | DEVICE_RECIPIENT))) { - st103_set_daddr (dev_p->value); - usb_cb_handle_event (USB_EVENT_ADDRESS, dev_p->value); + st103_set_daddr (dev->dev_req.value); + r = USB_EVENT_DEVICE_ADDRESSED; } else - usb_cb_ctrl_write_finish (dev_p->bmRequestType, dev_p->bRequest, - (struct req_args *)&dev_p->value); - - dev_p->state = STALLED; + r = USB_EVENT_CTRL_WRITE_FINISH; } else - dev_p->state = STALLED; + { + dev->state = STALLED; + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL); + } + + return r; } -static void handle_out0 (void) -{ - if (dev_p->state == IN_DATA || dev_p->state == LAST_IN_DATA) - /* host aborts the transfer before finish */ - dev_p->state = STALLED; - else if (dev_p->state == OUT_DATA) - handle_datastage_out (); - else if (dev_p->state == WAIT_STATUS_OUT) - dev_p->state = STALLED; - /* Unexpect state, STALL the endpoint */ +static void handle_out0 (struct usb_dev *dev) +{ + if (dev->state == OUT_DATA) + /* Usual case. */ + handle_datastage_out (dev); + else if (dev->state == WAIT_STATUS_OUT) + /* + * Control READ transfer finished by ZLP. + * Leave ENDP0 status RX_NAK, TX_NAK. + */ + dev->state = WAIT_SETUP; else - dev_p->state = STALLED; + { + /* + * dev->state == IN_DATA || dev->state == LAST_IN_DATA + * (Host aborts the transfer before finish) + * Or else, unexpected state. + * STALL the endpoint, until we receive the next SETUP token. + */ + dev->state = STALLED; + st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL); + } } - -static void -usb_handle_transfer (uint16_t istr_value) + + +static int +usb_handle_transfer (struct usb_dev *dev, uint16_t istr_value) { uint16_t ep_value = 0; - uint8_t ep_index; + uint8_t ep_num = (istr_value & ISTR_EP_ID); - ep_index = (istr_value & ISTR_EP_ID); - /* Decode and service non control endpoints interrupt */ - /* process related endpoint register */ - ep_value = st103_get_epreg (ep_index); + ep_value = st103_get_epreg (ep_num); - if (ep_index == 0) + if (ep_num == 0) { if ((ep_value & EP_CTR_TX)) { - st103_ep_clear_ctr_tx (ep_index); - handle_in0 (); + st103_ep_clear_ctr_tx (ep_num); + return USB_MAKE_EV (handle_in0 (dev)); } if ((ep_value & EP_CTR_RX)) { - st103_ep_clear_ctr_rx (ep_index); + st103_ep_clear_ctr_rx (ep_num); if ((ep_value & EP_SETUP)) - handle_setup0 (); + return USB_MAKE_EV (handle_setup0 (dev)); else - handle_out0 (); + { + handle_out0 (dev); + return 0; + } } - - if (dev_p->state == STALLED) - st103_ep_set_rxtx_status (ENDP0, EP_RX_STALL, EP_TX_STALL); } else { + uint16_t len; + if ((ep_value & EP_CTR_RX)) { - st103_ep_clear_ctr_rx (ep_index); - usb_cb_rx_ready (ep_index); + len = st103_get_rx_count (ep_num); + st103_ep_clear_ctr_rx (ep_num); + return USB_MAKE_TXRX (ep_num, 0, len); } if ((ep_value & EP_CTR_TX)) { - uint32_t len = st103_get_tx_count (ep_index); - - st103_ep_clear_ctr_tx (ep_index); - usb_cb_tx_done (ep_index, len); + len = st103_get_tx_count (ep_num); + st103_ep_clear_ctr_tx (ep_num); + return USB_MAKE_TXRX (ep_num, 1, len); } } + + return 0; } -void usb_lld_reset (uint8_t feature) +void usb_lld_reset (struct usb_dev *dev, uint8_t feature) { - usb_lld_set_configuration (0); - dev_p->current_feature = feature; + usb_lld_set_configuration (dev, 0); + dev->feature = feature; st103_set_btable (); st103_set_daddr (0); } @@ -954,16 +950,6 @@ void usb_lld_tx_enable (int ep_num, size_t len) st103_ep_set_tx_status (ep_num, EP_TX_VALID); } -int usb_lld_tx_data_len (int ep_num) -{ - return st103_get_tx_count (ep_num); -} - -int usb_lld_rx_data_len (int ep_num) -{ - return st103_get_rx_count (ep_num); -} - void usb_lld_stall_tx (int ep_num) { st103_ep_set_tx_status (ep_num, EP_TX_STALL); @@ -1021,20 +1007,22 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind, st103_set_epreg (ep_num, epreg_value); } -void usb_lld_set_configuration (uint8_t config) +void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config) { - dev_p->current_configuration = config; + dev->configuration = config; } -uint8_t usb_lld_current_configuration (void) +uint8_t usb_lld_current_configuration (struct usb_dev *dev) { - return dev_p->current_configuration; + return dev->configuration; } -void usb_lld_set_data_to_recv (void *p, size_t len) +int usb_lld_set_data_to_recv (struct usb_dev *dev, void *p, size_t len) { + struct ctrl_data *data_p = &dev->ctrl_data; data_p->addr = p; data_p->len = len; + return 0; } void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n) @@ -1118,9 +1106,10 @@ void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n) * BUFLEN: size of the data. */ int -usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl) +usb_lld_reply_request (struct usb_dev *dev, const void *buf, size_t buflen) { - uint32_t len_asked = ctl->len; + struct ctrl_data *data_p = &dev->ctrl_data; + uint32_t len_asked = dev->dev_req.len; uint32_t len; data_p->addr = (void *)buf; @@ -1136,12 +1125,12 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl) if (data_p->len < USB_MAX_PACKET_SIZE) { len = data_p->len; - dev_p->state = LAST_IN_DATA; + dev->state = LAST_IN_DATA; } else { len = USB_MAX_PACKET_SIZE; - dev_p->state = IN_DATA; + dev->state = IN_DATA; } if (len) @@ -1152,6 +1141,6 @@ usb_lld_reply_request (const void *buf, size_t buflen, struct req_args *ctl) } st103_set_tx_count (ENDP0, len); - st103_ep_set_tx_status (ENDP0, EP_TX_VALID); - return USB_SUCCESS; + st103_ep_set_rxtx_status (ENDP0, EP_RX_NAK, EP_TX_VALID); + return USB_EVENT_NONE; } diff --git a/usb_lld.h b/usb_lld.h index 0dcab3b..4c25d7c 100644 --- a/usb_lld.h +++ b/usb_lld.h @@ -37,45 +37,52 @@ enum DESCRIPTOR_TYPE #define USB_SETUP_SET(req) ((req & REQUEST_DIR) == 0) #define USB_SETUP_GET(req) ((req & REQUEST_DIR) != 0) -enum -{ - USB_UNSUPPORT = 0, - USB_SUCCESS = 1, -}; - -struct req_args { +struct device_req { + uint8_t type; + uint8_t request; uint16_t value; uint16_t index; uint16_t len; }; -void usb_cb_device_reset (void); -int usb_cb_setup (uint8_t req, uint8_t req_no, struct req_args *arg); -int usb_cb_interface (uint8_t cmd, struct req_args *arg); -int usb_cb_get_descriptor (uint8_t rcp, uint8_t desc_type, uint8_t desc_index, - struct req_args *arg); -int usb_cb_handle_event (uint8_t event_type, uint16_t value); -void usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, - struct req_args *arg); -void usb_cb_tx_done (uint8_t ep_num, uint32_t len); -void usb_cb_rx_ready (uint8_t ep_num); +struct ctrl_data { + uint8_t *addr; + uint16_t len; + uint8_t require_zlp; +}; -enum { - USB_EVENT_ADDRESS, - USB_EVENT_CONFIG, - USB_EVENT_SUSPEND, - USB_EVENT_WAKEUP, - USB_EVENT_STALL, +struct usb_dev { + uint8_t configuration; + uint8_t feature; + uint8_t state; + struct device_req dev_req; + struct ctrl_data ctrl_data; }; enum { - USB_SET_INTERFACE, - USB_GET_INTERFACE, - USB_QUERY_INTERFACE, + USB_EVENT_NONE=0, /* Processed in lower layer. */ + /* Device reset and suspend. */ + USB_EVENT_DEVICE_RESET, + USB_EVENT_DEVICE_SUSPEND, + /* Device Requests (Control WRITE Transfer): Standard */ + USB_EVENT_SET_CONFIGURATION, + USB_EVENT_SET_INTERFACE, + USB_EVENT_SET_FEATURE_DEVICE, + USB_EVENT_SET_FEATURE_ENDPOINT, + USB_EVENT_CLEAR_FEATURE_DEVICE, + USB_EVENT_CLEAR_FEATURE_ENDPOINT, + /* Device Requests (Control READ Transfer): Standard */ + USB_EVENT_GET_STATUS_INTERFACE, + USB_EVENT_GET_DESCRIPTOR, + USB_EVENT_GET_INTERFACE, + /* Device Requests (Control READ/WRITE Transfer): Non-Standard */ + USB_EVENT_CTRL_REQUEST, + USB_EVENT_CTRL_WRITE_FINISH, + /* Device addressed. */ + USB_EVENT_DEVICE_ADDRESSED, }; -enum DEVICE_STATE -{ +enum DEVICE_STATE { UNCONNECTED, ATTACHED, POWERED, @@ -84,17 +91,32 @@ enum DEVICE_STATE CONFIGURED }; -void usb_lld_init (uint8_t feature); -int usb_lld_reply_request (const void *buf, size_t buflen, - struct req_args *arg); -int usb_lld_rx_data_len (int ep_num); -void usb_lld_reset (uint8_t feature); -void usb_lld_set_configuration (uint8_t config); -uint8_t usb_lld_current_configuration (void); +void usb_lld_init (struct usb_dev *dev, uint8_t feature); + +/* + * Return value is encoded integer: + * event-no: 8-bit, 0 if TX/RX + * tx/rx-flag: 1-bit, 0 if rx, 1 if tx + * endpoint no: 7-bit + * length: 16-bit + */ +#define USB_EVENT_TXRX(e) ((e >> 23) & 1) +#define USB_EVENT_LEN(e) (e & 0xffff) +#define USB_EVENT_ENDP(e) ((e >> 16) & 0x7f) +#define USB_EVENT_ID(e) ((e >> 24)) +int usb_lld_event_handler (struct usb_dev *dev); + +int usb_lld_reply_request (struct usb_dev *dev, + const void *buf, size_t buflen); +int usb_lld_set_data_to_recv (struct usb_dev *dev, void *p, size_t len); +void usb_lld_ctrl_error (struct usb_dev *dev); +void usb_lld_ctrl_good (struct usb_dev *dev); + +void usb_lld_reset (struct usb_dev *dev, uint8_t feature); +void usb_lld_set_configuration (struct usb_dev *dev, uint8_t config); +uint8_t usb_lld_current_configuration (struct usb_dev *dev); void usb_lld_prepare_shutdown (void); void usb_lld_shutdown (void); -void usb_interrupt_handler (void); -void usb_lld_set_data_to_recv (void *p, size_t len); #ifdef MCU_KINETIS_L void usb_lld_tx_enable_buf (int ep_num, const void *buf, size_t len); @@ -118,10 +140,9 @@ void usb_lld_setup_endpoint (int ep_num, int ep_type, int ep_kind, void usb_lld_stall_tx (int ep_num); void usb_lld_stall_rx (int ep_num); -int usb_lld_tx_data_len (int ep_num); void usb_lld_txcpy (const void *src, int ep_num, int offset, size_t len); void usb_lld_write (uint8_t ep_num, const void *buf, size_t len); +void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len); void usb_lld_to_pmabuf (const void *src, uint16_t addr, size_t n); void usb_lld_from_pmabuf (void *dst, uint16_t addr, size_t n); -void usb_lld_rxcpy (uint8_t *dst, int ep_num, int offset, size_t len); #endif -- cgit v1.2.3