Linux/Android——input子系统核心

春衣少年当酒歌,起舞四顾以笑和。这篇文章主要讲述Linux/Android——input子系统核心 相关的知识,希望能为你提供帮助。
本文转载自:http://blog.csdn.net/jscese/article/details/42123673
  之前的博客有涉及到linux的input子系统,这里学习记录一下input模块.
input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备,
常用的输入设备也就是鼠标,键盘,触摸屏。
稍微细分一点整个输入体系,就是  硬件驱动层,input核心中转层,事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分别提供接口.
之前有分析usbtouchscreen的驱动,也就是硬件驱动部分,这里简单记录一下input核心中转处理 input.c .
 
                                                                              撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42123673
input_init:  源码位于/kernel/drivers/input/input.c ,模块初始调用口subsys_initcall(input_init),
由kernel启动的时候由kernel_init— — > do_basic_setup(); — — > do_initcalls调用到,这个启动逻辑,后续有机会去学习一下,
这里首先调用到初始函数:
 
[objc]  view plain  copy  

  1. static  int  __init  input_init(void)   
  2. {   
  3.         int  err;    
  4.    
  5.         err  =  class_register(& input_class);   //注册input  class,可在/sys/class下看到对应节点文件   
  6.         if  (err)  {   
  7.                 pr_err("unable  to  register  input_dev  class\n");    
  8.                 return  err;    
  9.         }   
  10.    
  11.         err  =  input_proc_init();   //proc  fs的下的一些初始操作,函数原型在input.c,可查看/proc/bus/input   
  12.         if  (err)   
  13.                 goto  fail1;    
  14.    
  15.         err  =  register_chrdev(INPUT_MAJOR,  "input",  & input_fops);   //  注册input字符设备,主节点为INPUT_MAJOR==13,可以去input_fops里看注册函数,注册到/dev/input   
  16.         if  (err)  {   
  17.                 pr_err("unable  to  register  char  major  %d",  INPUT_MAJOR);    
  18.                 goto  fail2;    
  19.         }   
  20.    
  21.         return  0;    
  22.    
  23.   fail2:        input_proc_exit();    
  24.   fail1:        class_unregister(& input_class);    
  25.         return  err;    
  26. }   

这就是最开始的初始化过程了.
 
 
可以看下注册方法函数:
 
[objc]  view plain  copy  
  1. static  const  struct  file_operations  input_fops  =  {   
  2.         .owner  =  THIS_MODULE,   
  3.         .open  =  input_open_file,   
  4.         .llseek  =  noop_llseek,   
  5. };    
 
这里面关注open file方法即可,后面分析。
 
input.c中还有很多其它的接口以及全局数据,后面陆续联通,先从设备驱动最先调用到的注册 input_register_device
 
