`
isiqi
  • 浏览: 15990239 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

linux输入子系统(4)

阅读更多

<!--[if !supportLists]-->1.5 <!--[endif]-->事件报告的传递

输入子系统设备报告各种事件通过input_report_XXX族函数,例如程序清单 1.5<!--[if gte mso 9]><xml> <w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F005200650066003200380032003000370031003000350031000000</w:data> </xml><![endif]-->中报告按键事件。按键、相对坐标、绝对坐标和同步事件报告的函数如<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span> REF _Ref282071220 \h <span style='mso-element:field-separator'></span></span><![endif]-->程序清单 1.12<!--[if gte mso 9]><xml> <w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F005200650066003200380032003000370031003200320030000000</w:data> </xml><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->所示。

程序清单 <!--[if supportFields]><span style='mso-bookmark:_Ref282071220'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282071220'><span lang=EN-US><span style='mso-spacerun:yes'>&nbsp;</span>STYLEREF 1 \s <span style='mso-element:field-separator'></span></span></span><![endif]-->1<!--[if supportFields]><span style='mso-bookmark: _Ref282071220'></span><span style='mso-element:field-end'></span><![endif]-->.<!--[if supportFields]><span style='mso-bookmark:_Ref282071220'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282071220'><span lang=EN-US> SEQ </span></span><span style='mso-bookmark:_Ref282071220'><span style='font-family:黑体;mso-ascii-font-family: Arial'>程序清单</span><span lang=EN-US> \* ARABIC \s 1 <span style='mso-element: field-separator'></span></span></span><![endif]-->12<!--[if supportFields]><span style='mso-bookmark:_Ref282071220'></span><span style='mso-element:field-end'></span><![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]><span lang=DE><span style='mso-element:field-begin'></span> = 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![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]><span lang=EN-US><span style='mso-element:field-begin'></span> = 1 \* GB2 <span style='mso-element: field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->将按键的value转化为布尔类型的值。所以按键传给input corevalue0(释放)或者1(按下)

input_event函数的代码如<!--[if supportFields]><span lang=DE style='mso-ansi-language:DE'><span style='mso-element:field-begin'></span> REF _Ref282071839 \h <span style='mso-element:field-separator'></span></span><![endif]-->程序清单 1.13<!--[if gte mso 9]><xml> <w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F005200650066003200380032003000370031003800330039000000</w:data> </xml><![endif]--><!--[if supportFields]><span lang=DE style='mso-ansi-language: DE'><span style='mso-element:field-end'></span></span><![endif]-->所示。

程序清单 <!--[if supportFields]><span style='mso-bookmark:_Ref282071839'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282071839'><span lang=EN-US><span style='mso-spacerun:yes'>&nbsp;</span>STYLEREF 1 \s <span style='mso-element:field-separator'></span></span></span><![endif]-->1<!--[if supportFields]><span style='mso-bookmark: _Ref282071839'></span><span style='mso-element:field-end'></span><![endif]-->.<!--[if supportFields]><span style='mso-bookmark:_Ref282071839'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282071839'><span lang=EN-US> SEQ </span></span><span style='mso-bookmark:_Ref282071839'><span style='font-family:黑体;mso-ascii-font-family: Arial'>程序清单</span><span lang=EN-US> \* ARABIC \s 1 <span style='mso-element: field-separator'></span></span></span><![endif]-->13<!--[if supportFields]><span style='mso-bookmark:_Ref282071839'></span><span style='mso-element:field-end'></span><![endif]--> 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); <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

input_handle_event(dev, type, code, value); <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

spin_unlock_irqrestore(&dev->event_lock, flags);

}

}

EXPORT_SYMBOL(input_event);

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

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->由于输入事件具有随机性,因此用输入事件来增加内核熵池的熵。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![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)

{

int disposition = INPUT_IGNORE_EVENT;

switch (type) {

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

case EV_KEY:

if (is_event_supported(code, dev->keybit, KEY_MAX) && <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

!!test_bit(code, dev->key) != value) { <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

if (value != 2) { <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 3 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

__change_bit(code, dev->key); <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 4 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

if (value) <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 5 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

input_start_autorepeat(dev, code);

}

disposition = INPUT_PASS_TO_HANDLERS; <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 6 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

}

break;

case EV_ABS:

if (is_event_supported(code, dev->absbit, ABS_MAX)) { <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 7 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

value = input_defuzz_abs_event(value, <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 8 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

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

if (dev->abs[code] != value) { <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 9 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

dev->abs[code] = value;

disposition = INPUT_PASS_TO_HANDLERS;

}

}

break;

case EV_REL:

if (is_event_supported(code, dev->relbit, REL_MAX) && value) <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 10 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![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]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->检查按键是否为驱动所支持,只有之前注册过的按键才会继续传递。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->检查报告的按键状态是否和上次相同。如果连续多次报告按键按下,则只处理第一次。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 3 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->如果不是连击事件。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 4 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->翻转按键的当前状态(按下和释放)

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 5 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->如果是按下,则开始连击计时。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 6 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->标记消息传递方向。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 7 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->检查绝对坐标轴是否驱动所支持的。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 8 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->根据当前报告的值和上次报告的值确定传给处理程序的绝对值大小。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 9 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->如果本次需要报告的绝对值和上次不同,则将事件传递给处理函数。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 10 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->检查相对坐标轴是否被驱动所支持。

可以看到input_handle_event分发事件有两个方向:驱动的回调函数dev->eventinput coreinput_pass_event。下面继续分析input_pass_event,代码如<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span> REF _Ref282075682 \h <span style='mso-element:field-separator'></span></span><![endif]-->程序清单 1.14<!--[if gte mso 9]><xml> <w:data>08D0C9EA79F9BACE118C8200AA004BA90B02000000080000000E0000005F005200650066003200380032003000370035003600380032000000</w:data> </xml><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->所示。

程序清单 <!--[if supportFields]><span style='mso-bookmark:_Ref282075682'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282075682'><span lang=EN-US><span style='mso-spacerun:yes'>&nbsp;</span>STYLEREF 1 \s <span style='mso-element:field-separator'></span></span></span><![endif]-->1<!--[if supportFields]><span style='mso-bookmark: _Ref282075682'></span><span style='mso-element:field-end'></span><![endif]-->.<!--[if supportFields]><span style='mso-bookmark:_Ref282075682'></span><span style='mso-element:field-begin'></span><span style='mso-bookmark:_Ref282075682'><span lang=EN-US> SEQ </span></span><span style='mso-bookmark:_Ref282075682'><span style='font-family:黑体;mso-ascii-font-family: Arial'>程序清单</span><span lang=EN-US> \* ARABIC \s 1 <span style='mso-element: field-separator'></span></span></span><![endif]-->14<!--[if supportFields]><span style='mso-bookmark:_Ref282075682'></span><span style='mso-element:field-end'></span><![endif]--> 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 supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

if (handle)

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

else

list_for_each_entry_rcu(handle, &dev->h_list, d_node) <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

if (handle->open) <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 3 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

handle->handler->event(handle, type, code, value); <!--[if supportFields]><span lang=DE><span style='mso-element:field-begin'></span> = 4 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=DE><span style='mso-element:field-end'></span></span><![endif]-->

rcu_read_unlock();

}

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

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 1 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->获取独占设备的handle的指针。如果有独占设备的handle,则仅仅将事件传给独占的handle对应的handler

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 2 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->遍历与此设备连接的每一个handle

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 3 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->如果hnadle已经被打开。

<!--[if supportFields]><span lang=EN-US><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&nbsp;</span>= 4 \* GB2 <span style='mso-element:field-separator'></span></span><![endif]--><!--[if supportFields]><span lang=EN-US><span style='mso-element:field-end'></span></span><![endif]-->将事件分发给handler的事件处理函数。

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics