使用udev禁用触摸板
前言
最初的需求是,鼠标与触摸板互斥地使用,就是外接鼠标时自动禁用触摸板,拔出时自动启动触摸板。
其实这篇博文其实不算教程,只是个折腾的过程啦。
关于udev规则请man udev。
教程请看http://www.reactivated.net/writing_udev_rules.html(注意udevadm已经取代udevinfo和udevtest等命令)。
解决方法
1. 新建一个名为99-touchpad.rules的文件,将以下内容复制进去
ACTION=="add", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", ENV{XAUTHORITY}="/home/_USER_NAME_/.Xauthority", ENV{DISPLAY}=":0.0", RUN+="/usr/bin/synclient TouchpadOff=1" ACTION=="remove", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", ENV{XAUTHORITY}="/home/_USER_NAME_/.Xauthority", ENV{DISPLAY}=":0.0", RUN+="/usr/bin/synclient TouchpadOff=0"
2. 将上面内容中的_USER_NAME_替换为自己的用户名
3. 将文件移动到/etc/udev/ruels.d/
4. 在/etc/rc.local中加入
udevadm trigger --verbose --subsystem-match=input
如果你对博主的折腾过程感兴趣,请继续往下看吧。
怎样写udev规则
1.查找鼠标的udev标识(Attribute)
首先要知道鼠标设备结点在哪,一般是在/dev/input/下,当你拔掉鼠标后会发现某个"文件"不见了,证明那个就是要找的设备结点了。
然后使用下面的命令来找匹配条件,它会向上查找设备路径链,打印每一层设备路径的标识,我们只要找出那些独特的标识来匹配鼠标就可以了。
udevadm info --attribute-walk --name 设备结点
以我为例,我输入 udevadm info --attribute-walk --name /dev/input/mouse0 会出现:
View Code
looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/input/input32/mouse0': KERNEL=="mouse0" SUBSYSTEM=="input" DRIVER=="" looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/input/input32': KERNELS=="input32" SUBSYSTEMS=="input" DRIVERS=="" ATTRS{name}==" USB OPTICAL MOUSE" ATTRS{phys}=="usb-0000:00:1d.0-1.2/input0" ATTRS{uniq}=="" ATTRS{properties}=="0" ...
实际上要匹配我现在使用的鼠标很简单,可以用KERNEL=="mouse0"和SUBSYSTEM=="input"作为条件,甚至可以用ATTRS{name}==" USB OPTICAL MOUSE"来匹配,只是这样写不那么通用而已。
2.查找鼠标在udev属性值(property value)
实际上设备在udev里除了标识,还有以环境变量来表示的属性,可以用下面的命令来查看:
udevadm info --query all --name 设备结点
以我为例,输入 udevadm info --query all --name /dev/input/mouse0 就会出现:
View Code
P: /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/input/input32/mouse0 N: input/mouse0 S: input/by-id/usb-15d9_USB_OPTICAL_MOUSE-mouse S: input/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-mouse E: DEVLINKS=/dev/input/by-id/usb-15d9_USB_OPTICAL_MOUSE-mouse /dev/input/by-path/pci-0000:00:1d.0-usb-0:1.2:1.0-mouse E: DEVNAME=/dev/input/mouse0 E: DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/input/input32/mouse0 E: DISPLAY=:0.0 E: ID_BUS=usb E: ID_INPUT=1 E: ID_INPUT_MOUSE=1 E: ID_MODEL=USB_OPTICAL_MOUSE ....
经我不完全调查,鼠标、键盘、手柄都会出现SUBSYSTEM=="input"标识,但是鼠标会有一个特殊环境变量ID_INPUT_MOUSE=1。根据这两个条件可以写出更通用的udev规则。
3.确定匹配后运行程序
使用 synclient TouchpadOff=1 可以很方便的禁用触摸板。其实xinput也可以,只是参数比较烦而已。
那么规则可以这样写:
ACTION=="add", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", RUN+="/usr/bin/synclient TouchpadOff=1" ACTION=="remove", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", RUN+="/usr/bin/synclient TouchpadOff=0"
udev规则是一条一行,语句之间以逗号分隔,以第一条为例,它的意思是:
当出现ACTION为"add"、SUBSYSTEM为"input"、ID_INPUT_MOUSE属性(udev环境变量)为1时,执行/usr/bin/synclient TouchpadOff=1。
再次提醒,更多的udev规则语法可 man udev 来查看。
4.添加规则文件
将规则文件复制到/etc/udev/rules.d/目录下,命令规则是 序号-规则文件名.rules 。假如有多个规则文件同时匹配,udev会优先读取序号较小的规则文件,安全起见还是把序号设为99比较好。
执行下面的命令会重新读取所有规则文件。如果是修改已有的规则文件,则不用做这一步。
sudo udevadm control --reload-rules
如果这样运行起来没有问题,恭喜你不用看下去了。
如果还不行,请继续看博主苦逼的折腾过程吧。
1.获取udev调试信息
使用下面的命令可以查看udev的调试信息:
sudo udevd --debug
当出现类似下面的信息时,说时某个udev事件已经匹配某条规则(99-touchpad.rules就是我的规则文件),并执行RUN的内容。
[274.412309] [2587] udev_rules_apply_to_event: RUN '/usr/bin/synclient TouchpadOff=1' /etc/udev/rules.d/99-touchpad.rules:1
但是我却发现了这样的信息:
[274.413026] [2631] udev_event_spawn: starting '/usr/bin/synclient TouchpadOff=1' [274.428549] [2632] udev_event_spawn: starting '/usr/bin/synclient TouchpadOff=1' [274.430729] [2581] spawn_read: '/usr/bin/synclient TouchpadOff=1'(err) 'Failed to connect to X Server.' [274.430729] [2587] spawn_read: '/usr/bin/synclient TouchpadOff=1'(err) 'Failed to connect to X Server.'
2.环境变量惹的祸
https://bbs.archlinux.org/viewtopic.php?id=83177
有人和我遇上同样的问题,他的解决办法是把X下的环境变量记录在一个脚本下面,在脚本最后才执行synclient。因此在udev匹配后执行那个脚本就可以了。
查看当前所有环境变量,以 declare -x 环境变量=值 的形式返回:
export -p
要找出哪些变量引起'Failed to connect to X Server.'我的做法是:
(1)export -p > ~/test.sh && chmod 777 ~/test.sh
(2)在test.sh最后加上一句 synclient TouchpadOff=1
(3)将规则文件中的RUN定义为执行test.sh脚本。
(4)删除or恢复test.sh脚本内的一些环境变量定义,二分法,你懂的。
(5)拔出or插入鼠标,并使用 sudo udevd --debug 监视synclient是否执行成功,重复第(4)步直到环境变量定义语句不能再删。
最后我发现环境变量XAUTHORITY和DISPLAY会影响synclient执行,只要参照你自己的系统来定义就行了。
如果udev事件匹配后运行一个脚本那也太麻烦了吧,还要找个地方放脚本呢。其实环境变量定义还可以放在udev规则里,不是在RUN里export哦。
3.udev里的设备属性(property value)就是环境变量
http://www.reactivated.net/writing_udev_rules.html
网上有些udev例子会用 ENV{设备属性}=值 来声明一些标志(注意不要混淆上面匹配条件语法,区别在于运算符)。它也说到这个语法也可以在udev下声明环境变量。但是所谓的属性(环境变量)在终端是echo不出来的,更重要的是,man udev 上面写 ENV{设备属性}=值 这句话是"Set a device property value. "的,它真的是环境变量吗?我们可以做个小实验来验证一下。
上面不是说过只要定义好XAUTHORITY和DISPLAY的环境变量,synclient就能正常运行,那么我们在udev规则文件利用 ENV{环境变量}=值 来定义这两个环境变量,再察看udev调试信息。(如果觉得不科学,还可以在RUN里执行/usr/bin/env 重定向来看)。
好吧,最后你会发现manpages其实也有不详尽的地方。
最后,我的udev规则是这样的:
ACTION=="add", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", ENV{XAUTHORITY}="/home/fish47/.Xauthority", ENV{DISPLAY}=":0.0", RUN+="/usr/bin/synclient TouchpadOff=1" ACTION=="remove", SUBSYSTEM=="input", ENV{ID_INPUT_MOUSE}=="1", ENV{XAUTHORITY}="/home/fish47/.Xauthority", ENV{DISPLAY}=":0.0", RUN+="/usr/bin/synclient TouchpadOff=0"
后记
貌似udev在开机时不会触发鼠标插入事件,也有可能udev比X先启动,调用synclient那肯定是'Failed to connect to X Server.'了。
我的做法是在 /usr/share/X11/xorg.conf.d/50-synaptics.conf 在第一个Section里插入一句 Option "TouchpadOff" "1"(man synaptics 可看到更多帮助),这样一开机就会禁用触摸板了。


浙公网安备 33010602011771号