Repository navigation
Reset the USB port when the device does not return after checkm8 - #11
dl-alexandre wants to merge 1 commit into
Conversation
After "Checkmate!" the device drops off USB and must come back in download mode. On some Linux hosts it never does until the cable is replugged at the device within palera1n's 20-second window. Disabling and re-enabling the hub port forces the re-detection: on a J71b the device came back 4 s after a reset where three bare attempts never did. setup-host's udev rule makes the port's disable control writable for the USB access group when a device enters DFU. During the Pongo bootstrap, Orchard watches palera1n's log and resets that port up to three times if the device has not returned 2.5 s after checkm8. Hosts without the control (macOS, or no rule) behave as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
34a5b99 to
d3cad49
Compare
|
Rebased onto main after #9/#10 and the shared |
After "Checkmate!" the device drops off USB and must come back in download mode. On some Linux hosts it never does until the cable is replugged at the device within palera1n's 20-second window. Disabling and re-enabling the hub port forces the re-detection: on a J71b the device came back 4 s after a reset where three bare attempts never did. setup-host's udev rule makes the port's disable control writable for the USB access group when a device enters DFU. During the Pongo bootstrap, Orchard watches palera1n's log and resets that port up to three times if the device has not returned 2.5 s after checkm8. Hosts without the control (macOS, or no rule) behave as before. [Orchard: from #11 (34a5b99); wired into start_pongo so every boot path gets it; port_control ignores macOS's numeric locations instead of crashing; the port is re-enabled even if the wait is interrupted; the stop event no longer shadows Thread._stop, which broke join() on Python 3.12 and older]
|
Thanks! Merged to main as 1b17d8c with you as author, wired into the new shared |
Problem
After
Checkmate!the device drops off USB and has to come back in download mode within palera1n's 20-second window. On my x86_64 Arch laptop it often never comes back by itself. Orchard's instruction ("disconnect and reconnect the cable at the iPad once") is then the only way through, and it's easy to miss: four attempts today timed out, three of them in a row. In the host's kernel log there was no USB event at all between the post-checkmate disconnect and the device rebooting into iPadOS about 25 s later:Change
Linux only, and only when the port can be controlled:
setup-host's rules gain one line. When a device enters DFU (05ac:1227), udev makes its hub port'sdisableattribute group-writable (/sys%p/port/disable).udevadm verifyaccepts the generated file.apple/replug.py. Before palera1n starts,port_control()resolves the DFU device's port control (the device's sysfs node is gone after checkm8) and returnsNoneif it's missing or not writable.PortResetthen follows palera1n's log. If the device hasn't returned (Entered download mode/Download mode device found) 2.5 s afterCheckmate!→DFU mode device disconnected, it writes1then0to the control and waits up to 5 s, at most three times. It always re-enables the port, and it stops with the bootstrap.apple/boot.pyruns it aroundrun_process_groupand reports the number of resets. When a control exists, the cable instruction says Orchard resets the port and to replug only if the logo stays about 15 s. Otherwise the message and behavior are unchanged (macOS, or Linux without the rule).The RAM
runpath has its own palera1n call (#10). I left it alone here to avoid conflicting with that PR, and it can reusePortResetafterwards.Evidence
One full
orchard launchon a J71b with a standalone prototype of the same logic (root-run script, same timings), and no manual replug:The launch then completed (Pongo → recovery → installed system). That's one run. None of the four unassisted attempts that day recovered by itself within the 20 s window, so the reset looks like the cause, but more runs on more hosts would settle it. A port reset re-runs USB enumeration without cutting VBUS, which was enough here. Hosts that need a real power cycle would need
uhubctl-style power switching instead.Testing
New
tests/test_replug.py:It passed 5 out of 5 runs.
tests.test_host_setuppasses.test_installed_wheel_runs_with_all_source_access_blockedfails the same way onmainin my editable dev environment.🤖 Generated with Claude Code