基于嵌入式Linux系统的键盘驱动设计

时间:2013-04-23来源:网络

首先设置输入设备的功能,input_set_capability(sim_key,EV_KEY,KEY_A)函数完成键盘A键的输入使能,类似可完成B~X共24个按键的输入使能。然后设置键盘的码表。该键盘包含20个按键,码表可表示为:static unsigned char sim_keycode[24]={KEY_A,KEY_B,KEY_C,KEY_D,KEY_E,KEY_F,KEY_G,KEY_H,KEY_I,KEY_J,KEY_K,KEY_L,KEY_M,KEY_N,KEY_O,KEY_P,KEY_Q,KEY_R,KEY_S,KEY_T,KEY_U,KEY_V,KEY_W,KEY_X)。当相应键按下时,码表中的键值将被作为键盘码上报到用户空间的进程。初始化工作完成之后,调用函数input_register_device(sim_kb)向内核注册输入设备。
由于键盘设备的输入是异步的,可能会在任何时间得到按键事件,所以需向内核申请中断以保证对键盘输入的实时响应。中断函数完成键盘的扫描操作,并上报输入事件到用户进程,是整个驱动模块的功能主体。然而使用中断会遇到一个问题,在键盘的扫描过程中,按键的每次按下和抬起都会有10~20 ms的毛刺抖动存在,会将用户的一次按键操作误当作几次按键来处理。所以为了获取稳定的按键信息,必须要想办法去掉这种抖动。去毛刺的一种常见的方法是在注册输入设备时定义一个定时器timer,当触发中断时先关闭I/O中断,然后启动定时器,等跳过毛刺抖动以后再去调用扫描程序得到键值,并重新打开中断。按键事件被发送到input子系统核心后通知给用户进程,从而实现查键过程。

4 基于input子系统的事件传递机制
实现底层驱动程序与用户进程通信的最主要的函数是input_event(struct input_dev * dev,unsigned int type,unsigned int code,int value),也是input输入子系统的核心,其实现机制如下。
Linux系统在启动过程中会向系统核心注册input_handler,一般将其称为handler处理器,表示对输入事件的具体处理,input_handler为输入设备的功能实现了一个接口。在执行input_register_device注册输入设备的时候,会自动将input_dev结构与系统中已注册的input_
handler进行遍历匹配。与对应的input_handler成功匹配后,Linux内核自动创建evdev结构体来表示输入事件设备,该结构中包含了input _handle等字段,作为连接input_dev与input_handler的媒介。其中Linux内核中与键盘设备匹配的input_handler代码为:
static struct input_handler evdev_handler={
.event=evdev_event,
.connect=evdev_connect,
.disconnect=evdev_disconnect,
.fops=&evdev_fops,
.minor=EVDEV_MINOR_BASE,
.name=“evdev”,
.id_table=evdev_ids,
};
evdev_event函数为事件处理函数,输入设备所上报的事件通过evdev_handler中的evdev_event函数包装成input_event标准输入格式,并存放在evdev下的evdev_list缓冲区中,该结构代码如下:
struct input_event{
struct timeval time; //事件发生的时间
__u16 type; //事件类型
__u16 code; //子事件
__s32 value; //事件发生的相关值
};
用户进程读取键盘事件时即会按照此种特定格式进行。值得注意的是,当读取事件为鼠标输入时,需要先后读取X轴坐标和Y轴坐标两种数据,以完成完整的读取操作。
在Linux系统中,所有的外设都是通过虚拟文件系统向应用程序提供接口,所以每个具有独立功能的外设在Linux系统中都对应着相应的设备文件。同时,在内核中代表设备文件的结构体包含了实现该设备功能的特定操作函数。
完成驱动模块的安装之后,Linux系统会在/devr目录下自动创建输入事件设备文件,本文中该设备名为event0。用户进程打开对应的输入事件设备文件event0,即可执行相应的文件操作,如rcad、ioctl等。文件操作函数最终要进入内核,并调用存储在事件设备结构体中的
evdev_handler.evdev_fops操作函数集完成对应的文件操作。
e.JPG
例如用户进程在执行rcad操作时,会调用内核中evdev_fops->evdev_rcad函数,先判断当前输入事件设备缓冲区中是否有待读取的input _event事件。若缓冲区中无按键事件,进程则放入等待队列进行睡眠,直到有按键事件产生并保存到缓冲区后,将睡眠进程唤醒,调用copy_ to_user复制函数完成输入事件从内核空间到用户空间的拷贝,从而实现读取操作。

结语
通过以上分析可以得出,键盘设备所产生的输入事件以input子系统为传递介质,并通过虚拟文件系统接口得以通知用户进程。本文从键盘的驱动开发出发,呈现了较为完整的输入事件由内核空间传递到用户空间进程的过程,对于驱动开发者了解底层驱动的机制和更加有效地设计驱动模块有着较为重要的意义。经过测试,该键盘具有良好的响应特性,并实现了所预期的功能。

1 2

关键词: SN74HC164 矩阵键盘 驱动控制模块 Linux内核 input子系统

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版