内核input子系统分析
打开/driver/input/input.c 这就是input代码的核心
找到
static int __init input_init(void)
{
err = class_register(&input_class);注册一个类,注册后会在sys/class出现input目录.
......
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);注册一个主设备号为13的input设备,
}
打开input_fops
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
};
只有一个往内核中注册一个open函数,那么read,write,等函数也应该注册,则应该在input_open_file中注册,
分析static int input_open_file(struct inode *inode, struct file *file)
{
struct input_handler *handler = input_table[iminor(inode) >> 5];把input_table数组中的某一个成员赋值给handler,这个下面会具体分析
if (!handler || !(new_fops = fops_get(handler->fops)))获取handler中的file_operations结构体
return -ENODEV;
old_fops = file->f_op;
file->f_op = new_fops;
err = new_fops->open(inode, file);打开这个handler->fops->open函数
}
问1:input_table[iminor(inode) >> 5]这个数组是有谁来赋值的
int input_register_handler(struct input_handler *handler)
{
INIT_LIST_HEAD(&handler->h_list);
input_table[handler->minor >> 5] = handler;把handler赋值给input_table数组,位置以此设备号除以32
list_add_tail(&handler->node, &input_handler_list);把这个handler的节点加入input_handler_list链表中
list_for_each_entry(dev, &input_dev_list, node)一次遍历input_dev_list链表中的input_dev设备,然后对传进的handler进行匹配,寻找input_dev_list中有没有支持这个handler的设备
input_attach_handler(dev, handler);具体的匹配方法接下来会详细分析
}
问2:那谁来调用input_register_handler,也就是handler从哪里来
搜索得到
Evbug.c (drivers\input):106: return input_register_handler(&evbug_handler);
Evdev.c (drivers\input):745: return input_register_handler(&evdev_handler);
Input.c (drivers\input):1193:int input_register_handler(struct input_handler *handler)
Input.c (drivers\input):1219:EXPORT_SYMBOL(input_register_handler);
Input.h (include\linux):1130:int input_register_handler(struct input_handler *);
Joydev.c (drivers\input):647: return input_register_handler(&joydev_handler);
Keyboard.c (drivers\char):1367: error = input_register_handler(&kbd_handler);
---- = input_register_handler(&kbd_handler); Matches (1 in 1 files) ----
Keyboard.c (drivers\char):1367: error = input_register_handler(&kbd_handler);
那就打开keyboard.c以它为例详细分析这个是怎么注册的
static struct input_handler kbd_handler = {
.event = kbd_event,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,
.name = "kbd",
.id_table = kbd_ids,
};
int __init kbd_init(void)
{
error = input_register_handler(&kbd_handler);
}
其实就是吧kbd_handler这个结构体传递给input_table;
再总结一下:
int __init kbd_init(void)->error = input_register_handler(&kbd_handler)
{ input_table[handler->minor >> 5] = handler;
list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler);
}
分析如何匹配的 input_attach_handler(dev, kbd_hander)
{
id = input_match_device(handler->id_table, dev);如果匹配成功返回一个id
error = handler->connect(handler, dev, id);然后会根据返回的id找到设备和kbd_handler进行连接,这个连接connect函数就是kbd_handler->kbd_connect
}
接下来详细分析input_match_device
{
for (; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
continue;
.......
//针对handler->id->flags,比较不同的类型,如果比较成功
//进入下面的宏比较,否则进入下一个id
MATCH_BIT(evbit, EV_MAX);
.............
//安位比较所支持事件的类型,只有所有未匹配成功才能成功返回,否则进入下一id
return id;
}
return NULL;
}
如果匹配成功就会进入连接,分析kbd_connect
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
{
struct input_handle *handle;定义一个input_hanlde指针
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);分配input_handle结构体空间
handle->dev = dev;使分配的handle中的dev指向和handler匹配的input_dev
handle->handler = handler;使handle中的handler指向和input_dev匹配的input_handler
handle->name = "kbd";
error = input_register_handle(handle);注册这个新分配的handle;
error = input_open_device(handle);
}
继续分析
int input_register_handle(struct input_handle *handle)
{
struct input_handler *handler = handle->handler;
list_add_tail(&handle->d_node, &handle->dev->h_list); 把handle->d_node挂在input_dev->h_list上
list_add_tail(&handle->h_node, &handler->h_list);吧handle->h_node挂载handler->h_list上
这样就可以通过input_handler中的h_list找到handle,然后通过handle->dev找到匹配的input_dev
同样也可以通过input_dev中的h_list找到handl,然后通过handle->handler找到匹配的input_handler
这样input_handler,input
if (handler->start)
handler->start(handle);
return 0;
}继续分析
int input_open_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
int err;
handle->open++;//handle的打开计数加1,注意和evdev的open的区别
if (!dev->users++ && dev->open)
err = dev->open(dev);//如果此input-dev没有进程引用,并且定义了open
//方法,就调用open方法,
if (err) //retval=1说明,没有成功打开,
handle->open--;
}
总结connect的作用就是根据匹配成功的input_dev和input_handler,创建一个新的结构体input_handle,然后把结构体中的dev和handler分配指向input_dev和input_handler
这样的话,就可以通过input_handle这个结构体把input_dev和input_hanlder连接起来;
static int __init input_init(void)->err = register_chrdev(INPUT_MAJOR, "input", &input_fops)->input_fops-> input_open_file
{struct input_handler *handler = input_table[iminor(inode) >> 5];
if (!new_fops->open) {
fops_put(new_fops);
return -ENODEV;
}
err = new_fops->open(inode, file);这个open函数就是kbd_handler中的fops中的open;这个keyboard中没有初始化fops;
}
对于注册输入设备:
input_register_device
// 放入链表
list_add_tail(&dev->node, &input_dev_list);
// 对于每一个input_handler,都调用input_attach_handler
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler); // 根据input_handler的id_table判断能否支持这个input_dev
input_attach_handler
id = input_match_device(handler->id_table, dev);
error = handler->connect(handler, dev, id);
和input_handler类似,大家自行分析
内核input子系统分析的更多相关文章
- Linux input子系统分析
输入输出是用户和产品交互的手段,因此输入驱动开发在Linux驱动开发中很常见.同时,input子系统的分层架构思想在Linux驱动设计中极具代表性和先进性,因此对Linux input子系统进行深入分 ...
- linux kernel input 子系统分析
Linux 内核为了处理各种不同类型的的输入设备 , 比如说鼠标 , 键盘 , 操纵杆 , 触摸屏 , 设计并实现了一个对上层应用统一的试图的抽象层 , 即是Linux 输入子系统 . 输入子系统的层 ...
- input子系统分析
------------------------------------------ 本文系本站原创,欢迎转载! 转载请注明出处:http://ericxiao.cublog.cn/ -------- ...
- linux内核input子系统解析【转】
转自:http://emb.hqyj.com/Column/Column289.htm 时间:2017-01-04作者:华清远见 Android.X windows.qt等众多应用对于linux系统中 ...
- input子系统分析之三:驱动模块
内核版本:3.9.5 本节将以even handler来分析设备的注册和打开的过程,分析之前不妨回顾一下上节介绍的数据结构. 结合前两节分析可知,input子系统分为3层,最上一层是event han ...
- input子系统分析之一:框架
内核版本:3.9.5 输入设备总类繁杂,包括按键,键盘,触摸屏,鼠标,摇杆等等,它们本身都是字符设备,不过内核为了能将这些设备的共性抽象出来,简化驱动的开发,建立了一个Input子系统.Input子系 ...
- input子系统分析(转)
转自:http://www.linuxidc.com/Linux/2011-09/43187.htm 作者:作者:YAOZHENGUO2006 Input子系统处理输入事务,任何输入设备的驱动程序都可 ...
- input子系统分析之二:数据结构
内核版本:3.9.5 1. input_dev,用来标识输入设备 struct input_dev { const char *name; const char *phys; const char * ...
- linux内核输入子系统分析
1.为何引入input system? 以前我们写一些输入设备(键盘.鼠标等)的驱动都是采用字符设备.混杂设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可 ...
随机推荐
- shell中$0,$?,$!等变量意义
变量说明: $$ #Shell本身的PID(ProcessID) $! #Shell最后运行的后台Process的PID $? #最后运行的命令的结束代码(返回值) $- ...
- JQuery_元素属性操作
除了对元素内容进行设置和获取,通过jQuery 也可以对元素本身的属性进行操作,包括获取属性的属性值.设置属性的属性值,并且可以删除掉属性. <script type="text/ja ...
- windows下安装python模块
如何在windows下安装python模块 1. 官网下载安装包,比如(pip : https://pypi.python.org/pypi/pip#downloads) pip-9.0.1.tar. ...
- 浅谈HTTPS以及Fiddler抓取HTTPS协议
最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...
- 关于Application.Lock和Lock(obj) 转 http://www.cnblogs.com/yeagen/archive/2012/03/01/2375610.html
关于Application.Lock和Lock(obj) Posted on 2012-03-01 15:28 billpeng 阅读(3498) 评论(3) 编辑 收藏 1.Application. ...
- Sphinx Search 学习 (一)
参考资料一:(中文)http://www.coreseek.cn/docs/coreseek_3.2-sphinx_0.9.9.html (官方)http://sphinxsearch.com/doc ...
- Codeforces Round #374 (Div. 2) D. Maxim and Array
传送门 分析:其实没什么好分析的.统计一下负数个数.如果负数个数是偶数的话,就要尽量增加负数或者减少负数.是奇数的话就努力增大每个数的绝对值.用一个优先队列搞一下就行了. 我感觉这道题的细节极为多,非 ...
- javascript无线端的判断
经常在工作中要求网页做这样的处理判断:针对无线端的网页,我们需要兼容一种异于PC端的网页效果. 如下代码就可以实现无线端的判断: var mobs = ['android', 'ipad', 'ipo ...
- MHA+Atlas+mysql一主一从开启gtid安装配置与实验
各节点架构 (说明:生产环境有两个节点可以组成一套完整集群,我是测试环境,因此对于manager以及atlas和binlog server都是单点,如果生产环境,相应的将manager以及atlas和 ...
- php简写表达式,&& or || 缩写条件语句
有时候学的多了, 好多小细节 都忘了 ,比如 简单的表达式, 三元表达式 ?:; $aa or $bb 表达式 等等! 写一些简单的表达式,备忘! php用&&和||缩写条件语句 ...