From 67d6d753d66ffb821e9cfc4831d44f6b2f8549b8 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Dec 2018 23:57:53 +0700 Subject: [PATCH] replace all hcd pipe close by hcd_device_remove --- src/class/cdc/cdc_host.c | 5 - src/class/hid/hid_host.c | 1 - src/class/msc/msc_host.c | 3 - src/common/tusb_types.h | 5 - src/host/ehci/ehci.c | 225 ++++++++++++++------------------------- src/host/ehci/ehci.h | 8 +- src/host/hcd.h | 6 +- src/host/hub.c | 2 - src/host/usbh.c | 32 ++---- 9 files changed, 95 insertions(+), 192 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 53f62d68..159a1399 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -233,11 +233,6 @@ void cdch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t x void cdch_close(uint8_t dev_addr) { cdch_data_t * p_cdc = &cdch_data[dev_addr-1]; - - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_notif); - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_in); - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_out); - tu_memclr(p_cdc, sizeof(cdch_data_t)); } diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index aa93f783..1e44055e 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -67,7 +67,6 @@ static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_numbe static inline void hidh_interface_close(hidh_interface_info_t *p_hid) { - (void) hcd_pipe_close(p_hid->pipe_hdl); tu_memclr(p_hid, sizeof(hidh_interface_info_t)); } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index 0b135926..2c9b2dec 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -413,9 +413,6 @@ void msch_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t x void msch_close(uint8_t dev_addr) { - (void) hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, msch_data[dev_addr-1].ep_in); - (void) hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, msch_data[dev_addr-1].ep_out); - tu_memclr(&msch_data[dev_addr-1], sizeof(msch_interface_t)); osal_semaphore_reset(msch_sem_hdl); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 8be1e87f..d0a10ace 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -184,11 +184,6 @@ typedef enum TUSB_DEVICE_STATE_ADDRESSED , TUSB_DEVICE_STATE_CONFIGURED , TUSB_DEVICE_STATE_SUSPENDED , - - TUSB_DEVICE_STATE_REMOVING , - TUSB_DEVICE_STATE_SAFE_REMOVE , - - TUSB_DEVICE_STATE_INVALID_PARAMETER }tusb_device_state_t; typedef enum diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 1b528933..91a87f9d 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -113,7 +113,7 @@ static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE; static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE; static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE; -static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes); +static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes); static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE; static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE; @@ -149,10 +149,53 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid) return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed } -// TODO refractor abtract later +static void list_remove_qhd_by_addr(ehci_link_t* list_head, uint8_t dev_addr) +{ + for(ehci_link_t* prev = list_head; + !prev->terminate && (tu_align32(prev->address) != (uint32_t) list_head); + prev = list_next(prev) ) + { + // TODO check type for ISO iTD and siTD + ehci_qhd_t* qhd = (ehci_qhd_t*) list_next(prev); + if ( qhd->dev_addr == dev_addr ) + { + // TODO deactive all TD, wait for QHD to inactive before removal + prev->address = qhd->next.address; + + // EHCI 4.8.2 link the removed qhd to async head (which always reachable by Host Controller) + qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); + + if ( qhd->int_smask ) + { + // period list queue element is guarantee to be free in the next frame (1 ms) + qhd->used = 0; + }else + { + // async list use async advance handshake + // mark as removing, will completely re-usable when async advance isr occurs + qhd->removing = 1; + } + } + } +} + +// Close all opened endpoint belong to this device void hcd_device_remove(uint8_t rhport, uint8_t dev_addr) { - ehci_data.regs->command_bm.async_adv_doorbell = 1; // Async doorbell check EHCI 4.8.2 for operational details + // skip dev0 + if (dev_addr == 0) return; + + // Remove from async list + list_remove_qhd_by_addr( (ehci_link_t*) qhd_async_head(rhport), dev_addr ); + + // Remove from all interval period list + for(uint8_t i = 0; i < TU_ARRAY_SZIE(ehci_data.period_head_arr); i++) + { + list_remove_qhd_by_addr( (ehci_link_t*) &ehci_data.period_head_arr[i], dev_addr); + } + + // Async doorbell (EHCI 4.8.2 for operational details) + ehci_data.regs->command_bm.async_adv_doorbell = 1; } // EHCI controller init @@ -184,7 +227,6 @@ static bool ehci_init(uint8_t hostid) //------------- Periodic List -------------// // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only - for(uint32_t i=0; i<4; i++) { ehci_data.period_head_arr[i].int_smask = 1; // queue head in period list must have smask non-zero @@ -252,28 +294,6 @@ static tusb_error_t hcd_controller_stop(uint8_t hostid) //--------------------------------------------------------------------+ // CONTROL PIPE API //--------------------------------------------------------------------+ -bool hcd_pipe_control_close(uint8_t dev_addr) -{ - //------------- TODO pipe handle validate -------------// - ehci_qhd_t* p_qhd = qhd_control(dev_addr); - - p_qhd->removing = 1; - - if (dev_addr != 0) - { - TU_ASSERT( list_remove_qhd( (ehci_link_t*) qhd_async_head( _usbh_devices[dev_addr].rhport ), - (ehci_link_t*) p_qhd) ); - } - - return true; -} - -bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - // FIXME control only for now - return hcd_pipe_control_close(dev_addr); -} - bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { uint8_t const epnum = edpt_number(ep_addr); @@ -285,7 +305,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * ehci_qhd_t* qhd = qhd_control(dev_addr); ehci_qtd_t* qtd = qtd_control(dev_addr); - qtd_init(qtd, (uint32_t) buffer, buflen); + qtd_init(qtd, buffer, buflen); // first first data toggle is always 1 (data & setup stage) qtd->data_toggle = 1; @@ -306,20 +326,20 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - ehci_qhd_t* p_qhd = qhd_control(dev_addr); - ehci_qtd_t* p_setup = qtd_control(dev_addr); + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - qtd_init(p_setup, (uint32_t) setup_packet, 8); - p_setup->pid = EHCI_PID_SETUP; - p_setup->int_on_complete = 1; - p_setup->next.terminate = 1; + qtd_init(td, setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; // sw region - p_qhd->p_qtd_list_head = p_setup; - p_qhd->p_qtd_list_tail = p_setup; + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; // attach TD - p_qhd->qtd_overlay.next.address = (uint32_t) p_setup; + qhd->qtd_overlay.next.address = (uint32_t) td; return true; } @@ -384,8 +404,8 @@ bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], ui TU_ASSERT(p_qtd); - qtd_init(p_qtd, (uint32_t) buffer, total_bytes); - p_qtd->pid = p_qhd->pid_non_control; + qtd_init(p_qtd, buffer, total_bytes); + p_qtd->pid = p_qhd->pid; //------------- insert TD to TD list -------------// qtd_insert_to_qhd(p_qhd, p_qtd); @@ -408,31 +428,6 @@ bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t return true; } -/// pipe_close should only be called as a part of unmount/safe-remove process -bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - - // async list needs async advance handshake to make sure host controller has released cached data - // non-control does not use async advance, it will eventually free by control pipe close - // period list queue element is guarantee to be free in the next frame (1 ms) - p_qhd->removing = 1; // TODO redundant, only apply to control queue head - - if ( p_qhd->int_smask == 0 ) - { - // Async list - TU_ASSERT( list_remove_qhd( (ehci_link_t*) qhd_async_head( _usbh_devices[dev_addr].rhport ), - (ehci_link_t*) p_qhd), false ); - } - else - { - TU_ASSERT( list_remove_qhd( get_period_head( _usbh_devices[dev_addr].rhport, p_qhd->interval_ms ), - (ehci_link_t*) p_qhd), false ); - } - - return true; -} - bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); @@ -457,47 +452,20 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) // EHCI Interrupt Handler //--------------------------------------------------------------------+ -// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head. -// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing -static void async_advance_isr(ehci_qhd_t * const async_head) +// async_advance is handshake between usb stack & ehci controller. +// This isr mean it is safe to modify previously removed queue head from async list. +// In tinyusb, queue head is only removed when device is unplugged. +static void async_advance_isr(uint8_t rhport) { - // TODO do we need to close addr0 - if (async_head->removing) // closing control pipe of addr0 + (void) rhport; + + ehci_qhd_t* qhd_pool = ehci_data.qhd_pool; + for(uint32_t i = 0; i < HCD_MAX_ENDPOINT; i++) { - async_head->removing = 0; - async_head->p_qtd_list_head = async_head->p_qtd_list_tail = NULL; - async_head->qtd_overlay.halted = 1; - - _usbh_devices[0].state = TUSB_DEVICE_STATE_UNPLUG; - } - - for(uint8_t dev_addr=1; dev_addr < CFG_TUSB_HOST_DEVICE_MAX; dev_addr++) - { - // check if control endpoint is removing - ehci_qhd_t *p_control_qhd = qhd_control(dev_addr); - - if ( p_control_qhd->removing ) + if ( qhd_pool[i].removing ) { - p_control_qhd->removing = 0; - p_control_qhd->used = 0; - - // Host Controller has cleaned up its cached data for this device, set state to unplug - _usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_UNPLUG; - - for (uint8_t i=0; idev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), XFER_RESULT_SUCCESS, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } } @@ -621,7 +589,7 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) } // call USBH callback - hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid_non_control == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); + hcd_event_xfer_complete(p_qhd->dev_addr, edpt_addr(p_qhd->ep_number, p_qhd->pid == EHCI_PID_IN ? 1 : 0), error_event, p_qhd->total_xferred_bytes); p_qhd->total_xferred_bytes = 0; } @@ -675,7 +643,7 @@ static void xfer_error_isr(uint8_t hostid) } //------------- Host Controller Driver's Interrupt Handler -------------// -void hal_hcd_isr(uint8_t hostid) +void hal_hcd_isr(uint8_t rhport) { ehci_registers_t* regs = ehci_data.regs; @@ -692,7 +660,7 @@ void hal_hcd_isr(uint8_t hostid) if (regs->portsc_bm.connect_status_change) { - port_connect_status_change_isr(hostid); + port_connect_status_change_isr(rhport); } regs->portsc |= port_status; // Acknowledge change bits in portsc @@ -700,27 +668,27 @@ void hal_hcd_isr(uint8_t hostid) if (int_status & EHCI_INT_MASK_ERROR) { - xfer_error_isr(hostid); + xfer_error_isr(rhport); } //------------- some QTD/SITD/ITD with IOC set is completed -------------// if (int_status & EHCI_INT_MASK_NXP_ASYNC) { - async_list_xfer_complete_isr( qhd_async_head(hostid) ); + async_list_xfer_complete_isr( qhd_async_head(rhport) ); } if (int_status & EHCI_INT_MASK_NXP_PERIODIC) { for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) { - period_list_xfer_complete_isr( hostid, i ); + period_list_xfer_complete_isr( rhport, i ); } } //------------- There is some removed async previously -------------// if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC { - async_advance_isr( qhd_async_head(hostid) ); + async_advance_isr(rhport); } } @@ -758,7 +726,7 @@ static inline ehci_qhd_t* qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; iremoving = 0; p_qhd->p_qtd_list_head = NULL; p_qhd->p_qtd_list_tail = NULL; - p_qhd->pid_non_control = edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint + p_qhd->pid = edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// p_qhd->qtd_overlay.halted = 0; p_qhd->qtd_overlay.next.terminate = 1; p_qhd->qtd_overlay.alternate.terminate = 1; - if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT) + if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) { p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 } } -static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) +static void qtd_init(ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes) { tu_memclr(p_qtd, sizeof(ehci_qtd_t)); @@ -892,7 +860,7 @@ static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes) p_qtd->total_bytes = total_bytes; p_qtd->expected_bytes = total_bytes; - p_qtd->buffer[0] = data_ptr; + p_qtd->buffer[0] = (uint32_t) buffer; for(uint8_t i=1; i<5; i++) { p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; @@ -911,33 +879,4 @@ static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) return (ehci_link_t*) tu_align32(p_link_pointer->address); } -static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current) -{ - ehci_link_t *p_prev = p_head; - uint32_t max_loop = 0; - while( (tu_align32(p_prev->address) != (uint32_t) p_head) && // not loop around - (tu_align32(p_prev->address) != (uint32_t) p_current) && // not found yet - !p_prev->terminate && // not advanceable - max_loop < HCD_MAX_ENDPOINT) - { - p_prev = list_next(p_prev); - max_loop++; - } - - return (tu_align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL; -} - -static bool list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove) -{ - ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove); - - TU_ASSERT(p_prev); - - p_prev->address = p_remove->address; - // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller) - p_remove->address = ((uint32_t) p_head) | (EHCI_QTYPE_QHD << 1); - - return true; -} - #endif diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index d0d74670..c1c27479 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -184,7 +184,7 @@ typedef struct ATTR_ALIGNED(32) //--------------------------------------------------------------------+ uint8_t used; uint8_t removing; // removed from asyn list, waiting for async advance - uint8_t pid_non_control; + uint8_t pid; uint8_t interval_ms; // polling interval in frames (or milisecond) uint16_t total_xferred_bytes; // number of bytes xferred until a qtd with ioc bit set @@ -229,7 +229,8 @@ typedef struct ATTR_ALIGNED(32) { TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); /// Split (Full-Speed) Isochronous Transfer Descriptor -typedef struct ATTR_ALIGNED(32) { +typedef struct ATTR_ALIGNED(32) +{ // Word 0: Next Link Pointer ehci_link_t next; @@ -332,7 +333,8 @@ enum ehci_portsc_change_mask_{ EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE }; -typedef volatile struct { +typedef volatile struct +{ union { uint32_t command; diff --git a/src/host/hcd.h b/src/host/hcd.h index 257a7da5..fb0612ed 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -108,7 +108,7 @@ bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; void hcd_port_reset(uint8_t hostid); tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible -// Call by USBH after event device remove +// HCD closs all opened endpoints belong to this device void hcd_device_remove(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ @@ -135,8 +135,7 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr); bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr); -// TODO remove -bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); //--------------------------------------------------------------------+ @@ -145,7 +144,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * // TODO control xfer should be used via usbh layer bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // TODO remove #if 0 tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; diff --git a/src/host/hub.c b/src/host/hub.c index 411e1ae9..e2e91d73 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -251,9 +251,7 @@ void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xf void hub_close(uint8_t dev_addr) { - hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, hub_data[dev_addr-1].ep_status); tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t)); - // osal_semaphore_reset(hub_enum_sem_hdl); } diff --git a/src/host/usbh.c b/src/host/usbh.c index 456eff53..31024f1f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -118,7 +118,7 @@ static host_class_driver_t const usbh_class_drivers[] = #endif }; -enum { USBH_CLASS_DRIVER_COUNT = sizeof(usbh_class_drivers) / sizeof(host_class_driver_t) }; +enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SZIE(usbh_class_drivers) }; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION @@ -146,7 +146,7 @@ static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, //--------------------------------------------------------------------+ tusb_device_state_t tuh_device_get_state (uint8_t const dev_addr) { - TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_INVALID_PARAMETER); + TU_ASSERT( dev_addr <= CFG_TUSB_HOST_DEVICE_MAX, TUSB_DEVICE_STATE_UNPLUG); return (tusb_device_state_t) _usbh_devices[dev_addr].state; } @@ -241,13 +241,6 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return TUSB_ERROR_NONE; } -static inline tusb_error_t usbh_pipe_control_close(uint8_t dev_addr) -{ - hcd_edpt_close(_usbh_devices[dev_addr].rhport, dev_addr, 0); - - return TUSB_ERROR_NONE; -} - //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ @@ -321,13 +314,12 @@ void hcd_event_device_remove(uint8_t hostid) // return true if found and unmounted device, false if cannot find static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - bool is_found = false; - //------------- find the all devices (star-network) under port that is unplugged -------------// for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) { usbh_device_t* dev = &_usbh_devices[dev_addr]; + // TODO Hub multiple level if (dev->rhport == rhport && (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub (hub_port == 0 || dev->hub_port == hub_port) && @@ -336,29 +328,17 @@ static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_ // Invoke callback before close driver if (tuh_umount_cb) tuh_umount_cb(dev_addr); - // TODO Hub multiple level // Close class driver for (uint8_t drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++) usbh_class_drivers[drv_id].close(dev_addr); - // TODO refractor - // set to REMOVING to allow HCD to clean up its cached data for this device - // HCD must set this device's state to TUSB_DEVICE_STATE_UNPLUG when done - dev->state = TUSB_DEVICE_STATE_REMOVING; - memset(dev->itf2drv, 0xff, sizeof(dev->itf2drv)); // invalid mapping memset(dev->ep2drv , 0xff, sizeof(dev->ep2drv )); // invalid mapping - usbh_pipe_control_close(dev_addr); + hcd_device_remove(rhport, dev_addr); -// hcd_device_remove(rhport, dev_addr); - - is_found = true; + dev->state = TUSB_DEVICE_STATE_UNPLUG; } } - - // FIXME remove - if (is_found) hcd_device_remove(_usbh_devices[0].rhport, 0); - } //--------------------------------------------------------------------+ @@ -515,7 +495,7 @@ bool enum_task(hcd_event_t* event) new_dev->speed = dev0->speed; new_dev->state = TUSB_DEVICE_STATE_ADDRESSED; - usbh_pipe_control_close(0); // hcd_device_remove(rhport, 0); // close device 0 + hcd_device_remove(dev0->rhport, 0); // close device 0 dev0->state = TUSB_DEVICE_STATE_UNPLUG; // open control pipe for new address