Document ADB in the car: TCP over the NCM link, one SSH hop via the Orin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDwfd6Ki8UfG4hK6W5YpJz
This commit is contained in:
2026-10-11 13:20:29 +09:00
parent d965031a56
commit 5d5653acec
3 changed files with 104 additions and 16 deletions
+1
View File
@@ -24,5 +24,6 @@ flutter test
flutter run --dart-define=YUKART_GW=ws://<host>:7700/ # default: the car Orin, ws://192.168.55.1:7700/ flutter run --dart-define=YUKART_GW=ws://<host>: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 practice guidelines, refer to the [guidelines](docs/GUIDELINES.md);
- For implementation plans and history, refer to [them](docs/impl/); - For implementation plans and history, refer to [them](docs/impl/);
+98
View File
@@ -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.
+5 -16
View File
@@ -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 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. 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: on the Orin link the tablet is the USB host.
USB debugging is unavailable there. ADB over TCP is not, and it travels over the ADB runs over TCP on the NCM link instead, reached from halogen through one SSH
same NCM link: forward via the Orin. Mechanism, steps and troubleshooting:
[ADB in the car](../../ADB-IN-CAR.md).
```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.
### CI ### CI