Android中Input型输入设备驱动原理分析

枕上从妨一夜睡,灯前读尽十年诗。这篇文章主要讲述Android中Input型输入设备驱动原理分析相关的知识,希望能为你提供帮助。
转自:http://blog.csdn.net/eilianlau/article/details/6969361
话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也增加几个属于android自己的机制。典型的IPC
Android中的input设备驱动主要包括:游戏杆(joystick)、鼠标(mouse)和事件设备(Event)。
1、Input输入子系统的构架,在网上找到两幅灰常漂亮的图。
       

Android中Input型输入设备驱动原理分析

文章图片

      下面这幅更漂亮,更直观的能看出input型输入子系统究竟是什么咚咚,更能够体现出,用户空间,内核空间,驱动程序是怎么关联起来的。。。
       
Android中Input型输入设备驱动原理分析

文章图片

Input驱动同样也是字符设备,主设备号是13,次设备号是64~95之间自动生成的,这个Input驱动程序那是相当相当的复杂。在android内核中主要需要关注一下几个文件
      a)include/linux/input.h(驱动头文件)
      b)driver/input/input.c (驱动核心实现,包含大量的操作接口)
    c)driver/input/event.c (event机制)
    d)driver/input/joydev.c (joystick驱动)
【Android中Input型输入设备驱动原理分析】    e)driver/input/mousedev.c(鼠标驱动)
其实上面这些东西都不要我们自己去实现内核已经帮我们实现好了,不过我们在写硬件驱动的时候需要和Inputcore交互,所以需要用到上面这些函数中的接口,也就是说上面这些函数是透明的。
2、Event事件驱动原理及其实现
在内核中,用input_dev来描述一个Input设备,该结构的定义如下,其中内核中使用input_register_device(struct input_dev *dev)来注册一个input设备
这个结构体好长,所以就列了几个。。。。它的定义在input.h当中
struct input_dev {
  。。。。。。。。。。。
      struct input_id id; /*指向input_id结构*/
      bool sync;                            
      struct device dev; /**这些设备都归属总线设备模型*/
      struct list_head      h_list; //
      struct list_head      node;   //input_handle链表的list节点
};
用input_handler表示input设备的接口,使用input_register_handler(structinput_handler *handler)注册
struct input_handler {

      void *private;
。。。。。。。。。。
      int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
      void (*disconnect)(struct input_handle *handle);
      void (*start)(struct input_handle *handle);

      const struct file_operations *fops;
      int minor;
      const char *name;

      const struct input_device_id *id_table;

