diff --git a/README.md b/README.md index 5e99a18..ea2cba0 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,6 @@ flutter test flutter run --dart-define=YUKART_GW=ws://:7700/ # default: the car Orin, ws://192.168.55.1:7700/ ``` +- For debugging the app in the car (ADB over the Orin link), refer to [ADB in the car](docs/ADB-IN-CAR.md); - For implementation practice guidelines, refer to the [guidelines](docs/GUIDELINES.md); - For implementation plans and history, refer to [them](docs/impl/); diff --git a/docs/ADB-IN-CAR.md b/docs/ADB-IN-CAR.md new file mode 100644 index 0000000..0eadc30 --- /dev/null +++ b/docs/ADB-IN-CAR.md @@ -0,0 +1,98 @@ +--- +type: reference +--- +# ADB in the car + +**In one line: ADB over TCP on the tablet's USB-Ethernet link to the Orin, reached +from halogen through one SSH port-forward via the Orin.** TCP mode is armed once +over a USB cable to halogen, and again after every tablet reboot. + +## Why USB debugging is unavailable in the car + +A USB link has exactly one host and one device. The tablet's single USB-C port can +be either, decided by the USB-C CC resistors at plug-in: + +| Plugged into | Tablet role | USB debugging | +|---|---|---| +| halogen | device | yes: ADB is a USB function the tablet offers as a device | +| the Orin (via the PD hub) | **host** | no: a host offers no USB functions | + +A data hub does not help: it adds more devices under the same host. The PD hub in +the car only passes power through, so the tablet charges while it is the host. + +## What the link is + +The Orin runs Jetson's USB device mode (`l4t-usb-device-mode`) and presents itself +as a USB network adapter, with a DHCP server on it. The tablet's kernel binds it as +**NCM** and Android brings it up as an ordinary **Ethernet** network: + +``` +tablet 192.168.55.100 ⇄ USB NCM ⇄ Orin 192.168.55.1 +``` + +The app reaches `svc-gw` over this network. It requests the network explicitly and +binds to it, because a network without internet never becomes Android's default +while WiFi or LTE is up. `adbd` is a system daemon and needs none of that: once +it listens on TCP, it listens on every interface, this one included. + +## The path from halogen + +halogen is not on `192.168.55.0/24`; the Orin is. halogen reaches the Orin over +the LAN or the tailnet (the Orin has an LTE uplink), so one SSH local forward +bridges the gap: + +``` +adb (halogen) → localhost:15555 ═SSH═▶ Orin → 192.168.55.100:5555 → adbd (tablet) +``` + +Authorisation is unchanged: the tablet still checks ADB's RSA key, and halogen's +key was accepted at the USB pairing. The tablet's port is reachable only from the +NCM link (and from WiFi, while TCP mode is on and WiFi is up). + +## Steps + +**1. Arm, at the desk** (USB cable to halogen; once per tablet boot): + +```bash +adb -s 1f1530c87d84 tcpip 5555 +``` + +**2. In the car** (tablet on the Orin, app link up): + +```bash +ssh -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=10 \ + -L 15555:192.168.55.100:5555 mikkeli-orin-nano & +adb connect localhost:15555 +adb devices # → localhost:15555 device +flutter run -d localhost:15555 --dart-define=YUKART_GW=ws://192.168.55.1:7700/ +``` + +The default gateway address already is `ws://192.168.55.1:7700/`; the define only +matters if a desk build was installed last. + +**3. Disarm** (optional): `adb usb` returns ADB to USB only. A reboot does the same. + +Local port 15555, not 5555: halogen's adb server scans localhost 5555–5585 for +emulators, and a tunnel there shows up a second time as `emulator-5554`. + +## When it does not work + +| Symptom | Check | +|---|---| +| `connect` refused or times out | From the Orin: `nc -zv 192.168.55.100 5555`. Refused means TCP mode is off: the tablet rebooted; re-arm over USB | +| No route to `192.168.55.100` from the Orin | The USB link is down: cable, PD hub, or the tablet asleep (see the initial plan, "The USB link, as measured") | +| `unauthorized` | Accept the prompt on the tablet; the halogen key was revoked or never accepted | +| `bind: Address already in use` on 15555 | An old tunnel is still running: `pkill -f 15555:192.168.55.100` | + +## Alternatives + +- **adb on the Orin itself.** `adb connect 192.168.55.100:5555` there, no tunnel. + Needs `adb` installed on the Orin, and `flutter run` stays on halogen anyway. +- **Wireless debugging** (Android 11+, pairing codes) survives better, but it only + runs over WiFi, so it does not use this link. + +## Status + +The NCM link and the app over it are verified (2026-10-09). The ADB path above is +**untested in the car**; HyperOS may need its USB-debugging security options for +installs over TCP as it did over USB. diff --git a/docs/impl/plans/INITIAL.md b/docs/impl/plans/INITIAL.md index db3293d..fb66b87 100644 --- a/docs/impl/plans/INITIAL.md +++ b/docs/impl/plans/INITIAL.md @@ -109,23 +109,12 @@ The app binds the process to the USB Ethernet network only when the gateway address is on `192.168.55.0/24`, so a desk build pointed at halogen over WiFi is not routed into a dead USB link. -### ADB in the car, without a hub +### ADB in the car -The tablet's only USB port is the Orin link, and in it the tablet is the host — -USB debugging is unavailable there. ADB over TCP is not, and it travels over the -same NCM link: - -```bash -adb tcpip 5555 # at the desk, over USB, once per tablet boot -# in the car, from halogen, through the Orin over the tailnet: -ssh -N -L 5555:192.168.55.100:5555 mikkeli-orin-nano & -adb connect localhost:5555 -flutter run -d localhost:5555 -``` - -The tablet keeps the RSA authorisation from the USB pairing. `adb usb` turns TCP -mode off again; a reboot does too. Android's *Wireless debugging* (pairing) is -WiFi-only and does not help here. Untested in the car so far. +USB debugging is unavailable there: on the Orin link the tablet is the USB host. +ADB runs over TCP on the NCM link instead, reached from halogen through one SSH +forward via the Orin. Mechanism, steps and troubleshooting: +[ADB in the car](../../ADB-IN-CAR.md). ### CI