linux键盘input_event浅析【转】
转自:http://blog.csdn.net/tdstds/article/details/18710965
input_event(mxckbd_dev, EV_KEY, mxckpd_keycodes[scancode], 0);
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);
}
}
***********************************************************************************************
static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max)
{
return code <= max && test_bit(code, bm);
}
static inline int test_bit(int nr, const volatile unsigned long *addr)
{
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}
***********************************************************************************************
void add_input_randomness(unsigned int type, unsigned int code, unsigned int value)
{
static unsigned char last_value;
/* ignore autorepeat and the like */
if (value == last_value)
return;
DEBUG_ENT("input event\n");
last_value = value;
add_timer_randomness(&input_timer_state, (type << 4) ^ code ^ (code >> 4) ^ value);
}
***********************************************************************************************
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);
else
input_stop_autorepeat(dev);
}
// INPUT_PASS_TO_HANDLERS: 事件处理的方式是传递给事件处理器
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);
}
static void input_pass_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handler *handler;
struct input_handle *handle;
rcu_read_lock();
handle = rcu_dereference(dev->grab);
//如果是绑定的handle,则调用绑定的handler->event函数
if (handle)
handle->handler->event(handle, type, code, value);
else
{
//如果没有绑定,则遍历dev的h_list链表,寻找handle,如果handle已经打开,说明有进程读取设备关联的evdev。
bool filtered = false;
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
{
if (!handle->open)
continue;
handler = handle->handler;
if (!handler->filter)
{
if (filtered)
break;
// 调用相关的事件处理器的event函数,进行事件的处理
handler->event(handle, type, code, value);
}
else if(handler->filter(handle, type, code, value))
filtered = true;
}
}
rcu_read_unlock();
}
static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) // evdev.c
{
struct evdev *evdev = handle->private;
struct evdev_client *client;
struct input_event event;
struct timespec ts;
ktime_get_ts(&ts);
// 将传过来的事件,赋值给input_event结构
event.time.tv_sec = ts.tv_sec;
event.time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
event.type = type;
event.code = code;
event.value = value;
rcu_read_lock();
client = rcu_dereference(evdev->grab);
if (client) // 如果evdev绑定了client那么,处理这个客户端,触摸屏驱动没有绑定
evdev_pass_event(client, &event);
else // // 遍历client链表,调用evdev_pass_event函数
list_for_each_entry_rcu(client, &evdev->client_list, node)
evdev_pass_event(client, &event);
rcu_read_unlock();
wake_up_interruptible(&evdev->wait); //唤醒等待的进程
}
// evdev_pass_event函数最终将事件传递给了用户端的client结构中的input_event数组中,只需将这个input_event数组
// 复制给用户空间,进程就能收到触摸屏按下的信息了。具体处理由具体的应用程序来完成。
static void evdev_pass_event(struct evdev_client *client, struct input_event *event) // evdev.c
{
/*
* Interrupts are disabled, just acquire the lock
*/
spin_lock(&client->buffer_lock);
client->buffer[client->head++] = *event; // 将事件赋值给客户端的input_event 数组
client->head &= EVDEV_BUFFER_SIZE - 1;
spin_unlock(&client->buffer_lock);
if (event->type == EV_SYN)
kill_fasync(&client->fasync, SIGIO, POLL_IN);
}
***********************************************************************************************
linux键盘input_event浅析【转】的更多相关文章
- Linux模块机制浅析
Linux模块机制浅析 Linux允许用户通过插入模块,实现干预内核的目的.一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析. 模块的Hello World! ...
- Linux 设备模型浅析之 uevent 篇(2)
Linux 设备模型浅析之 uevent 篇 本文属本人原创,欢迎转载,转载请注明出处.由于个人的见识和能力有限,不可能面 面俱到,也可能存在谬误,敬请网友指出,本人的邮箱是 yzq.seen@gma ...
- linux内核cfs浅析
linux调度器的一般原理请参阅<linux进程调度浅析>.之前的调度器cfs之前的linux调度器一般使用用户设定的静态优先级,加上对于进程交互性的判断来生成动态优先级,再根据动态优先级 ...
- Linux 键盘输入#的时候变成£
/********************************************************************************* * Linux 键盘输入#的时候变 ...
- Linux模块机制浅析_转
Linux模块机制浅析 转自:http://www.cnblogs.com/fanzhidongyzby/p/3730131.htmlLinux允许用户通过插入模块,实现干预内核的目的.一直以来,对l ...
- Linux进程IPC浅析[进程间通信SystemV共享内存]
Linux进程IPC浅析[进程间通信SystemV共享内存] 共享内存概念,概述 共享内存的相关函数 共享内存概念,概述: 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到 ...
- 【ARM-Linux开发】Linux模块机制浅析
Linux模块机制浅析 Linux允许用户通过插入模块,实现干预内核的目的.一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析. 模块的Hello World! ...
- 13.Linux键盘驱动 (详解)
版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的 ...
- 13.Linux键盘按键驱动 (详解)
在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的4个按键代表键盘中的L.S.空格键.回车键 1.先来介 ...
随机推荐
- Educational Codeforces Round 56 Div. 2 翻车记
A:签到. B:仅当只有一种字符时无法构成非回文串. #include<iostream> #include<cstdio> #include<cmath> #in ...
- 十三个有彩蛋的Linux命令
原文链接: https://my.oschina.net/u/4045573/blog/2986313 一键下载安装配置文本全部命令所需环境 sudo apt-get updategit clon ...
- P3216 [HNOI2011]数学作业
题目描述 小 C 数学成绩优异,于是老师给小 C 留了一道非常难的数学作业题: 给定正整数 N 和 M ,要求计算Concatenate (1 .. N) Mod M 的值,其中 Concatenat ...
- 如何将SLIC集成到ESXi中
如何将SLIC集成到ESXi中 参考 http://forums.mydigitallife.info/threads/12982-ESX-ESXi-Bios-Tools/page34?p=72183 ...
- 【BZOJ1046】上升序列(动态规划,贪心)
[BZOJ1046]上升序列(动态规划,贪心) 题面 BZOJ 洛谷 题解 我一开始看错题了,一度以为是字典序最小的序列. 最后发现它要求的字典序是位置的字典序最小. 那就很好办了. 设\(f[i]\ ...
- Linux内核设计与实现第八周读书笔记
第四章 进程调度 进程在操作系统看来是程序的运行态表现形式. 4.1多任务 多任务操作系统就是能同时并发地交互执行多个进程的操作系统. 多任务操作系统会使多个进程处于堵塞或者睡眠状态.这些任务尽管位于 ...
- Android Fragment 替代方案
refs: Square 开源库Flow和Mortar的介绍https://github.com/hehonghui/android-tech-frontier/tree/master/android ...
- 【贪心/Trie】【CF1083B】 The Fair Nut and Strings
Description 有 \(k\) 个长度为 \(n\) 的只含 \(a\) 或 \(b\) 字符串,并不知道它们具体是多少,只知道它们的字典序不小于字符串 \(A\),同时不大于字符串 \(B\ ...
- Qt 查找功能
版权声明 该文章原创于Qter开源社区(www.qter.org),作者yafeilinux,转载请注明出处! 导语 这一篇我们来加上查找菜单的功能.因为要涉及Qt Creator的很多实用功 ...
- tp 用group去重
$baseGoodIds_arr = [1,2,3,4,5,6,7,8,9];$relate_gimgs = D('GoodsImages')->where(['good_id' => [ ...