linux输入子系统(4)

============================================
作者:yuanlulu
http://blog.csdn.net/yuanlulu


版权没有,但是转载请保留此段声明
============================================


1.5     事件报告的传递

输入子系统设备报告各种事件通过input_report_XXX族函数,例如程序清单 1.5<!--[if gte mso 9]><![endif]-->中报告按键事件。按键、相对坐标、绝对坐标和同步事件报告的函数如<!--[if supportFields]> REF _Ref282071220 /h <![endif]-->程序清单 1.12<!--[if gte mso 9]><![endif]--><!--[if supportFields]><![endif]-->所示。

 

程序清单 <!--[if supportFields]> STYLEREF 1 /s <![endif]-->1<!--[if supportFields]><![endif]-->.<!--[if supportFields]> SEQ 程序清单 /* ARABIC /s 1 <![endif]-->12<!--[if supportFields]><![endif]-->  事件报告函数

/* 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);                                                                                   <!--[if supportFields]> = 1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->

}

 

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,并且在<!--[if supportFields]> = 1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->处将按键的value转化为布尔类型的值。所以按键传给input corevalue0(释放)或者1(按下)

input_event函数的代码如<!--[if supportFields]>REF _Ref282071839 /h <![endif]-->程序清单 1.13<!--[if gte mso 9]><![endif]--><!--[if supportFields]><![endif]-->所示。

程序清单 <!--[if supportFields]> STYLEREF 1 /s <![endif]-->1<!--[if supportFields]><![endif]-->.<!--[if supportFields]> SEQ 程序清单 /* ARABIC /s 1 <![endif]-->13<!--[if supportFields]><![endif]-->  input_event

/* driver/input/input.c */

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

{

         unsignedlong flags;

 

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

                   spin_lock_irqsave(&dev->event_lock,flags);

                   add_input_randomness(type,code, value);                                                                         <!--[if supportFields]> = 1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->

                   input_handle_event(dev,type, code, value);                                                                        <!--[if supportFields]> = 2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->

                   spin_unlock_irqrestore(&dev->event_lock,flags);

         }

}

EXPORT_SYMBOL(input_event);

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

<!--[if supportFields]> =1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->由于输入事件具有随机性,因此用输入事件来增加内核熵池的熵。

<!--[if supportFields]> =2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->调用事件分发函数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)

