34
34
#include "hub.h"
35
35
36
36
//--------------------------------------------------------------------+
37
- // USBH Configuration
37
+ // Configuration
38
38
//--------------------------------------------------------------------+
39
39
#ifndef CFG_TUH_TASK_QUEUE_SZ
40
40
#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
89
89
}
90
90
91
91
//--------------------------------------------------------------------+
92
- // USBH-HCD common data structure
92
+ // Data Structure
93
93
//--------------------------------------------------------------------+
94
94
typedef struct {
95
95
tuh_bus_info_t bus_info ;
@@ -131,8 +131,60 @@ typedef struct {
131
131
132
132
} usbh_device_t ;
133
133
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
+
134
186
//--------------------------------------------------------------------+
135
- // MACRO CONSTANT TYPEDEF
187
+ // Class Driver
136
188
//--------------------------------------------------------------------+
137
189
#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
138
190
#define DRIVER_NAME (_name ) _name
@@ -235,71 +287,21 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) {
235
287
}
236
288
237
289
//--------------------------------------------------------------------+
238
- // INTERNAL OBJECT & FUNCTION DECLARATION
290
+ // Function Inline and Prototypes
239
291
//--------------------------------------------------------------------+
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 );
240
296
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 -------------//
294
297
TU_ATTR_ALWAYS_INLINE static inline usbh_device_t * get_device (uint8_t dev_addr ) {
295
298
TU_VERIFY (dev_addr > 0 && dev_addr <= TOTAL_DEVICES , NULL );
296
299
return & _usbh_devices [dev_addr - 1 ];
297
300
}
298
301
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
+ }
303
305
304
306
TU_ATTR_ALWAYS_INLINE static inline bool queue_event (hcd_event_t const * event , bool in_isr ) {
305
307
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
341
343
//--------------------------------------------------------------------+
342
344
// Device API
343
345
//--------------------------------------------------------------------+
344
-
345
346
bool tuh_mounted (uint8_t dev_addr ) {
346
347
usbh_device_t * dev = get_device (dev_addr );
347
348
TU_VERIFY (dev );
@@ -562,7 +563,6 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
562
563
563
564
case HCD_EVENT_DEVICE_REMOVE :
564
565
TU_LOG1 ("[%u:%u:%u] USBH DEVICE REMOVED\r\n" , event .rhport , event .connection .hub_addr , event .connection .hub_port );
565
-
566
566
if (_usbh_data .enumerating_daddr == 0 &&
567
567
event .rhport == _usbh_data .dev0_bus .rhport &&
568
568
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) {
572
572
} else {
573
573
process_removed_device (event .rhport , event .connection .hub_addr , event .connection .hub_port );
574
574
}
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
583
575
break ;
584
576
585
577
case HCD_EVENT_XFER_COMPLETE : {
@@ -1286,15 +1278,13 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i
1286
1278
//--------------------------------------------------------------------+
1287
1279
// Detaching
1288
1280
//--------------------------------------------------------------------+
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
-
1294
1281
// a device unplugged from rhport:hub_addr:hub_port
1295
1282
static void process_removed_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port ) {
1296
1283
// 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
+
1298
1288
do {
1299
1289
for (uint8_t dev_id = 0 ; dev_id < TOTAL_DEVICES ; dev_id ++ ) {
1300
1290
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
1306
1296
(hub_port == 0 || dev -> bus_info .hub_port == hub_port )) {
1307
1297
TU_LOG_USBH ("[%u:%u:%u] unplugged address = %u\r\n" , rhport , hub_addr , hub_port , daddr );
1308
1298
1299
+ #if CFG_TUH_HUB
1309
1300
if (is_hub_addr (daddr )) {
1310
1301
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
+ {
1313
1306
// Invoke callback before closing driver (maybe call it later ?)
1314
1307
if (tuh_umount_cb ) {
1315
1308
tuh_umount_cb (daddr );
@@ -1329,27 +1322,27 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
1329
1322
}
1330
1323
}
1331
1324
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 ) ) {
1335
1328
break ;
1336
1329
}
1337
1330
1338
1331
// find a marked hub to process
1339
1332
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 ;
1342
1335
1343
1336
// update hub_addr and hub_port for next loop
1344
1337
hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX ;
1345
1338
hub_port = 0 ;
1346
1339
break ;
1347
1340
}
1348
1341
}
1349
- #else
1350
- (void ) removing_hubs ;
1342
+ #else
1351
1343
break ;
1352
- #endif
1344
+ #endif
1345
+
1353
1346
} while (1 );
1354
1347
}
1355
1348
0 commit comments