| /* | |
| * SPDX-FileCopyrightText: Copyright (c) 2019 Ha Thach (tinyusb.org) | |
| * SPDX-License-Identifier: MIT | |
| * | |
| * This file is part of the TinyUSB stack. | |
| */ | |
| #ifndef TUSB_HUB_H_ | |
| #define TUSB_HUB_H_ | |
| #include "common/tusb_common.h" | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| //--------------------------------------------------------------------+ | |
| // Configuration | |
| //--------------------------------------------------------------------+ | |
| #ifndef CFG_TUH_HUB_BUFSIZE | |
| #define CFG_TUH_HUB_BUFSIZE 12 | |
| #endif | |
| //--------------------------------------------------------------------+ | |
| // | |
| //--------------------------------------------------------------------+ | |
| enum { | |
| HUB_REQUEST_GET_STATUS = 0 , | |
| HUB_REQUEST_CLEAR_FEATURE = 1 , | |
| // 2 is reserved | |
| HUB_REQUEST_SET_FEATURE = 3 , | |
| // 4-5 are reserved | |
| HUB_REQUEST_GET_DESCRIPTOR = 6 , | |
| HUB_REQUEST_SET_DESCRIPTOR = 7 , | |
| HUB_REQUEST_CLEAR_TT_BUFFER = 8 , | |
| HUB_REQUEST_RESET_TT = 9 , | |
| HUB_REQUEST_GET_TT_STATE = 10 , | |
| HUB_REQUEST_STOP_TT = 11 | |
| }; | |
| enum { | |
| HUB_FEATURE_HUB_LOCAL_POWER_CHANGE = 0, | |
| HUB_FEATURE_HUB_OVER_CURRENT_CHANGE | |
| }; | |
| enum{ | |
| HUB_FEATURE_PORT_CONNECTION = 0, | |
| HUB_FEATURE_PORT_ENABLE = 1, | |
| HUB_FEATURE_PORT_SUSPEND = 2, | |
| HUB_FEATURE_PORT_OVER_CURRENT = 3, | |
| HUB_FEATURE_PORT_RESET = 4, | |
| // 5-7 are reserved | |
| HUB_FEATURE_PORT_POWER = 8, | |
| HUB_FEATURE_PORT_LOW_SPEED = 9, | |
| // 10-15 are reserved | |
| HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, | |
| HUB_FEATURE_PORT_ENABLE_CHANGE = 17, | |
| HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, | |
| HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, | |
| HUB_FEATURE_PORT_RESET_CHANGE = 20, | |
| HUB_FEATURE_PORT_TEST = 21, | |
| HUB_FEATURE_PORT_INDICATOR = 22 | |
| }; | |
| enum { | |
| HUB_CHARS_POWER_GANGED_SWITCHING = 0, | |
| HUB_CHARS_POWER_INDIVIDUAL_SWITCHING = 1, | |
| }; | |
| enum { | |
| HUB_CHARS_OVER_CURRENT_GLOBAL = 0, | |
| HUB_CHARS_OVER_CURRENT_INDIVIDUAL = 1, | |
| }; | |
| // Hub Interface Protocol (USB 2.0 spec Table 11-16) | |
| typedef enum { | |
| HUB_PROTOCOL_FULL_SPEED = 0, // Full speed hub | |
| HUB_PROTOCOL_HIGH_SPEED_STT = 1, // Hi-speed hub with single TT | |
| HUB_PROTOCOL_HIGH_SPEED_MTT = 2, // Hi-speed hub with multiple TTs | |
| } hub_protocol_t; | |
| typedef struct TU_ATTR_PACKED{ | |
| uint8_t bLength ; ///< Size of descriptor | |
| uint8_t bDescriptorType ; ///< Other_speed_Configuration Type | |
| uint8_t bNbrPorts; | |
| uint16_t wHubCharacteristics; | |
| uint8_t bPwrOn2PwrGood; | |
| uint8_t bHubContrCurrent; | |
| uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) | |
| uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff | |
| } hub_desc_cs_t; | |
| TU_VERIFY_STATIC(sizeof(hub_desc_cs_t) == 9, "size is not correct"); | |
| TU_VERIFY_STATIC(CFG_TUH_HUB_BUFSIZE >= sizeof(hub_desc_cs_t), "buffer is not big enough"); | |
| typedef struct TU_ATTR_PACKED { | |
| struct TU_ATTR_PACKED { | |
| uint8_t logical_power_switching_mode : 2; // [0..1] gannged or individual power switching | |
| uint8_t compound_device : 1; // [2] hub is part of compound device | |
| uint8_t over_current_protect_mode : 2; // [3..4] global or individual port over-current protection | |
| uint8_t tt_think_time : 2; // [5..6] TT think time | |
| uint8_t port_indicator_supported : 1; // [7] port indicator supported | |
| }; | |
| uint8_t rsv1; | |
| } hub_characteristics_t; | |
| TU_VERIFY_STATIC(sizeof(hub_characteristics_t) == 2, "size is not correct"); | |
| // data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) | |
| typedef struct { | |
| union{ | |
| struct TU_ATTR_PACKED { | |
| uint16_t local_power_source : 1; | |
| uint16_t over_current : 1; | |
| uint16_t : 14; | |
| }; | |
| uint16_t value; | |
| } status, change; | |
| } hub_status_response_t; | |
| TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); | |
| // data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num | |
| typedef struct { | |
| union TU_ATTR_PACKED { | |
| struct TU_ATTR_PACKED { | |
| // Bit 0-4 are for change & status | |
| uint16_t connection : 1; // [0] 0 = no device, 1 = device connected | |
| uint16_t port_enable : 1; // [1] port is enabled | |
| uint16_t suspend : 1; // [2] | |
| uint16_t over_current : 1; // [3] over-current exists | |
| uint16_t reset : 1; // [4] 0 = no reset, 1 = resetting | |
| // From Bit 5 are for status only | |
| uint16_t rsv5_7 : 3; // [5..7] reserved | |
| uint16_t port_power : 1; // [8] 0 = port is off, 1 = port is on | |
| uint16_t low_speed : 1; // [9] low speed device attached | |
| uint16_t high_speed : 1; // [10] high speed device attached | |
| uint16_t port_test_mode : 1; // [11] port in test mode | |
| uint16_t port_indicator_control : 1; // [12] 0: default color, 1: indicator is software controlled | |
| uint16_t TU_RESERVED : 3; // [13..15] reserved | |
| }; | |
| uint16_t value; | |
| } status, change; | |
| } hub_port_status_response_t; | |
| TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); | |
| //--------------------------------------------------------------------+ | |
| // HUB API | |
| //--------------------------------------------------------------------+ | |
| // Clear port feature | |
| bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, | |
| tuh_xfer_cb_t complete_cb, uintptr_t user_data); | |
| // Set port feature | |
| bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, | |
| tuh_xfer_cb_t complete_cb, uintptr_t user_data); | |
| // Get port status | |
| // If hub_port != 0, resp is ignored. hub_port_get_status_local() can be used to retrieve the status | |
| bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void *resp, | |
| tuh_xfer_cb_t complete_cb, uintptr_t user_data); | |
| // Get the last port status read by hub_port_get_status(), valid until the next data-stage request to this hub. | |
| // This does not send a request to the device | |
| bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp); | |
| // Get status from Interrupt endpoint | |
| bool hub_edpt_status_xfer(uint8_t daddr); | |
| // Reset a port | |
| TU_ATTR_ALWAYS_INLINE static inline | |
| bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { | |
| return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data); | |
| } | |
| // Clear Port Reset Change | |
| TU_ATTR_ALWAYS_INLINE static inline | |
| bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { | |
| return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); | |
| } | |
| // Get Hub status (port = 0) | |
| TU_ATTR_ALWAYS_INLINE static inline | |
| bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { | |
| return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data); | |
| } | |
| // Clear Hub feature | |
| TU_ATTR_ALWAYS_INLINE static inline | |
| bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { | |
| return hub_port_clear_feature(hub_addr, 0, feature, complete_cb, user_data); | |
| } | |
| //--------------------------------------------------------------------+ | |
| // Internal Class Driver API | |
| //--------------------------------------------------------------------+ | |
| bool hub_init(void); | |
| bool hub_deinit(void); | |
| uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); | |
| bool hub_set_config(uint8_t daddr, uint8_t itf_num); | |
| bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); | |
| void hub_close(uint8_t dev_addr); | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #endif |