嵌入式技术
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代表自动重复。
全部0条评论
快来发表一下你的评论吧 !