--- type: report date: 2026-10-08 --- # Stable Device Naming: CAN Interfaces and SIM7600 Ports ## Problem Kernel names come from registration order. That order isn't stable, so anything configured as `can1` or `ttyUSB3` can point at a different device after a reboot or replug. - **CAN:** `mttcan` (onboard) and `pcan` (USB, via `/etc/modules`) both load at boot. The `canN` names go to whichever registers first, so the PCAN adapter can end up as `can0` and the onboard controller as `can1`. - **SIM7600:** five `ttyUSB*` ports. Their numbers shift if another USB-serial device enumerates first. ## Result | Device | Identified by | Stable name | |--------|---------------|-------------| | Onboard MTTCAN | platform device `c310000.mttcan` | `can_onboard` | | PEAK PCAN-USB | USB `0c72:000c` | `can_pcan` | | SIM7600 NMEA port | USB `1e0e:9001`, interface 01 | `/dev/sim7600-gps` (symlink) | | SIM7600 spare AT port | USB `1e0e:9001`, interface 03 (ModemManager ignores it) | `/dev/sim7600-at` (symlink) | | SIM7600 modem | ModemManager `simtech` plugin (USB IDs and per-interface port probing) | n/a, nothing configured by port name | | SIM7600 data | NetworkManager `povo` connection with `ifname '*'` | n/a, follows whatever modem ModemManager exposes | `can_onboard` was verified with a live rename (`mttcan c310000.mttcan can_onboard: renamed from can0`). **Verified across a cold boot (2026-10-08)** with the PCAN-USB and SIM7600 both attached before power-on: `pcan` registered *first* and took `can0`, which is the race this rule exists for. udev renamed it (`pcan 1-2.4:1.0 can_pcan: renamed from can0`), and `mttcan` then got `can0` and was renamed to `can_onboard`. ModemManager came up on `cdc-wdm0` (qmi_wwan auto-loaded), `povo` auto-connected with `wwan0` at metric 1000 below WiFi, and gpsd started on `/dev/sim7600-gps`. Hot-plug verified too (2026-10-09): the PCAN-USB plugged in while the system was running came up as `can_pcan`. ## CAN: `/etc/udev/rules.d/70-can-names.rules` ``` SUBSYSTEM=="net", ACTION=="add", KERNELS=="c310000.mttcan", NAME="can_onboard" SUBSYSTEM=="net", ACTION=="add", ATTRS{idVendor}=="0c72", ATTRS{idProduct}=="000c", NAME="can_pcan" ``` - **Both** interfaces get names outside the kernel's `canN` pool. Renaming only the PCAN and pinning the onboard controller to `can0` would race: if `pcan` registers first, it briefly holds `can0` and the onboard rename collides. - Underscores rather than hyphens: systemd escapes `-` in device unit names (`sys-subsystem-net-devices-can\x2dpcan.device`). - The file must sort before `80-net-setup-link.rules`, which only assigns a name when `NAME` is still empty. - PCAN matching relies on the netdev's sysfs parent being the USB interface. In PEAK 9.2.0, `pcan_netdev.c` calls `SET_NETDEV_DEV(ndev, pcandev_to_dev(pdev))`, and for USB devices that returns `&usb_intf->dev`, so `ATTRS{idVendor}` matches. - PEAK's own `assign=` module parameter (`peak`, `devid`, `pcanX:canY`) can only produce `canN` names, so it doesn't avoid the race. - **More than one PCAN-USB:** both would match `can_pcan`, and the second rename would fail. Give each adapter a device ID (PEAK tools: `pcan-settings`), then add a per-ID match and distinct names. Apply without a reboot (interface must be DOWN): ``` sudo udevadm control --reload sudo udevadm trigger --action=add /sys/class/net/can0 ``` Usage: `sudo ip link set can_pcan up type can bitrate 500000 && candump can_pcan`. Generic detection still works: `ip -d link show type can` lists both regardless of name. ## SIM7600: why no further rules are needed - ModemManager identifies the modem by USB ID and probes each port, which gives it the `(at)`, `(gps)`, `(qmi)` and `(net)` roles. It never relies on a `ttyUSB` number. - NetworkManager binds the `povo` GSM connection to the ModemManager modem object (`ifname '*'`), not to a device node. - gpsd is the only consumer of a raw port, and it uses the `/dev/sim7600-gps` udev symlink (`/etc/udev/rules.d/99-sim7600-gps.rules`, matching `ENV{ID_USB_INTERFACE_NUM}=="01"`). - `ttyUSB2` is mentioned in the [SIM7600 report](SIM7600-SETUP.md) only for manual AT sessions. `ls -l /dev/serial/by-id/` shows the stable path (`...-if02-port0`) if numbering ever shifts. ## Affected references - [PCAN setup report](PCAN-SETUP.md): its `can0`/`can1` examples are from before this change. - `halogen-workstation-roadmap` phase 17 lists "presence of `can0`" as a CAN heuristic. That heuristic is now false on this host; `ip -d link show type can` still works.