Linux/Android——input_handler之evdev

少年意气强不羁,虎胁插翼白日飞。这篇文章主要讲述Linux/Android——input_handler之evdev 相关的知识,希望能为你提供帮助。
本文转载自:
  在前文Linux/Android— — input子系统核心 (三)  中概括了总体的结构,以及介绍了input核心的职责,其中有说道注册input设备时会去匹配已有的事件处理器handler,
而这个handler也是存放在一个链表里面的,这里介绍下input子系统中的事件处理input_handler机制.
 
                                                                              撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42238377#t6
 
evdev:  /kernel/drivers/input下众多事件处理器handler其中的一个,可以看下源码/kernel/drivers/input/evdev.c中的模块init:
 
[objc]  view plain  copy  

  1. static  int  __init  evdev_init(void)   
  2. {   
  3.         return  input_register_handler(& evdev_handler);    
  4. }   

这个初始化就是往input核心中注册一个input_handler类型的evdev_handler,调用的是input.c提供的接口,input_handler结构前文有介绍,看下evdev_handler的赋值:
 
 
[objc]  view plain  copy  
  1. static  struct  input_handler  evdev_handler  =  {   
  2.         .event            =  evdev_event,   
  3.         .connect        =  evdev_connect,   
  4.         .disconnect  =  evdev_disconnect,   
  5.         .fops              =  & evdev_fops,   
  6.         .minor            =  EVDEV_MINOR_BASE,   
  7.         .name              =  "evdev",   
  8.         .id_table      =  evdev_ids,   
  9. };    

赋值各个函数指针!
 
 
 
input_register_handler:  可以看到上面的evdev handler 就是调用这个接口注册到input核心中的,同样evdev.c同目录下也还有其它的handler,有兴趣可以看看它们的init函数,都是会调用到这个接口去注册的.
 
[objc]  view plain  copy  
  1. /** 
  2.   *  input_register_handler  -  register  a  new  input  handler 
  3.   *  @handler:  handler  to  be  registered 
  4.   * 
  5.   *  This  function  registers  a  new  input  handler  (interface)  for  input 
  6.   *  devices  in  the  system  and  attaches  it  to  all  input  devices  that 
  7.   *  are  compatible  with  the  handler. 
  8.   */   
  9. int  input_register_handler(struct  input_handler  *handler)   
  10. {   
  11.         struct  input_dev  *dev;    
  12.         int  retval;    
  13.    
  14.         retval  =  mutex_lock_interruptible(& input_mutex);    
  15.         if  (retval)   
  16.                 return  retval;    
  17.    
  18.         INIT_LIST_HEAD(& handler-> h_list);    
  19.    
  20.         if  (handler-> fops  !=  NULL)  {   
  21.                 if  (input_table[handler-> minor  > >   5])  {   
  22.                         retval  =  -EBUSY;    
  23.                         goto  out;    
  24.                 }   
  25.                 input_table[handler-> minor  > >   5]  =  handler;   //给input.c定义的全局handler  数组赋值,evdev  handler的次设备号为64,这里除以32,赋值在input_table[2]   
  26.         }   
  27.    
  28.         list_add_tail(& handler-> node,  & input_handler_list);     //添加进handler  链表   
  29.    
  30.         list_for_each_entry(dev,  & input_dev_list,  node)      //同样遍历input_dev这个链表,依次调用下面的input_attach_handler去匹配input_dev,这个跟input_dev注册的时候的情形类似   
  31.                 input_attach_handler(dev,  handler);    
  32.    
  33.         input_wakeup_procfs_readers();    
  34.    
  35.   out:   
  36.         mutex_unlock(& input_mutex);    
  37.         return  retval;    
  38. }   
 
 
input核心中保存的handler数组:
 
[objc]  view plain  copy  
  1. static  struct  input_handler  *input_table[8];    
 
这是保存注册到input核心中的handler数组,因为在之前input注册的时候注册的字符设备主设备号为13.字符设备的次设备号为0~255,可以有256个设备,
这里后面会看到一个handler可以connect处理32个input设备,所以input体系中,最多拥有8个handler
 
这个匹配过程和上一篇中的过程是一样的,最后匹配上的话会调用匹配上的handler 中connect指针指向的函数.
 
另外可以注意的是evdev是匹配所有设备的,因为:
 
[objc]  view plain  copy  
  1. static  const  struct  input_device_id  evdev_ids[]  =  {   
  2.         {  .driver_info  =  1  },      /*  Matches  all  devices  */   
  3.         {  },                        /*  Terminating  zero  entry  */   
  4. };    

如果没有特定的handler添加进handler链表,那么在匹配的时候,只要有这个evdev的handler,最后都会匹配到evdev,这个具体可以去看看上篇的匹配过程.
 
我这边调试的是usb触摸屏,所以用的是evdev的handler,下面看下evdev的connect.
 
