您的位置首页>企业动态>

Linux输入子系统:事件的编码

导读大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux输入子系统:事件的编码问题。输入系统协议使用类型和编码的编解码器来表示输

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux输入子系统:事件的编码问题。

输入系统协议使用类型和编码的编解码器来表示输入设备的值,并使用它来通知用户空间中的应用程序。本文档解释了这些类型和代码,并指出何时以及如何使用它们。

单个硬件事件可以生成多个输入事件,每个输入事件包含单个数据项的新数据值。EV_SYN是一种特殊的事件类型,用于将同时生成的多个输入数据划分为多个数据包。在下面的描述中,术语事件指的是单个输入事件,包括类型、代码和参数值。

输入协议是基于状态的协议,只有当对应事件代码对应的参数值发生变化时,才会发送事件。但是状态是由Linux的输入子系统维护的,驱动程序不需要维护输入的状态,即使参数值不变,向输入子系统发送事件也不会有问题。用户可以使用linux/input.h中定义的EVIOCG*ioctls获取当前事件代码和参数状态。设备支持的报告事件类型也可以通过sysfs的类/输入/事件*/设备/功能/获得,设备的特性和总和可以通过类/输入/事件*/设备/属性获得。

内核版本:V3.4.10

事件类型:

类型对应于一组具有相同逻辑输入结构的代码。每种类型都有一组用于生成输入事件的可用代码。有关每种类型可用代码的详细信息,请参考代码部分的内容。

* EV_SYN:

-事件之间使用的拆分标志。事件可以在时间或空间上划分,如在多点触摸协议的例子中。

* EV_KEY:

-用于描述键盘、按键或类似键盘设备的状态变化。

* EV_REL:

-用于描述相对坐标轴上数值的变化,例如,鼠标向左移动5个单位。

* EV_ABS:

-用于描述相对坐标轴上数值的变化,例如描述触摸屏上坐标的数值。

* EV_MSC:

-使用此类型描述现有类型无法匹配的情况。

* EV_SW:

-用于描述具有两种状态的输入开关。

* EV_LED:

-用于控制设备的发光二极管灯的开启和关闭。

* EV_SND:

-用于向设备输出提示声音。

* EV_REP:

-用于自动自动重复设备。

* EV_FF:

-用于向输入设备发送强制反馈命令。(振动?)

* EV_PWR:

-尤其是电源开关的输入。

* EV_FF_STATUS:

-接收设备的强制反馈状态。

事件代码:

事件代码用于更准确地定义事件的类型。

EV_SYN:

EV_SYN事件没有具体的值定义,它们的用法只在发送evdev的事件字符串中定义。

* SYN_REPORT:

-当多个输入数据同时发生变化时,使用SYN_REPORT对这些数据进行打包和同步。例如,鼠标移动可以报告REL_X和REL_Y两个值,然后发出一个SYN_REPORT。下一次鼠标移动可以再次发出REL X和REL Y的两个值,然后跟随另一个SYN_REPORT。

* SYN_CONFIG:

TBD

* SYN_MT_REPORT:

-用于同步和分离触摸事件。更多信息,请参考内核文档:multi-touch-protocol.txt。

* SYN_DROPPED:

-用于指示evdev客户端事件队列的缓冲区溢出。客户端顶盖会忽略所有事件,包括下一个SYN_REPORT事件,并查询设备以获取其状态(使用EVIOCG* ioctls)。

EV_KEY:

EV_KEY事件采用KEY_或BTN_的形式。例如,KEY_A代表键盘上的A键。当按下一个键时,会发出一个键码和值为1的事件。释放密钥时,会发出一个值为0的事件。一些硬件在重复按键时会发出事件,这些事件的值为2。通常,KEY_用作键盘上的一个键,而BTN_用于切换按钮事件。

几个ev _ keys的代码有特殊意义:

* BTN _工具_:

-这些代码用于协调触摸板、平板电脑和触摸屏的输入。这些设备可以使用手指、笔或其他工具。当事件发生且检测到工具正在使用时,相应的BTN _工具_代码事件应将该值设置为1,当工具不再与输入设备交互时,该值应重置为0。所有触控板,何时

事件发生时,平板和触摸屏映泰至少使用一种BTN_TOOL_ code。

 * BTN_TOUCH:

