登录
注册
一键加入QQ群
友善之臂官方网站
首 页
联系我们
淘宝店铺
维基教程
资料下载
搜索帖子!
NanoPC-T2
Core4418
NanoPC-T3 Plus
Core6818
NanoPi-M4B
NanoPC-T4
NanoPC-T6
NanoPi-NEO
NanoPi-NEO Core
NanoPi-NEO Air
NanoPi-M1 Plus
NanoPi-Duo2
NanoPi-NEO3
核心板:
Smart210
Tiny210
Smart4418
Smart6818
SOM-RK3399V2
CM3588(新品)
路由器:
R1
R1S
R2S
R2S Plus
R2C Plus
R4S
R5S
R5C
R6C
R6S
热门版块:
Linux技术交流区
友善之臂最新动态
开发板实战手册及教程
NanoPi 玩家交流区
ROM发布区
Android技术交流区
默认风格
用户中心首页
编辑个人资料
查看个人资料
好友列表
用户权限查看
积分管理
积分转换
特殊组购买
收藏夹
我的主题
基本统计信息
到访IP统计
管理团队
管理统计
在线统计
会员排行
版块排行
帖子排行
个人首页
我的收藏
好友近况
友善之家
Linux技术交流区
【分享】对输入子系统分析总结
友友粉丝快线
开发板销售中心
嵌入式最新资讯
友善之臂最新动态
友善之臂官方客服中心
开发板实战手册及教程
应用方案和定制开发
NanoPi 交流与讨论
NanoPi 玩家交流区
ROM发布区
硬软DIY及开发
嵌入式交流与讨论
Android技术交流区
Linux技术交流区
U-boot技术交流区
WinCE技术交流区
Ubuntu技术交流区
裸机程序和微型OS
OpenWRT讨论区
开发板硬件讨论区
相关资料下载及使用技巧
站点服务
二手交易区
我的论坛我的贴
站务管理与公告
上一主题
下一主题
«
1
2
»
Pages: 1/2 Go
新 帖
主题 : 【分享】对输入子系统分析总结
复制链接
|
浏览器收藏
|
打印
wuweidong
畅游在知识的海洋...
级别: 论坛版主
作者资料
发送短消息
加为好友
UID:
33629
精华:
4
发帖:
554
金钱:
3075 两
威望:
615 点
贡献值:
5 点
综合积分:
1188 分
注册时间:
2010-12-03
最后登录:
2015-09-22
楼主
发表于: 2011-11-15 21:51
只看楼主
|
小
中
大
【分享】对输入子系统分析总结
管理提醒:
本帖被 xoom 执行置顶操作(2012-03-14)
图片:
这两天学习了看了韦东山的第二期视频关于输入子系统部分,做了相关记录,分享给大家
在drivers/input/input.c中:
进入模块入口函数input_init :
复制代码
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
而input_fops只有open和llseek函数:
复制代码
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
.llseek = noop_llseek,
};
那么没有read函数的话该怎么读数据呢?
进入 input_open_file函数:
复制代码
struct input_handler *handler;//定义一个input_handler指针
handler = input_table[iminor(inode) >> 5];//根据传入文件的次设备号从
//input_table中提取出一个input_handler
if (handler)
new_fops = fops_get(handler->fops);//从input_handler中提取出new_fops
file->f_op = new_fops;//将new_fops赋值给当前文件的file_operations
err = new_fops->open(inode, file);
经过这些操作后,当app再来调用read,write,open等函数时,最终都会调用到file->f_op 中的read,write,open等函数。
那么input_open_file函数中的input_table 又是从何而来的呢?
搜索代码可知,
在input.c的input_register_handler函数中构造了input_table:
复制代码
if (handler->fops != NULL) {
if (input_table[handler->minor >> 5]) {
retval = -EBUSY;
goto out;
}
//给input_table中的 第handler->minor >> 5项赋值
input_table[handler->minor >> 5] = handler;
}
又是谁在调用input_register_handler呢?
搜索内核可知:
evdev.c,tsdev.c,joydev.c,keyboard.c,mousedev.c等文件调用了 input_register_handler,我们以evdev.c为例
在drivers/input/evdev.c中:
进入模块入口函数evdev_init:
复制代码
return input_register_handler(&evdev_handler);
evdev_handler的定义如下:
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,//前面所用到的 new_fops指的就是这里定义的的fops
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
这里需要插入的讲解一下输入子系统的架构!如图:
当通过input_register_device注册一个input_dev设备或者通过 input_register_handler注册一个input_handler时,input_dev与input_handler 会进行匹配,如何匹配?
在input_handler中有一个id_table,里面包含的就是这个input_handler能处 理的input_dev,当input_handler与input_dev匹配成功的话,则会调用 input_handler里 的connect函数。
下面我们来看下input_register_device和input_register_handler分别做了什么:
复制代码
input_register_device:
//将刚注册的input_dev放入input_dev_list链表
list_add_tail(&dev->node, &input_dev_list);
/*对 input_handler_list中的每一个input_handler都调用
*input_attach_handler(dev, handler);这个函数,来查看是否有input_handler *合适该input_dev
*/
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
input_register_handler:
//将刚注册的input_handler放入input_table中
input_table[handler->minor >> 5] = handler;
//将刚注册的input_handler放入 input_handler_list链表中
list_add_tail(&handler->node, &input_handler_list);
/*对 input_dev_list 中的每一个input_dev都调用
*input_attach_handler(dev, handler);这个函数,来查看是否有input_dev合 *适该input_handler
*/
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
由此可以看出,无论是先注册input_handler还是先注册input_dev最终 都 会调用来input_attach_handler(dev, handler);来进行两两匹配。现在我们来看看 input_attach_handler是如何将input_handler和input_dev进行匹配的。
在input_attach_handler函数中:
/*先进行匹配,匹配的依据就是input_handler中的id_table与
*input_dev中的id里的信息是否相同
*/
id = input_match_device(handler, dev);
/*再调用input_handler中的connect函数完成连接,具体如何连接,
*需要分析connect函数
*/
error = handler->connect(handler, dev, id);
我们以evdev.c中的 input_handler结构中的connect函数为例,分析connect 函数做了些什么。
在evdev_connect函数中:
复制代码
/*分配一个evdev结构体,该结构体中含一个input_handle结构
*注意:不同于input_handler结构
*/
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
/*设置evdev结构中的input_handle
*@input_handle的dev变量指向input_dev结构
*@input_handle的handler变量指向input_handler结构
*/
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev;
/*向内核注册input_handle*/
error = input_register_handle(&evdev->handle);
下面我们来看注册 input_register_handle做了些什么:
复制代码
/*将input_handle添加到input_dev中的h_list链表中
*以后当input_dev需要使用对应的input_handler时就可以通过自身的 *h_list链表找到input_handle,从而找到匹配的input_handler。
*/
list_add_tail_rcu(&handle->d_node, &dev->h_list);
/*将input_handle添加到input_handler中的h_list链表中,
*以后当input_handler需要使用对应的input_dev时就可以通过自身的
*h_list链表找到input_handle,从而找到匹配的input_dev
*/
list_add_tail_rcu(&handle->h_node, &handler->h_list);
对于输入设备,我们知道一般需要读取其数据,那么经过上述的一些列动作 后又是如何读取到数据的呢?我们来看下evdev.c中的input_handler中的fops
中的read函数:
在evdev_read函数中:
复制代码
//如果没有数据且nonblock的话,则EAGAIN
if (client->head == client->tail && evdev->exist &&
(file->f_flags & O_NONBLOCK))
return -EAGAIN;
//否则,睡眠
retval = wait_event_interruptible(evdev->wait,client->head != client->tail || ! evdev->exist);
既然有睡眠,那么何时被唤醒,搜索代码。
在evdev_event函数中:
//唤醒
wake_up_interruptible(&evdev->wait);
evdev_event是input_handler中的成员,当有数据可读(如触摸屏被按下,按键 被按下)时,event函数会被调用。而event函数是怎么被调用到的?这就得看设 备层了,设备层的驱动做了如下工作:
<1>在中断函数中确定判断发生了什么事件,并且相应的值是多少
<2>通过input_event()函数上报事件
<3>通过input_sync()函数表明上报结束
分析input_event函数我们就可以知道input_handler中的event函数是如何被调用到的了。
在input_event中,调用了input_handle_event函数,在input_handle_event函数 中调用了input_pass_event函数;
在input_pass_event函数中:
复制代码
struct input_handler *handler;
/*从注册的input_dev的h_list中将input_handle一个个拿出来*/
list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
if (!handle->open)
continue;
//如果该input_handle被打开,则该input_handle->input_handler即为可 //处理该input_dev的handler
handler = handle->handler;
if (!handler->filter) {
if (filtered)
break;
/*最终调用到event函数*/
handler->event(handle, type, code, value);
} else if (handler->filter(handle, type, code, value))
filtered = true;
}
最后,回归到如何写符合输入子系统框架的驱动程序,四个步骤:
<1>分配一个input_dev结构体
<2>设置input_dev
<3> 注册input_dev
<4>在中断函数中上报事件
输入子系统记录完毕
估计看到这的人已经疯了
转载请注明来至wuweidong:
http://www.100ask.net/showtopic-3567.aspx
[ 此帖被wuweidong在2012-01-28 10:37重新编辑 ]
好好学习,天天鲁管
顶端
回复
引用
分享
gt945
级别: 侠客
作者资料
发送短消息
加为好友
UID:
6350
精华:
2
发帖:
110
金钱:
895 两
威望:
486 点
贡献值:
2 点
综合积分:
260 分
注册时间:
2009-05-29
最后登录:
2016-10-11
1楼
发表于: 2011-11-15 22:05
只看该作者
|
小
中
大
应该加精
顶端
回复
引用
分享
wuweidong
畅游在知识的海洋...
级别: 论坛版主
作者资料
发送短消息
加为好友
UID:
33629
精华:
4
发帖:
554
金钱:
3075 两
威望:
615 点
贡献值:
5 点
综合积分:
1188 分
注册时间:
2010-12-03
最后登录:
2015-09-22
2楼
发表于: 2011-11-16 10:28
只看该作者
|
小
中
大
比较难看懂
好好学习,天天鲁管
顶端
回复
引用
分享
ux_linux
级别: 新手上路
作者资料
发送短消息
加为好友
UID:
62356
精华:
0
发帖:
4
金钱:
20 两
威望:
4 点
贡献值:
0 点
综合积分:
8 分
注册时间:
2012-01-26
最后登录:
2017-09-13
3楼
发表于: 2012-01-27 12:54
只看该作者
|
小
中
大
楼主,韦东山的视频怎么样?我看过国嵌的,讲得太浅了
顶端
回复
引用
分享
kasim
*無鈳取玳
级别: 论坛版主
作者资料
发送短消息
加为好友
QQ联系
UID:
27
精华:
12
发帖:
5398
金钱:
40120 两
威望:
17929 点
贡献值:
71 点
综合积分:
11036 分
注册时间:
2008-01-16
最后登录:
2014-11-22
4楼
发表于: 2012-01-27 14:28
只看该作者
|
小
中
大
回 3楼(ux_linux) 的帖子
小马过河的道理不会不知道吧
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
顶端
回复
引用
分享
wuweidong
畅游在知识的海洋...
级别: 论坛版主
作者资料
发送短消息
加为好友
UID:
33629
精华:
4
发帖:
554
金钱:
3075 两
威望:
615 点
贡献值:
5 点
综合积分:
1188 分
注册时间:
2010-12-03
最后登录:
2015-09-22
5楼
发表于: 2012-01-27 17:18
只看该作者
|
小
中
大
回 3楼(ux_linux) 的帖子
国嵌和韦东山的都挺好。
国嵌的入门快,韦东山的视频比较深入,都可以看一看
好好学习,天天鲁管
顶端
回复
引用
分享
wuweidong
畅游在知识的海洋...
级别: 论坛版主
作者资料
发送短消息
加为好友
UID:
33629
精华:
4
发帖:
554
金钱:
3075 两
威望:
615 点
贡献值:
5 点
综合积分:
1188 分
注册时间:
2010-12-03
最后登录:
2015-09-22
6楼
发表于: 2012-01-27 17:25
只看该作者
|
小
中
大
回 4楼(kasim) 的帖子
确实像kasim说的一样,你自己下载来看看就一清二楚了
好好学习,天天鲁管
顶端
回复
引用
分享
ux_linux
级别: 新手上路
作者资料
发送短消息
加为好友
UID:
62356
精华:
0
发帖:
4
金钱:
20 两
威望:
4 点
贡献值:
0 点
综合积分:
8 分
注册时间:
2012-01-26
最后登录:
2017-09-13
7楼
发表于: 2012-01-29 14:55
只看该作者
|
小
中
大
终于在网上找到韦东山的视频,驱动方面还没看,但是裸板程序绝对的讲得最好!
贡献一下:
http://dl.dbank.com/c03o1ebwlo
顶端
回复
引用
分享
lgbfa
级别: 侠客
作者资料
发送短消息
加为好友
UID:
47357
精华:
0
发帖:
76
金钱:
390 两
威望:
78 点
贡献值:
0 点
综合积分:
152 分
注册时间:
2011-05-21
最后登录:
2017-09-13
8楼
发表于: 2012-02-02 09:42
只看该作者
|
小
中
大
我快看疯了
顶端
回复
引用
分享
huang301
级别: 侠客
作者资料
发送短消息
加为好友
UID:
42613
精华:
0
发帖:
121
金钱:
2261 两
威望:
124 点
贡献值:
0 点
综合积分:
242 分
注册时间:
2011-04-09
最后登录:
2016-10-11
9楼
发表于: 2012-02-17 13:42
只看该作者
|
小
中
大
第二期讲的好不好啊
顶端
回复
引用
分享
上一主题
下一主题
«
1
2
»
Pages: 1/2 Go
友善之家
Linux技术交流区
http://www.aiothome.net
访问内容超出本站范围,不能确定是否安全
继续访问
取消访问