input_register_device:[objc]  view plain  copy  
  1. /** 
  2.   *  input_register_device  -  register  device  with  input  core 
  3.   *  @dev:  device  to  be  registered 
  4.   * 
  5.   *  This  function  registers  device  with  input  core.  The  device  must  be 
  6.   *  allocated  with  input_allocate_device()  and  all  it‘s  capabilities 
  7.   *  set  up  before  registering. 
  8.   *  If  function  fails  the  device  must  be  freed  with  input_free_device(). 
  9.   *  Once  device  has  been  successfully  registered  it  can  be  unregistered 
  10.   *  with  input_unregister_device();   input_free_device()  should  not  be 
  11.   *  called  in  this  case. 
  12.   */   
  13.    
  14. int  input_register_device(struct  input_dev  *dev)   
  15. {   
  16.         static  atomic_t  input_no  =  ATOMIC_INIT(0);        
  17.                 //这个原子变量,代表总共注册的input设备,每注册一个加1,因为是静态变量,所以每次调用都不会清零的   
  18.         struct  input_handler  *handler;    
  19.         const  charchar  *path;    
  20.         int  error;    
  21.    
  22.         __set_bit(EV_SYN,  dev-> evbit);     //EN_SYN  这个是设备都要支持的事件类型,所以要设置   
  23.    
  24.         /* 
  25.           *  If  delay  and  period  are  pre-set  by  the  driver,  then  autorepeating 
  26.           *  is  handled  by  the  driver  itself  and  we  don‘t  do  it  in  input.c. 
  27.           */   
  28.                 //  这个内核定时器是为了重复按键而设置的   
  29.         init_timer(& dev-> timer);    
  30.         if  (!dev-> rep[REP_DELAY]  & &   !dev-> rep[REP_PERIOD])  {   
  31.                 dev-> timer.data  =  (long)  dev;    
  32.                 dev-> timer.function  =  input_repeat_key;    
  33.                 dev-> rep[REP_DELAY]  =  250;    
  34.                 dev-> rep[REP_PERIOD]  =  33;    
  35.                 //如果没有定义有关重复按键的相关值,就用内核默认的   
  36.         }   
  37.    
  38.         if  (!dev-> getkeycode)   
  39.                 dev-> getkeycode  =  input_default_getkeycode;    
  40.         if  (!dev-> setkeycode)   
  41.                 dev-> setkeycode  =  input_default_setkeycode;    
  42.                 //以上设置的默认函数由input核心提供   
  43.         dev_set_name(& dev-> dev,  "input%ld",   
  44.                           (unsigned  long)  atomic_inc_return(& input_no)  -  1);    
  45.                 //设置input_dev中device的名字,这个名字会在/class/input中出现   
  46.         error  =  device_add(& dev-> dev);    
  47.                 //将device加入到linux设备模型中去   
  48.         if  (error)   
  49.                 return  error;    
  50.    
  51.         path  =  kobject_get_path(& dev-> dev.kobj,  GFP_KERNEL);    
  52.         printk(KERN_INFO  "input:  %s  as  %s\n",   
  53.                 dev-> name  ?  dev-> name  :  "Unspecified  device",  path  ?  path  :  "N/A");    
  54.         kfree(path);    
  55.                 //这个得到路径名称,并打印出来   
  56.         error  =  mutex_lock_interruptible(& input_mutex);    
  57.         if  (error)  {   
  58.                 device_del(& dev-> dev);    
  59.                 return  error;    
  60.         }   
  61.    
  62.         list_add_tail(& dev-> node,  & input_dev_list);    
  63.                 //  将新分配的input设备连接到input_dev_list链表上   
  64.         list_for_each_entry(handler,  & input_handler_list,  node)   
  65.                 input_attach_handler(dev,  handler);    
  66.                 //遍历input_handler_list链表,配对  input_dev  和  input_handler   
  67.                 //input_attach_handler  这个函数是配对的关键,下面将详细分析   
  68.         input_wakeup_procfs_readers();    
  69.                 //  和proc文件系统有关,暂时不考虑   
  70.         mutex_unlock(& input_mutex);    
  71.    
  72.         return  0;    
  73.       }   



可以看到前面都是一些初始设置,加入到input.c 的全局input_dev 链表里面,同时下面就行匹配对应handler的时候需要遍历 handler 链表:
 
[objc]  view plain  copy  
  1. static  LIST_HEAD(input_dev_list);    
  2. static  LIST_HEAD(input_handler_list);    

可以看到用到了一个list_for_each_entry,  刚开始看到还没看懂,这是一个宏定义,原型是在/kernel/include/linux/list.h:
 
 
[objc]  view plain  copy  
  1. /** 
  2.   *  list_for_each_entry        -        iterate  over  list  of  given  type 
  3.   *  @pos:        the  type  *  to  use  as  a  loop  cursor. 
  4.   *  @head:        the  head  for  your  list. 
  5.   *  @member:        the  name  of  the  list_struct  within  the  struct. 
  6.   */   
  7. #define  list_for_each_entry(pos,  head,  member)                                \   
  8.         for  (pos  =  list_entry((head)-> next,  typeof(*pos),  member);         \   
  9.                   & pos-> member  !=  (head);           \        //就是个for循环,跳出条件遍历了一遍,又回到链表头   
  10.                   pos  =  list_entry(pos-> member.next,  typeof(*pos),  member))   
 
 
 
input_attach_handler(dev, handler)则是匹配这个要注册dev的handler:
 
[objc]  view plain  copy  
  1. static  int  input_attach_handler(struct  input_dev  *dev,  struct  input_handler  *handler)   
  2. {   
  3.         const  struct  input_device_id  *id;    
  4.         int  error;    
  5.    
  6.         id  =  input_match_device(handler,  dev);   //返回匹配的id,类型是struct  input_device_id   
  7.         if  (!id)   
  8.                 return  -ENODEV;    
  9.    
  10.         error  =  handler-> connect(handler,  dev,  id);   //< span> < span  class="comment"> //配对成功调用handler的connect函数,这个函数在事件处理器中定义,主要生成一个input_handle结构,并初始化,还生成一个事件处理器相关的设备结构< /span> < /span>    
  11.         if  (error  & &   error  !=  -ENODEV)   
  12.                 pr_err("failed  to  attach  handler  %s  to  device  %s,  error:  %d\n",   
  13.                               handler-> name,  kobject_name(& dev-> dev.kobj),  error);    
  14.    
  15.         return  error;    
  16. }   
 
 
可以看下匹配 id 的结构:
 
