@@ -81,10 +81,12 @@ typedef struct {
81
81
82
82
// Device State
83
83
struct TU_ATTR_PACKED {
84
- volatile uint8_t connected : 1 ;
85
- volatile uint8_t addressed : 1 ;
86
- volatile uint8_t configured : 1 ;
87
- volatile uint8_t suspended : 1 ;
84
+ volatile uint8_t connected : 1 ; // After 1st transfer
85
+ volatile uint8_t addressed : 1 ; // After SET_ADDR
86
+ volatile uint8_t configured : 1 ; // After SET_CONFIG and all drivers are configured
87
+ volatile uint8_t suspended : 1 ; // Bus suspended
88
+
89
+ // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh
88
90
};
89
91
90
92
// Device Descriptor
@@ -248,7 +250,7 @@ static inline usbh_device_t* get_device(uint8_t dev_addr)
248
250
}
249
251
250
252
static bool enum_new_device (hcd_event_t * event );
251
- static void process_device_unplugged (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port );
253
+ static void process_removing_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port );
252
254
static bool usbh_edpt_control_open (uint8_t dev_addr , uint8_t max_packet_size );
253
255
static bool usbh_control_xfer_cb (uint8_t daddr , uint8_t ep_addr , xfer_result_t result , uint32_t xferred_bytes );
254
256
@@ -420,7 +422,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
420
422
421
423
case HCD_EVENT_DEVICE_REMOVE :
422
424
TU_LOG_USBH ("[%u:%u:%u] USBH DEVICE REMOVED\r\n" , event .rhport , event .connection .hub_addr , event .connection .hub_port );
423
- process_device_unplugged (event .rhport , event .connection .hub_addr , event .connection .hub_port );
425
+ process_removing_device (event .rhport , event .connection .hub_addr , event .connection .hub_port );
424
426
425
427
#if CFG_TUH_HUB
426
428
// TODO remove
@@ -450,7 +452,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
450
452
else
451
453
{
452
454
usbh_device_t * dev = get_device (event .dev_addr );
453
- TU_ASSERT (dev , );
455
+ TU_VERIFY (dev && dev -> connected , );
454
456
455
457
dev -> ep_status [epnum ][ep_dir ].busy = 0 ;
456
458
dev -> ep_status [epnum ][ep_dir ].claimed = 0 ;
@@ -739,29 +741,33 @@ void usbh_int_set(bool enabled)
739
741
// TODO has some duplication code with device, refactor later
740
742
bool usbh_edpt_claim (uint8_t dev_addr , uint8_t ep_addr )
741
743
{
744
+ // Note: addr0 only use tuh_control_xfer
742
745
usbh_device_t * dev = get_device (dev_addr );
743
-
744
- // addr0 only use tuh_control_xfer
745
- TU_ASSERT (dev );
746
+ TU_ASSERT (dev && dev -> connected );
746
747
747
748
uint8_t const epnum = tu_edpt_number (ep_addr );
748
749
uint8_t const dir = tu_edpt_dir (ep_addr );
749
750
750
- return tu_edpt_claim (& dev -> ep_status [epnum ][dir ], _usbh_mutex );
751
+ TU_VERIFY (tu_edpt_claim (& dev -> ep_status [epnum ][dir ], _usbh_mutex ));
752
+ TU_LOG_USBH ("[%u] Claimed EP 0x%02x\r\n" , dev_addr , ep_addr );
753
+
754
+ return true;
751
755
}
752
756
753
757
// TODO has some duplication code with device, refactor later
754
758
bool usbh_edpt_release (uint8_t dev_addr , uint8_t ep_addr )
755
759
{
760
+ // Note: addr0 only use tuh_control_xfer
756
761
usbh_device_t * dev = get_device (dev_addr );
757
-
758
- // addr0 only use tuh_control_xfer
759
- TU_ASSERT (dev );
762
+ TU_VERIFY (dev && dev -> connected );
760
763
761
764
uint8_t const epnum = tu_edpt_number (ep_addr );
762
765
uint8_t const dir = tu_edpt_dir (ep_addr );
763
766
764
- return tu_edpt_release (& dev -> ep_status [epnum ][dir ], _usbh_mutex );
767
+ TU_VERIFY (tu_edpt_release (& dev -> ep_status [epnum ][dir ], _usbh_mutex ));
768
+ TU_LOG_USBH ("[%u] Released EP 0x%02x\r\n" , dev_addr , ep_addr );
769
+
770
+ return true;
765
771
}
766
772
767
773
// TODO has some duplication code with device, refactor later
@@ -870,7 +876,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr)
870
876
switch (event -> event_id )
871
877
{
872
878
// case HCD_EVENT_DEVICE_REMOVE:
873
- //
879
+ // // mark device as removing to prevent further xfer before the event is processed in usbh task
874
880
// break;
875
881
876
882
default :
@@ -1116,7 +1122,7 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i
1116
1122
}
1117
1123
1118
1124
//--------------------------------------------------------------------+
1119
- //
1125
+ // Detaching
1120
1126
//--------------------------------------------------------------------+
1121
1127
1122
1128
TU_ATTR_ALWAYS_INLINE
@@ -1125,45 +1131,79 @@ static inline bool is_hub_addr(uint8_t daddr)
1125
1131
return (CFG_TUH_HUB > 0 ) && (daddr > CFG_TUH_DEVICE_MAX );
1126
1132
}
1127
1133
1134
+ //static void mark_removing_device_isr(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
1135
+ // for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
1136
+ // usbh_device_t *dev = &_usbh_devices[dev_id];
1137
+ // uint8_t const daddr = dev_id + 1;
1138
+ //
1139
+ // // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
1140
+ // if (dev->rhport == rhport && dev->connected &&
1141
+ // (hub_addr == 0 || dev->hub_addr == hub_addr) &&
1142
+ // (hub_port == 0 || dev->hub_port == hub_port)) {
1143
+ // if (is_hub_addr(daddr)) {
1144
+ // // If the device itself is a usb hub, mark all downstream devices.
1145
+ // // FIXME recursive calls
1146
+ // mark_removing_device_isr(rhport, daddr, 0);
1147
+ // }
1148
+ //
1149
+ // dev->removing = 1;
1150
+ // }
1151
+ // }
1152
+ //}
1153
+
1128
1154
// a device unplugged from rhport:hub_addr:hub_port
1129
- static void process_device_unplugged (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port )
1155
+ static void process_removing_device (uint8_t rhport , uint8_t hub_addr , uint8_t hub_port )
1130
1156
{
1131
1157
//------------- find the all devices (star-network) under port that is unplugged -------------//
1132
1158
// TODO mark as disconnected in ISR, also handle dev0
1133
- for ( uint8_t dev_id = 0 ; dev_id < TU_ARRAY_SIZE (_usbh_devices ); dev_id ++ )
1134
- {
1135
- usbh_device_t * dev = & _usbh_devices [dev_id ];
1136
- uint8_t const dev_addr = dev_id + 1 ;
1137
1159
1138
- if (dev -> rhport == rhport &&
1139
- (hub_addr == 0 || dev -> hub_addr == hub_addr ) && // hub_addr = 0 means roothub
1140
- (hub_port == 0 || dev -> hub_port == hub_port ) && // hub_port = 0 means all devices of downstream hub
1141
- dev -> connected )
1142
- {
1143
- TU_LOG_USBH ("Device unplugged address = %u\r\n" , dev_addr );
1160
+ #if 0
1161
+ // index as hub addr, value is hub port (0xFF for invalid)
1162
+ uint8_t removing_hubs [CFG_TUH_HUB ];
1163
+ memset (removing_hubs , TUSB_INDEX_INVALID_8 , sizeof (removing_hubs ));
1144
1164
1145
- if (is_hub_addr (dev_addr ))
1146
- {
1147
- TU_LOG (USBH_DEBUG , " is a HUB device\r\n" , dev_addr );
1148
- // If the device itself is a usb hub, unplug downstream devices.
1149
- // FIXME un-roll recursive calls to prevent potential stack overflow
1150
- process_device_unplugged (rhport , dev_addr , 0 );
1151
- }else
1152
- {
1165
+ removing_hubs [hub_addr - CFG_TUH_DEVICE_MAX ] = hub_port ;
1166
+
1167
+ // consecutive non-removing hub
1168
+ uint8_t nop_count = 0 ;
1169
+ #endif
1170
+
1171
+ for (uint8_t dev_id = 0 ; dev_id < TOTAL_DEVICES ; dev_id ++ ) {
1172
+ usbh_device_t * dev = & _usbh_devices [dev_id ];
1173
+ uint8_t const daddr = dev_id + 1 ;
1174
+
1175
+ // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
1176
+ if (dev -> rhport == rhport && dev -> connected &&
1177
+ (hub_addr == 0 || dev -> hub_addr == hub_addr ) &&
1178
+ (hub_port == 0 || dev -> hub_port == hub_port )) {
1179
+ TU_LOG_USBH ("Device unplugged address = %u\r\n" , daddr );
1180
+
1181
+ if (is_hub_addr (daddr )) {
1182
+ TU_LOG (USBH_DEBUG , " is a HUB device\r\n" , daddr );
1183
+
1184
+ // Submit removed event If the device itself is a hub (un-rolled recursive)
1185
+ // TODO a better to unroll recursrive is using array of removing_hubs and mark it here
1186
+ hcd_event_t event ;
1187
+ event .rhport = rhport ;
1188
+ event .event_id = HCD_EVENT_DEVICE_REMOVE ;
1189
+ event .connection .hub_addr = daddr ;
1190
+ event .connection .hub_port = 0 ;
1191
+
1192
+ hcd_event_handler (& event , false);
1193
+ } else {
1153
1194
// Invoke callback before closing driver (maybe call it later ?)
1154
- if (tuh_umount_cb ) tuh_umount_cb (dev_addr );
1195
+ if (tuh_umount_cb ) tuh_umount_cb (daddr );
1155
1196
}
1156
1197
1157
1198
// Close class driver
1158
- for (uint8_t drv_id = 0 ; drv_id < USBH_CLASS_DRIVER_COUNT ; drv_id ++ )
1159
- {
1160
- usbh_class_drivers [drv_id ].close (dev_addr );
1199
+ for (uint8_t drv_id = 0 ; drv_id < USBH_CLASS_DRIVER_COUNT ; drv_id ++ ) {
1200
+ usbh_class_drivers [drv_id ].close (daddr );
1161
1201
}
1162
1202
1163
- hcd_device_close (rhport , dev_addr );
1203
+ hcd_device_close (rhport , daddr );
1164
1204
clear_device (dev );
1165
1205
// abort on-going control xfer if any
1166
- if (_ctrl_xfer .daddr == dev_addr ) _set_control_xfer_stage (CONTROL_STAGE_IDLE );
1206
+ if (_ctrl_xfer .daddr == daddr ) _set_control_xfer_stage (CONTROL_STAGE_IDLE );
1167
1207
}
1168
1208
}
1169
1209
}
0 commit comments