--- type: report date: 2026-10-09 --- # USB Link to the Tablet (Orin as USB Network Gadget) ## Result | Item | State | |------|-------| | Physical | USB-C ↔ USB-C, tablet (Redmi Pad SE 8.7 4G, Android 16) = **USB host**, Orin's USB-C port = **USB device** | | Network | Orin `192.168.55.1` on `l4tbr0`, tablet gets `192.168.55.100` from the Orin's DHCP. Ping ~2.5 ms | | Function used | **NCM** (`usb1`, ECM/NCM MAC). RNDIS (`usb0`) is offered but the tablet ignores it | | Mass storage (`L4T-README`) | **Disabled** (`enable_ums=0`) | | Tablet charging over this cable | **Not possible** (see below) | ## How it works (stock L4T, no install needed) `nv-l4t-usb-device-mode.service` (package `nvidia-l4t-init`) builds a composite USB gadget on the USB-C port at boot. It has RNDIS + NCM network functions bridged into `l4tbr0`, an ACM serial console, and (stock) a mass-storage drive. When a host connects, a dedicated `dhcpd` hands out exactly one address. Settings live in `/opt/nvidia/l4t-usb-device-mode/nv-l4t-usb-device-mode-config.sh`: ``` net_ip=192.168.55.1 net_dhcp_start=192.168.55.100 net_dhcp_end=192.168.55.100 net_ipv4_defroute_router=192.168.55.100 net_ipv4_defroute_metric=32766 ``` The Orin also adds `default via 192.168.55.100 metric 32766`. This ranks below everything else, so it never takes traffic from Ethernet, WiFi or LTE. ### DHCP lease: 86400 s, not NVIDIA's 15 s (2026-10-14) NVIDIA ships `net_dhcp_lease_time=15`. It worked while the tablet's Android stretched short leases and renewed every ~30 s. On 2026-10-14 the tablet's NetworkStack (Mainline module) updated itself (`lastUpdateTime 08:21:19`) and began taking 15 s literally: the address expired, Android restarted `usb0`, and every WebSocket to svc-gw died on a **15.0 s cycle** (`DHCPDISCOVER` every 15 s in the Orin's log, `connection lost` in svc-gw's, ~0.3 s to reconnect). Now `net_dhcp_lease_time=86400` in the config file above; Android renews at 12 h. Safe on this link because: - the pool is one address for one host at a time (a single USB-C port); - the leases file is deleted on every plug-in: the udev rule `99-nv-l4t-usb-device-mode.rules` runs `nv-l4t-usb-device-mode-state-change.sh`, which stops `nv-l4t-usb-device-mode-runtime` on unplug and starts it on plug-in, and its start script recreates `/run/l4t-usb-devmode-dhcpd.leases` empty. A phone plugged in after the tablet always gets the address. Applied with `sudo systemctl restart nv-l4t-usb-device-mode-runtime.service` (the link drops for a few seconds). The file is part of `nvidia-l4t-init`; a package update may restore 15. Sign: svc-gw logging `connection lost` every 15 s while `DHCPDISCOVER` repeats. ## Android routes apps over it only when it is the default network The tablet joins the USB network, but Android only sends ordinary app traffic over its *default* network, and an Ethernet network without validated internet doesn't become default while WiFi or cellular is up. Tested: `http://192.168.55.1:5000` (camera-webui) didn't load until the tablet's WiFi and cellular were off; then it did. Consequence for the tablet app: request the Ethernet network explicitly (`ConnectivityManager.requestNetwork` with `TRANSPORT_ETHERNET`) and bind its sockets to it. Then the link works no matter what the tablet's internet is doing. The other option is NAT on the Orin so Android's check passes, but that would route the tablet's internet through the Orin (and in the car, through the metered povo SIM). Not chosen. ## Mass storage disabled `L4T-README` is NVIDIA's flashing-help drive and just causes prompts on the tablet. ``` D=/opt/nvidia/l4t-usb-device-mode sudo cp -n $D/nv-l4t-usb-device-mode-config.sh $D/nv-l4t-usb-device-mode-config.sh.orig sudo sed -i 's/^enable_ums=1$/enable_ums=0/' $D/nv-l4t-usb-device-mode-config.sh sudo systemctl restart nv-l4t-usb-device-mode # link drops for a few seconds ls /sys/kernel/config/usb_gadget/l4t/configs/*/ # acm.GS0, ncm.usb0, rndis.usb0. No mass_storage ``` ⚠ The file is **not** a dpkg conffile, so an `nvidia-l4t-init` upgrade silently restores `enable_ums=1`. The only effect is that the drive comes back. After a JetPack/L4T upgrade, check `grep ^enable_ums $D/nv-l4t-usb-device-mode-config.sh` and re-apply. (`dpkg-divert` was rejected: it would also hide upstream changes to the file's format, which fails worse than a returning drive.) RNDIS is left enabled. It's unused but harmless; `enable_rndis=0` would remove it the same way. ## Charging the tablet With one port on the tablet, the data cable to the Orin is also its only charging path, and the Orin doesn't charge it. **The Orin can't be the charger on this port, whatever the network protocol.** RNDIS vs NCM is irrelevant; power is separate from data: - In USB-C, *data* role (host/device) and *power* role (source/sink) are negotiated separately. "Tablet is host but gets charged" is normal, but it needs a power source that negotiates USB Power Delivery. - The Orin's USB-C port controller is a **FUSB301**. It only detects attachment and orientation, has no PD, and is wired as the flashing/device port. The kernel registers no USB-C port or PD device (`/sys/class/typec` is empty, there is no `usb_power_delivery` class). So the port can't offer charging power to the tablet. Options: | Option | Charging | Notes | |--------|----------|-------| | **PD hub with one data port** (on hand) | Full PD from the car charger, through to the tablet | Tablet → hub's USB-C host/PD port, charger → hub's PD-in, Orin USB-C → hub's data port. Same gadget/NCM setup, nothing changes on the Orin. Some hubs briefly re-enumerate when PD power appears or disappears (ignition), so the app should reconnect | | Reverse roles: Orin USB-A host + tablet USB tethering | ~4.5 W at most (5 V, USB-A) | Tablet becomes the router, tethering has to be enabled by hand on Android, and it needs `never-default` on the Orin so the Orin's traffic doesn't leave via the tablet | The **PD hub** is the practical choice, and it's now in use. ### PD power cycling through the hub (tested 2026-10-09) Setup: tablet → hub (USB-C host/PD), car-style charger → hub PD-in, Orin USB-C → hub data port. Three PD unplug/replug cycles while pinging the tablet every 0.5 s: | Cycle | USB-C detach (Orin) | Link stable again | Ping lost | |-------|---------------------|-------------------|-----------| | 1 | 00:14:29.3 | 00:14:36.1 | 3.1 s + 1.5 s | | 2 | 00:14:38.5 | 00:14:43.6 | 3.1 s + 1.5 s | | 3 | 00:14:51.4 | 00:15:02.0 | 11.8 s | - **Each cycle caused exactly one full detach** (`fusb301_detach`), not one per transition. The separate-edge test below shows it is the unplug. - Each detach follows the same pattern: re-attach after about 0.5 s, then the `l4tbr0` bridge ports flap about three times over 5–10 s (the tablet re-creating its USB network) before settling. - Recovery is automatic every time: the same DHCP lease, normal ping (~3 ms) afterwards. Nothing needs fixing on the Orin. #### Each edge separately (same day, one 60 s window each) | | PD unplugged (00:23:04) | PD plugged back (~00:24:12) | |---|---|---| | USB-C detach on the Orin | **yes**, full detach and re-attach | **no** | | Orin link (`l4tbr0` ports) | flapped twice, stable after 3.4 s | stayed up; one short gadget reconnect at 00:24:21.6 (0.7 s) | | Ping lost | 3.1 s | 5.0 s while the Orin's link was **up**, then 0.3 s and 1.5 s | | Total disruption | ~3.5 s | ~10 s | - Unplug: the hub cuts its data port, so the Orin sees a real disconnect, and recovery is quick. - Replug: no disconnect on the Orin's side. The tablet stops answering for about 5 s (most likely renegotiating power and switching to charging), then re-creates its USB network once. **The Orin's interface state does not reveal this outage**, so only an application-level heartbeat catches it. - Exact replug time isn't known; the first failed ping is used as its marker. - Repeat (plug-in at ~00:27:12): the tablet was silent for 7.8 s with the Orin's link up, then one gadget reconnect (00:27:25.1–27.0) and a fresh `DHCPDISCOVER`; about **15 s** to stable. Replug consistently costs more than unplug (3.5 s). #### The "silence" is Android sleeping, not the link | Test (2026-10-09) | Tablet state after PD unplug | Result | |---|---|---| | Idle, 3 min window | screen times out | Clean for ~60 s, then pings answered only in brief bursts right at its 30 s DHCP renewals, then silent. **No kernel link events**: USB stayed up throughout | | Video playing, 150 s window | kept awake | 3.1 s outage at the unplug, then **zero loss for 2 min+** | | Video playing, PD off → **plugged in** (90 s window) | kept awake | No USB-C detach; one gadget reconnect (link down 0.7 s), fresh DHCP, **~2.2 s** to ping replies, then zero loss | - Off charger and idle, Android suspends about 60 s after the screen times out ("keep awake on charge" no longer applies). The USB gadget link stays electrically up, but the tablet only wakes for timers (DHCP renewal every ~30 s). - The earlier "replug silence" was the same thing. Those windows started with the tablet already asleep, so plugging power in woke it, and the 5–8 s was wake-up plus re-creating its USB network. - So with the tablet awake, the hub's PD changes cost **~3.5 s on unplug** (full detach) and **~2.2 s on plug-in** (gadget reconnect only). Everything beyond that came from tablet sleep. - To the Orin, a sleeping tablet is indistinguishable from a dead link, except by heartbeat. - Rule of thumb: **about 3 s blank per power-state change**. The app keeping the tablet awake (full UI or an overlay widget) takes sleep off the table. - Known edge case, not a blocker: an underpowered or marginal charger that keeps falling back between PD and 5 V/1 A would cut the link on every renegotiation, possibly every few seconds. Use a solid PD charger. If the link ever flaps periodically, suspect the charger first. - At ignition, accessory power drops during cranking, so a start is likely to produce both edges back to back (not tested in the car yet). Consequence: in the car, expect a link outage of up to about 12 s at every ignition change. That is a requirement for the services (failure detection and redelivery; project-yukart ARCHITECTURE decision 24), not something to fix in the host setup.