BTN_TOUCH用于触摸接触事件。当一个输入工具被判定为有意义的物理接触时,这一特性的value值应该设为1。所谓有意义的物理接触可以是任何的接触,又或者是满足某种定义条件的接触。例如,触摸板可以当触摸的压力达到某一个值以上时才把value设为1,一个用笔的平板当笔划过但没有接触到平板的表面时,把BTN_TOOL_PEN的value设为1,而把BTN_TOUCH的value设为0.

 注意:为了配合一些老的传统mousedev模拟驱动程序可以工作,BTN_TOUCH必须作为一个同步帧的第一个evdevcode发出。

 注意:出于历史的原因,用户空间会把带有BTN_TOOL_FINGER和 BTN_TOUCH的触摸设备解释为触摸板,而类似的不带BTN_TOOL_FINGER的触摸设备则被解释为触摸屏。为了与目前的用户空间应用向后兼容,建议遵循这一区分原则。以后,这一区分方法将会失效,而会使用设备属性ioctl EVIOCGPROP(定义在linux/input.h)来传送设备的类型。

 * BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP:

- 这些codes表明一个,两个,三个和四个手指参与触摸板和触摸屏的操作。例如,如果用户使用两只手指在触摸板上试图滚动屏幕上的内容,在运动期间,应该发送value为1的BTN_TOOL_DOUBLETAP。注意的是所有的BTN_TOOL_codes 和 BTN_TOUCH code是用于正交目的的,一个触摸板由手指碰触时,应该在这两组中各生成一个事件code,至少在一个同步帧中带有一个value为1的BTN_TOOL_code。

 注意:出于历史原因,一些驱动会在同一个同步帧内发送多个value为1的上报手指数的codes,但是这一方法现在已经过时了(不再使用)。

 注意:在多手指触摸驱动中,应该使用input_mt_report_finger_count()函数来发出以上这些codes,详情请参看内核文档:mulTI-touch-protocol.txt。

 EV_REL:

----------

EV_REL事件描述了某种特性的相对变化量。例如,鼠标向左方移动了几个单位距离,但是他的绝对位置是未知的。如果我们可以知道绝对位置,那我们应该使用EV_ABS而不是EV_REL。

 下面这些属于EV_REL的codes有特别的意义:

 * REL_WHEEL, REL_HWHEEL:

  - 这两个codes用于对应的垂直方向和水平方向的滚轮。

 EV_ABS:

----------

EV_ABS事件描述了某一特性的绝对变化值,例如,触摸板会用它发出当前位置的绝对坐标值。

 以下这些属于EV_ABS的 codes有特殊的意义:

 * ABS_DISTANCE:

- 用来描述触摸工具离触摸表面的距离。这一事件应该只有当触摸工具在表面悬空滑过时发出,也就是说,在靠经触摸表面,但是BTN_TOUCH的value是0的时候。如果输入设备可以工作在3维坐标时,应该考虑使用ABS_Z会更好。

 * ABS_MT_:

- 用于描述多手指触摸输入设备。详情请参考内核文档:multi-touch-protocol.txt。

 EV_SW:

----------

EV_SW事件用于描述一个两态开关的状态,比如,SW_LID code用来指出笔记本电脑的屏幕已经合上了。

 当绑定一个设备或者从suspend状态中resuming回来,驱动程序必须上报开关的当前状态。从而保证设备,内核和用户空间的状态保持同步。

 在resume时,如果开关的状态和suspend之前相同,input子系统会这一重复的状态上报消息。驱动程序任何时候都无需记住开关的状态。

 EV_MSC:

----------

当事件不能用其它事件类型描述时,使用EV_MSC是将进行输入和输出事件的上报。

 EV_LED:

----------

EV_LED事件用来设置或查询设备上LED的状态。

 EV_REP:

----------

EV_REP 用来指出自动重复事件(autorepeating)。

 EV_SND:

----------

EV_SND用于对那些简单的发声设备发出发音指令。

 EV_FF:

----------

EV_FF事件用来初始化具有强制反馈能力的设备,并可以让这些设备发出反馈动作。

 EV_PWR:

----------

EV_PWR事件是一个特殊的类型,它是电源管理的专用事件,目前没有对它做出良好的定义,将来会完善这一事件。

 设备特性(Device properties):

