同じ機器を複数つないだ場合、デバイスファイル名の数字は入れ替わることが普通にある。
devpath(物理ポートの番号)を使って、別途デバイスファイル名をつけて固定する方法を記載する。
※ここではシリアルデバイスと想定
まず、/dev/ttyACM0〜/dev/ttyACM2がすでに存在するとして。
目的は/etc/udev/rules.d/99-serial.rules(なければ作る)に以下のような内容を記載する。
ーーーーーーーーーーここから
SUBSYSTEM=="tty", ATTRS{devpath}=="4.2", SYMLINK+="ttyTH0", GROUP="dialout", MODE="0660"
SUBSYSTEM=="tty", ATTRS{devpath}=="4.1", SYMLINK+="ttyTH1", GROUP="dialout", MODE="0660"
SUBSYSTEM=="tty", ATTRS{devpath}=="4.3", SYMLINK+="ttyTH2", GROUP="dialout", MODE="0660"
SUBSYSTEM=="tty", ATTRS{devpath}=="4.1", SYMLINK+="ttyTH1", GROUP="dialout", MODE="0660"
SUBSYSTEM=="tty", ATTRS{devpath}=="4.3", SYMLINK+="ttyTH2", GROUP="dialout", MODE="0660"
ここまでーーーーーーーーーー
ATTRS{devpath}の値は udevadm info -a -n (デバイスファイル名) | grep devpath を実行
例:
udevadm info -a -n /dev/ttyACM0 | grep devpath
Udevadm info starts with the device specified by the devpath and then
ATTRS{devpath}=="4.2"
ATTRS{devpath}=="4"
ATTRS{devpath}=="0"
ATTRS{devpath}=="4.2"
ATTRS{devpath}=="4"
ATTRS{devpath}=="0"
この最初のATTRS{devpath}=="4.2"をそのまま99-serial.rulesに記載することになる。
同様、/dev/ttyACM1がATTRS{devpath}=="4.1" /dev/ttyACM2がATTRS{devpath}=="4.3"だった場合が上記例となる。
記載して保存したら以下を実行
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo udevadm control --reload-rules
sudo udevadm trigger
ーーーーーー
USBのデバイスリセット
一度クローズすると再オープンに失敗することがある。この場合はUSBリセットが必要。
その場合はUSB バスアドレス(bus/device 番号)が必要
その場合はUSB バスアドレス(bus/device 番号)が必要
/dev/ttyACM0 → /dev/bus/usb/003/013
/dev/ttyACM1 → /dev/bus/usb/003/008
/dev/ttyACM2 → /dev/bus/usb/003/009
/dev/ttyACM1 → /dev/bus/usb/003/008
/dev/ttyACM2 → /dev/bus/usb/003/009
のように、/dev/bus/usb/(バス番号)/(デバイス番号) で表現される。
バス番号は以下で取得
udevadm info -a -n (デバイスファイル名) | grep busnum
例:
udevadm info -a -n /dev/ttyACM0 | grep busnum ATTRS{busnum}=="3"
ATTRS{busnum}=="3"
ATTRS{busnum}=="3"
ATTRS{busnum}=="3"
ATTRS{busnum}=="3"
の先頭行の3が対象。3桁0パディングは単なる慣習みたいだけど従っておくのが無難
デバイス番号は以下で取得
udevadm info -a -n (デバイスファイル名) | grep devnum
例:
udevadm info -a -n /dev/ttyACM0 | grep devnum ATTRS{devnum}=="13"
ATTRS{devnum}=="5"
ATTRS{devnum}=="1"
ATTRS{devnum}=="5"
ATTRS{devnum}=="1"
の先頭行の13が対象。これも3桁0パディングは単なる慣習みたいだけど従っておくのが無難
ttyACM0を初期化したい場合octl(fd, USBDEVFS_RESET, 0)を使う。そのためにopenするが、openの為にUSB バスアドレスが必要だった、という話。
char devices[] = "/dev/bus/usb/003/013";
int fd = open(devices, O_WRONLY);
if (fd < 0)
if (fd < 0)
perror("open");
else
{
if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
perror("ioctl");
close(fd);
close(fd);
}