在Linux中,按键、触摸屏、鼠标等等输入设备都可以依靠输入子系统提供的接口函数来实现他们的设备驱动,在输入子系统中,系统已经完成了这些输入设备的共性,所以根据子系统提供的接口,只需要完成各自的独特性即可完成一个输入设备的设备驱动。
Linux中,输入子系统由设备驱动层、核心层、事件处理层这三层组成。设备驱动层讲底层输入设备的响应转化为标准的输入事件,事件处理层就为应用程序提供统一的设备访问接口来跟底层交互数据,核心层则是连接驱动层和事件处理层的桥梁。
在输入子系统中重要的结构体就是input_dev结构体,它是我们展开工作的主题,每一个输入设备都对应着这样的一个结构体,部分重要内容如下:
unsigned long evbit[NBITS(EV_MAX)];//支持的事件类型
unsigned long keybit[NBITS(KEY_MAX)];//支持的按键位图
unsigned long relbit[NBITS(REL_MAX)];//支持相对坐标的位图
unsigned long absbit[NBITS(ABS_MAX)];//支持绝对坐标的位图
unsigned long mscbit[NBITS(MSC_MAX)];
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
unsigned long swbit[NBITS(SW_MAX)];
写一个符合输入子系统框架的驱动一般由下列几个步骤:
分配一个input_dev结构体
设置input_dev结构体(设置事件等等)
注册
硬件的相关操作
相关的API:
(1).分配一个输入设备
struct input_dev *input_allocate_device(void)//该函数为struct input_dev结构体分配内存,成功返回一个执行分配的结构体,失败返回NULL
(2).注册一个输入设备
input_register_device(struct input_dev *dev)//该函数用于向输入子系统核心注册一个输入设备
3).释放struct input_dev结构体占用的内存
input_free_device(struct input_dev *dev)
(4).注销设备对应的输入设备结构体
input_unregister_device(struct input_dev *dev)
(5).告诉子系统它支持哪些事件
set_bit(int nr, volatile void * addr)
(6).执行报告的事件
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
void input_sync(struct input_dev *dev)//报告同步事件
例子:由jz2440上的按键实现键盘输出(部分代码):
测试:
加载驱动,在终端执行:
cat /dev/tty1
按:s2,s3,s4
就可以得到ls
或者:
exec 0</dev/tty1 /*将dev/tty1设备输入代替标准输入*/
然后可以使用按键来输入
现象:
按下按键2 3 4
显示: ls