=================

正常情况下,用户空间基于设备发出的数据(比如事件的types)来建立一个输入设备,当两个设备都发出相同的事件types时,这时设备特性就可以提供额外的识别信息。

 INPUT_PROP_DIRECT + INPUT_PROP_POINTER:

--------------------------------------

INPUT_PROP_DIRECT特性表明设备的坐标直接和屏幕坐标向对应(无需琐碎的转换操作,像缩放,反转,旋转等)。非直接输入设备则需要一些必要的变换,比如触摸板上绝对到相对的变换。典型的直接输入设备有:触摸屏,手写板;非直接输入设备有:触摸板,鼠标。

 INPUT_PROP_POINTER特性表明设备不是利用屏幕来获取输入信息,从而需要一个屏幕上的指针来跟踪用户的移动。典型的指针设备有:触控板,鼠标;非指针设备:触摸屏。

 如果INPUT_PROP_DIRECT或者 INPUT_PROP_POINTER都没有设置,设备将会被认为是未定义,它的类型需要按传统的方式利用事件的types推导出来。

 INPUT_PROP_BUTTONPAD:

--------------------

有些触摸板,它的按键位于触摸板的底部,这样按下触摸板会产生一次按键消息,对于这种设备,应该设置该特性。自2009年以来,配置这种触控板的notebooks和macbooks变多越来越普遍。

 最初,这种按键特性是在bcm5974的驱动中通过名字的版本字段来进行编码,为了向后兼容性,用户空间有必要按这两种方法都进行检查。

 INPUT_PROP_SEMI_MT:

------------------

在2008年至2011年之间,很多触摸板只能检测到多个接触点,但是不知道它们的独立位置,只是知道触点的数量和包围它们的一个矩形。对于这样的设备,应该设置这个半多点触摸特性。

 不同的设备,这个矩形可能包围所有的触控点,就像边界框一样,也可能只是包围了一部分触控点,比如最后的两个触控点。这种不确定性限制了这个矩形的用处,只是有些手势识别会对它进行分析。

 如果没有设置INPUT_PROP_SEMI_MT特性,该设备被假设为全多点触控设备。

 使用指引:

==========

以下的使用指引确保了单点触摸和多点触摸可以正常地工作,更详尽的信息请参考文档:multi-touch-protocol.txt。

 鼠标:

----------

当鼠标移动时,REL_{X,Y}必须被上报。主键被按下时,BTN_LEFT必须被上报。 其它按键按下时,BTN_{MIDDLE,RIGHT,4,5,etc.}应该被上报。鼠标上的滚轮滚动时,REL_WHEEL and REL_HWHEEL事件应该被上报。

 触摸屏:

----------

触摸发生时,必须要用ABS_{X,Y}上报触摸的位置。触摸有效时,BTN_TOUCH必须被上报,而不必用BTN_{MOUSE,LEFT,MIDDLE,RIGHT}来表明一次触摸事件。有可能的话,BTN_TOOL_事件也可以应该上报。

 对于新的硬件,应该设置INPUT_PROP_DIRECT特性。

 触控板:

----------

传统的触控板只是想上面鼠标所说那样上报相对位置信息即可。

 具备绝对位置信息的触控板需要通过ABS_{X,Y}上报触控点的位置信息。同样,触摸有效时应该上报BTN_TOUCH事件。如果支持多点触摸,应该通过BTN_TOOL_上报有效触摸的数量。

 对于新的硬件,应该设置INPUT_PROP_POINTER特性。

 Tablets:

----------

当笔或其它工具被有效检测后,必须上报BTN_TOOL_事件,必须用ABS_{X,Y}上报触控的位置信息,同时应该上报BTN_TOUCH事件。当触控工具上的按钮有效时,应该上报BTN_{STYLUS,STYLUS2}消息。除了BTN_{MOUSE,LEFT}以外,其它任意的按键消息都可以用于上报平板上的按键,对于没有标记的按键,BTN_{0,1,2,etc}是个不错的选择,避免使用有特别意义的按键:像BTN_FORWARD之类,除非设备上特别标明了就是这一按键。

 对于新的硬件,INPUT_PROP_DIRECT和 INPUT_PROP_POINTER都应该被设置。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。