§ 1.4 Ubuntu下编辑串口设备udev规则

1. 查询设备信息

把电脑上插上了两个CH340转换芯片。

查询目前所有的 /dev/ttyUSB 开头的设备

ls -al /dev/ttyUSB*

输出日志:

$ ls -al /dev/ttyUSB*
crw-rw-rw- 1 kyle users 188, 0 Aug  5 22:27 /dev/ttyUSB0
crw-rw-rw- 1 kyle users 188, 1 Aug  5 23:16 /dev/ttyUSB1

可以看到当前有两个USB设备。

1.1 lsusb - 查询设备 USB ID号

lsusb

输出日志:

kyle@deepsense:/etc/udev/rules.d$ lsusb
Bus 002 Device 011: ID 2bc5:0670 Orbbec 3D Technology International, Inc Orbbec(R) Gemini(TM)
Bus 002 Device 012: ID 152d:0578 JMicron Technology Corp. / JMicron USA Technology Corp. JMS578 SATA 6Gb/s
Bus 002 Device 004: ID 2109:0817 VIA Labs, Inc. USB3.0 Hub             
Bus 002 Device 003: ID 2109:0817 VIA Labs, Inc. USB3.0 Hub             
Bus 002 Device 005: ID 0bda:8153 Realtek Semiconductor Corp. RTL8153 Gigabit Ethernet Adapter
Bus 002 Device 002: ID 05e3:0626 Genesys Logic, Inc. USB3.1 Hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 05e3:0610 Genesys Logic, Inc. Hub
Bus 001 Device 006: ID 1532:0098 Razer USA, Ltd Razer DeathAdder Essential

---------------这个是第1个CH340的设备--------------
Bus 001 Device 011: ID 1a86:7523 QinHeng Electronics CH340 serial converter

Bus 001 Device 005: ID 2109:2817 VIA Labs, Inc. USB2.0 Hub          

---------------这个是第2个CH340的设备--------------
Bus 001 Device 008: ID 1a86:7523 QinHeng Electronics CH340 serial converter

Bus 001 Device 004: ID 24ae:4005 Shenzhen Rapoo Technology Co., Ltd. Rapoo Gaming Keyboard
Bus 001 Device 003: ID 2109:2817 VIA Labs, Inc. USB2.0 Hub             
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

其中CH340的设备信息如下:

Bus 001 Device 008: ID 1a86:7523 QinHeng Electronics CH340 serial converter

其中CH340 USB ID号为:

  • idVendor 厂家ID号 1a86
  • idProduct 产品ID号 7523

但是如果设备里面有多个CH340,每一个CH340的USB ID idVendor idProduct 都是相等的。

因此不能通过USB ID号来识别。

1.2 udevadm - 查询USB设备的父链路

让每个不同设备固定插入到特定的USB口,则可以根据设备插到某个特定的父链路信息来标记唯一的设备。

1.2.1 查看设备1的父链路信息

查看 /dev/ttyUSB0 的父链路信息

udevadm info --attribute-walk --name=/dev/ttyUSB0

输出日志:

$ udevadm info --attribute-walk --name=/dev/ttyUSB0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

>>>>>>>>>>>>>>>>>> 当前设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.1/1-11.1:1.0/ttyUSB0/tty/ttyUSB0':
 KERNEL=="ttyUSB0"
 SUBSYSTEM=="tty"
 DRIVER==""
 ATTR{power/async}=="disabled"
 ATTR{power/control}=="auto"
 ATTR{power/runtime_active_kids}=="0"
 ATTR{power/runtime_active_time}=="0"
 ATTR{power/runtime_enabled}=="disabled"
 ATTR{power/runtime_status}=="unsupported"
 ATTR{power/runtime_suspended_time}=="0"
 ATTR{power/runtime_usage}=="0"

>>>>>>>>>>>>>>>>>> 第1个父设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.1/1-11.1:1.0/ttyUSB0':
 KERNELS=="ttyUSB0"
 SUBSYSTEMS=="usb-serial"
 DRIVERS=="ch341-uart"
 ATTRS{port_number}=="0"
 ATTRS{power/async}=="enabled"
 ATTRS{power/control}=="auto"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_active_time}=="0"
 ATTRS{power/runtime_enabled}=="disabled"
 ATTRS{power/runtime_status}=="unsupported"
 ATTRS{power/runtime_suspended_time}=="0"
 ATTRS{power/runtime_usage}=="0"

