From 4d57b4ea336d0ba89b97b388aa02f15c2d947a2a Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 13:57:07 +0700 Subject: clean up --- src/device/usbd.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/device') diff --git a/src/device/usbd.h b/src/device/usbd.h index 5338be157..bbdd1be99 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -41,8 +41,6 @@ //--------------------------------------------------------------------+ // Init device stack -// Note: when using with RTOS, this should be called after scheduler/kernel is started. -// Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. bool tud_init (void); // Task function should be called in main/rtos loop -- cgit v1.3.1 From b8b95e84944b4c07cc9c9f4a7e4d53e6256b42f0 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Sep 2020 15:45:03 +0700 Subject: add in_isr to all hcd event functions --- src/device/dcd.h | 2 +- src/host/ehci/ehci.c | 8 ++++---- src/host/hcd.h | 30 ++++++++++++++++-------------- src/host/hub.c | 2 +- src/host/ohci/ohci.c | 6 +++--- src/host/usbh.c | 14 +++++++------- 6 files changed, 32 insertions(+), 30 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 776f782b8..a5c485f9e 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -140,7 +140,7 @@ void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); //--------------------------------------------------------------------+ -// Event API (Implemented by device stack) +// Event API (implemented by stack) //--------------------------------------------------------------------+ // Called by DCD to notify device stack diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 295da4566..c2d5ebf7b 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -489,10 +489,10 @@ static void port_connect_status_change_isr(uint8_t hostid) if (ehci_data.regs->portsc_bm.current_connect_status) { hcd_port_reset(hostid); - hcd_event_device_attach(hostid); + hcd_event_device_attach(hostid, true); }else // device unplugged { - hcd_event_device_remove(hostid); + hcd_event_device_remove(hostid, true); } } @@ -512,7 +512,7 @@ static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd) { // end of request // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, XFER_RESULT_SUCCESS, true); p_qhd->total_xferred_bytes = 0; } } @@ -599,7 +599,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, tu_edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), p_qhd->total_xferred_bytes, error_event, true); p_qhd->total_xferred_bytes = 0; } diff --git a/src/host/hcd.h b/src/host/hcd.h index da530421d..eebf2c801 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -109,20 +109,6 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr); -//--------------------------------------------------------------------+ -// Event function -//--------------------------------------------------------------------+ -void hcd_event_handler(hcd_event_t const* event, bool in_isr); - -// Helper to send device attach event -void hcd_event_device_attach(uint8_t rhport); - -// Helper to send device removal event -void hcd_event_device_remove(uint8_t rhport); - -// Helper to send USB transfer event -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - //--------------------------------------------------------------------+ // Endpoints API //--------------------------------------------------------------------+ @@ -145,6 +131,22 @@ bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t // tusb_error_t hcd_pipe_cancel(); +//--------------------------------------------------------------------+ +// Event API (implemented by stack) +//--------------------------------------------------------------------+ + +// Called by HCD to notify stack +extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); + +// Helper to send device attach event +extern void hcd_event_device_attach(uint8_t rhport, bool in_isr); + +// Helper to send device removal event +extern void hcd_event_device_remove(uint8_t rhport, bool in_isr); + +// Helper to send USB transfer event +extern void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr); + #ifdef __cplusplus } #endif diff --git a/src/host/hub.c b/src/host/hub.c index 4fb28b72f..f88056c92 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -223,7 +223,7 @@ void hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_ event.attach.hub_port = port; hcd_event_handler(&event, true); - break; // handle one port at a time, next port if any will be handled in the next cycle + break; // TODO handle one port at a time, next port if any will be handled in the next cycle } } // NOTE: next status transfer is queued by usbh.c after handling this request diff --git a/src/host/ohci/ohci.c b/src/host/ohci/ohci.c index 114f52e7d..87da374d5 100644 --- a/src/host/ohci/ohci.c +++ b/src/host/ohci/ohci.c @@ -599,7 +599,7 @@ static void done_queue_isr(uint8_t hostid) hcd_event_xfer_complete(p_ed->dev_addr, tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - event, xferred_bytes); + xferred_bytes, event, true); } td_head = (ohci_td_item_t*) td_head->next; @@ -632,10 +632,10 @@ void hcd_int_handler(uint8_t hostid) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; - hcd_event_device_attach(0); + hcd_event_device_attach(hostid, true); }else { - hcd_event_device_remove(0); + hcd_event_device_remove(hostid, true); } } diff --git a/src/host/usbh.c b/src/host/usbh.c index da163f9e4..6304b6b48 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -268,7 +268,7 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr) } // interrupt caused by a TD (with IOC=1) in pipe of class class_code -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, uint32_t xferred_bytes) +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { usbh_device_t* dev = &_usbh_devices[ dev_addr ]; @@ -276,7 +276,7 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, { dev->control.pipe_status = result; // usbh_devices[ pipe_hdl.dev_addr ].control.xferred_bytes = xferred_bytes; not yet neccessary - osal_semaphore_post( dev->control.sem_hdl, true ); + osal_semaphore_post( dev->control.sem_hdl, true ); // FIXME post within ISR } else { @@ -293,11 +293,11 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint8_t result, } }; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } } -void hcd_event_device_attach(uint8_t rhport) +void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event = { @@ -308,10 +308,10 @@ void hcd_event_device_attach(uint8_t rhport) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -void hcd_event_device_remove(uint8_t hostid) +void hcd_event_device_remove(uint8_t hostid, bool in_isr) { hcd_event_t event = { @@ -322,7 +322,7 @@ void hcd_event_device_remove(uint8_t hostid) event.attach.hub_addr = 0; event.attach.hub_port = 0; - hcd_event_handler(&event, true); + hcd_event_handler(&event, in_isr); } -- cgit v1.3.1 From 87b989e8b4b497713cc4b88103dc6dfadc43e149 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Oct 2020 00:35:38 +0700 Subject: add usbh_edpt_claim/release implement USBH_EVENT_FUNC_CALL --- src/device/dcd.h | 2 +- src/host/hcd.h | 11 ++++++++ src/host/usbh.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- src/host/usbh.h | 9 ++++-- src/host/usbh_control.c | 8 +++++- src/host/usbh_hcd.h | 23 ++++++++++++++- 6 files changed, 120 insertions(+), 8 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index a5c485f9e..b7e5a8da0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -77,7 +77,7 @@ typedef struct TU_ATTR_ALIGNED(4) uint32_t len; }xfer_complete; - // USBD_EVENT_FUNC_CALL + // FUNC_CALL struct { void (*func) (void*); void* param; diff --git a/src/host/hcd.h b/src/host/hcd.h index ba3035300..db98f6110 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -45,6 +45,11 @@ typedef enum HCD_EVENT_DEVICE_ATTACH, HCD_EVENT_DEVICE_REMOVE, HCD_EVENT_XFER_COMPLETE, + + // Not an HCD event, just a convenient way to defer ISR function + USBH_EVENT_FUNC_CALL, + + HCD_EVENT_COUNT } hcd_eventid_t; typedef struct @@ -67,6 +72,12 @@ typedef struct uint8_t result; uint32_t len; } xfer_complete; + + // FUNC_CALL + struct { + void (*func) (void*); + void* param; + }func_call; }; } hcd_event_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index 4932e662c..595024b9c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -169,6 +169,11 @@ bool tuh_init(void) dev->control.sem_hdl = osal_semaphore_create(&dev->control.sem_def); TU_ASSERT(dev->control.sem_hdl != NULL); +#if CFG_TUSB_OS != OPT_OS_NONE + dev->mutex = osal_mutex_create(&dev->mutexdef); + TU_ASSERT(dev->mutex); +#endif + memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping } @@ -187,6 +192,8 @@ bool tuh_init(void) } //------------- USBH control transfer -------------// + +// TODO remove bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -216,6 +223,58 @@ bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8 return true; } +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + // pre-check to help reducing mutex lock + TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0)); + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only claim the endpoint if it is not busy and not claimed yet. + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 1; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + +bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + usbh_device_t* dev = &_usbh_devices[dev_addr]; + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER); +#endif + + // can only release the endpoint if it is claimed and not busy + bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1); + if (ret) + { + dev->ep_status[epnum][dir].claimed = 0; + } + +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_unlock(dev->mutex); +#endif + + return ret; +} + bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { usbh_device_t* dev = &_usbh_devices[dev_addr]; @@ -402,6 +461,8 @@ void tuh_task(void) switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: + // TODO due to the shared _usbh_ctrl_buf, we must complete enumerating + // one device before enumerating another one. TU_LOG2("USBH DEVICE ATTACH\r\n"); enum_new_device(&event); break; @@ -443,6 +504,10 @@ void tuh_task(void) } break; + case USBH_EVENT_FUNC_CALL: + if ( event.func_call.func ) event.func_call.func(event.func_call.param); + break; + default: break; } } @@ -465,6 +530,8 @@ static uint8_t get_new_address(void) // is a lengthy process with a seires of control transfer to configure // newly attached device. Each step is handled by a function in this // section +// TODO due to the shared _usbh_ctrl_buf, we must complete enumerating +// one device before enumerating another one. //--------------------------------------------------------------------+ static bool enum_get_addr0_device_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); @@ -785,7 +852,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - // Check if class is supportedVe + // Check if class is supported uint8_t drv_id; for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) { @@ -799,6 +866,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura } else { + usbh_class_driver_t const * driver = &usbh_class_drivers[drv_id]; + // Interface number must not be used already TODO alternate interface TU_ASSERT( dev->itf2drv[desc_itf->bInterfaceNumber] == 0xff ); dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id; @@ -813,8 +882,8 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura { uint16_t itf_len = 0; - TU_LOG2("%s open\r\n", usbh_class_drivers[drv_id].name); - TU_ASSERT( usbh_class_drivers[drv_id].open(dev->rhport, dev_addr, desc_itf, &itf_len) ); + TU_LOG2("%s open\r\n", driver->name); + TU_ASSERT( driver->open(dev->rhport, dev_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 814770722..fde1dd11c 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -65,6 +65,7 @@ typedef struct { } usbh_class_driver_t; typedef bool (*tuh_control_complete_cb_t)(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result); + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -106,11 +107,15 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); // CLASS-USBH & INTERNAL API //--------------------------------------------------------------------+ -bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); - bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Claim an endpoint before submitting a transfer. +// If caller does not make any transfer, it must release endpoint for others. +bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); + +bool usbh_control_xfer (uint8_t dev_addr, tusb_control_request_t* request, uint8_t* data); // TODO remove later + #ifdef __cplusplus } #endif diff --git a/src/host/usbh_control.c b/src/host/usbh_control.c index 595c011f5..70800eba6 100644 --- a/src/host/usbh_control.c +++ b/src/host/usbh_control.c @@ -58,6 +58,8 @@ static usbh_control_xfer_t _ctrl_xfer; bool tuh_control_xfer (uint8_t dev_addr, tusb_control_request_t const* request, void* buffer, tuh_control_complete_cb_t complete_cb) { + // TODO need to claim the endpoint first + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -83,6 +85,10 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) ep_addr; + (void) xferred_bytes; + + usbh_device_t* dev = &_usbh_devices[dev_addr]; const uint8_t rhport = dev->rhport; @@ -106,7 +112,7 @@ bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t resu hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); return true; } - __attribute__((fallthrough)); + __attribute__((fallthrough)); case STAGE_DATA: _ctrl_xfer.stage = STAGE_ACK; diff --git a/src/host/usbh_hcd.h b/src/host/usbh_hcd.h index f203f3baa..20348eed1 100644 --- a/src/host/usbh_hcd.h +++ b/src/host/usbh_hcd.h @@ -40,6 +40,10 @@ #include "common/tusb_common.h" #include "osal/osal.h" +#ifndef CFG_TUH_EP_MAX +#define CFG_TUH_EP_MAX 9 +#endif + //--------------------------------------------------------------------+ // USBH-HCD common data structure //--------------------------------------------------------------------+ @@ -80,7 +84,24 @@ typedef struct { } control; uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) - uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) + uint8_t ep2drv[CFG_TUH_EP_MAX][2]; // map endpoint to driver ( 0xff is invalid ) + + struct TU_ATTR_PACKED + { + volatile bool busy : 1; + volatile bool stalled : 1; + volatile bool claimed : 1; + + // TODO merge ep2drv here, 4-bit should be sufficient + }ep_status[CFG_TUH_EP_MAX][2]; + + +// Mutex for claiming endpoint, only needed when using with preempted RTOS +#if CFG_TUSB_OS != OPT_OS_NONE + osal_mutex_def_t mutexdef; + osal_mutex_t mutex; +#endif + } usbh_device_t; extern usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1]; // including zero-address -- cgit v1.3.1