Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/USB
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-07 14:52:28 -04:00
..
README.md docs: reconcile USB, Waydroid, audio and charging 2026-08-07 14:52:28 -04:00

USB — the Pixel 3 as a KVM device

Current — 2026-08-07

The direction is settled: another computer sends its display into the phone over GUD; the phone returns keyboard, pointer and touch as boot HID. The same composite keeps NCM for control and carries a smoo FunctionFS responder for host-backed storage. This is not the earlier UVC/VNC sketch.

Piece Current state
Display in souveraine-usb-kvm: GUD FunctionFS responder, RGB565 surface on Wayland
Hands back Boot keyboard + relative pointer; window keyboard, mouse and touch become HID reports
Storage smoo-gadget FunctionFS responder; ublk_drv on the phone
Control link NCM remains in the composite
Mode owner usb-signaller exposes kvm_mode; GUD and smoo readiness gate the bind, and failure restores the prior mode
Human/agent surface sessiond owns the audited usb / set_usb_mode verbs; held-power Power Options exposes HID and full KVM
Canonical source receiver/session/UI/package in ~/Projects/souveraine; device mechanism in ~/Projects/usb-signaller; package recipes in Pixel3Arch
Build proof full ARM64 release receiver and sessiond built on ArchDev; receiver tests + strict Clippy pass
Phone Not installed yet. Live phone still has usb-signaller 0.3.1-3, no smoo, and advertises no HID/KVM mode

TASK-62 owns the package and glass landing. The material below is the 2026-08-04 exploration ledger; it remains useful for host mode and for why the discarded UVC/VNC routes were considered, but it is no longer the build plan.

Baseline measured on the phone (2026-08-04, historical)

Piece State
Kernel gadget framework CONFIG_USB_GADGET=y, CONFIG_USB_CONFIGFS=y — built in, no modules
HID gadget CONFIG_USB_CONFIGFS_F_HID=y — the keyboard/mouse half of KVM already ships
FunctionFS CONFIG_USB_CONFIGFS_F_FS=y (flexible userspace gadgets, MTP path)
UVC gadget CONFIG_USB_CONFIGFS_F_UVC not set — the video half is the one missing config line
Other functions NCM, ECM, RNDIS, EEM, ACM, serial, OBEX, mass storage; no UAC1/2, no MIDI
Live configfs Two gadgets bound: dbg (acm.GS0, acm.GS1, ncm.usb0) and usb-signaller-developer (ncm.usb0) on UDC a600000.usb (dwc3, super-speed capable, currently high-speed)
Mode switching usb-signaller 0.3.1-3 active (dev mode at boot via usb-signaller-default-mode); blueline-usb-gadget 1.0.0-2; dev mode = NCM usb0 (172.16.42.1) + ACM
Video hardware Venus encoder /dev/video12 + decoder /dev/video13; CAMSS sensors /dev/video0-11; no v4l2loopback
Other packages v4l-utils, libusb, libgusb, libusbmuxd

Host mode — the dock question (2026-08-04, Casey: "if I plug a USB-C dock into the phone right now…")

DeX-style: the phone as the computer, a dock supplying monitors + keyboard

  • mouse. Measured against the running kernel and Google's own vendor DT (sdm845-b1c1-usb.dtsi, LineageOS kernel lineage-22.2):
