使用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 可看到更多帮助),这样一开机就会禁用触摸板了。

posted @ 2012-09-09 15:26  背泳的鱼  阅读(1035)  评论(0)    收藏  举报