Pin CAN interface names by udev; document device naming
mttcan and pcan both load at boot, so the PCAN adapter could take can0 and push the onboard controller to can1. A udev rule now names them can_onboard (platform c310000.mttcan) and can_pcan (USB 0c72:000c), both outside the canN pool so a transient canN can never collide. Also records why the SIM7600 needs nothing more: ModemManager and NM don't use ttyUSB numbers, and gpsd already uses a symlink. can_onboard is verified live; can_pcan is checked against the driver source only (adapter not plugged in). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
---
|
||||
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 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`).
|
||||
`can_pcan` was checked against the driver source only, because the adapter wasn't plugged in. **To do:** plug the adapter in and confirm with `ip -br link`.
|
||||
|
||||
## 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.
|
||||
@@ -100,6 +100,9 @@ $ ip link show type can
|
||||
- `can0` = onboard MTTCan
|
||||
- `can1` = PCAN-USB adapter
|
||||
|
||||
> **2026-10-08:** `canN` order is not stable across boots. Interfaces are now pinned to `can_onboard` / `can_pcan`
|
||||
> by a udev rule; read `can1` below as `can_pcan`. See [device naming](DEVICE-NAMING.md).
|
||||
|
||||
### Step 5: Bring Up the Interface
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user