【doc/input】input系统基础

来源:互联网 发布:royce巧克力淘宝假货 编辑:程序博客网 时间:2024/06/01 07:19

在我的印象中,input系统应该是将输入设备进行了抽象得到的一个统一的接口。常见的键盘,光鼠,轨迹球,传感器我们都可以归到input系统中来。

 

编写一个input的基本的步骤是:

1创建input device和driver

1.0 一个简单的例子

一个简单的例子是一个简单的I/O按键(BUTTON)。当一个按下或者释放的动都都会产生一个BUTTON_IRQ。

 

  

1.1 上面的例子是做什么的?

首先,他包含了<linux/input.h>这个文件,在input.h的文件中包含了input子系统中相关的接口函数。

__init函数在模块加载或者是内核启动的时候被调动,会申请到使用的资源

然后通过input_allocate_device()申请一个新的输入设备结构体并且设置输入的位域(bitfields)。这种方式会告诉其他的输入系统中的设备当前注册的是什么,会产生什么events或者是被这个输入设备接受什么。当前的例子设备智慧产生EV_KEY类型的事件,并且只有BTN_0 event编码。因此我们只要设置这两位,采用如下的方式:

,but with more than single bits the first approach tends to be shorter

注册输入设备结构体通过调用input_register_device(&button_dev);来实现。

这个会把button_dev结构体和input driver来关联起来,并且会调用device handler modules _connect函数来通知说有一个新的input device出现了。input_register_device()可能休眠,所以不能被中断或者是spinlock来调用。

 

当使用的时候,仅仅使用到的driver是button_interrupt().

当有任何一个按键中断检测到的时候,通过input_report_key()来上报给input_system.没有必要来检测按键是否是两个一样的值,这个检查的过程在input_report_* 函数内部检查了。(这里需要看看kernel中如何对同一个值的处理)

 

当我们发送了一个完整的report的时候,input_sync会通知到底是谁接收了这个event。(需要看代码看看如何接收的)

 

1.2 dev->open() & dev->close()

在当前的例子中驱动不停的重复轮训查看device,因为他没有中断并且轮询方式太浪费时间,或者如果device用了一个valuable resource(例如interrupt), 能够通过使用open和close这样的回调函数来知道什么时候他可以停止轮询或者是释放中断,什么是否必须恢复轮询或者是再次获得中断。如上所述,在驱动代码中应该变为如下的:

  

注意:input core会记录device的用户数量并且保证dev->open()仅仅是用户第一次连接设备时被调用,并且dev->close()被最后一个使用者离开时被调用。双方的回调必须是线性的,即先是open设备,使用完成后close设备。

 

1.3 基本的event类型

最简单的event类型是EV_KEY,被用作keys或者是buttons的event类型。通过input_report_key(struct input_dev *dev, int code, int value)来上报。

在linux/input.h中定义了允许使用的值(0~~KEY_MAX)。value是表示实际发生的是哪一个值,非零值表示有按键按下,零值表示按键松开。

 

除了EV_KEY,还有两个基本的event类型:EV_REL和EV_ABS。被用来上报设备的相对和绝对值。一个相对值比如说鼠标在X轴上的运动。鼠标会上报相对上个位置的相对值,因为在工作的时候并没有一个绝对的位置。绝对值事件一般是操纵杆和数字转换的设备,通常在系统中有实际的值。

 

上报EV_REL和上报EV_KEY是见是一样的,只要调用input_report_rel(struct input_dev *dev, int code, int value)。时间会产生一个非零值。

 

但是EV_ABS需要一些注意的地方。在调用input_register_device之前,不得不先填充设备所拥有的相关绝对数值。如果你的button device绝对值如下设置:

或者采用这个方式来声明:input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);

这个设定一般适用于操纵杆(joystick)的X坐标[0~255],and with a center flat position of size 8.

 

如果你不需要absfuzz和absflat,你可以设置为0,意思是所获得的值时准确的。(the thing is precise and alwasys returns to exactly the center position)

 

1.4 BITS_TO_LONGS(), BIT_WORD(), BIT_MASK()

这是三个在bitops.h中定义的宏。

  

1.5 id*和fields

在通过input device driver注册input device 的时候要注意dev->name要设定。顶一个自己喜欢的字串就好。

id fields包含BUS ID(PCI,USB,...),vendor ID 和device ID。bus ID在input.h文件中定义。vendor ID和device ID在pci_ids.h,usb_ids.h和类似的头文件中定义了。这些都需要在设备注册之前被设置。

idtype field存放的是input device的特定的信息。

id和名字通过evdev接口可以传递给用户空间。

 

1.6 keycode, keycodemax, keycodesize fields

keycode是一个对input system来说映射scancodes的数组。keycode max是数组的大小。

用户空间可以询问和修改当前的keycode mapping通过EVIOCGKEYCODE和EVIOCSKEYCODE ioctls。

 

1.7 dev->getkeycode() 和 dev->setkeycode()

getkeycode和setkeycode()允许驱动获得不是通过keycode/keycodesize/keycodemax提供的值;

 

1.8 key 自动重复

是input.c模块负责。硬件的自动重复没有使用,因为大多数的设备不存在这种情况,反而出现这种情况应该是出问题了。

 

1.9 其他的event type,处理输出的event

其他的还有类似的 /

EV_LED-来作为键盘灯的

EV_SND-键盘蜂鸣器

这些也同key event类似,但是他们是作为输出的event。如果你的设备上需要这些类型,你就必须设定这些位。例如:

  

 这个回调例程被中断或者是一个BH,所以不能有休眠存在,也不能太长时间才完成。当然这里考虑的也都是中断需要处理的事情。

 

这一篇是对doc下的input系统自己的简单笔记,下面会做一个实际的input的驱动来仔细分析,并且看看input core是如何工作的。

原创粉丝点击