linux输入子系统(4)

1.5      事件报告的传递

输入子系统设备报告各种事件通过 input_report_XXX 族函数,例如 程序清单 1 .5 中报告按键事件。按键、相对坐标、绝对坐标和同步事件报告的函数如 程序清单 1 .12 所示。

 

程序清单 1 . 12   事件报告函数

/* include/linux/input.h */

static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)

{

         input_event(dev, EV_KEY, code, !!value);                                                                                  

}

 

static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)

{

         input_event(dev, EV_REL, code, value);

}

 

static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)

{

         input_event(dev, EV_ABS, code, value);

}

 

static inline void input_sync(struct input_dev *dev)

{

         input_event(dev, EV_SYN, SYN_REPORT, 0);

}

可以看到,这四个函数都调用了 input_event ,并且在 将按键的 value 转化为布尔类型的值。所以按键传给 input core value 0( 释放 ) 或者 1( 按下 )

input_event 函数的代码如 程序清单 1 .13 所示。

程序清单 1 . 13   input_event

/* driver/input/input.c */

void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

{

         unsigned long flags;

 

         if (is_event_supported(type, dev->evbit, EV_MAX)) {

                   spin_lock_irqsave(&dev->event_lock, flags);

                   add_input_randomness(type, code, value);                                                                        

                   input_handle_event(dev, type, code, value);                                                                       

                   spin_unlock_irqrestore(&dev->event_lock, flags);

         }

}

EXPORT_SYMBOL(input_event);

本函数总共有两行有效的调用:

由于输入事件具有随机性,因此用输入事件来增加内核熵池的熵。

调用事件分发函数 input_handle_event ,做进一步的传递。

input_handle_event 的代码如所示。

 

/* driver/input/input.c */

#define INPUT_IGNORE_EVENT                 0

#define INPUT_PASS_TO_HANDLERS       1

#define INPUT_PASS_TO_DEVICE              2

#define INPUT_PASS_TO_ALL                      (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)

 

static void input_handle_event(struct input_dev *dev,

                                   unsigned int type, unsigned int code, int value)

{

         int disposition = INPUT_IGNORE_EVENT;

 

         switch (type) {

         ····························

         case EV_KEY:

                   if (is_event_supported(code, dev->keybit, KEY_MAX) &&                                            

                       !!test_bit(code, dev->key) != value) {                                                                        

 

                            if (value != 2) {                                                                                                         

                                     __change_bit(code, dev->key);                                                                       

                                     if (value)                                                                                                          

                                               input_start_autorepeat(dev, code);

                            }

 

                            disposition = INPUT_PASS_TO_HANDLERS;                                                                                     

                   }

                   break;

 

         case EV_ABS:

                   if (is_event_supported(code, dev->absbit, ABS_MAX)) {                                               

 

                            value = input_defuzz_abs_event(value,                                                                    

                                               dev->abs[code], dev->absfuzz[code]);

 

                            if (dev->abs[code] != value) {                                                                                  

                                     dev->abs[code] = value;

                                     disposition = INPUT_PASS_TO_HANDLERS;

                            }

                   }

                   break;

 

         case EV_REL:

                   if (is_event_supported(code, dev->relbit, REL_MAX) && value)                                    

                            disposition = INPUT_PASS_TO_HANDLERS;

 

                   break;

                  ························

         }

 

         if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)

                   dev->sync = 0;

 

         if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)

                   dev->event(dev, type, code, value);

 

         if (disposition & INPUT_PASS_TO_HANDLERS)

                   input_pass_event(dev, type, code, value);

}

上述代码中去除了其他事件的部分,线面说明按键、相对坐标和绝对坐标的处理部分:

检查按键是否为驱动所支持,只有之前注册过的按键才会继续传递。

检查报告的按键状态是否和上次相同。如果连续多次报告按键按下,则只处理第一次。

如果不是连击事件。

翻转按键的当前状态 ( 按下和释放 )

如果是按下,则开始连击计时。

标记消息传递方向。

检查绝对坐标轴是否驱动所支持的。

根据当前报告的值和上次报告的值确定传给处理程序的绝对值大小。

如果本次需要报告的绝对值和上次不同,则将事件传递给处理函数。

检查相对坐标轴是否被驱动所支持。

可以看到 input_handle_event 分发事件有两个方向:驱动的回调函数 dev->event input core input_pass_event 。下面继续分析 input_pass_event ,代码如 程序清单 1 .14 所示。

 

程序清单 1 . 14   input_pass_event

/* driver/input/input.c */

static void input_pass_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

{

         struct input_handle *handle;

 

         rcu_read_lock();

         handle = rcu_dereference(dev->grab);                                                                                         

         if (handle)

                   handle->handler->event(handle, type, code, value);

         else

                   list_for_each_entry_rcu(handle, &dev->h_list, d_node)                                                    

                            if (handle->open)                                                                                                      

                                     handle->handler->event(handle, type, code, value);                                        

         rcu_read_unlock();

}

 

这个函数将事件分发给相关的 handler

获取独占设备的 handle 的指针。如果有独占设备的 handle ,则仅仅将事件传给独占的 handle 对应的 handler

遍历与此设备连接的每一个 handle

如果 hnadle 已经被打开。

将事件分发给 handler 的事件处理函数。

到这里, input core 分发事件的任务已经完成,接下来由各个 handler 处理接收到的事件。

你可能感兴趣的:(linux,list,struct,report,input,each)