Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/57-pi-dock-head.md
Fimeg 18c58fc079 docs: the day viewtop got its package, its titles and its borders
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.
2026-08-04 18:18:17 -04:00

5.6 KiB
Raw Blame History

TASK 57 — the Pi dock head

Status: open. Created 2026-08-04, from Casey: "I need a 'I plugged in this dock and my pixel 3 screens lit up' system" — the Pi 4 becomes the phone's display and input head. The phone stays a gadget (device mode — charging and tethering keep working), the Pi is the host that drives the monitor and the dock's peripherals, and the phone's desktop streams to it over the existing NCM link. Rejected paths, already argued: scrcpy (Android only — no ADB on mainline), waypipe (forwards apps, not a shell; our shell is a compositor, not forwardable), and DP alt-mode (unwired/unknown on blueline — the Pi bridge works today).

Repos: the phone side is souveraine-viewtop (capture) + the phone kernel/userspace; the Pi side is its own OS (bring-up state unknown — "major malfunctions" TBD, find them first).

The topology

[Dell dock: keyboard/mouse + monitor]         [Pixel 3, device mode]
        │ HDMI / USB-A                                │
        ▼                                            USB-C→A
[Pi 4] ◄──────────────────────────────────────────────┘
        │   NCM link (usb0, 172.16.42.x) — phone compositor
        │   capture → Venus H.264 → out over the cable
        └── always-on: udev sees the phone's NIC → viewer fullscreen

The phone's port stays in the one mode that already works. The Pi's USB-A port is a host: it sources VBUS (charges the phone, ~1.2 A shared), and the phone's default developer gadget (NCM + ACM via usb-signaller) comes up the moment the cable lands — no configuration on either side.

What exists, measured

Piece Where State
NCM gadget usb-signaller default developer mode, usb0 172.16.42.1 Live — WiFi SSH (10.10.20.234 via wlan0) survives everything USB, so the management path is never at risk
Venus H.264 encoder /dev/video12, decoder /dev/video13 (v4l-utils 1.32.0-2) Present; encoder idle and unproven at 1080p — load it first
Compositor capture souveraine-viewtop — window capture landed (86d0f93) Written and merged; whether zwlr_screencopy exists on the wire is unverified — if not, expose capture through our own IPC
Pi 4 Casey's, bring-up TBD Pi state unknown; needs OS + network check before anything
Link headroom USB 2.0 HS, 480 Mbps vs H.264 1080p30 at ~510 Mbps ~50× — bandwidth is not the constraint, latency is
Phone screen 540×1080 portrait The Pi must scale/rotate the stream to the monitor — free the Pi to do the transform (hardware scaler on the Pi 4)

Phases

  1. Pi bring-up — what's on it, what's broken, network reach. Then plug the phone into the Pi's USB-A: confirm the Pi sees a new NIC (172.16.42.1 pingable), the phone charges, tethering still works.
  2. Static chain — phone: test pattern (or any source) → Venus H.264 → NCM; Pi: decode (hardware) → fullscreen on HDMI. Proves the transport before the capture exists. Latency budget: <100 ms is a usable desk; measure, don't assume.
  3. Real capture — phone: compositor capture → Venus encode → stream. Trigger: the phone starts streaming when usb0 has carrier (not the typec udev event — blueline mainline has no typec driver, so usb-signaller's cable monitor never fires; the NIC is the honest signal). Pi: udev rule on the phone's gadget NIC → launch viewer.
  4. Input — dock keyboard/mouse → Pi evdev → over the same cable → inject into the phone's compositor via its IPC (both ends are ours). This is the step that makes it a dock rather than a monitor.
  5. Parked — the car version. A car head unit is the same problem with a dashboard for a far end; the same bridge applies over NCM or WiFi. "Android Auto" against stock head units is a separate universe — the AA transport is closed Android proprietary userspace (the f_accessory/AOA family lives in Android's kernel forks, not mainline), no open phone-side implementation, zero kernel work involved. Not a task until Casey wants it to be.

Open questions

  • Screencopy or custom capture IPC? (Determines the phone-side build.)
  • Does the Venus encoder take the compositor's buffer format directly, or is there a packing/stride hop (TASK-46 hit this with CAMSS)?
  • Portrait 540×1080 vs monitor: stream native and let the Pi scale, or rotate on the phone? (Native stream + Pi transform is simpler.)
  • Latency target per use: desk cursor (<100 ms) vs video (<200 ms).

Acceptance (measured)

  • Plug the phone into the Pi's USB-A: the monitor lights up with the phone's desktop within seconds, no interaction on either side, phone keeps charging.
  • The phone's own screen can be off/dimmed while the Pi shows the desktop.
  • The laptop's shell and the phone's wifi networking are untouched by a dock session.
  • Dock keyboard/mouse drive the phone's desktop (Phase 4) with no visible double-handling of input.
  • A Pi that loses the phone exits cleanly and waits (no zombie viewer).

Connects to

TASK-58 (host power — when the SMB2 boost lands, the phone can power the Pi through the same cable, killing the Pi's wall wart), TASK-51 (the capture punch list — the same capture feeds both UI verification and this stream), TASK-54 (the frame-callback culling — the phone-side stream must not fight the compositor's render budget), USB/README.md (the exploration record and the rejected-paths argument), usb-signaller (the gadget side is already built and default).