[objc]  view plain  copy  
  1. struct  input_device_id  {   
  2.    
  3.         kernel_ulong_t  flags;    
  4.    
  5.         __u16  bustype;    
  6.         __u16  vendor;    
  7.         __u16  product;    
  8.         __u16  version;    
  9.    
  10.         kernel_ulong_t  evbit[INPUT_DEVICE_ID_EV_MAX  /  BITS_PER_LONG  +  1];    
  11.         kernel_ulong_t  keybit[INPUT_DEVICE_ID_KEY_MAX  /  BITS_PER_LONG  +  1];    
  12.         kernel_ulong_t  relbit[INPUT_DEVICE_ID_REL_MAX  /  BITS_PER_LONG  +  1];    
  13.         kernel_ulong_t  absbit[INPUT_DEVICE_ID_ABS_MAX  /  BITS_PER_LONG  +  1];    
  14.         kernel_ulong_t  mscbit[INPUT_DEVICE_ID_MSC_MAX  /  BITS_PER_LONG  +  1];    
  15.         kernel_ulong_t  ledbit[INPUT_DEVICE_ID_LED_MAX  /  BITS_PER_LONG  +  1];    
  16.         kernel_ulong_t  sndbit[INPUT_DEVICE_ID_SND_MAX  /  BITS_PER_LONG  +  1];    
  17.         kernel_ulong_t  ffbit[INPUT_DEVICE_ID_FF_MAX  /  BITS_PER_LONG  +  1];    
  18.         kernel_ulong_t  swbit[INPUT_DEVICE_ID_SW_MAX  /  BITS_PER_LONG  +  1];    
  19.    
  20.         kernel_ulong_t  driver_info;    
  21. };    
 
 
 
有两个函数input_match_device 以及 下面的 connect需要了解:
 
input_match_device: 
[objc]  view plain  copy  
  1. static  const  struct  input_device_id  *input_match_device(struct  input_handler  *handler,   
  2.                                                         struct  input_dev  *dev)   
  3. {   
  4.         const  struct  input_device_id  *id;    
  5.         int  i;    
  6.    
  7.         for  (id  =  handler-> id_table;   id-> flags  ||  id-> driver_info;   id++)  {   
  8.    
  9.                 if  (id-> flags  &   INPUT_DEVICE_ID_MATCH_BUS)    //匹配总线id   
  10.                         if  (id-> bustype  !=  dev-> id.bustype)   
  11.                                 continue;    
  12.    
  13.                 if  (id-> flags  &   INPUT_DEVICE_ID_MATCH_VENDOR)    //匹配生产商id   
  14.                         if  (id-> vendor  !=  dev-> id.vendor)   
  15.                                 continue;    
  16.    
  17.                 if  (id-> flags  &   INPUT_DEVICE_ID_MATCH_PRODUCT)  //匹配产品id   
  18.                         if  (id-> product  !=  dev-> id.product)   
  19.                                 continue;    
  20.    
  21.                 if  (id-> flags  &   INPUT_DEVICE_ID_MATCH_VERSION)  //匹配版本   
  22.                         if  (id-> version  !=  dev-> id.version)   
  23.                                 continue;    
  24.    
  25.                 MATCH_BIT(evbit,    EV_MAX);     //匹配id的evbit和input_dev中evbit的各个位,如果不匹配则continue,数组中下一个设备   
  26.                 MATCH_BIT(keybit,  KEY_MAX);    
  27.                 MATCH_BIT(relbit,  REL_MAX);    
  28.                 MATCH_BIT(absbit,  ABS_MAX);    
  29.                 MATCH_BIT(mscbit,  MSC_MAX);    
  30.                 MATCH_BIT(ledbit,  LED_MAX);    
  31.                 MATCH_BIT(sndbit,  SND_MAX);    
  32.                 MATCH_BIT(ffbit,    FF_MAX);    
  33.                 MATCH_BIT(swbit,    SW_MAX);    
  34.    
  35.                 if  (!handler-> match  ||  handler-> match(handler,  dev))   
  36.                         return  id;    
  37.         }   
  38.    
  39.         return  NULL;    
  40. }   
 
 
MATCH_bit 原型:
 
[objc]  view plain  copy  
  1. #define  MATCH_BIT(bit,  max)  \   
  2.                 for  (i  =  0;   i  <   BITS_TO_LONGS(max);   i++)  \   
  3.                         if  ((id-> bit[i]  &   dev-> bit[i])  !=  id-> bit[i])  \   
  4.                                 break;   \   
  5.                 if  (i  !=  BITS_TO_LONGS(max))  \   
  6.                         continue;    
 
 
可以看到这么多步的目的除了初始以及添加input_dev到链表,就是为了去匹配  input_handler_list  中对应的handler  ,
匹配的最终是需要比对handler以及input_dev中的 id,其中input_dev 中的id类型为  input_id  :
 
[objc]  view plain  copy  
  1. struct  input_id  {   
  2.         __u16  bustype;    
  3.         __u16  vendor;    
  4.         __u16  product;    
  5.         __u16  version;    
  6. };    

