Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Pico-PIO-USB host: a device that drops off the root port during attach debounce is never reported again

Open
#4,271 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
c

Research direction

Read src/host/usbh.c around the 150 ms attach debounce and src/portable/raspberrypi/pio_usb/hcd_pio_usb.c around hcd_port_connect_status() and root-port connection handling. Reproduce with a Pico-PIO-USB host and a device that disconnects during debounce, then trace how the root port handles disconnect and reconnect before its first reset. Done when the device is detected and enumerates after reconnecting without reinitializing the host.

Written by the indexing model from the issue text.

Description

Bug 🐞
Operating System

Others

Commit SHA

472a9c333: 0.21.0 (dae3f9a36) plus GP2040-CE’s two patches (control transfer timeout, ad7acc849 backport). The code involved (usbh.c root-port debounce, hcd_pio_usb.c) is unchanged in master 702e55db3.

Board

Haute42 COSMOX C-AT (RP2040) running GP2040-CE, device plugged into its Pico-PIO-USB host port (Pico-PIO-USB ba9733c = 5a37a66 + 2 commits)

Firmware

GP2040-CE in PS5 mode, with a PS4/PS5 auth dongle on the PIO-USB host port. The host side uses TinyUSB with TUH_CFGID_RPI_PIO_USB_CONFIGURATION.

What happened ?

If a device plugged straight into the Pico-PIO-USB root port drops off the bus during the 150 ms attach debounce, it’s never enumerated. After that, the port never reports any device again, even after physically unplugging and replugging, until the host is re-initialized.

What happens:

  1. On a new connection, pio_usb_host_frame() sets root->connected = true and root->suspended = true (“need a bus reset before operating”) and raises CONNECT.
  2. usbh ignores attach/remove events on that root port for ENUM_DEBOUNCING_DELAY_MS (150 ms), then checks hcd_port_connect_status().
  3. While the port is suspended, pio_usb doesn’t run connection_check(), so it doesn’t notice the disconnect either, and root->connected stays true.
  4. hcd_port_connect_status() reads the raw line state. If the device is off the bus at that moment, usbh logs “Device unplugged while debouncing”, ends the enumeration and waits for the next attach event.
  5. pio_usb only detects a new connection while !root->connected, so that event never comes. The root-port retry in master (f9a0687e8) doesn’t kick in either, because hcd_port_connect_status() is false at that point.

0.17 didn’t have this: enum_new_device() reset the root port right away, so pio_usb was already operating and reported the disconnect and reconnect.

We hit it with a PS4/PS5 auth dongle (Booter5, 0079:1893). It connects and drops off the bus several times while powering up, so it was never enumerated, whether plugged in together with the board or into an already running one. Plugged straight into a Mac, it works fine.

This change in hcd_pio_usb.c fixed it for us:

bool hcd_port_connect_status(uint8_t rhport) {
  uint8_t const pio_rhport = RHPORT_PIO(rhport);

  root_port_t *root = PIO_USB_ROOT_PORT(pio_rhport);
  port_pin_status_t line_state = pio_usb_bus_get_line_state(root);
  bool const connected = (line_state != PORT_PIN_SE0);

  // Until the port is reset, pio_usb neither watches for a disconnect nor reports a new connection
  // while it still marks the port connected. If the device dropped off the bus in the meantime
  // (e.g. while usbh debounces the attach), usbh gives up on it here, so mark the port disconnected
  // to let pio_usb report the device again once it reconnects.
  if (!connected && root->connected && root->suspended) {
    root->connected = false;
  }

  return connected;
}

With it, every cold plug and hot plug enumerated and the dongle worked: 6 cold plugs, plus hot plugs, on a PS5 and on a Mac. It could also be fixed on the Pico-PIO-USB side, by noticing disconnects while the port waits for its first reset.

How to reproduce ?
  1. A TinyUSB host on Pico-PIO-USB (CFG_TUH_RPI_PIO_USB=1).
  2. Connect a device that drops off the bus within the first ~150 ms after connecting, then reconnects. Our dongle does this on every power-up.
  3. The device is never enumerated, and nothing plugged into that port is detected afterwards until reboot.

We haven’t tried it, but a second board running a TinyUSB device example that calls tud_disconnect() ~50 ms after connecting and tud_connect() again a few hundred ms later should hit the same window deterministically.

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

No CFG_TUSB_DEBUG log, because the board has no UART available. We added counters instead, shown on the board’s display:

  • without the fix: 1 attach event, the enumeration ends with “unplugged while debouncing”, and there are no further attach events, ever;
  • with the fix: 4 attach events and 3 failed enumerations (the first at the debounce check, one on a failed transfer), then the device mounts.
Screenshots

No response

I have checked existing issues, discussion and documentation
  • I confirm I have checked existing issues, discussion and documentation.
Dominant language
C
Stars
7.2k
Forks
1.6k
Avg merge
1d 12h
Merged PRs (30d)
96

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from hathach/tinyusb

All issues in hathach/tinyusb

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.