感谢终结者投递本文】
本文接着input子系统学习笔记五 按键驱动实例分析上接续分析这个按键驱动实例!
input_report_key()向子系统报告事件
在 button_interrupt()中断函数中,不需要考虑重复按键的重复点击情况,input_report_key()函数会自动检查这个问题,并报告一次事件给输入子系统。该函数的代码如下:
C++代码
- static inline void input_report_key(struct input_dev *dev,unsigned int
- code, int value)
- {
- input_event(dev, EV_KEY, code, !!value);
- }
该函数的第 1 个参数是产生事件的输入设备, 第2 个参数是产生的事件, 第3 个参数是事件的值。需要注意的是, 2 个参数可以取类似 BTN_0、 BTN_1、BTN_LEFT、BTN_RIGHT 等值,这些键值被定义在 include/linux/input.h 文件中。当第 2 个参数为按键时,第 3 个参数表示按键的状态,value 值为 0 表示按键释放,非 0 表示按键按下。
input_event()
在 input_report_key()函数中正在起作用的函数是 input_event()函数,该函数用来向输入子系统报告输入设备产生的事件,这个函数非常重要,它的代码如下:
Java代码
- 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);
- }
- }
is_event_supported()
C++代码
- static inline int is_event_supported(unsigned int code,
- unsigned long *bm, unsigned int max)
- {
- return code <= max && test_bit(code, bm);
- }
该函数检查 input_dev.evbit 中的相应位是否设置,如果设置返回 1,否则返回 0。每一种类型的事件都在 input_dev.evbit 中用一个位来表示,构成一个位图,如果某位为 1,表示该输入设备支持这类事件,如果为 0,表示输入设备不支持这类事件。目前 Linux 支持十多种事件类型,所以用一个 long 型变量就可以全部表示了。
input_handle_event()
input_handle_event()函数向输入子系统传送事件信息。第 1 个参数是输入设备 input_dev,第 2 个参数是事件的类型,第 3 个参数是键码,第 4 个参数是键值。该函数的代码如下:
C++代码
- 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_SYN:
- switch (code) {
- case SYN_CONFIG:
- disposition = INPUT_PASS_TO_ALL;
- break;
-
- case SYN_REPORT:
- if (!dev->sync) {
- dev->sync = 1;
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
- case SYN_MT_REPORT:
- dev->sync = 0;
- disposition = INPUT_PASS_TO_HANDLERS;
- break;
- }
- break;
-
- 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);
- }
-
- disposition = INPUT_PASS_TO_HANDLERS;
-
-
-
-
-
-
- }
- break;
-
- case EV_SW:
- if (is_event_supported(code, dev->swbit, SW_MAX) &&
- !!test_bit(code, dev->sw) != value) {
-
- __change_bit(code, dev->sw);
- disposition = INPUT_PASS_TO_HANDLERS;
- }
- break;
-
- case EV_ABS:
- if (is_event_supported(code, dev->absbit, ABS_MAX)) {
-
- if (test_bit(code, input_abs_bypass)) {
- disposition = INPUT_PASS_TO_HANDLERS;
- break;
- }
-
- 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;
-
- case EV_MSC:
- if (is_event_supported(code, dev->mscbit, MSC_MAX))
- disposition = INPUT_PASS_TO_ALL;
-
- break;
-
- case EV_LED:
- if (is_event_supported(code, dev->ledbit, LED_MAX) &&
- !!test_bit(code, dev->led) != value) {
-
- __change_bit(code, dev->led);
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_SND:
- if (is_event_supported(code, dev->sndbit, SND_MAX)) {
-
- if (!!test_bit(code, dev->snd) != !!value)
- __change_bit(code, dev->snd);
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_REP:
- if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
- dev->rep[code] = value;
- disposition = INPUT_PASS_TO_ALL;
- }
- break;
-
- case EV_FF:
- if (value >= 0)
- disposition = INPUT_PASS_TO_ALL;
- break;
-
- case EV_PWR:
- disposition = INPUT_PASS_TO_ALL;
- 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_pass_event()
input_pass_event()函数将事件传递到合适的函数,然后对其进行处理,该函数的代码如下:
C++代码
- 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);
-
- if (handle)
- handle->handler->event(handle, type, code, value);
- else {
- 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;
-
- handler->event(handle, type, code, value);
-
- } else if (handler->filter(handle, type, code, value))
- filtered = true;
- }
- }
- 原文 http://www.ourunix.org/post/295.html