evdev_connect:  注册的evdev_handler中connect指向的函数为evdev_connect:
[objc]  view plain  copy  
  1. /* 
  2.   *  Create  new  evdev  device.  Note  that  input  core  serializes  calls 
  3.   *  to  connect  and  disconnect  so  we  don‘t  need  to  lock  evdev_table  here. 
  4.   */   
  5. static  int  evdev_connect(struct  input_handler  *handler,  struct  input_dev  *dev,   
  6.                           const  struct  input_device_id  *id)   
  7. {   
  8.         struct  evdev  *evdev;    
  9.         int  minor;    
  10.         int  error;    
  11.    
  12.         for  (minor  =  0;   minor  <   EVDEV_MINORS;   minor++)   
  13.                 if  (!evdev_table[minor])   
  14.                         break;    
  15.    
  16.         if  (minor  ==  EVDEV_MINORS)  {   
  17.                 pr_err("no  more  free  evdev  devices\n");    
  18.                 return  -ENFILE;    
  19.         }   
  20.    
  21. //  可以看到这里evdev  handler匹配连接好的设备都以evdev  类型存在这个evdev_table数组的,这个数组大小为32个,这就是我上面说到的,为什么只有8个handler   
  22.    
  23. //这里是判断evdev的32个位置中是否有空   
  24.    
  25.         evdev  =  kzalloc(sizeof(struct  evdev),  GFP_KERNEL);   //为上面定义的*evdev分配内存空间   
  26.         if  (!evdev)   
  27.                 return  -ENOMEM;    
  28.    
  29.         INIT_LIST_HEAD(& evdev-> client_list);   //以下都是对这个  evdev的初始化了   
  30.         spin_lock_init(& evdev-> client_lock);    
  31.         mutex_init(& evdev-> mutex);    
  32.         init_waitqueue_head(& evdev-> wait);    
  33.    
  34.         dev_set_name(& evdev-> dev,  "event%d",  minor);     //给这个evdev命名   
  35.         evdev-> exist  =  true;    
  36.         evdev-> minor  =  minor;       //  以minor为索引赋值   
  37.    
  38.         evdev-> handle.dev  =  input_get_device(dev);     //evdev中的handle变量的初始化  ,后面分析这个handle  ,这里面保存的就是已经匹配成功的input_dev  和  handler   
  39.         evdev-> handle.name  =  dev_name(& evdev-> dev);    
  40.         evdev-> handle.handler  =  handler;    
  41.         evdev-> handle.private  =  evdev;    
  42.    
  43.         evdev-> dev.devt  =  MKDEV(INPUT_MAJOR,  EVDEV_MINOR_BASE  +  minor);    
  44.         evdev-> dev.class  =  & input_class;    
  45.         evdev-> dev.parent  =  & dev-> dev;    
  46.         evdev-> dev.release  =  evdev_free;    
  47.         device_initialize(& evdev-> dev);    
  48.    
  49.         error  =  input_register_handle(& evdev-> handle);   //把这个evdev中初始化好的handle  注册到input核心中去,代表一个匹配成功的组合   
  50.         if  (error)   
  51.                 goto  err_free_evdev;    
  52.    
  53.         error  =  evdev_install_chrdev(evdev);     //把这个初始化好的evdev添加到上面说到过的evdev_table数组,以minor索引序号   
  54.         if  (error)   
  55.                 goto  err_unregister_handle;    
  56.    
  57.         error  =  device_add(& evdev-> dev);   //把这个device  添加到/sys/class/input/下面,所以我们可以看到/dev/input下面看到:event0~31  字样字符设备文件,这就是在上面命名的   
  58.         if  (error)   
  59.                 goto  err_cleanup_evdev;    
  60.    
  61.         return  0;    
  62.    
  63.   err_cleanup_evdev:   
  64.         evdev_cleanup(evdev);    
  65.   err_unregister_handle:   
  66.         input_unregister_handle(& evdev-> handle);    
  67.   err_free_evdev:   
  68.         put_device(& evdev-> dev);    
  69.         return  error;    
  70. }   



evdev:
这里的evdev变量的结构如下:
 
[objc]  view plain  copy  
  1. struct  evdev   
  2. {   
  3.         int  open;   //打开标志   
  4.         int  minor;   //次设备号   
  5.         struct  input_handle  handle;   //包含的handle   
  6.         wait_queue_head_t  wait;   //等待队列   
  7.    
  8.         struct  evdev_client  __rcu  *grab;   //强制绑定的evdev_client结构   
  9.         struct  list_head  client_list;   //evdev_client  链表,这说明一个evdev设备可以处理多个evdev_client,可以有多个进程访问evdev设备   
  10.    
  11.         spinlock_t  client_lock;   /*  protects  client_list  */   
  12.         struct  mutex  mutex;    
  13.         struct  device  dev;    
  14.         bool  exist;    
  15. };    


