You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/frameworks/usb-manager.md
+26-3Lines changed: 26 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ USB host support is opt-in and ESP32-S3-only (needs USB OTG):
10
10
./scripts/build_mpos.sh esp32s3 --usb
11
11
```
12
12
13
-
This compiles in the `usb` C module (`c_mpos/usb/`) and disables MicroPython's TinyUSB *device* mode (USB-serial REPL goes away; console remains over UART REPL / USB-Serial-JTAG). On stock builds`USBManager.is_available()`is `False`and every arm call is a harmless no-op.
13
+
This compiles in the `usb` C module (`c_mpos/usb/`) alongside TinyUSB device mode. **CDC is the default**: the device boots with a USB-serial console and the OTG peripheral stays in device mode. Host mode starts only on explicit request — Settings → "USB Host Mode", or`USBManager.activate()`— and while it is active USB-CDC is gone (console remains over UART REPL where exposed, or WebREPL over WiFi). Deactivating brings CDC back; the choice persists across reboots. Holding BOOT at boot forces CDC regardless of the persisted flag.
14
14
15
15
USBManager centralizes all USB-host operations in a single class with class methods:
16
16
@@ -62,10 +62,25 @@ A healthy, enumerated HID reads exactly like a wedged adapter (connected + enabl
62
62
63
63
### Display switching
64
64
65
-
`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.
65
+
When host mode is active, `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.
66
66
67
67
## Usage
68
68
69
+
### Host mode activation
70
+
71
+
```python
72
+
from mpos import USBManager
73
+
74
+
USBManager.activate() # leave CDC device mode, start host, arm display+HID
75
+
USBManager.deactivate() # stop host, bring CDC back (REPL rejoins automatically)
76
+
USBManager.host_mode_active() # live host state
77
+
```
78
+
79
+
Both persist the choice (`host_mode` in the `com.micropythonos.usb`
80
+
preferences) so reboots keep it; pass `persist=False` for a one-shot switch.
81
+
`mpos.main` honors the persisted flag at boot. Both are idempotent and safe
82
+
to retry. On stock builds (no `usb` module) they return `False`.
Both are idempotent and safe to retry. On stock builds (no `usb` module) they return `None`.
94
+
Both are idempotent and safe to retry. On stock builds (no `usb` module) they return `None`. In host-mode builds these run automatically: `activate()` calls them, and boot does too when host mode persisted.
80
95
81
96
### Manual display switching
82
97
@@ -108,6 +123,10 @@ usb.hid_loop_lag() # ms since the HID task pumped events (~100 healthy)
108
123
### Class Methods
109
124
110
125
-`is_available()` - `True` when the `usb` C module is importable (`--usb` build).
126
+
-`activate(persist=True)` - Leave CDC device mode, start the host stack, arm display + HID. Returns `False` on stock builds or failure.
127
+
-`deactivate(persist=True)` - Stop host (UI back to panel, indevs removed), bring CDC back. Returns `False` on stock builds or failure.
128
+
-`host_mode_active()` - Live host state (`True` between successful activate/deactivate).
129
+
-`host_boot_requested()` - Persisted flag honored at boot (`False` when BOOT held).
111
130
-`arm_display(width=640, height=480)` - Construct (once) and start the adapter handle, ensure the poll timer. Returns the `usb.Display` or `None`.
112
131
-`arm_hid()` - Start the HID client, create the shared `HIDHub` plus `USBMouse`/`USBHIDKeyboard` indevs (disabled until their kind streams). Returns the mouse or `None`.
113
132
-`switch_to_usb(width=640, height=480, timeout_s=0)` - Blocking-init the adapter and swap the UI to it.
@@ -119,10 +138,14 @@ usb.hid_loop_lag() # ms since the HID task pumped events (~100 healthy)
119
138
-`usb.Display(port=0, width=0, height=0, ignore_edid=False)` - Adapter handle. `start()`, `poll()` (True on READY/disconnect/mode change), `ready()`, `width()`, `height()`, `chip_name()`, `update_565(x, y, w, h, buf)`, `fill(x, y, w, h, color)`, `flush(timeout_ms=100)`, `set_mode(w, h)`, `force_reenum()` (root-port power cycle).
- ESP32-S3 only; DisplayLink DL-1xx only (tested on DL-165/DL-195).
146
+
- Activating host mode kills USB-CDC until deactivated (announce it before
147
+
toggling on no-UART boards); UART REPL where exposed, WebREPL over WiFi,
148
+
and holding BOOT at boot (forces CDC) are the ways back.
126
149
- 640x480 minimum mode; rotation fixed to `_0`; RGB565 only.
127
150
- 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.
128
151
- A wedged adapter behind an externally powered hub is not recoverable by port resets — power-cut the adapter itself.
0 commit comments