Ask Verdict Evidence
Multi-monitor (DP alt mode) Unwired in every tree that exists. Google's board DT wires the port as DRP + USB-PD (pmi8998_pdphy, source 5V@0.9A, sink 5V/9V@3A, try-sink) with no DP alt-mode path — no redriver, no typec mux, no altmode node; the only "mux" is test GPIO104 for HS enumeration. Matches Google's official spec (USB 3.1 Gen 1, no video out). The silicon is capable — mainline sdm845.dtsi fully wires mdss_dp → QMP USB3-DP PHY (usb_1_qmpphy_dp_in) — but no sdm845 board in mainline wires it end-to-end either vendor DT (fetched), mainline dtsi (local tree)
USB keyboard/mouse Yes — this is what LineageOS actually gives you. DRP port + PD = real host mode. Our tree pins dr_mode = "peripheral" and usb-signaller holds the port as a gadget, so we don't do it today — but the hardware does vendor DT, our board DT
Via a plain OTG adapter Works — classic USB-A keyboard/flash-drive case standard OTG
Via a Dell dock (WD19…) Host mode: works on LineageOS, one role-switch away on ours. Monitors over DP alt mode: no. Monitors over DisplayLink (software display over USB host): only with a DisplayLink driver per-dock, plug it in
Charging from the dock Yes (PD sink 5V/9V@3A wired in the vendor DT) vendor DT

The correction (2026-08-04): an earlier draft called the DP gap a "connector mux on the board — hardware." That was asserted from memory and is wrong as stated. The evidence: Google wired the port for data+PD and never enabled DP alt mode in any tree, and the hardware question that remains — whether the PCB even routes DP lanes from the QMP PHY to the connector — is unproven in both directions. If LineageOS drove real monitors over the dock, the lanes exist (via DisplayLink, not alt mode). Decisive physical test: a USB-C→HDMI alt-mode adapter (not DisplayLink) with the port in host mode; if the board routes DP, a wired-up kernel has something to talk to.

The daily-driver catch: the USB-C port is the management port — tethering and dev mode (SSH over usb0) die while it is a host. Deliberate, documented mode switch only; cold boots stay Casey's.

Host mode — the live test (recipe, 2026-08-04)

