Skip to content

Commit 7f294b9

Browse files
usb: document port-exact HID skip, transient option, index entry
1 parent bb92f5d commit 7f294b9

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

docs/architecture/frameworks.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,18 @@ task = TaskManager.create_task(my_coroutine())
279279
TaskManager.sleep(seconds)
280280
```
281281

282+
### USBManager
283+
USB host support on ESP32 (`--usb` builds): DisplayLink display adapters plus HID mice/keyboards, with display/panel auto-switching and hub-port recovery.
284+
285+
```python
286+
from mpos import USBManager
287+
288+
if USBManager.is_available():
289+
USBManager.arm_display()
290+
USBManager.arm_hid()
291+
```
292+
See [USBManager](../frameworks/usb-manager.md) for details.
293+
282294
### SharedPreferences
283295
Per-app configuration storage (exception to the pattern - instance-based).
284296

docs/frameworks/usb-manager.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,18 @@ The layers, bottom to top:
4848

4949
- **C module `usb`** (`c_mpos/usb/`): `Display` class (start/poll/ready, frame upload) plus module-level host functions (`bus_devices`, `lsusb`, `hub_ports`, `reset_port`, watchdog toggles) and HID transport (`hid_start/poll/drain/state/...`). Upstream Pico_USB_Disp is vendored under `c_mpos/usb/upstream/` with a few clearly-commented MPOS adaptations (hub-port watchdog, `lsusb`, held-handle hook).
5050
- **Drivers**: `drivers/display/usb_display.py` (`USBDisplayDriver`, a `DisplayDriver` behind a shim bus) and `drivers/indev/usb_hid.py` (parser registry + `HIDHub` demux + `USBMouse` + `USBHIDKeyboard`). Report parsing is Python-side, so new device kinds never need C changes.
51-
- **USBManager** (`mpos/usb/`): boot arming (`arm_display`, `arm_hid`), the 1 s LVGL poll timer (HID pump + display state machine + auto-switch), panel/USB swapping, touch remapping, and HID/watchdog coexistence (idle-reset suppression while HID is claimed or parked).
51+
- **USBManager** (`mpos/usb/`): boot arming (`arm_display`, `arm_hid`), the 1 s LVGL poll timer (HID pump + display state machine + auto-switch), panel/USB swapping, touch remapping, and HID/watchdog coexistence (port-exact idle-reset skip for claimed HIDs, parked-only global suppression).
5252

5353
Only DisplayLink DL-1xx adapters work on ESP32-S3 (Full-Speed OTG); DL-165/DL-195 recommended. T6/MS91xx need High-Speed, i.e. ESP32-P4 only (protocol code is vendored but untested on hardware).
5454

5555
### HCD channel budget
5656

5757
The S3 DWC_OTG core has 8 host channels (~7 usable): one channel per USB *pipe*, held for the pipe's lifetime. Rule of thumb: **max 1 hub + 2 downstream devices** on S3. ESP32-P4/S31 have 16 channels, so **1 hub + 4 devices** fits there. Claim priority is display > mouse > keyboard; a claim that fails with channel exhaustion parks silently with backoff until a topology change or `usb.hid_retry()`.
5858

59+
### HID/watchdog coexistence
60+
61+
A healthy, enumerated HID reads exactly like a wedged adapter (connected + enabled, no bus growth), which the hub watchdog's idle auto-reset would otherwise `PORT_RESET` ~15s after plug. Two-part answer: open HID handles resolve to their (hub, port), so the sweep skips the auto-reset exactly on HID-owned ports and logs `HID device, auto-reset skipped` inline, while other ports keep healing; parked devices have no open handle and stay covered by a global suppression (restored when the park clears). The disabled-port recovery path is never suppressed.
62+
5963
### Display switching
6064

6165
`mpos.main` arms the display at boot without waiting; the poll timer switches the UI over automatically when a monitor becomes ready and reverts on disconnect. The swap suspends the LVGL pump, tears down activities, repoints indevs to the new display (panel touch is remapped through the panel's own proven mapping — no per-board tables), moves the topmenu, and restarts the launcher. Resolution floor is 640x480: smaller modes need a sub-25 MHz pixel clock that real monitors cannot sync to.
@@ -120,6 +124,6 @@ usb.hid_loop_lag() # ms since the HID task pumped events (~100 healthy)
120124

121125
- ESP32-S3 only; DisplayLink DL-1xx only (tested on DL-165/DL-195).
122126
- 640x480 minimum mode; rotation fixed to `_0`; RGB565 only.
123-
- Full display + mouse + keyboard combo cannot fit the S3 channel budget persistently (the keyboard parks until something unplugs).
127+
- Full display + mouse + keyboard combo cannot fit the S3 channel budget persistently (the keyboard parks until something unplugs); transient keyboard polling (`usb.hid_set_kbd_transient(True)`) holds no persistent pipe and is the experimental fit-the-combo option.
124128
- A wedged adapter behind an externally powered hub is not recoverable by port resets — power-cut the adapter itself.
125129
- Field upgrades across this rename need `--erase-all` or a lib re-sync: the frozen C module changed name (`usb_disp` to `usb`), so stale flash shadows will not fall back.

0 commit comments

Comments
 (0)