Linux有许多子系统,usb、video、input...input 就是今天的主角--输入子系统的相关代码位于 driver目录下的input文件夹。 打开Kconifg文件,第12行开始有这样一段话 “Say Y here if you have any input device (mouse, keyboard, tablet,joystick, steering wheel ...)...”。 这段话有几层意思,鼠标、键盘、游戏手柄等等 这些都属于输入设备;这些输入设备的驱动都是 通过输入子系统来实现的(当然,这些设备也依 赖于usb子系统)。所有这些输入设备都各有不同,那么 输入子系统也就只能实现他们的共性, 差异性则由设备驱动来实现。差异性 又体现在哪里?最直观的就表现在这 些设备功能上的不同了。对于我们写 驱动的人来说在设备驱动中就只要使 用输入子系统提供的工具(也就是函 数)来完成这些“差异”就行了,其他 的则是输入子系统的工作。这个思想 不仅存在于输入子系统,其他子系统 也是一样。
既然完成“差异性”是我们写设备驱动的人的工 作,那么这些工作具体包含哪些内容
两个关键函数:
一、入口函数:buttons_init
二、出口函数:buttons_exit
一、buttons_init函数:在module_init的修饰下,buttons_init成为了驱动的入口函 数,对于我们 写驱动的人来说最重要的就是这个函数了。我们 做的大部分工作都是在这个函数内完成的。主要分为5个部分:
1、分配核心结构体input_dev。
2、3、填充结构体成员。
4、注册input_dev结构体
5、硬件相关的设置
实现方式:buttons_init
1、分配一个input_dev结构体 ==》buttons_dev = input_allocate_device();
如果你了解过更多的子系统你会发现,几 乎每一个子系统都有一个结构体需要你创
建,这个结构体里面有各种各样的成员,随 后会调用各种接口来填充这个结构体,最后
会把这个结构体注册进内核。
input_allocate_device这个函数不仅申请和初始化了相应的内存,同时还初始化了部分
input结构体成员。
有兴趣的可以看一下内核源码了解input结 构体每一个成员代表的含义。input结构体定
义位于include\linux\input.h
2、设置能产生哪类事件
set_bit(EV_KEY, buttons_dev->evbit);
set_bit(EV_REP, buttons_dev->evbit);
3、设置能产生这类事件中的哪些事件
set_bit(KEY_L, buttons_dev->keybit); /* 将这个按键按下当做键盘的 L 来处理,下同 */
set_bit(KEY_ENTER, buttons_dev->keybit);
4、注册input_dev结构体
input_register_device(buttons_dev);
“事件”是输入子系统的核心,首先要告诉 内核我这个设备能够产生哪些事件,比如按
键、绝对位移等等。然后还需要在按键产生 后手动将事件上报给内核。看完输入子系统
可以看看触摸屏驱动,你会对输入子系统有 更加深刻的了解。
5、硬件相关的操作
初始化、注册定时器
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
add_timer(&buttons_timer);
注册中断
request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
出口函数:buttons_exit
在module_exit的修饰下,buttons_exit成为了驱动的出口函 数,很多人对这个函数不重视,其实它很重要。
它完成了很多 清理工作,比如:
1、释放中断
2、卸载定时器
3、卸载input_dev
4、释放内存
不同的设备驱动在硬件设置这一部分会有 很大的区别,这需要你对驱动框架有一定的
了解。最好的办法还是去看内核自带的驱动 源码。
有人会问这个驱动用到了按键驱动,为什 么没有看到对GPIO的初始化,那是因为这个
工作被request_irq这个函数完成了,有兴趣 的同学可以看一下它的具体实现。
别忘了在入口函数最后一定要有返回值, 不然你的驱动会时好时坏。
buttons_exit
以上4步分别是由以下4个函数完成的:
free_irq(pins_desc[i].irq, &pins_desc[i]);
del_timer(&buttons_timer);
input_unregister_device(buttons_dev);
input_free_device(buttons_dev);
这几个函数从参数上看要比之前的函数简单, 虽然简单但是很重要。而且他们是一一对应的,
你用了什么函数来注册,就得调用对应的函数来 卸载;你用了什么函数来申请内存,就得调用对
应的函数来释放它。
Linux的这种思想也告诉我们一个道理:做事 要有始有终。
这些函数很重要:
函数input_allocate_device,用来分配并初始化内 存空间,同时初始化部分input_dev结构体成员,与
它对应的函数是input_free_device;
函数input_register_device,用于注册input_dev结 构体,与它对于的函数是input_unregister_device;
函数input_event用于上报事件;
函数del_timer用于卸载定时器。
阅读(1408) | 评论(0) | 转发(0) |