From 821f85cb200c870b874c6681801d20410930dbc5 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 30 Sep 2013 15:34:22 +0700 Subject: [PATCH] refractor hub --- demos/host/host_os_none/host_os_none.uvopt | 14 ++-- tinyusb/host/hub.c | 97 +++++++++++++++++++++- tinyusb/host/usbh.c | 79 +----------------- 3 files changed, 101 insertions(+), 89 deletions(-) diff --git a/demos/host/host_os_none/host_os_none.uvopt b/demos/host/host_os_none/host_os_none.uvopt index 6a966136..4aada821 100644 --- a/demos/host/host_os_none/host_os_none.uvopt +++ b/demos/host/host_os_none/host_os_none.uvopt @@ -760,10 +760,10 @@ 1 0 0 - 1 + 0 0 - 114 - 123 + 1 + 1 0 ..\..\..\tinyusb\host\hub.c hub.c @@ -778,8 +778,8 @@ 0 0 0 - 337 - 338 + 1 + 1 0 ..\..\..\tinyusb\host\usbh.c usbh.c @@ -1080,10 +1080,10 @@ 2 0 0 - 26 + 18 0 145 - 154 + 147 0 ..\..\bsp\lpc43xx\startup_keil\startup_LPC43xx.s startup_LPC43xx.s diff --git a/tinyusb/host/hub.c b/tinyusb/host/hub.c index da457a35..ec033b86 100644 --- a/tinyusb/host/hub.c +++ b/tinyusb/host/hub.c @@ -59,11 +59,99 @@ typedef struct { }usbh_hub_t; usbh_hub_t hub_data[TUSB_CFG_HOST_DEVICE_MAX] TUSB_CFG_ATTR_USBRAM; -descriptor_hub_desc_t hub_descriptor TUSB_CFG_ATTR_USBRAM; +uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)] TUSB_CFG_ATTR_USBRAM; //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION +// HUB //--------------------------------------------------------------------+ +tusb_error_t hub_enumerate_subtask(void) +{ + tusb_error_t error; + + OSAL_SUBTASK_BEGIN + + hub_port_status_response_t * p_port_status; + + //------------- Get Port Status -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, + 4, hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + if ( !p_port_status->status_change.connect_status ) SUBTASK_EXIT(TUSB_ERROR_NONE); // only handle connection change + + if ( !p_port_status->status_current.connect_status ) + { // TODO HUB Disconnection + + SUBTASK_EXIT(TUSB_ERROR_NONE); + } + + // Hub connection + //------------- Clear Hub Port Connect Status Change -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_CLEAR_FEATURE, HUB_FEATURE_PORT_CONNECTION_CHANGE, usbh_devices[0].hub_port, + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + //------------- Get Port Status again to make sure Connect Change is cleared -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, + 4, hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + SUBTASK_ASSERT( !p_port_status->status_change.connect_status); // this has to be cleared + + //--------------------------------------------------------------------+ + // PORT RESET & WAIT FOR STATUS ENDPOINT & GET STATUS & CLEAR RESET CHANGE + //--------------------------------------------------------------------+ + //------------- Set Port Reset -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, usbh_devices[0].hub_port, + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + osal_task_delay(200); // TODO Hub wait for Status Endpoint on Reset Change + + //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, + 4, hub_enum_buffer ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + p_port_status = (hub_port_status_response_t *) hub_enum_buffer; + SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && + p_port_status->status_current.port_power && p_port_status->status_current.port_enable); + + usbh_devices[0].speed = (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : + (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + + OSAL_SUBTASK_INVOKED_AND_WAIT( + usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), + HUB_REQUEST_CLEAR_FEATURE, HUB_FEATURE_PORT_RESET_CHANGE, usbh_devices[0].hub_port, + 0, NULL ), + error + ); + SUBTASK_ASSERT_STATUS( error ); + + OSAL_SUBTASK_END +} //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) @@ -97,12 +185,13 @@ tusb_error_t hub_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t cons OSAL_SUBTASK_INVOKED_AND_WAIT( usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_DEVICE), HUB_REQUEST_GET_DESCRIPTOR, 0, 0, - 9, &hub_descriptor ), + sizeof(descriptor_hub_desc_t), hub_enum_buffer ), error ); SUBTASK_ASSERT_STATUS(error); - hub_data[dev_addr-1].port_number = hub_descriptor.bNbrPorts; // only care about this field in hub descriptor + // only care about this field in hub descriptor + hub_data[dev_addr-1].port_number = ((descriptor_hub_desc_t*) hub_enum_buffer)->bNbrPorts; //------------- Set Port_Power on all ports -------------// static uint8_t i; diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c index 6115939b..5b6eeffd 100644 --- a/tinyusb/host/usbh.c +++ b/tinyusb/host/usbh.c @@ -354,84 +354,7 @@ tusb_error_t enumeration_body_subtask(void) if ( usbh_devices[0].hub_addr != 0) // connected/disconnected via hub { - hub_port_status_response_t * p_port_status; - - //------------- Get Port Status -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, - 4, enum_data_buffer ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - p_port_status = (hub_port_status_response_t *) enum_data_buffer; - if ( !p_port_status->status_change.connect_status ) SUBTASK_EXIT(TUSB_ERROR_NONE); // only handle connection change - - if ( !p_port_status->status_current.connect_status ) - { // TODO HUB Disconnection - - SUBTASK_EXIT(TUSB_ERROR_NONE); - } - - // Hub connection - //------------- Clear Hub Port Connect Status Change -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_CLEAR_FEATURE, HUB_FEATURE_PORT_CONNECTION_CHANGE, usbh_devices[0].hub_port, - 0, NULL ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - //------------- Get Port Status again to make sure Connect Change is cleared -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, - 4, enum_data_buffer ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - p_port_status = (hub_port_status_response_t *) enum_data_buffer; - SUBTASK_ASSERT( !p_port_status->status_change.connect_status); // this has to be cleared - - //--------------------------------------------------------------------+ - // PORT RESET & WAIT FOR STATUS ENDPOINT & GET STATUS & CLEAR RESET CHANGE - //--------------------------------------------------------------------+ - //------------- Set Port Reset -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_SET_FEATURE, HUB_FEATURE_PORT_RESET, usbh_devices[0].hub_port, - 0, NULL ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - osal_task_delay(200); // TODO Hub wait for Status Endpoint on Reset Change - - //------------- Get Port Status to check if port is enabled, powered and reset_change -------------// - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_GET_STATUS, 0, usbh_devices[0].hub_port, - 4, enum_data_buffer ), - error - ); - SUBTASK_ASSERT_STATUS( error ); - - p_port_status = (hub_port_status_response_t *) enum_data_buffer; - SUBTASK_ASSERT ( p_port_status->status_change.reset && p_port_status->status_current.connect_status && - p_port_status->status_current.port_power && p_port_status->status_current.port_enable); - - usbh_devices[0].speed = (p_port_status->status_current.high_speed_device_attached) ? TUSB_SPEED_HIGH : - (p_port_status->status_current.low_speed_device_attached ) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - - OSAL_SUBTASK_INVOKED_AND_WAIT( - usbh_control_xfer_subtask( usbh_devices[0].hub_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_OTHER), - HUB_REQUEST_CLEAR_FEATURE, HUB_FEATURE_PORT_RESET_CHANGE, usbh_devices[0].hub_port, - 0, NULL ), - error - ); + OSAL_SUBTASK_INVOKED_AND_WAIT( hub_enumerate_subtask(), error ); SUBTASK_ASSERT_STATUS( error ); } else