      struct list_head      h_list;
      struct list_head      node;
};
Event事件驱动实现过程
1)Input设备注册
int input_register_device(struct input_dev *dev)
{
      static atomic_t input_no = ATOMIC_INIT(0);
      struct input_handler *handler;
      const char *path;
      int error;
      /* Every input device generates EV_SYN/SYN_REPORT events. */
      __set_bit(EV_SYN, dev-> evbit); //see to inpu.h

      /* KEY_RESERVED is not supposed to be transmitted to userspace. */
      __clear_bit(KEY_RESERVED, dev-> keybit);
      /* Make sure that bitmasks not mentioned in dev-> evbit are clean. */
      input_cleanse_bitmasks(dev);
      /*
      * If delay and period are pre-set by the driver, then autorepeating
      * is handled by the driver itself and we don‘t do it in input.c.
      */
      init_timer(& dev-> timer);
      //处理重复按键.如果没赋值则为其赋默认的值
      if (!dev-> rep[REP_DELAY] & & !dev-> rep[REP_PERIOD]) {
            dev-> timer.data = https://www.songbingjia.com/android/(long) dev;
            dev-> timer.function = input_repeat_key;
            dev-> rep[REP_DELAY] = 250;
            dev-> rep[REP_PERIOD] = 33;
      }
      if (!dev-> getkeycode)//获取键的扫描码
            dev-> getkeycode = input_default_getkeycode;
      if (!dev-> setkeycode)//设置键值
            dev-> setkeycode = input_default_setkeycode;
      dev_set_name(& dev-> dev, "input%ld",
                    (unsigned long) atomic_inc_return(& input_no) - 1);
      //将input_dev中封装的device注册到sysfs
      error = device_add(& dev-> dev);
      if (error)
            return error;
      path = kobject_get_path(& dev-> dev.kobj, GFP_KERNEL);
      printk(KERN_INFO "input: %s as %s\n",
            dev-> name ? dev-> name : "Unspecified device", path ? path : "N/A");
      kfree(path);

      error = mutex_lock_interruptible(& input_mutex);
      if (error) {
            device_del(& dev-> dev);
            return error;
      }
      //将input_device挂到input_dev_list链表中
      list_add_tail(& dev-> node, & input_dev_list);
      //对挂载在input_dev_list中的每一个handler调用input_attach_handler(dev, handler);
      list_for_each_entry(handler, & input_handler_list, node)
            input_attach_handler(dev, handler);
      input_wakeup_procfs_readers();
      mutex_unlock(& input_mutex);
      return 0;
}
上述函数首先将input_device挂接到input_dev_list链表上,然后对挂载在input_dev_list中的每一个handler调用input_attach_handler(dev, handler)来进行匹配,举个例子,设备模型中的device和driver的匹配,所有的input device都挂载在input_dev_list上而所有的handler都挂载在input_handler_list上,那么它们是怎么联系起来的?匹配过程如下

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
      const struct input_device_id *id;
      int error;
      id = input_match_device(handler, dev);
      if (!id)
            return -ENODEV;
      error = handler-> connect(handler, dev, id);
      if (error & & error != -ENODEV)
            printk(KERN_ERR
                  "input: failed to attach handler %s to device %s, "
                  "error: %d\n",
                  handler-> name, kobject_name(& dev-> dev.kobj), error);
      return error;
}
上面函数调用input_match_device来对handler, dev通过input_device_id *id来进行匹配如果匹配成功则调用handler-> connect来关联struct input_dev *dev, 和struct input_handler *handler结构。下面看看input_match_device(handler, dev)的过程
#define MATCH_BIT(bit, max) \
            for (i = 0; i < BITS_TO_LONGS(max); i++) \
                  if ((id-> bit[i] & dev-> bit[i]) != id-> bit[i]) \
                        break; \
            if (i != BITS_TO_LONGS(max)) \
                  continue;

static const struct input_device_id *input_match_device(struct input_handler *handler,struct input_dev *dev)
{
      const struct input_device_id *id;
      int i;
      for (id = handler-> id_table; id-> flags || id-> driver_info; id++) {//flags配置匹配的类型
            if (id-> flags & INPUT_DEVICE_ID_MATCH_BUS)//匹配总线类型
                  if (id-> bustype != dev-> id.bustype)
                        continue;
            if (id-> flags & INPUT_DEVICE_ID_MATCH_VENDOR)//匹配厂商
                  if (id-> vendor != dev-> id.vendor)
                        continue;
            if (id-> flags & INPUT_DEVICE_ID_MATCH_PRODUCT)//匹配制造商
                  if (id-> product != dev-> id.product)
                        continue;
            if (id-> flags & INPUT_DEVICE_ID_MATCH_VERSION)//匹配版本号
                  if (id-> version != dev-> id.version)
                        continue;
          //如果上面的id-> flags匹配成功或者是id-> flags没有定义则执行下面的函数
            MATCH_BIT(evbit,  EV_MAX);
            MATCH_BIT(keybit, KEY_MAX);
            MATCH_BIT(relbit, REL_MAX);
            MATCH_BIT(absbit, ABS_MAX);
            MATCH_BIT(mscbit, MSC_MAX);
            MATCH_BIT(ledbit, LED_MAX);
            MATCH_BIT(sndbit, SND_MAX);
            MATCH_BIT(ffbit,  FF_MAX);
            MATCH_BIT(swbit,  SW_MAX);
            if (!handler-> match || handler-> match(handler, dev))
                  return id;
      }
      return NULL;
}

其中handler的注册和上述类似,感兴趣的朋友可以读linux内核源码

 

    推荐阅读