Skip to content

host_stop() wedges after a UAC device was attached but never opened (S3 host, P4 sound card) #29

Description

@bdbarnett

2026-09-23, S3 Touch on 61ba01c hosting the P4 wearing cdc+uac. A probe started the host with classes=("uac",), listed uac_audio.audio_devices() (one device, one stream, never opened) and called stop():

usbif_host: teardown starting (new devices now declined)
usbif_host: closing cdc / hid / midi / msc / uac
usbif_host: device_close
usbif_host: device_close returned
usbif_host: pre-deregister drain done
usbif_host: deregister -> 0x0
usbif_host: device_free_all -> 0x10c
usbif_host_stop: task DID NOT EXIT -- timed out (marked wedged) after 200 tick(s) (2000 ms)
usbif_host_stop: calling usb_phy_otg_device_mode()
usbif_host_stop: calling tusb_init()

The next host.start() in the same session then fails with OSError: [Errno 5] EIO; a hard reset clears it. device_free_all -> 0x10c is ESP_ERR_NOT_FINISHED: the library still held the device when we asked it to free everything, so the host task never reached its exit. The README's 8-of-8 clean stops were measured with devices that had been opened and closed through a class driver; this is the other path, a device that was only enumerated.

Activity

  1. bdbarnett commented on Oct 8, 2026

    @bdbarnett
    ContributorAuthor

    Status 2026-10-08: not reproduced tonight. The only S3 host on the bench is the LCD-7, and its native USB port is unplugged, so nothing can host the P4 panel. What the code says about the log above, for whoever runs it next:

    • device_free_all -> 0x10c isn't the failure. ESP_ERR_NOT_FINISHED is what usb_host_device_free_all() returns whenever any device is still attached (usb/include/usb/usb_host.h:361 in ESP-IDF 5.5.4: "wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE"). With a hub in the path there's always one.
    • What's missing is the line after it. The ALL_FREE wait (usbif_host.c, 100 polls of 10 ms) always prints ALL_FREE seen or NOT seen, then uninstall -> .... Neither appeared before host_stop() gave up at 2000 ms.
    • That budget is tight. Before the wait, teardown pumps events in each class driver's _for_host_stop() close (UAC's alone is ten 10 ms polls), then a 200 ms drain. An ALL_FREE that never comes adds a full second on top. So this could be ALL_FREE not arriving for an enumerated-but-unopened device, outlasting host_stop()'s 2 s, and host_stop() then marking the task wedged (which is the EIO on the next start()). It could also be a usb_host_lib_handle_events() call that blocks.

    Next run: timestamp each teardown line (esp_timer_get_time()), and run once with the P4 straight on the S3's port and once behind the hub. That separates the two. If it's the budget, the fix is to make host_stop() wait longer than the teardown's own worst case and let the uninstall result decide whether the host is wedged. Waits on an S3 host cabled to the P4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions