详细解读Linux的输入子系统

嵌入式技术

1372人已加入

描述

1. 简介

这时一组驱动的集合,它们可以用于所有的基于linux的输入设备,虽然目前它只是用于USB输入设备,将来(2.5、2.6版本)它们将会被扩展并替换掉现存的多数输入系统,这就是为什么它们被放在drivers/input/目录下,而不是drivers/usb/。

输入设备驱动的核心是input模块,它需要在其他输入模块之前被加载--它是输入系统其它两个模块之间通讯的桥梁:

1.1 设备驱动(Device drivers)

这些模块负责和实际的硬件打交道(例如通过USB),给input模块提供相应的事件(按键,鼠标移动)

1.2 事件处理模块(Event handlers)

这些模块从input模块获得事件信息,并根据需要通过不同的接口传递这些事件--往kernel传递按键事件,或者通过模拟的PS/2接口给GPM和X传递鼠标移动事件,等等。

2. 一个简单的例子

通常,对于大多数配置来说,系统有一个USB鼠标和一个USB键盘,你需要加载以下几个模块(或者把它们编译到内核中):

input

mousedev

keybdev

usbcore

uhci_hcdor ohci_hcd or ehci_hcd

usbhid

在这之后,USB键盘直接就可以工作了,USB鼠标会作为一个字符设备,主次设备号分别为13和63:

crw-r--r--   1 root    root      13,  63 Mar 28 22:45 mice

你需要主动创建该鼠标设备节点,创建的命令如下:

cd/dev

mkdirinput

mknodinput/mice c 13 63

之后,你必须告诉GPM和XFree你要使用这个鼠标设备 - 对于GPM,应该象以下的指令:

gpm-t ps2 -m /dev/input/mice

对于X:

Section"Pointer"

Protocol   "ImPS/2"

Device     "/dev/input/mice"

ZAxisMapping 4 5

EndSection

做完以上步骤以后,你就可以正常地使用USB鼠标和键盘了。

3. 详细描述

~~~~~~~~~~~~~~~~~~~~~~~

3.1 设备驱动(Device drivers)

~~~~~~~~~~~~~~~~~~

设备驱动模块产生输入事件,这些事件在没有经过处理之前是没有什么用处的,所以你需要用到3.2节的某些模块。

3.1.1 usbhid

~~~~~~~~~~~~

usbhid可以说是最庞大和复杂的驱动了。它处理所有的HID设备,他之所以这么复杂和庞大,原因是设备类型种类繁多,USB HID的规格也相当不简单。

目前,它处理USB鼠标,游戏控制杆,方向盘,键盘,轨迹球和数字化仪。

而且,USB也使用HID来实现监视器控制,扬声器控制,UPSs,LCDs等等很多外设。

监视器和扬声器控制比较容易添加到hid/input接口中,但是UPSs和LCDs就不是这么简单,为此,设计了hiddev接口,详细的信息请参考Documentation/hid/hiddev.txt。

usbhid模块非常易于使用,它没有任何参数,自动检测插入的HID设备,是的,它能用合适的方式进行检测。

不过,因为设备实在是太过于多样性了,你可能遇到某些设备工作的不好。这时你可以在hid-core.c的开始加上#defineDEBUG,把syslog traces发给我。

3.1.2 usbmouse

~~~~~~~~~~~~~~

对于嵌入式系统,只为了使用鼠标功能而加入整个庞大的usbhid显然不是一个好的选择,这时可以只使用usbmouse驱动,它只处理usb鼠标。它使用了简易的HIDBP协议。当然这要求你的鼠标必须也要支持这一简易协议。最好,如果你没有很强烈地理由,请使用usbhid。

3.1.3 usbkbd

~~~~~~~~~~~~

就像usbmouse一样,这个模块用简易的HIDBP协议与键盘通信。它很小,但不支持任何额外的按键。没有特别的原因时,也请使用usbhid。

3.1.4 wacom

~~~~~~~~~~~

这是Wacom Graphire和Intuos tablets的驱动。它不是用于Wacom PenPartner,一个由HID驱动处理的设备。尽管Intuos 和Graphiretablets声称他们是HID tablets,但实际上不是,所以需要这个特别的驱动。

3.1.5 iforce

~~~~~~~~~~~~

用于I-Force游戏杆和滚轮的驱动,通过USB和RS232连接。现在它包含了ForceFeedback的支持,尽管Immersion公司认为该协议是商业机密而且没有公开它的任何信息。

3.2 Event handlers

~~~~~~~~~~~~~~~~~~

Eventhandlers根据实际需要,把设备的事件分发到用户空间或者内核中。

3.2.1 keybdev

~~~~~~~~~~~~~

keybdev目前是一个不太好的骇客工具,它把输入事件转换为体系相关的键盘raw模式(x86中的Xlated AT Set2),然后传递给keyboard.c模块中的handle_scancode函数。当体系的keybdev能产生rawmode时,它会工作得很好,其他体系也能添加进来。

正确地方法是直接把输入事件传递到keyboard.c中,最好的是keyboard.c本身就是一个event handler。这一工作由下面提到的网页提供了一个input patch来完成。

3.2.2 mousedev

~~~~~~~~~~~~~~

mousedev也是一个骇客工具,它使得那些需要使用鼠标的程序可以工作。它从鼠标或者数字化仪获取事件,然后生成了一个PS/2类型(例如/dev/psaux)的鼠标设备来让用户空间的程序使用。理想的情况下,程序应该使用一个更加合理的接口,例如evdev。

上面提到的Mousedev设备在/dev/input中的呈现如下:

crw-r--r--   1 root    root      13,  32 Mar 28 22:45 mouse0

crw-r--r--   1 root    root      13,  33 Mar 29 00:41 mouse1

crw-r--r--   1 root    root      13,  34 Mar 29 00:41 mouse2

crw-r--r--   1 root    root      13,  35 Apr 1 10:50 mouse3

...

...

crw-r--r--   1 root    root      13,  62 Apr 1 10:50 mouse30

crw-r--r--   1 root    root      13,  63 Apr 1 10:50 mice

除了最后的'mice',每个'mouse'设备被分配给单一的鼠标或者是数字化仪。最后的'mice',这个单一的字符设备由所有的鼠标和数字化仪共享,就算没有任何真正的鼠标连接进来,这个设备也依然存在。这一特性对USB鼠标的热插拔功能很有用。这样尽管没有鼠标连接,程序依然可以打开该设备。

在XFree86中,内核的配置项:CONFIG_INPUT_MOUSEDEV_SCREEN_[XY],指定了屏幕的像素。如果你想在X中使用数字化仪,这点是必要的,因为她的移动会被通过虚拟的PS/2鼠标发送到X中,这时需要计算正确地比例。如果你只是使用鼠标,这个配置值是没有用处的。

依赖于程序希望读取什么数据,Mousedev会生成PS/2, ImPS/2(Microsoft IntelliMouse) 或者

ExplorerPS/2 (IntelliMouse Explorer)协议格式的数据。你可以把GPM和X设置成这里的任一种。如果你想使用USB鼠标上的滚轮,你可以配置为ImPS/2,而当你希望使用额外的按键时,就使用ExplorerPS/2。

3.2.3 joydev

~~~~~~~~~~~~

Joydev实现了Linux joystick 的v0.x和v1.x版的api,有点类似之前内核使用的驱动:drivers/char/joystick/joystick.c。细节请进一步参考内核文档:joystick-api.txt。一旦有joystick连接到系统中,我们可以通过/dev/input中的以下节点访问它:

crw-r--r--   1 root    root      13,   0 Apr 1 10:50 js0

crw-r--r--   1 root    root      13,   1 Apr 1 10:50 js1

crw-r--r--   1 root    root      13,   2 Apr 1 10:50 js2

crw-r--r--   1 root    root      13,   3 Apr 1 10:50 js3

...

一直可以到:js31.

3.2.4 evdev

~~~~~~~~~~~

evdev是一个通用的输入事件接口,它把内核产生的事件,连同时间戳一起,直接传递到用户空间的应用程序中。该接口的API还在不断完善中,但现在已经可以使用它们。该接口我们会在下面的第5节说明。

GPM和X可以通过该方式来获取键盘和鼠标的事件。无需内核特别支持,它就可以允许X对它进行多线程的访问。事件编码对所有平台都是统一的并且是硬件无关的。

设备节点位于 /dev/input:

crw-r--r--   1 root    root      13,  64 Apr 1 10:49 event0

crw-r--r--   1 root    root      13,  65 Apr 1 10:50 event1

crw-r--r--   1 root    root      13,  66 Apr 1 10:50 event2

crw-r--r--   1 root    root      13,  67 Apr 1 10:50 event3

...

一直可以到:event31.

4. 验证是否可以正常工作

~~~~~~~~~~~~~~~~~~~~~~~~

在键盘上敲几个键就足以检查USB键盘是否工作正常,也能检查是否内核的驱动是否工作正常。

敲入命令:"cat /dev/input/mouse0" (c, 13, 32)可以验证鼠标是否被正确地枚举,当你移动鼠标时,屏幕会显示一些字符。

你可以用jstest工具来测试joystick是否正常工作,该工具在joystick包中(参见文档:Documentation/input/joystick.txt)

可以使用evtest工具对event设备进行测试,该工具可以从LinuxConsole项目的CVS中获取(见下面的URL)

5. Event interface

~~~~~~~~~~~~~~~~~~

如果你希望在你的任何应用中(X,gpm,svgalib ...)添加event设备的支持,我(vojtech@ucw.cz)非常乐意尽我所能提供帮助。这里我说明一下当前的进展状况,虽然还在不断地扩展中,但是基本的接口是不会改变而导致不兼容的问题:

你可以在/dev/input/eventX设备上使用阻塞,非阻塞的读操作,也可以用select()操作。你会在一次读取中返回一个完整的输入事件,它的结构如下:

struct input_event {

structtimeval time;

unsignedshort type;

unsignedshort code;

unsignedint value;

};

'time'字段是时间戳,它返回时间发生时的时间。关于type字段,EV_REL代表返回的是相对移动值,EV_KEY代表的是按键按下或释放,更多的类型定义可以参见:include/linux/input.h。

'code'字段是事件的编码,例如可以是REL_X或KEY_BACKSPACE,你也可以从include/linux/input.h中得到完整的列表。

'value'字段是该事件携带的参数值。可以是EV_REL事件的相对变化量,EV_ABS事件的一个新的绝对值(joysticks...),对于EV_KEY事件,该值是0代表按键释放,为1代表按键按下,为2代表自动重复。



 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分