Confirmed on the device: the role switch is real (/sys/class/usb_role/ a600000.usb-role-switch, role currently device), passwordless sudo works, and usb-signaller owns com.meego.usb_moded on the system bus (its modes are all device-side today — Developer/Tethering/MTP — so host mode is a direct sysfs switch, and usb-signaller's restart is the way back).

# 1. give up the gadget first — a bound gadget + host role breaks
echo "" | sudo tee /sys/kernel/config/usb_gadget/usb-signaller-developer/UDC

# 2. switch the port to host
echo host | sudo tee /sys/class/usb_role/a600000.usb-role-switch/role

# 3. plug the dock, then observe:
lsusb
dmesg | tail -30

# 4. back — WiFi SSH survives the whole trip, so this always works:
echo device | sudo tee /sys/class/usb_role/a600000.usb-role-switch/role
sudo systemctl restart usb-signaller    # re-provisions the developer gadget
cat /sys/class/usb_role/a600000.usb-role-switch/role

Gotchas: the dock is self-powered (Dell docks carry their own PSU), so its hub can enumerate even if the phone's VBUS sourcing is weak or absent — the dwc3 node has no vbus-supply, so bus-powered OTG peripherals (plain keyboards) may not power, which is itself a measurement. If the dock's hub enumerates, its keyboard/mouse are just kernel HID input — the shell gets a real keyboard for free. If the dock's monitors ever light up, the DP lanes exist and we go hunt the mux wiring; with no typec/altmode wired, expect nothing from them.

Original KVM notion — superseded by TASK-62

Plug the phone into another machine's USB port. The phone controls that machine and sees its screen — keyboard, mouse, monitor, in one cable. Two halves, with very different states of readiness:

Input half — HID gadget: already built. The kernel handles the USB HID descriptors; userspace writes 8-byte keyboard reports to /dev/hidg0 and 4-byte mouse reports to /dev/hidg1. This is the half that reaches bootloaders/BIOS (the pelya project proved it) — no video ever reaches a BIOS, so a BIOS-stage KVM is HID plus whatever screen the machine itself has.

Display half — two routes:

  • Route A (works today, zero kernel change): the live NCM link. The controlled machine serves its display over the USB network (VNC/waypipe); the phone shows it in a surface. Touches become HID reports. Worst part is latency, and the link is super-speed-capable.
  • Route B (one config line away): UVC gadget. The phone presents as a UVC camera; the controlled machine runs a "screen-as-webcam" tool (OBS virtual cam and friends) which is the stream source; the phone decodes (Venus decoder ✓) and shows it. The reverse direction also exists: Venus encoder + UVC = the PC sees the phone's own screen as a webcam — an in-the-cable scrcpy.

Prior art (verified)

  • tejado/android-usb-gadget — USB Gadget Tool (F-Droid): configfs roles for keyboard/mouse, FIDO CTAP, CCID, UVC camera; activates gadgets at boot.
  • Android 14 "Device as Webcam"CONFIG_USB_CONFIGFS_F_UVC + configfs recipe (MJPEG 1080p30, dwMaxVideoFrameBufferSize etc.); enabled by default in GKI since android12-5.10. The configfs UVC setup pattern is the one to copy.
  • pelya/android-keyboard-gadget — the classic: /dev/hidg0 keyboard, /dev/hidg1 mouse, hid-gadget-test; works into BIOS/bootloader.
  • Kernel docsusb/gadget_hid.rst (hid_gadget_test) and usb/gadget_uvc.html; the UVC reference app is gitlab.freedesktop.org/camera/uvc-gadget — "queue image buffers from a variety of sources", i.e. the phone-side userspace we would adapt to feed viewtop/compositor frames into the gadget.

Original questions — answered by TASK-62

  1. Directions: KVM-into-another-machine only, or also the reverse (phone screen out as webcam)? Both share the UVC config; the userspace differs.
  2. Route A or B first? A proves the whole loop today with no rebuild; B is the "real peripheral" feel but needs a kernel rebuild + cold boot — and that is Casey's call, on the daily driver.
  3. Touch → HID mapping: a KVM mode turns the phone's screen into a touchpad/screen for the target machine. The machinery is the mirror of TASK-50's touch intent — same input-routing problem, other direction.
  4. Where does the mode live? usb-signaller gains a "kvm" mode (profile
    • service), or sessiond owns it as a mode with a verb. The agent angle is real: Ani gets a keyboard/mouse that reaches any host — doctrine §13 says she should have the verb, not a config file.
  5. The kernel path: enabling F_UVC is one config line, but the kernel package still publishes unsigned raw .pkg.tar.zst (TASK-25's repo-add --sign is unbuilt) and installs are cold-boot events.

Original next steps — historical

  1. Prove HID today — provision a HID keyboard function into a scratch gadget on the phone (configfs, no reboot), bind it, write hid-gadget-test key reports, watch the laptop enumerate a second keyboard. One session, no rebuild.
  2. Route A latency test — laptop serves its screen (VNC/waypipe) over the live 172.16.42.1 link; phone displays it; measure.
  3. Route B — config one-liner + rebuild + cold boot (Casey); configfs UVC setup per the AOSP recipe; uvc-gadget userspace fed by a capture surface.
  4. usb-signaller "kvm" mode once the pieces exist, with clean teardown/provision against the dev mode.

Original acceptance sketch — historical

  • Phone plugged into the laptop enumerates as keyboard+mouse; typing from the phone lands in the laptop's focused app.
  • Route A: the laptop's screen renders on the phone with usable latency.
  • Route B: the laptop's virtual-cam tool lists the phone as a camera; the phone shows the stream.
  • Switching modes never strands the daily driver's tethering/dev mode.

Connects to

TASK-25 (kernel package signing — the rebuild path), TASK-50 (her hand on the glass — the touch→HID bridge is the mirror of the touch intent), doctrine §13 (the KVM mode as a verb), usb-signaller (the mode host), souveraine-viewtop (the display surface and capture path).

The buildable work lives here

TASK-57 (the Pi dock head — phone as gadget, Pi as display/input head over NCM) and TASK-58 (host power — the SMB2 OTG boost, one kernel change that unlocks host-mode power, power sharing, and phone→Pi power).