summaryrefslogtreecommitdiff
path: root/tinyusb/host
diff options
context:
space:
mode:
authorhathach <[email protected]>2013-09-30 16:13:08 +0700
committerhathach <[email protected]>2013-09-30 16:13:08 +0700
commit5fb22e3f34db0d9e91df8ca306cc97518bb99792 (patch)
treeb680b1bf2656504714e4fc204503999990767d80 /tinyusb/host
parent821f85cb200c870b874c6681801d20410930dbc5 (diff)
refractor hub
Diffstat (limited to 'tinyusb/host')
-rw-r--r--tinyusb/host/hub.c56
-rw-r--r--tinyusb/host/hub.h46
2 files changed, 63 insertions, 39 deletions
diff --git a/tinyusb/host/hub.c b/tinyusb/host/hub.c
index ec033b868..672ac4c10 100644
--- a/tinyusb/host/hub.c
+++ b/tinyusb/host/hub.c
@@ -64,15 +64,25 @@ uint8_t hub_enum_buffer[sizeof(descriptor_hub_desc_t)] TUSB_CFG_ATTR_USBRAM;
//--------------------------------------------------------------------+
// HUB
//--------------------------------------------------------------------+
-tusb_error_t hub_enumerate_subtask(void)
+tusb_error_t hub_port_clear_feature_subtask(uint8_t feature)
{
tusb_error_t error;
OSAL_SUBTASK_BEGIN
- hub_port_status_response_t * p_port_status;
+ SUBTASK_ASSERT(HUB_FEATURE_PORT_CONNECTION_CHANGE <= feature &&
+ feature <= HUB_FEATURE_PORT_RESET_CHANGE);
- //------------- Get Port Status -------------//
+ //------------- Clear Port Feature request -------------//
+ 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, feature, usbh_devices[0].hub_port,
+ 0, NULL ),
+ error
+ );
+ SUBTASK_ASSERT_STATUS( error );
+
+ //------------- Get Port Status to check if feature 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,
@@ -81,26 +91,22 @@ tusb_error_t hub_enumerate_subtask(void)
);
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
+ //------------- Check if feature is cleared -------------//
+ hub_port_status_response_t * p_port_status = (hub_port_status_response_t *) hub_enum_buffer;
+ SUBTASK_ASSERT( !BIT_TEST_(p_port_status->status_change.value, feature-16) );
- if ( !p_port_status->status_current.connect_status )
- { // TODO HUB Disconnection
+ OSAL_SUBTASK_END
+}
- SUBTASK_EXIT(TUSB_ERROR_NONE);
- }
+tusb_error_t hub_enumerate_subtask(void)
+{
+ tusb_error_t error;
- // 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 );
+ OSAL_SUBTASK_BEGIN
+
+ hub_port_status_response_t * p_port_status;
- //------------- Get Port Status again to make sure Connect Change is cleared -------------//
+ //------------- 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,
@@ -110,7 +116,17 @@ tusb_error_t hub_enumerate_subtask(void)
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
+ 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);
+ }
+
+ // Acknowledge Port Connection Change
+ OSAL_SUBTASK_INVOKED_AND_WAIT( hub_port_clear_feature_subtask(HUB_FEATURE_PORT_CONNECTION_CHANGE), error );
+ SUBTASK_ASSERT_STATUS( error );
//--------------------------------------------------------------------+
// PORT RESET & WAIT FOR STATUS ENDPOINT & GET STATUS & CLEAR RESET CHANGE
diff --git a/tinyusb/host/hub.h b/tinyusb/host/hub.h
index cc36ef0a6..445b4e2a3 100644
--- a/tinyusb/host/hub.h
+++ b/tinyusb/host/hub.h
@@ -144,32 +144,40 @@ enum{
// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub)
typedef struct {
- ATTR_PACKED_STRUCT(struct) {
- uint16_t local_power_source : 1;
- uint16_t over_current : 1;
- uint16_t : 14;
- }status, status_change;
+ union{
+ ATTR_PACKED_STRUCT(struct) {
+ uint16_t local_power_source : 1;
+ uint16_t over_current : 1;
+ uint16_t : 14;
+ };
+
+ uint16_t value;
+ } status, status_change;
} hub_status_response_t;
STATIC_ASSERT( sizeof(hub_status_response_t) == 4, "size is not correct");
// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num
typedef struct {
- ATTR_PACKED_STRUCT(struct) {
- uint16_t connect_status : 1;
- uint16_t port_enable : 1;
- uint16_t suspend : 1;
- uint16_t over_current : 1;
- uint16_t reset : 1;
+ union {
+ ATTR_PACKED_STRUCT(struct) {
+ uint16_t connect_status : 1;
+ uint16_t port_enable : 1;
+ uint16_t suspend : 1;
+ uint16_t over_current : 1;
+ uint16_t reset : 1;
+
+ uint16_t : 3;
+ uint16_t port_power : 1;
+ uint16_t low_speed_device_attached : 1;
+ uint16_t high_speed_device_attached : 1;
+ uint16_t port_test_mode : 1;
+ uint16_t port_indicator_control : 1;
+ uint16_t : 0;
+ };
- uint16_t : 3;
- uint16_t port_power : 1;
- uint16_t low_speed_device_attached : 1;
- uint16_t high_speed_device_attached : 1;
- uint16_t port_test_mode : 1;
- uint16_t port_indicator_control : 1;
- uint16_t : 0;
- }status_current, status_change;
+ uint16_t value;
+ } status_current, status_change;
} hub_port_status_response_t;
STATIC_ASSERT( sizeof(hub_port_status_response_t) == 4, "size is not correct");