注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小白的博客

嵌入式爱好者

 
 
 

日志

 
 

input输入子系统框架分析  

2012-09-13 10:41:02|  分类: 韦东山视频第二轮 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
注册handler:

static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};

static const struct file_operations evdev_fops = {
.owner = THIS_MODULE,
.read = evdev_read,
.write = evdev_write,
.poll = evdev_poll,
.open = evdev_open,
.release = evdev_release,
.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
.flush = evdev_flush,
.llseek = no_llseek,
};

input_register_handler(&evdev_handler);
     //根据次设备号,让数组中的某一项指向这个handler
     input_table[handler->minor >> 5] = handler;
     //将这个handler放入链表尾
     list_add_tail(&handler->node, &input_handler_list);
     //遍历input_dev_list链表,里面是注册的input_dev结构体
     list_for_each_entry(dev, &input_dev_list, node)z
          input_attach_handler(dev, handler);
               //根据handler.id_table与dev.id判断dev与handler是否匹配,如果匹配就返回handler.id_table
               input_match_device(handler, dev);
               //在匹配的情况下,调用handler->connect来使handler与dev建立连接
               handler->connect(handler, dev, id);
                      evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
                      evdev->handle.dev = input_get_device(dev);
                      evdev->handle.handler = handler;
                      input_register_handle(&evdev->handle);
                            struct input_handler *handler = handle->handler;
                            struct input_dev *dev = handle->dev;
                            //建立双向连接
                            list_add_tail_rcu(&handle->d_node, &dev->h_list);
                            //建立双向连接
                            list_add_tail_rcu(&handle->h_node, &handler->h_list);

我们看到在注册handler的时候,首先将使数组input_table中的某一项指向handler,接着将handler放入一个链表里面!然后就是遍历dev链表,寻找根handler匹配的设备,一旦发现了这个设备就调用handler->connect来使handler与dev建立连接。他们建立连接的方式是这样的:定义一个struct evdev结构体,它有一个成员handle,在handle与dev之间建立双向连接,同时在handle与handler之间建立双向连接!这样的话,我们可以通过此设备号找到handler,根据handler所指向的handle找到它所支持的dev!

注册dev:

input_register_device(input);
     //将dev放入链表
     list_add_tail(&dev->node, &input_dev_list);
     list_for_each_entry(handler, &input_handler_list, node)
           input_attach_handler(dev, handler);
下面就跟注册handler一样了,这里是遍历handler链表,来寻找与dev匹配的handler,一旦发现了就调用handler->connect来建立连接!

上面的框架分为两层,底层是dev文件和handler文件,这两个文件向上层文件,也就是input.c文件注册dev和handler。这样的话我们就可以自上而下地调用handler里的函数来处理dev了!具体我们是如何处理dev的呢?我们可以从input.c文件入手:

static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
.llseek = noop_llseek,
};

register_chrdev(INPUT_MAJOR, "input", &input_fops);//注册字符设备

当open文件的时候,会调用input_open_file,我们就从input_open_file来着手分析:
input_open_file
     //根据次设备号取出handler
     handler = input_table[iminor(inode) >> 5];
     //获取handler里面的fops
     new_fops = fops_get(handler->fops);
     //保存旧的file->f_op
     old_fops = file->f_op;
     //将新的file_operations结构体也就是handler里面的file_operations赋值给file->f_op
     file->f_op = new_fops;
     //执行handler里面的file_operations里面的open函数
     new_fops->open(inode, file);

这样一来的话,我们实际就是根据handler->fops结构体来操作具体的设备!

本节我们具体分析到这里,下一节会根据具体的实例我进一步阐明!
  评论这张
 
阅读(1830)| 评论(4)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017