3434#include "hub.h"
3535
3636//--------------------------------------------------------------------+
37- // USBH Configuration
37+ // Configuration
3838//--------------------------------------------------------------------+
3939#ifndef CFG_TUH_TASK_QUEUE_SZ
4040 #define CFG_TUH_TASK_QUEUE_SZ 16
@@ -89,7 +89,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si
8989}
9090
9191//--------------------------------------------------------------------+
92- // USBH-HCD common data structure
92+ // Data Structure
9393//--------------------------------------------------------------------+
9494typedef struct {
9595 tuh_bus_info_t bus_info ;
@@ -131,8 +131,60 @@ typedef struct {
131131
132132} usbh_device_t ;
133133
134+ // sum of end device + hub
135+ #define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB)
136+
137+ // all devices excluding zero-address
138+ // hub address start from CFG_TUH_DEVICE_MAX+1
139+ // TODO: hub can has its own simpler struct to save memory
140+ static usbh_device_t _usbh_devices [TOTAL_DEVICES ];
141+
142+ // Mutex for claiming endpoint
143+ #if OSAL_MUTEX_REQUIRED
144+ static osal_mutex_def_t _usbh_mutexdef ;
145+ static osal_mutex_t _usbh_mutex ;
146+ #else
147+ #define _usbh_mutex NULL
148+ #endif
149+
150+ // Event queue: usbh_int_set() is used as mutex in OS NONE config
151+ OSAL_QUEUE_DEF (usbh_int_set , _usbh_qdef , CFG_TUH_TASK_QUEUE_SZ , hcd_event_t );
152+ static osal_queue_t _usbh_q ;
153+
154+ // Control transfers: since most controllers do not support multiple control transfers
155+ // on multiple devices concurrently and control transfers are not used much except for
156+ // enumeration, we will only execute control transfers one at a time.
157+ typedef struct {
158+ uint8_t * buffer ;
159+ tuh_xfer_cb_t complete_cb ;
160+ uintptr_t user_data ;
161+
162+ volatile uint8_t stage ;
163+ uint8_t daddr ;
164+ volatile uint16_t actual_len ;
165+ uint8_t failed_count ;
166+ } usbh_ctrl_xfer_info_t ;
167+
168+ typedef struct {
169+ uint8_t controller_id ; // controller ID
170+ uint8_t enumerating_daddr ; // device address of the device being enumerated
171+ uint8_t attach_debouncing_bm ; // bitmask for roothub port attach debouncing
172+ tuh_bus_info_t dev0_bus ; // bus info for dev0 in enumeration
173+ usbh_ctrl_xfer_info_t ctrl_xfer_info ; // control transfer
174+ } usbh_data_t ;
175+
176+ static usbh_data_t _usbh_data = {
177+ .controller_id = TUSB_INDEX_INVALID_8 ,
178+ };
179+
180+ typedef struct {
181+ TUH_EPBUF_TYPE_DEF (tusb_control_request_t , request );
182+ TUH_EPBUF_DEF (ctrl , CFG_TUH_ENUMERATION_BUFSIZE );
183+ } usbh_epbuf_t ;
184+ CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf ;
185+
134186//--------------------------------------------------------------------+
135- // MACRO CONSTANT TYPEDEF
187+ // Class Driver
136188//--------------------------------------------------------------------+
137189#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
138190 #define DRIVER_NAME (_name ) _name
@@ -235,71 +287,21 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) {
235287}
236288
237289//--------------------------------------------------------------------+
238- // INTERNAL OBJECT & FUNCTION DECLARATION
290+ // Function Inline and Prototypes
239291//--------------------------------------------------------------------+
292+ static bool enum_new_device (hcd_event_t * event );
293+ static void process_removed_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port );
294+ static bool usbh_edpt_control_open (uint8_t dev_addr , uint8_t max_packet_size );
295+ static bool usbh_control_xfer_cb (uint8_t daddr , uint8_t ep_addr , xfer_result_t result , uint32_t xferred_bytes );
240296
241- // sum of end device + hub
242- #define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB)
243-
244- // all devices excluding zero-address
245- // hub address start from CFG_TUH_DEVICE_MAX+1
246- // TODO: hub can has its own simpler struct to save memory
247- static usbh_device_t _usbh_devices [TOTAL_DEVICES ];
248-
249- // Mutex for claiming endpoint
250- #if OSAL_MUTEX_REQUIRED
251- static osal_mutex_def_t _usbh_mutexdef ;
252- static osal_mutex_t _usbh_mutex ;
253- #else
254- #define _usbh_mutex NULL
255- #endif
256-
257- // Event queue: usbh_int_set() is used as mutex in OS NONE config
258- OSAL_QUEUE_DEF (usbh_int_set , _usbh_qdef , CFG_TUH_TASK_QUEUE_SZ , hcd_event_t );
259- static osal_queue_t _usbh_q ;
260-
261- // Control transfers: since most controllers do not support multiple control transfers
262- // on multiple devices concurrently and control transfers are not used much except for
263- // enumeration, we will only execute control transfers one at a time.
264- typedef struct {
265- uint8_t * buffer ;
266- tuh_xfer_cb_t complete_cb ;
267- uintptr_t user_data ;
268-
269- volatile uint8_t stage ;
270- uint8_t daddr ;
271- volatile uint16_t actual_len ;
272- uint8_t failed_count ;
273- } usbh_ctrl_xfer_info_t ;
274-
275- typedef struct {
276- uint8_t controller_id ; // controller ID
277- uint8_t enumerating_daddr ; // device address of the device being enumerated
278- uint8_t attach_debouncing_bm ; // bitmask for roothub port attach debouncing
279- tuh_bus_info_t dev0_bus ; // bus info for dev0 in enumeration
280- usbh_ctrl_xfer_info_t ctrl_xfer_info ; // control transfer
281- } usbh_data_t ;
282-
283- static usbh_data_t _usbh_data = {
284- .controller_id = TUSB_INDEX_INVALID_8 ,
285- };
286-
287- typedef struct {
288- TUH_EPBUF_TYPE_DEF (tusb_control_request_t , request );
289- TUH_EPBUF_DEF (ctrl , CFG_TUH_ENUMERATION_BUFSIZE );
290- } usbh_epbuf_t ;
291- CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf ;
292-
293- //------------- Helper Function -------------//
294297TU_ATTR_ALWAYS_INLINE static inline usbh_device_t * get_device (uint8_t dev_addr ) {
295298 TU_VERIFY (dev_addr > 0 && dev_addr <= TOTAL_DEVICES , NULL );
296299 return & _usbh_devices [dev_addr - 1 ];
297300}
298301
299- static bool enum_new_device (hcd_event_t * event );
300- static void process_removed_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port );
301- static bool usbh_edpt_control_open (uint8_t dev_addr , uint8_t max_packet_size );
302- static bool usbh_control_xfer_cb (uint8_t daddr , uint8_t ep_addr , xfer_result_t result , uint32_t xferred_bytes );
302+ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr (uint8_t daddr ) {
303+ return (CFG_TUH_HUB > 0 ) && (daddr > CFG_TUH_DEVICE_MAX );
304+ }
303305
304306TU_ATTR_ALWAYS_INLINE static inline bool queue_event (hcd_event_t const * event , bool in_isr ) {
305307 TU_ASSERT (osal_queue_send (_usbh_q , event , in_isr ));
@@ -341,7 +343,6 @@ TU_ATTR_ALWAYS_INLINE static inline void usbh_device_close(uint8_t rhport, uint8
341343//--------------------------------------------------------------------+
342344// Device API
343345//--------------------------------------------------------------------+
344-
345346bool tuh_mounted (uint8_t dev_addr ) {
346347 usbh_device_t * dev = get_device (dev_addr );
347348 TU_VERIFY (dev );
@@ -562,7 +563,6 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
562563
563564 case HCD_EVENT_DEVICE_REMOVE :
564565 TU_LOG1 ("[%u:%u:%u] USBH DEVICE REMOVED\r\n" , event .rhport , event .connection .hub_addr , event .connection .hub_port );
565-
566566 if (_usbh_data .enumerating_daddr == 0 &&
567567 event .rhport == _usbh_data .dev0_bus .rhport &&
568568 event .connection .hub_addr == _usbh_data .dev0_bus .hub_addr &&
@@ -572,14 +572,6 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
572572 } else {
573573 process_removed_device (event .rhport , event .connection .hub_addr , event .connection .hub_port );
574574 }
575-
576- #if CFG_TUH_HUB
577- // TODO remove
578- if (event .connection .hub_addr != 0 && event .connection .hub_port != 0 ) {
579- // done with hub, waiting for next data on status pipe
580- (void ) hub_edpt_status_xfer (event .connection .hub_addr );
581- }
582- #endif
583575 break ;
584576
585577 case HCD_EVENT_XFER_COMPLETE : {
@@ -1286,15 +1278,13 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i
12861278//--------------------------------------------------------------------+
12871279// Detaching
12881280//--------------------------------------------------------------------+
1289-
1290- TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr (uint8_t daddr ) {
1291- return (CFG_TUH_HUB > 0 ) && (daddr > CFG_TUH_DEVICE_MAX );
1292- }
1293-
12941281// a device unplugged from rhport:hub_addr:hub_port
12951282static void process_removed_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port ) {
12961283 // Find the all devices (star-network) under port that is unplugged
1297- uint32_t removing_hubs_bm = 0 ;
1284+ #if CFG_TUH_HUB
1285+ uint8_t removing_hubs [CFG_TUH_HUB ] = { 0 };
1286+ #endif
1287+
12981288 do {
12991289 for (uint8_t dev_id = 0 ; dev_id < TOTAL_DEVICES ; dev_id ++ ) {
13001290 usbh_device_t * dev = & _usbh_devices [dev_id ];
@@ -1306,10 +1296,13 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
13061296 (hub_port == 0 || dev -> bus_info .hub_port == hub_port )) {
13071297 TU_LOG_USBH ("[%u:%u:%u] unplugged address = %u\r\n" , rhport , hub_addr , hub_port , daddr );
13081298
1299+ #if CFG_TUH_HUB
13091300 if (is_hub_addr (daddr )) {
13101301 TU_LOG_USBH (" is a HUB device %u\r\n" , daddr );
1311- removing_hubs_bm |= TU_BIT (dev_id - CFG_TUH_DEVICE_MAX );
1312- } else {
1302+ removing_hubs [dev_id - CFG_TUH_DEVICE_MAX ] = 1 ;
1303+ } else
1304+ #endif
1305+ {
13131306 // Invoke callback before closing driver (maybe call it later ?)
13141307 if (tuh_umount_cb ) {
13151308 tuh_umount_cb (daddr );
@@ -1329,27 +1322,27 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
13291322 }
13301323 }
13311324
1332- // if removing a hub, we need to remove all of its downstream devices
1333- # if CFG_TUH_HUB
1334- if (removing_hubs_bm == 0 ) {
1325+ # if CFG_TUH_HUB
1326+ // if a hub is removed, we need to remove all of its downstream devices
1327+ if (tu_mem_is_zero ( removing_hubs , CFG_TUH_HUB ) ) {
13351328 break ;
13361329 }
13371330
13381331 // find a marked hub to process
13391332 for (uint8_t h_id = 0 ; h_id < CFG_TUH_HUB ; h_id ++ ) {
1340- if (tu_bit_test ( removing_hubs_bm , h_id ) ) {
1341- removing_hubs_bm &= ~ TU_BIT ( h_id ) ;
1333+ if (removing_hubs [ h_id ] ) {
1334+ removing_hubs [ h_id ] = 0 ;
13421335
13431336 // update hub_addr and hub_port for next loop
13441337 hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX ;
13451338 hub_port = 0 ;
13461339 break ;
13471340 }
13481341 }
1349- #else
1350- (void ) removing_hubs ;
1342+ #else
13511343 break ;
1352- #endif
1344+ #endif
1345+
13531346 } while (1 );
13541347}
13551348
0 commit comments