我有一台 Ubuntu 服务器(22.04.2 LTS),其中连接了多个 PCAN 设备,
CAN 驱动程序信息:
$ modinfo pcan
filename: /lib/modules/6.5.0-26-generic/misc/pcan.ko
license: GPL
version: Release_20240116_n
description: Driver for PEAK-System CAN interfaces
author: [email protected]
author: [email protected]
srcversion: 9B91AA025C2BA6422309BBB
alias: usb:v0C72p0014d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v0C72p0013d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v0C72p0011d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v0C72p0012d*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v0C72p000Dd*dc*dsc*dp*ic*isc*ip*in*
alias: usb:v0C72p000Cd*dc*dsc*dp*ic*isc*ip*in*
alias: pci:v0000001Cd0000001Asv*sd*bc*sc*i*
alias: pci:v0000001Cd00000019sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000018sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000017sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000016sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000014sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000013sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000010sv*sd*bc*sc*i*
alias: pci:v0000001Cd0000000Asv*sd*bc*sc*i*
alias: pci:v0000001Cd00000002sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000009sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000008sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000007sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000006sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000005sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000004sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000003sv*sd*bc*sc*i*
alias: pci:v0000001Cd00000001sv*sd*bc*sc*i*
depends: i2c-algo-bit
retpoline: Y
name: pcan
vermagic: 6.5.0-26-generic SMP preempt mod_unload modversions
parm: fdusemsi: 0=INTA; 1=MSI (not shared); 2=MSI (shared) (def=0) (byte)
parm: fdirqcl: PCIe FD IRQ Count Limit (default=16) (uint)
parm: fdirqtl: PCIe FD IRQ Time Limit (default=10) (uint)
parm: usemsi: 0=INTA; 1=MSI (not shared); 2=MSI (shared) (def=0) (byte)
parm: fast_fwd: set fast forward option in USB device (def=0) (ushort)
parm: irqmaxloop: max loops in ISR per CAN (0=default def=6) (uint)
parm: irqmaxrmsg: max msgs read per Rx IRQ (0=default def=8) (uint)
parm: type:type of PCAN interface (isa, sp, epp) (array of charp)
parm: io:io-port address for either PCAN-ISA, PC/104 or Dongle (array of ulong)
parm: irq:interrupt number for either PCAN-ISA, PC/104 or Dongle (array of byte)
parm: btr0btr1:initial bitrate (BTR0BTR1 format) for all channels (ushort)
parm: bitrate:initial nominal bitrate for all channels (charp)
parm: dbitrate:initial data bitrate for all CAN-FD channels (charp)
parm: rxqsize: size of the Rx FIFO of a channel (def=2000) (ushort)
parm: rxqprealloc:allocate Rx FIFO once at probe time (byte)
parm: txqsize: size of the Tx FIFO of a channel (def=500) (ushort)
parm: txqprealloc:allocate Tx FIFO once at probe time (byte)
parm: dmamask: [24..64] (def=64) (ushort)
parm: deftsmode: default ts mode (ushort)
parm: defblperiod: default bus load msg period (def=500 ms.) (ushort)
parm: drvclkref: driver clock reference (def=0) (ushort)
parm: txqhiwat: Tx fifo hi-water ratio [5000..10000] def=10000) (short)
已连接设备列表:
~ $ ls /dev/* | grep -P "pcan\d+"
/dev/pcan32
/dev/pcan33
/dev/pcan34
/dev/pcan35
/dev/pcan36
/dev/pcan37
/dev/pcan38
/dev/pcan39
udevadm
一台设备的信息:
~ $ udevadm info --query=all --name=/dev/pcan32
P: /devices/pci0000:00/0000:00:14.0/usb2/2-13/2-13.3/2-13.3.1/2-13.3.1.1/2-13.3.1.1:1.0/pcan/pcanusb32
N: pcanusb32
L: 0
S: pcan-usb/0/can0
S: pcan32
S: U3-PCAN-1
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb2/2-13/2-13.3/2-13.3.1/2-13.3.1.1/2-13.3.1.1:1.0/pcan/pcanusb32
E: DEVNAME=/dev/pcanusb32
E: MAJOR=238
E: MINOR=32
E: SUBSYSTEM=pcan
E: USEC_INITIALIZED=1453865341559
E: DEVLINKS=/dev/pcan-usb/0/can0 /dev/pcan32 /dev/U3-PCAN-1
但是,当使用 python-can 检测可用设备时,我得到以下信息:
In [1]: from can.interface import detect_available_configs
In [2]: print("\n".join(map(str, detect_available_configs('pcan'))))
{'interface': 'pcan', 'channel': 'PCAN_USBBUS1', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS2', 'supports_fd': True, 'controller_number': 0, 'device_features': 3, 'device_id': 0, 'device_name': 'PCAN-USB FD', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS3', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS4', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS5', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 1, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS6', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS7', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS8', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1}
我怎么知道每个/dev/pcanX
设备映射到哪个PCAN_USBBUSX
?
因为在 Linux 系统中,第一个设备获得第一个索引,第二个设备获得第二个索引等等...,
我可以假设第一个 pcan 设备(在我的情况下/dev/pcan32
)被映射到PCAN_USBBUS1
并且第二个设备/dev/pcan33
被映射到PCAN_USBBUS2
吗?
等等......
我需要一种方法来确定每个/dev/pcan<X>
映射到哪个 PythonPCAN_USBBUS<X>
答案1
我创建了一个 Python 脚本,也许可以解决这个问题:
from can.interface import detect_available_configs
import glob
import os
can_devices: list[dict[str, str]] = detect_available_configs('pcan')
def get_devices() -> tuple[tuple[str, int, str], ...]:
devices = sorted(
glob.glob('/dev/pcan-usb*/*/*'),
key=lambda x: int(os.readlink(x)[-2:])
)
links = sorted(
# U*-PCAN-* is a symlink to /dev/pcan-usb* that was created by udev rules
# based on the physical connection of the device
# e.g.:
# KERNEL=="pcanusb*", ATTRS{devpath}=="13.2.4.1.2", MODE="0660", SYMLINK+="U4-PCAN-1"
# KERNEL=="pcanusb*", ATTRS{devpath}=="13.2.4.1.3", MODE="0660", SYMLINK+="U4-PCAN-2"
glob.glob('/dev/U*-PCAN-*'),
key=lambda x: int(os.readlink(x)[-2:])
)
return tuple((i, int(i.split('/')[3]), j) for i, j in zip(devices, links))
shift = 0
for index, (dev, can_index, link) in enumerate(get_devices()):
if can_index + shift < index:
shift += 1
# can_devices[can_index + shift]['link'] = link
can_devices[can_index + shift].update({
'link': link,
'device': dev,
'dev': os.readlink(dev).replace('../..', '/dev')
})
print("\n".join(map(str, can_devices)))
结果得到以下结果:
{'interface': 'pcan', 'channel': 'PCAN_USBBUS1', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U3-PCAN-1', 'device': '/dev/pcan-usb/0/can0', 'dev': '/dev/pcanusb32'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS2', 'supports_fd': True, 'controller_number': 0, 'device_features': 3, 'device_id': 0, 'device_name': 'PCAN-USB FD', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U3-PCAN-2', 'device': '/dev/pcan-usb_fd/0/can0', 'dev': '/dev/pcanusbfd33'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS3', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U4-PCAN-1', 'device': '/dev/pcan-usb/1/can0', 'dev': '/dev/pcanusb34'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS4', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U4-PCAN-2', 'device': '/dev/pcan-usb/2/can0', 'dev': '/dev/pcanusb35'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS5', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 1, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U2-PCAN-1', 'device': '/dev/pcan-usb/3/can0', 'dev': '/dev/pcanusb36'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS6', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U2-PCAN-2', 'device': '/dev/pcan-usb/4/can0', 'dev': '/dev/pcanusb37'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS7', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U1-PCAN-1', 'device': '/dev/pcan-usb/5/can0', 'dev': '/dev/pcanusb38'}
{'interface': 'pcan', 'channel': 'PCAN_USBBUS8', 'supports_fd': False, 'controller_number': 0, 'device_features': 0, 'device_id': 0, 'device_name': 'PCAN-USB', 'device_type': 5, 'channel_condition': 1, 'link': '/dev/U1-PCAN-2', 'device': '/dev/pcan-usb/6/can0', 'dev': '/dev/pcanusb39'}
请有人告诉我我的方法是否正确。10x
:)