{

         intdisposition = INPUT_IGNORE_EVENT;

 

         switch(type) {

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

         caseEV_KEY:

                   if(is_event_supported(code, dev->keybit, KEY_MAX) &&                                             <!--[if supportFields]> = 1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->

                       !!test_bit(code, dev->key) != value) {                                                                         <!--[if supportFields]> = 2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->

 

                            if(value != 2) {                                                                                                          <!--[if supportFields]> = 3 /* GB2 <![endif]-->⑶<!--[if supportFields]><![endif]-->

                                     __change_bit(code,dev->key);                                                                        <!--[if supportFields]> = 4 /* GB2 <![endif]-->⑷<!--[if supportFields]><![endif]-->

                                     if(value)                                                                                                           <!--[if supportFields]> = 5 /* GB2 <![endif]-->⑸<!--[if supportFields]><![endif]-->

                                               input_start_autorepeat(dev,code);

                            }

 

                            disposition= INPUT_PASS_TO_HANDLERS;                                                     <!--[if supportFields]> = 6 /* GB2 <![endif]-->⑹<!--[if supportFields]><![endif]-->                                

                   }

                   break;

 

         caseEV_ABS:

                   if(is_event_supported(code, dev->absbit, ABS_MAX)) {                                                <!--[if supportFields]> = 7 /* GB2 <![endif]-->⑺<!--[if supportFields]><![endif]-->

 

                            value= input_defuzz_abs_event(value,                                                                     <!--[if supportFields]> = 8 /* GB2 <![endif]-->⑻<!--[if supportFields]><![endif]-->

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

 

                            if(dev->abs[code] != value) {                                                                                   <!--[if supportFields]> = 9 /* GB2 <![endif]-->⑼<!--[if supportFields]><![endif]-->

                                     dev->abs[code]= value;

                                     disposition= INPUT_PASS_TO_HANDLERS;

                            }

                   }

                   break;

 

         caseEV_REL:

                   if(is_event_supported(code, dev->relbit, REL_MAX) && value)                                     <!--[if supportFields]> = 10 /* GB2 <![endif]-->⑽<!--[if supportFields]><![endif]-->

                            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);

}

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

<!--[if supportFields]> =1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->检查按键是否为驱动所支持,只有之前注册过的按键才会继续传递。

<!--[if supportFields]> =2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->检查报告的按键状态是否和上次相同。如果连续多次报告按键按下,则只处理第一次。

<!--[if supportFields]> =3 /* GB2 <![endif]-->⑶<!--[if supportFields]><![endif]-->如果不是连击事件。

<!--[if supportFields]> =4 /* GB2 <![endif]-->⑷<!--[if supportFields]><![endif]-->翻转按键的当前状态(按下和释放)

<!--[if supportFields]> =5 /* GB2 <![endif]-->⑸<!--[if supportFields]><![endif]-->如果是按下,则开始连击计时。

<!--[if supportFields]> =6 /* GB2 <![endif]-->⑹<!--[if supportFields]><![endif]-->标记消息传递方向。

<!--[if supportFields]> =7 /* GB2 <![endif]-->⑺<!--[if supportFields]><![endif]-->检查绝对坐标轴是否驱动所支持的。

<!--[if supportFields]> =8 /* GB2 <![endif]-->⑻<!--[if supportFields]><![endif]-->根据当前报告的值和上次报告的值确定传给处理程序的绝对值大小。

<!--[if supportFields]> =9 /* GB2 <![endif]-->⑼<!--[if supportFields]><![endif]-->如果本次需要报告的绝对值和上次不同,则将事件传递给处理函数。

<!--[if supportFields]> =10 /* GB2 <![endif]-->⑽<!--[if supportFields]><![endif]-->检查相对坐标轴是否被驱动所支持。

可以看到input_handle_event分发事件有两个方向:驱动的回调函数dev->eventinput coreinput_pass_event。下面继续分析input_pass_event,代码如<!--[if supportFields]> REF _Ref282075682 /h <![endif]-->程序清单 1.14<!--[if gte mso 9]><![endif]--><!--[if supportFields]><![endif]-->所示。

 

程序清单 <!--[if supportFields]> STYLEREF 1 /s <![endif]-->1<!--[if supportFields]><![endif]-->.<!--[if supportFields]> SEQ 程序清单 /* ARABIC /s 1 <![endif]-->14<!--[if supportFields]><![endif]-->  input_pass_event

/* driver/input/input.c */

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

{

         structinput_handle *handle;

 

         rcu_read_lock();

         handle =rcu_dereference(dev->grab);                                                                                          <!--[if supportFields]> = 1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->

         if(handle)

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

         else

                   list_for_each_entry_rcu(handle,&dev->h_list, d_node)                                                     <!--[if supportFields]> = 2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->

                            if(handle->open)                                                                                                       <!--[if supportFields]> = 3 /* GB2 <![endif]-->⑶<!--[if supportFields]><![endif]-->

                                     handle->handler->event(handle,type, code, value);                                         <!--[if supportFields]> = 4 /* GB2 <![endif]-->⑷<!--[if supportFields]><![endif]-->

         rcu_read_unlock();

}

 

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

<!--[if supportFields]> =1 /* GB2 <![endif]-->⑴<!--[if supportFields]><![endif]-->获取独占设备的handle的指针。如果有独占设备的handle,则仅仅将事件传给独占的handle对应的handler

<!--[if supportFields]> =2 /* GB2 <![endif]-->⑵<!--[if supportFields]><![endif]-->遍历与此设备连接的每一个handle

<!--[if supportFields]> =3 /* GB2 <![endif]-->⑶<!--[if supportFields]><![endif]-->如果hnadle已经被打开。

<!--[if supportFields]> =4 /* GB2 <![endif]-->⑷<!--[if supportFields]><![endif]-->将事件分发给handler的事件处理函数。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值