输入子系统

Posted -glb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了输入子系统相关的知识,希望对你有一定的参考价值。

输入子系统框架:

drivers/input/input.c

 

input_init  > err = register_chrdev(INPUT_MAJOR, "input", &input_fops);

static const struct file_operations input_fops = 
      .owner = THIS_MODULE,
      .open = input_open_file,  
      .llseek = noop_llseek,
  ;
问:怎样读按键呢?

input_open_file
 handler = input_table[iminor(inode) >> 5];
  new_fops = fops_get(handler->fops);
  file->f_op = new_fops;  err = new_fops->open(inode, file)

app: read > .......>file->f_op->read
input_table[]数组由谁构造?
input_table数组是在
input_register_handler函数中被构造的。那么input_register_handler函数又是被谁调用的?
搜索一下,发现是由evdev.c,keyboard.c, mousedev.c等这几个文件调用,它们通过调用input_register_handler函数向上注册handler。

注册input_handler
input_register_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_dev,调用input_attach_handler
              input_attach_handler(dev, handler);//根据input_handler中的id_table,判断能否支持这个设备。


注册输入设备:
input_register_device
//放入链表
list_add_tail(&dev->node, &input_dev_list);
//对于每一个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_dev还是input_handler,都调用input_attach_handler进行两两匹配。


 

 1 static const struct file_operations input_fops = 
 2     .owner = THIS_MODULE,
 3     .open = input_open_file,  //在该结构体中,只有一个input_open_file这个函数,这个函数只是起一个中转作用,在里面肯定还做了其他事情。
 4     .llseek = noop_llseek,
 5 ;
 6 
 7 static int __init input_init(void)
 8 
 9     int err;
10 
11     err = class_register(&input_class);
12     if (err) 
13         pr_err("unable to register input_dev class\n");
14         return err;
15     
16 
17     err = input_proc_init();
18     if (err)
19         goto fail1;
20 
21     err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
22     if (err) 
23         pr_err("unable to register char major %d", INPUT_MAJOR);
24         goto fail2;
25     
26 
27     return 0;
 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 
 7     err = mutex_lock_interruptible(&input_mutex);
 8     if (err)
 9         return err;
10 
11     /* No load-on-demand here? */
   /*次设备号右移5位,即相当于除以32,以这个数为下标,从input_table数组中取出一项,赋给handler.*/
12 handler = input_table[iminor(inode) >> 5]; 13 if (handler)/*handler中有一个file_operation结构体,把handler中的file_operation结构体取出来赋给new_fops.*/ 14 new_fops = fops_get(handler->fops); 15 16 mutex_unlock(&input_mutex); 17 18 /* 19 * That‘s _really_ odd. Usually NULL ->open means "nothing special", 20 * not "no device". Oh, well... 21 */ 22 if (!new_fops || !new_fops->open) 23 fops_put(new_fops); 24 err = -ENODEV; 25 goto out; 26 27 28 old_fops = file->f_op; 29 file->f_op = new_fops; /*打开的这个文件的f_op= 新的fops*/ 30 31 err = new_fops->open(inode, file);/*调用新的fops中的open函数,以后如果读的话,就是用到了handler里面的新的fops*/ 32 if (err) 33 fops_put(file->f_op); 34 file->f_op = fops_get(old_fops); 35 36 fops_put(old_fops); 37 out: 38 return err;
 1 struct input_handler 
 2 
 3     void *private;
 4 
 5     void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 6     bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 7     bool (*match)(struct input_handler *handler, struct input_dev *dev);
 8     int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
 9     void (*disconnect)(struct input_handle *handle);
10     void (*start)(struct input_handle *handle);
11 
12     const struct file_operations *fops;
13     int minor;
14     const char *name;
15 
16     const struct input_device_id *id_table;
17 
18     struct list_head    h_list;
19     struct list_head    node;
20 ;

 

input_table[]数组是在input_register_handler这个函数中构造的。

 1 int input_register_handler(struct input_handler *handler)
 2 
 3     struct input_dev *dev;
 4     int retval;
 5 
 6     retval = mutex_lock_interruptible(&input_mutex);
 7     if (retval)
 8         return retval;
 9 
10     INIT_LIST_HEAD(&handler->h_list);
11 
12     if (handler->fops != NULL) 
13         if (input_table[handler->minor >> 5]) 
14             retval = -EBUSY;
15             goto out;
16         
17         input_table[handler->minor >> 5] = handler;
18     
19 
20     list_add_tail(&handler->node, &input_handler_list);
21 
22     list_for_each_entry(dev, &input_dev_list, node)
23         input_attach_handler(dev, handler);
24 
25     input_wakeup_procfs_readers();
26 
27  out:
28     mutex_unlock(&input_mutex);
29     return retval;

input_register_handler这个函数又是被谁调用的呢?选取evdev.c进行分析。

 1 static struct input_handler evdev_handler = 
 2     .event        = evdev_event,
 3     .connect    = evdev_connect,
 4     .disconnect    = evdev_disconnect,
 5     .fops        = &evdev_fops,   /*这个fops以前是由我们自己构造,现在内核已经帮我们做好了。*/
 6     .minor        = EVDEV_MINOR_BASE,
 7     .name        = "evdev",
 8     .id_table    = evdev_ids,//表示该handler能够支持哪些输入设备。如果能够支持的话,就调用connect函数。
 9 ;
10 
11 static int __init evdev_init(void)
12 
  /*input_register_handler会将evdev_handler向上注册,通过上面的分析可知,就是把这个evdev_handler放入Input_table数组
中,以次设备号右移5位为下标。这样的话,在input_open_file中获得的handler就是evdev_handler这个结构体,new_fops就是evdev_handler
结构体中的fops
*/ 13 return input_register_handler(&evdev_handler); 14 

 

以上是关于输入子系统的主要内容,如果未能解决你的问题,请参考以下文章

linux输入子系统

OpenHarmony 源码解析之多模输入子系统(事件派发流程)

Linux 输入子系统原理理解(原创)

输入子系统

Linux驱动开发之输入子系统

linux 的 输入子系统 与 平台设备系统个人理解