关于这个结构变量我的理解是抽象出来一个设备,代表一个input_dev与其匹配好的handler的组合(handle),可以看作提供给事件处理层的一个封装.
 
 
input_handle:
这个代表一个匹配成功的input dev和 handler组合,定义在input.h中,每个evdev中包含一个input_handle,并且注册到input核心中:
 
[objc]  view plain  copy  
  1. /** 
  2.   *  struct  input_handle  -  links  input  device  with  an  input  handler 
  3.   *  @private:  handler-specific  data 
  4.   *  @open:  counter  showing  whether  the  handle  is  ‘open‘,  i.e.  should  deliver 
  5.   *        events  from  its  device 
  6.   *  @name:  name  given  to  the  handle  by  handler  that  created  it 
  7.   *  @dev:  input  device  the  handle  is  attached  to 
  8.   *  @handler:  handler  that  works  with  the  device  through  this  handle 
  9.   *  @d_node:  used  to  put  the  handle  on  device‘s  list  of  attached  handles 
  10.   *  @h_node:  used  to  put  the  handle  on  handler‘s  list  of  handles  from  which 
  11.   *        it  gets  events 
  12.   */   
  13. struct  input_handle  {   
  14.    
  15.         voidvoid  *private;     //指向上面封装的evdev   
  16.    
  17.         int  open;    
  18.         const  charchar  *name;    
  19.    
  20.         struct  input_dev  *dev;       //input  设备   
  21.         struct  input_handler  *handler;     //  一个input的handler   
  22.    
  23.         struct  list_head        d_node;     //链表结构   
  24.         struct  list_head        h_node;    
  25. };    
 
input_register_handle:
  看看这个handle的注册,不要和handler搞混淆了,这不是一个概念~
[objc]  view plain  copy  
  1. /** 
  2.   *  input_register_handle  -  register  a  new  input  handle 
  3.   *  @handle:  handle  to  register 
  4.   * 
  5.   *  This  function  puts  a  new  input  handle  onto  device‘s 
  6.   *  and  handler‘s  lists  so  that  events  can  flow  through 
  7.   *  it  once  it  is  opened  using  input_open_device(). 
  8.   * 
  9.   *  This  function  is  supposed  to  be  called  from  handler‘s 
  10.   *  connect()  method. 
  11.   */   
  12. int  input_register_handle(struct  input_handle  *handle)   
  13. {   
  14.         struct  input_handler  *handler  =  handle-> handler;    
  15.         struct  input_dev  *dev  =  handle-> dev;     //取出两个成员   
  16.    
  17. ...   
  18.    
  19.         /* 
  20.           *  Filters  go  to  the  head  of  the  list,  normal  handlers 
  21.           *  to  the  tail. 
  22.           */   
  23.         if  (handler-> filter)   
  24.                 list_add_rcu(& handle-> d_node,  & dev-> h_list);    
  25.         else   
  26.                 list_add_tail_rcu(& handle-> d_node,  & dev-> h_list);    
  27.    
  28. //把这个handle的d_node  加到对应input_dev的h_list链表里面   
  29.    
  30. ...   
  31.    
  32.         list_add_tail_rcu(& handle-> h_node,  & handler-> h_list);    
  33.    
  34. //把这个handle的h_node  加到对应input_handler的h_list链表里面   
  35.    
  36. ...   
  37.    
  38. }   
 
这个注册是把handle 本身的链表加入到它自己的input_dev 以及 input_handler的h_list链表中,这样以后就可以通过h_list遍历到这个handle,
这样就实现了三者的绑定联系.
 
 
另外在evdev中还有个结构:
 
[objc]  view plain  copy  
  1. struct  evdev_client  {   
  2.         unsigned  int  head;     //buffer数组的索引头   
  3.         unsigned  int  tail;       //buffer数组的索引尾   
  4.         unsigned  int  packet_head;   /*  [future]  position  of  the  first  element  of  next  packet  */   
  5.         spinlock_t  buffer_lock;   /*  protects  access  to  buffer,  head  and  tail  */   
  6.         struct  wake_lock  wake_lock;    
  7.         bool  use_wake_lock;    
  8.         char  name[28];    
  9.         struct  fasync_struct  *fasync;         //异步通知函数   
  10.         struct  evdev  *evdev;     //包含一个evdev变量   
  11.         struct  list_head  node;     //链表   
  12.         unsigned  int  bufsize;    
  13.         struct  input_event  buffer[];       //input_event数据结构的数组,input_event代表一个事件,基本成员:类型(type),编码(code),值(value)   
  14. };    
 
 
这个结构会在evdev被打开的时候 创建,这里关于evdev的初始以及在input系统中承接作用暂时介绍到这里,
【Linux/Android——input_handler之evdev】前文  Linux/Android— — 输入子系统input_event传递 (二)  中有记录从设备驱动传递上来的event是怎么到input核心,然后接着往上传递的,接下来就是用到evdev传递了.下篇介绍.

    推荐阅读