input子系统学习笔记六 按键驱动实例分析下 您所在的位置:网站首页 linux按键驱动实验分析 input子系统学习笔记六 按键驱动实例分析下

input子系统学习笔记六 按键驱动实例分析下

2024-07-02 18:51| 来源: 网络整理| 查看: 265

        本文接着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;          /*调用 is_event_supported()函数检查输入设备是否支持该事件*/          if (is_event_supported(type, dev->evbit, EV_MAX)) {                    spin_lock_irqsave(&dev->event_lock, flags);//调用 spin_lock_irqsave()函数对将事件锁锁定。                  add_input_randomness(type,code,value);//add_input_randomness()函数对事件发送没有一点用处,只是用来对随机数熵池增加一些贡献,因为按键输入是一种随机事件,所以对熵池是有贡献的。                  input_handle_event(dev, type, code, value);//调用 input_handle_event()函数来继续输入子系统的相关模块发送数据。该函数较为复杂,下面单独进行分析。                  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 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:          //调用 is_event_supported()函数判断是否支持该按键。                    if (is_event_supported(code, dev->keybit, KEY_MAX) &&                  !!test_bit(code, dev->key) != value) {                          //调用 test_bit()函数来测试按键状态是否改变。                          if (value != 2) {                                  __change_bit(code,dev->key);/*调用__change_bit()函数改变键的状态。*/                                            if (value)                                                  input_start_autorepeat(dev, code);/*处理重复按键的情况。*/                                            else                                                  input_stop_autorepeat(dev);                          }                    disposition = INPUT_PASS_TO_HANDLERS;/*将 disposition变量设置为 INPUT_PASS_TO_HANDLERS,表示事件需要 handler 来处理。disposition 的取值有如下几种:                         1. #define INPUT_IGNORE_EVENT 0                         2. #define INPUT_PASS_TO_HANDLERS 1                         3. #define INPUT_PASS_TO_DEVICE 2                         4.#define INPUT_PASS_TO_ALL(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)                 INPUT_IGNORE_EVENT 表示忽略事件,不对其进行处理。INPUT_PASS_ TO_HANDLERS 表示将事件交给handler处理。INPUT_PASS_TO_DEVICE 表示将事件交给 input_dev 处理。INPUT_PASS_TO_ALL 表示将事件交给 handler 和 input_dev 共同处理。 */            }          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 = 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)/*处理 EV_SYN 事件,这里并不对其进行关心。*/            dev->sync = 0;          /*首先判断 disposition 等于 INPUT_PASS_TO_DEVICE,然后判断 dev->event 是否对其指定了一个处理函数,如果这些条件都满足,则调用自定义的 dev->event()函数处理事件。有些事件是发送给设备,而不是发送给 handler 处理的。event()函数用来向输入子系统报告一个将要发送给设备的事件,例如让 LED 灯点亮事件、蜂鸣器鸣叫事件等。当事件报告给输入子系统后,就要求设备处理这个事件。*/          if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)          dev->event(dev, type, code, value);          /*第 87、88 行,如果事件需要 handler 处理,则调用 input_pass_event()函数         */          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;/*分配一个 input_handle 结构的指针。*/          rcu_read_lock();            handle = rcu_dereference(dev->grab);/*得到 dev->grab 的指针。         grab 是强制为 input device 的 handler,这时要调用 handler的 event 函数。*/          if (handle)          handle->handler->event(handle, type, code, value);          else {          bool filtered = false;              /*表示如果没有为 input device 强制指定 handler,为 grab 赋值,即就会遍历 input device->h_list 上的 handle 成员。如果该 handle 被打开,表示该设备已经被一个用户进程使用。就会调用与输入设备对应的 handler 的 event()函数。注意,只有在 handle 被打开的情况下才会接收到事件,这就是说,只有设备被用户程序使用时,才有必要向用户空间导出信息。*/          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;          }          } 


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有