Chinaunix首页 | 论坛 | 博客
  • 博客访问: 108133
  • 博文数量: 40
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 337
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-09 23:49
文章分类
文章存档

2016年(4)

2015年(2)

2014年(30)

2013年(4)

我的朋友

分类: LINUX

2016-08-20 17:07:41

   如上一篇《Linux input 子系统学习之开篇》所述,input.c文件是input子系统的核心,其目录是在lichee/linux-3.4/drivers/input/input.c。好的,我们现在就来分析一下这个文件吧。

  1、分析一个驱动,当然是从入口函数开始。

点击(此处)折叠或打开

  1. static int __init input_init(void)
  2. {
  3.     int err;

  4.     err = class_register(&input_class);
  5.     if (err) {
  6.         pr_err("unable to register input_dev class\n");
  7.         return err;
  8.     }

  9.     err = input_proc_init();
  10.     if (err)
  11.         goto fail1;

  12.     err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
  13.     if (err) {
  14.         pr_err("unable to register char major %d", INPUT_MAJOR);
  15.         goto fail2;
  16.     }

  17.     return 0;

  18.     fail2:    input_proc_exit();
  19.     fail1:    class_unregister(&input_class);

  20.     return err;
  21. }
  首先是注册一个input_class类,然后向系统申请设备号(主设备号是INPUT_MAJOR)。

 另外有个input_proc_init()
 

点击(此处)折叠或打开

  1. static int __init input_proc_init(void)
  2. {
  3.     struct proc_dir_entry *entry;

  4.     proc_bus_input_dir = proc_mkdir("bus/input", NULL);
  5.     if (!proc_bus_input_dir)
  6.         return -ENOMEM;

  7.     entry = proc_create("devices", 0, proc_bus_input_dir,
  8.              &input_devices_fileops);
  9.     if (!entry)
  10.         goto fail1;

  11.     entry = proc_create("handlers", 0, proc_bus_input_dir,
  12.              &input_handlers_fileops);
  13.     if (!entry)
  14.         goto fail2;

  15.     return 0;

  16.  fail2:    remove_proc_entry("devices", proc_bus_input_dir);
  17.  fail1: remove_proc_entry("bus/input", NULL);
  18.     return -ENOMEM;
  19. }
  很明显,这里会在proc下建立 bus/input,bus/input/devices,bus/input/handlers
 


2、下面,来看看 input_fops

     

点击(此处)折叠或打开

  1. static const struct file_operations input_fops = {
  2.     .owner = THIS_MODULE,
  3.     .open = input_open_file,
  4.     .llseek = noop_llseek,
  5. };
  

  很简单,里面主要的函数就是open函数,当上层去打开文件的时候,首先就会调用到这里的open函数。
 

点击(此处)折叠或打开

  1. static int input_open_file(struct inode *inode, struct file *file)
  2. {
  3.     struct input_handler *handler;
  4.     const struct file_operations *old_fops, *new_fops = NULL;
  5.     int err;

  6.     err = mutex_lock_interruptible(&input_mutex);
  7.     if (err)
  8.         return err;

  9.     /* No load-on-demand here? */
  10.     handler = input_table[iminor(inode) >> 5];
  11.     if (handler)
  12.         new_fops = fops_get(handler->fops);

  13.     mutex_unlock(&input_mutex);

  14.     /*
  15.      * That's _really_ odd. Usually NULL ->open means "nothing special",
  16.      * not "no device". Oh, well...
  17.      */
  18.     if (!new_fops || !new_fops->open) {
  19.         fops_put(new_fops);
  20.         err = -ENODEV;
  21.         goto out;
  22.     }

  23.     old_fops = file->f_op;
  24.     file->f_op = new_fops;

  25.     err = new_fops->open(inode, file);
  26.     if (err) {
  27.         fops_put(file->f_op);
  28.         file->f_op = fops_get(old_fops);
  29.     }
  30.     fops_put(old_fops);
  31. out:
  32.     return err;
  33. }
  先通过inode节点获取到次设备号,然后在input_table数组中,找到一个handler。找到handler后,获取其中的fops,并将此fops赋值给file->fops,最后实执行里面的open函数。

可以想象到,input_table这个数组里面都是input_handler,而这个数组肯定是另外的文件通过某种方式注册上去,然后把它放在数组里面的。说得这么明白,相信大家都猜测到了,这个当

然就是上
一篇所讲的input_register_handle函数了。
 
 好的,下一篇,我们就去看看这个神奇的input_register_handler函数。

阅读(1780) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~