STATE.md was five days stale. It now carries what is on the phone (viewtop r76, souveraine r333) and the four defects fixed on the glass: per-window capture was unreachable because quickshell holds wlr handles and the ext capture source is named by an ext handle with nothing correlating them; titles were never republished on commit; the border was a filled slab that relied on the client covering its middle; capture came back flipped. Also the packaging hole, which was the important one — viewtop's PKGBUILD existed and appeared in none of packages.yml's build lists, so nothing ever built it. Half closed: it builds now, but a viewtop commit still does not trigger a rebuild. TASK-15 question 1 is answered and closed: dropping the accelerometer claim took iio-sensor-proxy from 15.3% to 1.1%, sensors overall 17.2% to 2.6% of a core. Consequence noted against 08(g) — confidence loses accel's +0.3. New: 54, 55, 56, and 57/58 (Pi dock head, SMB2 OTG boost) with the USB notes they point at.
10 KiB
USB — the Pixel 3 as a KVM device
Exploration opened 2026-08-04 from Casey: "start exploring the notion of KVM from this thing." This folder holds USB-related design and measurement; the KVM exploration starts here.
What exists, measured on the phone (2026-08-04)
| 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.
The KVM notion
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,dwMaxVideoFrameBufferSizeetc.); 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/hidg0keyboard,/dev/hidg1mouse,hid-gadget-test; works into BIOS/bootloader. - Kernel docs —
usb/gadget_hid.rst(hid_gadget_test) andusb/gadget_uvc.html; the UVC reference app isgitlab.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.
Questions to settle, in order
- Directions: KVM-into-another-machine only, or also the reverse (phone screen out as webcam)? Both share the UVC config; the userspace differs.
- 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.
- 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.
- 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.
- The kernel path: enabling F_UVC is one config line, but the kernel
package still publishes unsigned raw
.pkg.tar.zst(TASK-25'srepo-add --signis unbuilt) and installs are cold-boot events.
Next steps (ordered, each measurable)
- Prove HID today — provision a HID keyboard function into a scratch
gadget on the phone (configfs, no reboot), bind it, write
hid-gadget-testkey reports, watch the laptop enumerate a second keyboard. One session, no rebuild. - Route A latency test — laptop serves its screen (VNC/waypipe) over the live 172.16.42.1 link; phone displays it; measure.
- Route B — config one-liner + rebuild + cold boot (Casey); configfs
UVC setup per the AOSP recipe;
uvc-gadgetuserspace fed by a capture surface. - usb-signaller "kvm" mode once the pieces exist, with clean teardown/provision against the dev mode.
Acceptance (measured)
- 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).