输入子系统驱动

在这里插入图片描述

输入子系统程序编写:
APP: open, read, write. ----> 对应提供驱动程序的读写等函数。

驱动: drv_open, drv_read, drv_write

硬件

代码步骤:
1,确定主设备号:
可以自已确定,也可让内核分配。
2,要构造驱动中的“open,read,write 等”
是将它们放在一个“file_operations”结构体中.
File_operations==> .open, .read, .write, .poll 等。
这里"open"函数会去配置硬件的相关引脚等,还有注册中断。
3, register_chrdev 注册字符设备构造的“file_operations”结构:
使用这个 file_operations 结构体。是把这个结构放到内核的某个以此设备的“主设备号”为
下标的数组中去。
Register_chrdev(主设备号,设备号, file_operations 结构) .
4,入口函数:
调用这个“register_chrdev()”函数。内核装载某个模块时,会自动调用这个“入口函数”。
5,出口函数

实例编写:
①,参考: linux-2.6.22.6\drivers\input\keyboard\gpio_keys.c

②,先包含头文件 和 初略框架:
头文件:
在这里插入图片描述
初略代码框架:
在这里插入图片描述
③,入口函数的框架:
在这里插入图片描述
3.1,定义 input_dev 结构变量:
在这里插入图片描述
3.2,用函数来分配这个 input_dev *buttons_dev 变量:
分配“input_dev”结构体是“input_allocate_device()”,则这里自已民写分配一个“input_dev”
结构是用此函数。
在这里插入图片描述
正常情况下要判断此“Input_dev”结构是否分配成功,但这里为简化代码不予判断。但
一般都会成功的。
3.3,自已的操作:用“set_bit()”设置某一位:
在这里插入图片描述
上面用 set_bit()设置了 evbit 数组中的“EV_KEY”按键类事件。但按键有 26 个字母还有其
他符号按键,那么能产生这一类“EV_KEY”里的哪些按键事件?要产生哪些按键事件,要看具体的原理图:
在这里插入图片描述
而现在要写一个通用的“按键”驱动程序。在为这里开发板上只有 4 个键,要是有很多就可
能设置成普通键盘那样了。但现在单板上只有 4 个按键,则这里定义成“L,S,Enter 和左 shift
键”。
3.4,能产生这类操作里的哪些事件
在这里插入图片描述
3.5,注册“input_dev”结构:
在这里插入图片描述
注册了“input_dev”结构体之后,就会把这里具体的“buttons_dev”设备结构体挂到内核
的“input_dev”输入设备的链表中去。接着就从右边的“input_handler”链表中一个个取出
来具体的 id_table[]与“buttons_dev”进行比较。若是能匹配说明“input_handler”结构中的
“id_table”能支持这个“input_dev”设备“buttons_dev”,这时支持后,就会接着调用
“input_handler”结构中的“.connect”函数。
到了“.connect”建立连接这个过程时,就会创建一个新的结构“input_handle” ,这个结
构中有两个成员“.handler”(具体处理方式)和“.dev”(具体设备)。“.dev”指向左边的设
备层,“.handle”指向右边的“处理方式”层。这个“input_handle”结构会分别放到左边设
备层的“input_dev”这个结构成员“h_list”链表中,也挂到处理方式层的“input_handler”
结构的成员“h_list”链表中去。
3.6,硬件相关操作的准备工作:
首先,定义一个结构体“pin”脚描述。
在这里插入图片描述
接着,定义 4 个按键的具体引脚定义和按键值。
在这里插入图片描述
3.7,硬件的相关操作:
首先,注册 4 个中断:
在这里插入图片描述
上面为减少代码,判断“request_irq()”的返回值代码省略去了。
其次,中断处理函数的编写、定义“定时器”和“中断函数”:
在这里插入图片描述
接着,定时器初始化 和 定时器初始化函数定义::
在这里插入图片描述
定时器初始化函数“buttons_timer_function()”的编写:
“确定按键值” —>“唤醒应用程序” 或 “发送信号”。
这里只需要上报"按键值":上报事件— input_event 上报事件.
在“硬件相关的操作”中,有数据产生时用“input_event()”上报事件:
—>input_event()函数会从“input_device->h_list"链表中找到结构“input_handle”中的
“handle”成员,以此最终找到右边纯软件的“处理方式”层中的“input_handler”结构,
调用此结构中的“.event”函数。
3.8,buttons_timer_function功能函数的完成
上报事件原型:void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
参 1, struct input_dev *dev: input_dev 结构变量指针。这里为“buttons_dev” .
参 2, unsigned int type:哪类事件。这里为“EV_KEY”按键类事件。
参 3, unsigned int code:哪个值。这里是指哪一个按键,为“pin_desc *pindesc->key_val”
(KEY_L,KEY_S,KEY_ENTER,KEY_LEFTSHIFT) .
参 4,int value: 这里表示“按下”或是“松开”。
上报事件后,还有一个上报同步事件:
原型: void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)。
事件类:是同步类事件“EV_SYN”。
后面 code 形参“SYN_REPORT”和 value 形参值为“0”时表示这个事件已经上报完了。
在这里插入图片描述
④,出口函数:
4.1,添加两个头文件:
在这里插入图片描述
4.2,释放中断:
原型: void free_irq(unsigned int irq, void *dev_id)
参 1, unsigned int irq:中断号。
参 2, void dev_id: pin 脚描述结构数组组元。
在这里插入图片描述
4.3,消除注册到内核定时器目录上的内容:
名称: del_timer()
功能: 消除注册到内核定时器目录上的内容
原型:
#include <linux/timer.h>
int del_timer (struct timer_list timer);
说明:
从内核定时器目录消除结构体。内核定时器的目录为连接 list 结构,不是消除结构体的内容,而是修改结构体的连接信息,因此该函数不参与结构体变量的分配和消除。
变量:
timer : 将要消除的内核定时器注册结构体的数据地址。
返回值 :
正常运行返回 1 ,否则返回 0 。
在这里插入图片描述
附1:假设驱动程序装载好了,按下一个“按键”后,那么中断处理函数“buttons_irq()”就会被调用。在中断处理函数中,是先将哪一个按键“dev_id”记录下来(“irq_pd = (struct pin_desc )dev_id;”),然后修改定时器(“mod_timer(&buttons_timer, jiffies+HZ/100);”将它 10ms“jiffies+HZ/100”再启动“&buttons_timer”这个函数),假设 10ms 时间到了,那么“定时器处理”函数(buttons_timer_function)初调用。
附2:buttons_timer_function()定时器处理函数的工作:
读引脚值(pinval = s3c2410_gpio_getpin(pindesc->pin);),再确实是松开还是按下:
if (pinval)
{
/
松开:最后一参数 int value,0 表示松开, 1 表示按下
/
input_event(buttons_dev, pindesc->EV_KEY, 0);
}
else
{
/
按下 */
input_event(buttons_dev, pindesc->EV_KEY, 1);
}
附3:input_event()上报事件
input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)。看最后一行:
list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);
对输入设备的“h_list” 链表里的每一个成员(就是中间作连接的只有".dev"和".handler"
成员的“input_handle”结构)。把这些“input_handle”结构取出来到“handle” .
若它们是打开时,就调用这个具体“input_handle”结构变量的成员“.handler”的“event()”
函数。以前需要自已构造“open,read,write”等函数,而现在是输入子系统框架中定义好的。
小结:
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值