PCAN_USBBUSX と /dev/pcanusbX 間のマッピング

PCAN_USBBUSX と /dev/pcanusbX 間のマッピング

複数のPCANデバイスが接続されているUbuntuサーバー(22.04.2 LTS)があります。
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システムでは、最初のデバイスが最初のインデックスを取得し、2番目のデバイスが2番目のインデックスを取得するように進むためです。

最初のpcanデバイス(私の場合/dev/pcan32)はにマッピングされ、PCAN_USBBUS1
2番目のデバイス/dev/pcan33はにマッピングされていると仮定できますかPCAN_USBBUS2
など...

/dev/pcan<X>それぞれがどのPythonにマップされているかを確認する方法が必要です。PCAN_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'}

誰かが私のアプローチが正しいことを教えてください。
10番 :)

関連情報