>>>>>>>>>>>>>>>>>> 第2个父设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.1/1-11.1:1.0':
 KERNELS=="1-11.1:1.0"
 SUBSYSTEMS=="usb"
 DRIVERS=="ch341"
 ATTRS{authorized}=="1"
 ATTRS{bAlternateSetting}==" 0"
 ATTRS{bInterfaceClass}=="ff"
 ATTRS{bInterfaceNumber}=="00"
 ATTRS{bInterfaceProtocol}=="02"
 ATTRS{bInterfaceSubClass}=="01"
 ATTRS{bNumEndpoints}=="03"
 ATTRS{power/async}=="enabled"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_enabled}=="enabled"
 ATTRS{power/runtime_status}=="suspended"
 ATTRS{power/runtime_usage}=="0"
 ATTRS{supports_autosuspend}=="1"
... 其他父设备信息 略 ...

在第二个父设备信息那,可以看到内核编号 KERNELS 1-11.1:1.0

注:内核编号与设备插哪个USB口有关系,因为我用了USB拓展坞,所以内核编号要长一些

1.2.2 查看设备2的父链路信息

查看 /dev/ttyUSB1 的父链路信息

udevadm info --attribute-walk --name=/dev/ttyUSB1

输出日志:

$ udevadm info --attribute-walk --name=/dev/ttyUSB1

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

>>>>>>>>>>>>>>>>>> 当前设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0/ttyUSB1/tty/ttyUSB1':
 KERNEL=="ttyUSB1"
 SUBSYSTEM=="tty"
 DRIVER==""
 ATTR{power/async}=="disabled"
 ATTR{power/control}=="auto"
 ATTR{power/runtime_active_kids}=="0"
 ATTR{power/runtime_active_time}=="0"
 ATTR{power/runtime_enabled}=="disabled"
 ATTR{power/runtime_status}=="unsupported"
 ATTR{power/runtime_suspended_time}=="0"
 ATTR{power/runtime_usage}=="0"

>>>>>>>>>>>>>>>>>> 第1个父设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0/ttyUSB1':
 KERNELS=="ttyUSB1"
 SUBSYSTEMS=="usb-serial"
 DRIVERS=="ch341-uart"
 ATTRS{port_number}=="0"
 ATTRS{power/async}=="enabled"
 ATTRS{power/control}=="auto"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_active_time}=="0"
 ATTRS{power/runtime_enabled}=="disabled"
 ATTRS{power/runtime_status}=="unsupported"
 ATTRS{power/runtime_suspended_time}=="0"
 ATTRS{power/runtime_usage}=="0"

>>>>>>>>>>>>>>>>>> 第2个父设备信息  <<<<<<<<<<<<<<<<<<<<<<
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0':
 KERNELS=="1-11.3:1.0"
 SUBSYSTEMS=="usb"
 DRIVERS=="ch341"
 ATTRS{authorized}=="1"
 ATTRS{bAlternateSetting}==" 0"
 ATTRS{bInterfaceClass}=="ff"
 ATTRS{bInterfaceNumber}=="00"
 ATTRS{bInterfaceProtocol}=="02"
 ATTRS{bInterfaceSubClass}=="01"
 ATTRS{bNumEndpoints}=="03"
 ATTRS{power/async}=="enabled"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_enabled}=="enabled"
 ATTRS{power/runtime_status}=="suspended"
 ATTRS{power/runtime_usage}=="0"
 ATTRS{supports_autosuspend}=="1"
... 其他父设备信息 略 ...

在第二个父设备信息那,可以看到内核编号 KERNELS 1-11.3:1.0

注:内核编号与设备插哪个USB口有关系,因为我用了USB拓展坞,所以内核编号要长一些

2. 编辑udev规则

2.1 查看udev规则列表

cd /etc/udev/rules.d

查看规则列表

2.2 创建夹爪的udev规则

sudo touch 99-deepsense-gripper2f.rules

编辑规则文件

sudo gedit 99-deepsense-gripper2f.rules

