summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIngHK <[email protected]>2024-03-31 10:28:53 +0200
committerIngHK <[email protected]>2024-03-31 10:28:53 +0200
commit14ce05fea374c1a372d8e531ad3c96b243899e1b (patch)
tree49311014953f61334e2e29ed604f52e294b81a69 /src
parentb644e4d95582748dfc9ab947bbb32fd994f34448 (diff)
parent9a981237df01456d60cdd7893493918d88af5e1a (diff)
Merge remote-tracking branch 'remotes/hathach/master' into max3421_nak_retry
Diffstat (limited to 'src')
-rw-r--r--src/host/usbh.c120
-rw-r--r--src/portable/raspberrypi/rp2040/hcd_rp2040.c10
2 files changed, 66 insertions, 64 deletions
diff --git a/src/host/usbh.c b/src/host/usbh.c
index 1edc43fd6..05091736e 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -412,9 +412,11 @@ bool tuh_deinit(uint8_t rhport) {
// deinit host controller
hcd_int_disable(rhport);
hcd_deinit(rhport);
-
_usbh_controller = TUSB_INDEX_INVALID_8;
+ // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0)
+ process_removing_device(rhport, 0, 0);
+
// deinit host stack if no controller is active
if (!tuh_inited()) {
// Class drivers
@@ -1138,43 +1140,42 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
return (uint8_t) result
-uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len);
}
-uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len);
}
-uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len);
}
-uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len);
}
-uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len);
}
-uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
-{
+uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id,
+ void* buffer, uint16_t len) {
_CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len);
}
@@ -1210,57 +1211,60 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
//------------- find the all devices (star-network) under port that is unplugged -------------//
// TODO mark as disconnected in ISR, also handle dev0
+ uint32_t removing_hubs = 0;
+ do {
+ for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
+ usbh_device_t* dev = &_usbh_devices[dev_id];
+ uint8_t const daddr = dev_id + 1;
-#if 0
- // index as hub addr, value is hub port (0xFF for invalid)
- uint8_t removing_hubs[CFG_TUH_HUB];
- memset(removing_hubs, TUSB_INDEX_INVALID_8, sizeof(removing_hubs));
-
- removing_hubs[hub_addr-CFG_TUH_DEVICE_MAX] = hub_port;
+ // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
+ if (dev->rhport == rhport && dev->connected &&
+ (hub_addr == 0 || dev->hub_addr == hub_addr) &&
+ (hub_port == 0 || dev->hub_port == hub_port)) {
+ TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr);
- // consecutive non-removing hub
- uint8_t nop_count = 0;
-#endif
+ if (is_hub_addr(daddr)) {
+ TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
+ removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX);
+ } else {
+ // Invoke callback before closing driver (maybe call it later ?)
+ if (tuh_umount_cb) tuh_umount_cb(daddr);
+ }
- for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
- usbh_device_t *dev = &_usbh_devices[dev_id];
- uint8_t const daddr = dev_id + 1;
+ // Close class driver
+ for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
+ usbh_class_driver_t const* driver = get_driver(drv_id);
+ if (driver) driver->close(daddr);
+ }
- // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub
- if (dev->rhport == rhport && dev->connected &&
- (hub_addr == 0 || dev->hub_addr == hub_addr) &&
- (hub_port == 0 || dev->hub_port == hub_port)) {
- TU_LOG_USBH("Device unplugged address = %u\r\n", daddr);
+ hcd_device_close(rhport, daddr);
+ clear_device(dev);
- if (is_hub_addr(daddr)) {
- TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
+ // abort on-going control xfer on this device if any
+ if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
+ }
+ }
- // Submit removed event If the device itself is a hub (un-rolled recursive)
- // TODO a better to unroll recursrive is using array of removing_hubs and mark it here
- hcd_event_t event;
- event.rhport = rhport;
- event.event_id = HCD_EVENT_DEVICE_REMOVE;
- event.connection.hub_addr = daddr;
- event.connection.hub_port = 0;
+ // if removing a hub, we need to remove its downstream devices
+ #if CFG_TUH_HUB
+ if (removing_hubs == 0) break;
- hcd_event_handler(&event, false);
- } else {
- // Invoke callback before closing driver (maybe call it later ?)
- if (tuh_umount_cb) tuh_umount_cb(daddr);
- }
+ // find a marked hub to process
+ for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) {
+ if (tu_bit_test(removing_hubs, h_id)) {
+ removing_hubs &= ~TU_BIT(h_id);
- // Close class driver
- for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
- usbh_class_driver_t const * driver = get_driver(drv_id);
- if ( driver ) driver->close(daddr);
+ // update hub_addr and hub_port for next loop
+ hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX;
+ hub_port = 0;
+ break;
}
-
- hcd_device_close(rhport, daddr);
- clear_device(dev);
- // abort on-going control xfer if any
- if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE);
}
- }
+ #else
+ (void) removing_hubs;
+ break;
+ #endif
+ } while(1);
}
//--------------------------------------------------------------------+
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index 08aef9314..b351a9a07 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -113,7 +113,7 @@ static void __tusb_irq_path_func(_handle_buff_status_bit)(uint bit, struct hw_en
static void __tusb_irq_path_func(hw_handle_buff_status)(void)
{
uint32_t remaining_buffers = usb_hw->buf_status;
- pico_trace("buf_status 0x%08x\n", remaining_buffers);
+ pico_trace("buf_status 0x%08lx\n", remaining_buffers);
// Check EPX first
uint bit = 0b1;
@@ -325,10 +325,8 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
ep->wMaxPacketSize = wMaxPacketSize;
ep->transfer_type = transfer_type;
- pico_trace("hw_endpoint_init dev %d ep %d %s xfer %d\n", ep->dev_addr, tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->transfer_type);
- pico_trace("dev %d ep %d %s setup buffer @ 0x%p\n", ep->dev_addr, tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)], ep->hw_data_buf);
+ pico_trace("hw_endpoint_init dev %d ep %02X xfer %d\n", ep->dev_addr, ep->ep_addr, ep->transfer_type);
+ pico_trace("dev %d ep %02X setup buffer @ 0x%p\n", ep->dev_addr, ep->ep_addr, ep->hw_data_buf);
uint dpram_offset = hw_data_offset(ep->hw_data_buf);
// Bits 0-5 should be 0
assert(!(dpram_offset & 0b111111));
@@ -343,7 +341,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
ep_reg |= (uint32_t) ((bmInterval - 1) << EP_CTRL_HOST_INTERRUPT_INTERVAL_LSB);
}
*ep->endpoint_control = ep_reg;
- pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
+ pico_trace("endpoint control (0x%p) <- 0x%lx\n", ep->endpoint_control, ep_reg);
ep->configured = true;
if ( ep != &epx )