linux输入子系统(4)
来源:互联网 发布:ubuntu删除virtualbox 编辑:程序博客网 时间:2024/06/05 16:20
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输入子系统(4)
- linux输入子系统(4)
- linux输入子系统(4)
- linux驱动子系统之输入子系统(4)
- linux驱动子系统之输入子系统(4)
- linux输入子系统(1)
- linux输入子系统(2)
- linux输入子系统(3)
- linux输入子系统(5)
- linux输入子系统(1)
- linux输入子系统(2)
- linux输入子系统(3)
- linux输入子系统(5)
- linux输入子系统(2)
- linux输入子系统(3)
- linux输入子系统(1)
- linux输入子系统(2)
- linux输入子系统(3)
- Task Scheduler in C#.Net
- 技术人员为什么要写博客
- MVC中使用EF(3):实现排序,过滤,分页
- linux中创建scst iscsi-scst
- org.gjt.mm.mysql.Driver和com.mysql.jdbc.Driver的区别
- linux输入子系统(4)
- 程序的链接和加载基础(2)
- 用JDIC写浏览器
- 找工作要看的
- plsql 乱码问题
- 大数加法 减法 乘法 除法 高精度四则运算
- vim基础
- xcode 添加Icon的方法
- MyBatis映射文件的resultMap如何做表关联