夹爪设备当前插的端口,内核编号 KERNELS 1-11.3:1.0

填写如下内容,修改 KERNELS 不添加 : 后的编号。创建一个设备的软链接叫做 deepsense-gripper2f 。用 /dev/deepsense-gripper2f 替代 /dev/ttyUSB*

KERNEL=="ttyUSB*", KERNELS=="1-11.3", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="deepsense-gripper2f"

关闭文件,刷新 udev 规则。

sudo service udev reload
sudo service udev restart

2.3 验证配置成功

两个设备同时热拔插下,之后二者上电顺序随机。注意需要再插到原来的USB端口上。

ls -l /dev | grep ttyUSB

输出日志:

$ ls -l /dev | grep ttyUSB
lrwxrwxrwx   1 root root           7 Aug  6 00:55 deepsense-gripper2f -> ttyUSB0
crw-rw-rw-   1 kyle users   188,   0 Aug  6 00:55 ttyUSB0
crw-rw-rw-   1 kyle users   188,   1 Aug  6 00:55 ttyUSB1

按照不同的设备上电的顺序,输出日志也有可能是:

$ ls -l /dev | grep ttyUSB
lrwxrwxrwx   1 root root           7 Aug  6 00:55 deepsense-gripper2f -> ttyUSB1
crw-rw-rw-   1 kyle users   188,   0 Aug  6 00:55 ttyUSB0
crw-rw-rw-   1 kyle users   188,   1 Aug  6 00:55 ttyUSB1

之后就可以直接使用端口号 /dev/deepsense-gripper2f 连接夹爪了。

查看 /dev/deepsense-gripper2f 的父链路信息

udevadm info --attribute-walk --name=/dev/deepsense-gripper2f

输出日志:

$ udevadm info --attribute-walk --name=/dev/deepsense-gripper2f

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0/ttyUSB1/tty/ttyUSB1':
 KERNEL=="ttyUSB1"
 SUBSYSTEM=="tty"
 DRIVER==""
 ATTR{power/async}=="disabled"
 ATTR{power/control}=="auto"
 ATTR{power/runtime_active_kids}=="0"
 ATTR{power/runtime_active_time}=="0"
 ATTR{power/runtime_enabled}=="disabled"
 ATTR{power/runtime_status}=="unsupported"
 ATTR{power/runtime_suspended_time}=="0"
 ATTR{power/runtime_usage}=="0"

looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0/ttyUSB1':
 KERNELS=="ttyUSB1"
 SUBSYSTEMS=="usb-serial"
 DRIVERS=="ch341-uart"
 ATTRS{port_number}=="0"
 ATTRS{power/async}=="enabled"
 ATTRS{power/control}=="auto"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_active_time}=="0"
 ATTRS{power/runtime_enabled}=="disabled"
 ATTRS{power/runtime_status}=="unsupported"
 ATTRS{power/runtime_suspended_time}=="0"
 ATTRS{power/runtime_usage}=="0"

looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11.3/1-11.3:1.0':
 >>>>>>>>>>>>>>>>>>>>>> 这里可以看到 内核为1-11.3 <<<<<<<<<<<<<<<<<<<<<<
 KERNELS=="1-11.3:1.0"
 SUBSYSTEMS=="usb"
 DRIVERS=="ch341"
 ATTRS{authorized}=="1"
 ATTRS{bAlternateSetting}==" 0"
 ATTRS{bInterfaceClass}=="ff"
 ATTRS{bInterfaceNumber}=="00"
 ATTRS{bInterfaceProtocol}=="02"
 ATTRS{bInterfaceSubClass}=="01"
 ATTRS{bNumEndpoints}=="03"
 ATTRS{power/async}=="enabled"
 ATTRS{power/runtime_active_kids}=="0"
 ATTRS{power/runtime_enabled}=="enabled"
 ATTRS{power/runtime_status}=="suspended"
 ATTRS{power/runtime_usage}=="0"
 ATTRS{supports_autosuspend}=="1"

3. 参考文章

Linux 笔记 | Ubuntu 使用udev绑定ttyUSB端口

http://keaa.net/linux-udev.html

Linux_udev规则

https://zhuanlan.zhihu.com/p/60278497