这跟上面 input_handler 结构里面的 input_device_id 匹配id 变量,来确认 handler!
 
在最开始的时候就有提到,整个input输入体系,分三个层次,现在的input核心层做的事就是:
在硬件驱动层调用 input_register_device时 ,往内核注册驱动的同时,根据硬件的相关id去匹配 适用的事件处理层(input_handler)!
这里匹配上之后就会调用对应 input_handler 的connect 函数。
 
input_handler:input_dev 变量代表的是硬件设备,前文Linux/Android— — 输入子系统input_event传递 (二)中有介绍
input_handler 变量代表的是事件处理器
同样在input.h 中定义:
 
[objc]  view plain  copy  
  1. /** 
  2.   *  struct  input_handler  -  implements  one  of  interfaces  for  input  devices 
  3.   *  @private:  driver-specific  data 
  4.   *  @event:  event  handler.  This  method  is  being  called  by  input  core  with 
  5.   *    interrupts  disabled  and  dev-> event_lock  spinlock  held  and  so 
  6.   *    it  may  not  sleep 
  7.   *  @filter:  similar  to  @event;   separates  normal  event  handlers  from 
  8.   *    "filters". 
  9.   *  @match:  called  after  comparing  device‘s  id  with  handler‘s  id_table 
  10.   *    to  perform  fine-grained  matching  between  device  and  handler 
  11.   *  @connect:  called  when  attaching  a  handler  to  an  input  device 
  12.   *  @disconnect:  disconnects  a  handler  from  input  device 
  13.   *  @start:  starts  handler  for  given  handle.  This  function  is  called  by 
  14.   *    input  core  right  after  connect()  method  and  also  when  a  process 
  15.   *    that  "grabbed"  a  device  releases  it 
  16.   *  @fops:  file  operations  this  driver  implements 
  17.   *  @minor:  beginning  of  range  of  32  minors  for  devices  this  driver 
  18.   *    can  provide 
  19.   *  @name:  name  of  the  handler,  to  be  shown  in  /proc/bus/input/handlers 
  20.   *  @id_table:  pointer  to  a  table  of  input_device_ids  this  driver  can 
  21.   *    handle 
  22.   *  @h_list:  list  of  input  handles  associated  with  the  handler 
  23.   *  @node:  for  placing  the  driver  onto  input_handler_list 
  24.   * 
  25.   *  Input  handlers  attach  to  input  devices  and  create  input  handles.  There 
  26.   *  are  likely  several  handlers  attached  to  any  given  input  device  at  the 
  27.   *  same  time.  All  of  them  will  get  their  copy  of  input  event  generated  by 
  28.   *  the  device. 
  29.   * 
  30.   *  The  very  same  structure  is  used  to  implement  input  filters.  Input  core 
  31.   *  allows  filters  to  run  first  and  will  not  pass  event  to  regular  handlers 
  32.   *  if  any  of  the  filters  indicate  that  the  event  should  be  filtered  (by 
  33.   *  returning  %true  from  their  filter()  method). 
  34.   * 
  35.   *  Note  that  input  core  serializes  calls  to  connect()  and  disconnect() 
  36.   *  methods. 
  37.   */   
  38. struct  input_handler  {   
  39.    
  40.         voidvoid  *private;    
  41.    
  42.         void  (*event)(struct  input_handle  *handle,  unsigned  int  type,  unsigned  int  code,  int  value);    
  43.         bool  (*filter)(struct  input_handle  *handle,  unsigned  int  type,  unsigned  int  code,  int  value);    
  44.         bool  (*match)(struct  input_handler  *handler,  struct  input_dev  *dev);    
  45.         int  (*connect)(struct  input_handler  *handler,  struct  input_dev  *dev,  const  struct  input_device_id  *id);     //上面就是调用这个函数指针   
  46.         void  (*disconnect)(struct  input_handle  *handle);    
  47.         void  (*start)(struct  input_handle  *handle);    
  48.    
  49.         const  struct  file_operations  *fops;    
  50.         int  minor;    
  51.         const  charchar  *name;    
  52.    
  53.         const  struct  input_device_id  *id_table;   //这个就是上面说到的  会跟input_dev中的input_id  比对  id项的   
  54.    
  55.         struct  list_head        h_list;    
  56.         struct  list_head        node;    
  57. };    

这个结构详细的含义,注释有。
 
这个结构里面暂时只需要理解的:
注册input_dev ,在事件处理数据链表里面匹配上 input_handler ,就会调用其 *connect 函数指针 进行连接,
将input_dev 跟 input_handler 进行绑定, 后续的运作事件的handler处理将会走这个input_handler的 *event !
在上篇input_event 传递中最后调用到event阶段.
 
这里简单记录到这里,下篇介绍input_handler 的处理机制~
【Linux/Android——input子系统核心】 

    推荐阅读