summaryrefslogtreecommitdiff
path: root/tinyusb/host/hub.c
diff options
context:
space:
mode:
authorhathach <[email protected]>2013-09-30 15:34:22 +0700
committerhathach <[email protected]>2013-09-30 15:34:22 +0700
commit821f85cb200c870b874c6681801d20410930dbc5 (patch)
tree8913a634bb69e35f1bb829067fe1a2e148eefb46 /tinyusb/host/hub.c
parent3cc169f2fd3159ecad494eb6223bbed6cc8135d6 (diff)
refractor hub
Diffstat (limited to 'tinyusb/host/hub.c')
-rw-r--r--tinyusb/host/hub.c97
1 files changed, 93 insertions, 4 deletions
diff --git a/tinyusb/host/hub.c b/tinyusb/host/hub.c
index da457a359..ec033b868 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;