diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 20cd7ba69..373dbbf9e 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -15,8 +15,9 @@ SRC_C += \ src/host/usbh.c \ src/host/hub.c \ src/host/ehci/ehci.c \ - src/class/cdc/cdc_host.c \ src/host/ehci/ehci.c \ + src/class/cdc/cdc_host.c \ + src/class/msc/msc_host.c \ src/portable/nxp/lpc18_43/hcd_lpc18_43.c include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject index 2b68bfa23..e0a2f6f97 100644 --- a/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject +++ b/examples/host/cdc_msc_hid/ses/lpc18xx/lpc18xx.emProject @@ -124,6 +124,10 @@ + USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5); - -// LPC_USB0->PORTSC1_D |= (1<<24); // FIXME force full speed for debugging + LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging #else // TODO OTG LPC_USB0->USBMODE_D = USBMODE_DEVICE; LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6b36ea94d..e62f47b72 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -158,7 +158,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it // notification endpoint tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc; - TU_ASSERT( hcd_edpt_open(rhport, dev_addr, ep_desc) ); + TU_ASSERT( usbh_edpt_open(rhport, dev_addr, ep_desc) ); p_cdc->ep_notif = ep_desc->bEndpointAddress; (*p_length) += p_desc[DESC_OFFSET_LEN]; @@ -179,7 +179,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 69c49b012..8abb3cd22 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ static inline bool hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_desc_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) { - p_hid->pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); + p_hid->pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID); p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor p_hid->interface_number = interface_number; diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index e20969f57..98c71eb70 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -293,7 +293,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) { diff --git a/src/class/vendor/vendor_host.c b/src/class/vendor/vendor_host.c index 3e8dac0f6..0524cb981 100644 --- a/src/class/vendor/vendor_host.c +++ b/src/class/vendor/vendor_host.c @@ -107,7 +107,7 @@ tusb_error_t cush_open_subtask(uint8_t dev_addr, tusb_desc_interface_t const *p_ pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_IN_MASK ) ? &custom_interface[dev_addr-1].pipe_in : &custom_interface[dev_addr-1].pipe_out; - *p_pipe_hdl = hcd_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); + *p_pipe_hdl = usbh_edpt_open(dev_addr, p_endpoint, TUSB_CLASS_VENDOR_SPECIFIC); TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl), TUSB_ERROR_HCD_OPEN_PIPE_FAILED ); p_desc = tu_desc_next(p_desc); diff --git a/src/host/ehci/ehci.c b/src/host/ehci/ehci.c index 048affb1e..e2ead7b08 100644 --- a/src/host/ehci/ehci.c +++ b/src/host/ehci/ehci.c @@ -120,10 +120,27 @@ void hcd_port_reset(uint8_t rhport) ehci_registers_t* regs = ehci_data.regs; - regs->portsc_bm.port_enabled = 0; // disable port before reset - regs->portsc_bm.port_reset = 1; +// regs->portsc_bm.port_enabled = 0; // disable port before reset +// regs->portsc_bm.port_reset = 1; + + uint32_t portsc = regs->portsc; + + portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED); + portsc |= EHCI_PORTSC_MASK_PORT_RESET; + + regs->portsc = portsc; } +#if 0 +void hcd_port_reset_end(uint8_t rhport) +{ + (void) rhport; + + ehci_registers_t* regs = ehci_data.regs; + regs->portsc_bm.port_reset = 0; +} +#endif + bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; diff --git a/src/host/ehci/ehci.h b/src/host/ehci/ehci.h index f11c4536a..a6342b2d2 100644 --- a/src/host/ehci/ehci.h +++ b/src/host/ehci/ehci.h @@ -311,10 +311,14 @@ enum ehci_usbcmd_pos_ { }; enum ehci_portsc_change_mask_{ + EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + EHCI_PORTSC_MASK_ALL = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE | diff --git a/src/host/hcd.h b/src/host/hcd.h index d9307ca09..f2ca0a1d6 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -104,6 +104,7 @@ static inline uint32_t hcd_frame_number(uint8_t rhport) /// return the current connect status of roothub port bool hcd_port_connect_status(uint8_t hostid); void hcd_port_reset(uint8_t hostid); +void hcd_port_reset_end(uint8_t rhport); tusb_speed_t hcd_port_speed_get(uint8_t hostid); // HCD closes all opened endpoints belong to this device diff --git a/src/host/hub.c b/src/host/hub.c index 00450b704..eb85dfa42 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -154,7 +154,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType); TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer); - TU_ASSERT(hcd_edpt_open(rhport, dev_addr, ep_desc)); + TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc)); hub_data[dev_addr-1].itf_num = itf_desc->bInterfaceNumber; hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress; diff --git a/src/host/usbh.c b/src/host/usbh.c index 7171f6bab..8536cec0a 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -116,7 +116,6 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _usbh_ctrl_buf[CFG_TUSB_H //------------- Helper Function Prototypes -------------// static inline uint8_t get_new_address(void); static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_desc); -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id); //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) @@ -225,6 +224,30 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size) return TUSB_ERROR_NONE; } +bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + bool ret = hcd_edpt_open(rhport, dev_addr, ep_desc); + + if (ret) + { + usbh_device_t* dev = &_usbh_devices[dev_addr]; + + // new endpoints belongs to latest interface (last valid value) + uint8_t drvid = 0xff; + for(uint8_t i=0; i < sizeof(dev->itf2drv); i++) + { + if ( dev->itf2drv[i] == 0xff ) break; + drvid = dev->itf2drv[i]; + } + TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT); + + uint8_t const ep_addr = ep_desc->bEndpointAddress; + dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid; + } + + return ret; +} + //--------------------------------------------------------------------+ // USBH-HCD ISR/Callback API //--------------------------------------------------------------------+ @@ -358,6 +381,8 @@ bool enum_task(hcd_event_t* event) { if( hcd_port_connect_status(dev0->rhport) ) { + TU_LOG2("Connect \r\n"); + // connection event osal_task_delay(POWER_STABLE_DELAY); // wait until device is stable. Increase this if the first 8 bytes is failed to get @@ -371,6 +396,8 @@ bool enum_task(hcd_event_t* event) } else { + TU_LOG2("Disconnect \r\n"); + // disconnection event usbh_device_unplugged(dev0->rhport, 0, 0); return true; // restart task @@ -424,6 +451,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR( usbh_pipe_control_open(0, 8) ); //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------// + TU_LOG2("Get 8 byte of Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -434,12 +462,16 @@ bool enum_task(hcd_event_t* event) bool is_ok = usbh_control_xfer(0, &request, _usbh_ctrl_buf); //------------- Reset device again before Set Address -------------// + TU_LOG2("Port reset \r\n"); + if (dev0->hub_addr == 0) { // connected directly to roothub TU_ASSERT(is_ok); // TODO some slow device is observed to fail the very fist controller xfer, can try more times hcd_port_reset( dev0->rhport ); // reset port after 8 byte descriptor osal_task_delay(RESET_DELAY); +// hcd_port_reset_end(dev0->rhport); +// osal_task_delay(RESET_DELAY); } #if CFG_TUH_HUB else @@ -458,6 +490,7 @@ bool enum_task(hcd_event_t* event) #endif //------------- Set new address -------------// + TU_LOG2("Set Address \r\n"); uint8_t const new_addr = get_new_address(); TU_ASSERT(new_addr <= CFG_TUSB_HOST_DEVICE_MAX); // TODO notify application we reach max devices @@ -484,6 +517,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT_ERR ( usbh_pipe_control_open(new_addr, ((tusb_desc_device_t*) _usbh_ctrl_buf)->bMaxPacketSize0 ) ); //------------- Get full device descriptor -------------// + TU_LOG2("Get Device Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -502,6 +536,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT(configure_selected <= new_dev->configure_count); // TODO notify application when invalid configuration //------------- Get 9 bytes of configuration descriptor -------------// + TU_LOG2("Get 9 bytes of Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_IN }, .bRequest = TUSB_REQ_GET_DESCRIPTOR, @@ -515,6 +550,7 @@ bool enum_task(hcd_event_t* event) TU_ASSERT( CFG_TUSB_HOST_ENUM_BUFFER_SIZE >= ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength ); //------------- Get full configuration descriptor -------------// + TU_LOG2("Get full Configuration Descriptor \r\n"); request.wLength = ((tusb_desc_configuration_t*)_usbh_ctrl_buf)->wTotalLength; // full length TU_ASSERT( usbh_control_xfer( new_addr, &request, _usbh_ctrl_buf ) ); @@ -522,6 +558,7 @@ bool enum_task(hcd_event_t* event) new_dev->interface_count = ((tusb_desc_configuration_t*) _usbh_ctrl_buf)->bNumInterfaces; //------------- Set Configure -------------// + TU_LOG2("Set Configuration Descriptor \r\n"); request = (tusb_control_request_t ) { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, .bRequest = TUSB_REQ_SET_CONFIGURATION, @@ -577,11 +614,7 @@ bool enum_task(hcd_event_t* event) { uint16_t itf_len = 0; - if ( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ) - { - mark_interface_endpoint(new_dev->ep2drv, p_desc, itf_len, drv_id); - } - + TU_ASSERT( usbh_class_drivers[drv_id].open(new_dev->rhport, new_addr, desc_itf, &itf_len) ); TU_ASSERT( itf_len >= sizeof(tusb_desc_interface_t) ); p_desc += itf_len; } @@ -597,7 +630,7 @@ bool enum_task(hcd_event_t* event) /* USB Host Driver task * This top level thread manages all host controller event and delegates events to class-specific drivers. * This should be called periodically within the mainloop or rtos thread. - * + *_usbh_devices[dev_addr]. @code int main(void) { @@ -661,25 +694,4 @@ static inline uint8_t get_configure_number_for_device(tusb_desc_device_t* dev_de return config_num; } -// Helper marking endpoint of interface belongs to class driver -// TODO merge with usbd -static void mark_interface_endpoint(uint8_t ep2drv[8][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id) -{ - uint16_t len = 0; - - while( len < desc_len ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - - ep2drv[ tu_edpt_number(ep_addr) ][ tu_edpt_dir(ep_addr) ] = driver_id; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } -} - - #endif diff --git a/src/host/usbh.h b/src/host/usbh.h index 42a2bd095..bc0abcccc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -94,6 +94,8 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t dev_addr); bool usbh_init(void); 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); + #ifdef __cplusplus } #endif