zoukankan      html  css  js  c++  java
  • input子系统分析之二:数据结构

    内核版本:3.9.5

    1. input_dev,用来标识输入设备

     1 struct input_dev {
     2     const char *name;
     3     const char *phys;
     4     const char *uniq;
     5     struct input_id id;//与input_handler匹配用的id
     6 
     7     unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
     8 
     9     unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//支持所有的事件类型
    10     unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//支持按键事件
    11     unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//支持相对位移事件
    12     unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//支持绝对位移事件
    13     unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//支持其它事件
    14     unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//支持led事件
    15     unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//支持声音事件
    16     unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//支持受力事件
    17     unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//支持开关机时间
    18 
    19     unsigned int hint_events_per_packet;
    20 
    21     unsigned int keycodemax;
    22     unsigned int keycodesize;
    23     void *keycode;
    24 
    25     int (*setkeycode)(struct input_dev *dev,
    26               const struct input_keymap_entry *ke,
    27               unsigned int *old_keycode);
    28     int (*getkeycode)(struct input_dev *dev,
    29               struct input_keymap_entry *ke);
    30 
    31     struct ff_device *ff;
    32 
    33     unsigned int repeat_key;//最近一次的按键值
    34     struct timer_list timer;
    35 
    36     int rep[REP_CNT];
    37 
    38     struct input_mt *mt;
    39 
    40     struct input_absinfo *absinfo;
    41 
    42     unsigned long key[BITS_TO_LONGS(KEY_CNT)];//反应设备当前的按键状态
    43     unsigned long led[BITS_TO_LONGS(LED_CNT)];//反应设备当前的led状态
    44     unsigned long snd[BITS_TO_LONGS(SND_CNT)];//反应设备当前的声音输入状态
    45     unsigned long sw[BITS_TO_LONGS(SW_CNT)];//反应设备当前的开关状态
    46 
    47     int (*open)(struct input_dev *dev);//第一次打开设备时调用,初始化设备用
    48     void (*close)(struct input_dev *dev);//最后一个应用程序释放设备时用,关闭设备
    49     int (*flush)(struct input_dev *dev, struct file *file);/*用于处理传递给设备的事件,如LED事件和声音事件*/
    50     int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
    51 
    52     struct input_handle __rcu *grab;//当前占有该设备的input_handle
    53 
    54     spinlock_t event_lock;
    55     struct mutex mutex;
    56 
    57     unsigned int users;//打开该设备的用户数量(input handlers)
    58     bool going_away;
    59 
    60     struct device dev;
    61 
    62     struct list_head    h_list;//该链表头用于链接此input_dev所关联的input_handle
    63     struct list_head    node;//用于将此input_dev链接到input_dev_list
    64 
    65     unsigned int num_vals;
    66     unsigned int max_vals;
    67     struct input_value *vals;
    68 
    69     bool devres_managed;
    70 };

    2.input_handler,用来标识输入事件处理

     1 struct input_handler {
     2 
     3     void *private;
     4 
     5     void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);/*event用于处理事件*/
     6     void (*events)(struct input_handle *handle,
     7                const struct input_value *vals, unsigned int count);
     8     bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
     9     bool (*match)(struct input_handler *handler, struct input_dev *dev);
    10     int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);/*connect用于建立handler和device的联系*/
    11     void (*disconnect)(struct input_handle *handle);/*disconnect用于解除handler和device的联系*/
    12     void (*start)(struct input_handle *handle);
    13 
    14     bool legacy_minors;
    15     int minor;//次设备号
    16     const char *name;
    17 
    18     const struct input_device_id *id_table;//用于和input_dev匹配
    19 
    20     struct list_head    h_list;//用于链接和此input_handler相关的input_handle
    21     struct list_head    node;//用于将该input_handler链入input_handler_list
    22 };

    3.input_handle,用来链接input_dev和input_handler的桥梁

     1 struct input_handle {
     2 
     3     void *private;
     4 
     5     int open;//记录设备的打开次数(有多少个应用程序访问设备)
     6     const char *name;
     7 
     8     struct input_dev *dev;//指向所属的device
     9     struct input_handler *handler;//指向所属的handler
    10 
    11     struct list_head    d_node;//用于将此input_handle链入所属input_dev的h_list链表
    12     struct list_head    h_node;//用于将此input_handle链入所属input_handler的h_list链表
    13 };

    可以看到,input_device和input_handler中都有一个h_list,而input_handle拥有指向input_dev和input_handler的指针,也就是说input_handle是用来关联input_dev和input_handler的,那么为什么一个input_device和input_handler

    中拥有的是h_list而不是一个handle呢?因为一个device可能对应多个handler,而一个handler也不能只处理一个device,比如说一个鼠标,它可以对应even handler,也可以对应mouse handler,因此当其注册时与系统中的handler进行匹配,就有可能产生两个实例,一个是evdev,另一个是mousedev,而任何一个实例中都只有一个handle.至于以何种方式来传递事件,就由用户程序打开哪个实例来决定.后面一个情况很容易理解,一个事件驱动不能只为一个甚至一种设备服务,系统中可能有多种设备都能使用这类handler,比如event handler就可以匹配所有的设备.在input子系统中,有8种事件驱动,每种事件驱动最多可以对应32个设备,因此dev实例总数最多可以达到256个.

    这三个数据结构的关系看起来有点乱!那么就用图表示出来,看起来应该会明了很多吧!三者的关系如下所示:

    可以看出input_handle是连接input_device和input_handler的桥梁,如图中的箭头所示从input_device可以通过input_handl找到input_handler,同样的input_handler可以通过 input_handle找到input_device

    下一节将以even handler为例介绍设备注册以及打开的过程.

  • 相关阅读:
    linux 下安装 mysql (centos7)版本
    linux 安装php7 -系统centos7
    Beta阶段事后分析
    Beta阶段展示博客
    Beta阶段测试报告
    Beta阶段发布说明
    第二十次ScrumMeeting博客
    第十九次ScrumMeeting博客
    第十八次ScrumMeeting博客
    第十七次ScrumMeeting博客
  • 原文地址:https://www.cnblogs.com/jason-lu/p/3155228.html
Copyright © 2011-2022 走看看