Chinaunix首页 | 论坛 | 博客
  • 博客访问: 267203
  • 博文数量: 107
  • 博客积分: 305
  • 博客等级: 二等列兵
  • 技术积分: 417
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-22 09:42
文章分类

全部博文(107)

文章存档

2014年(3)

2013年(41)

2012年(34)

2011年(28)

2008年(1)

分类: LINUX

2013-08-19 10:11:04

原文地址:input子系统分析2 作者:driver2012

    在分析1里,我们看到了input_dev、input_handler以及input_handle三者之间的联系和实现的原理。下面我们看下具体event事件的处理流程。我们的driver中一般是使用input_report_key()来上报事件,然后再以input_sync()来结束这次的上报事件。input_report_key()里使用的是input_event()来完成这步的操作,关于input_event(),先是判断本次事件是否被支持,若支持的话则调用input_handle_event(),input_handle_event()里面主要就是匹配传过来的事件类型及按键类型,然后针对不同的类型选择合适的处理方式。最后我们根据具体需要处理的类型进行处理。若需要输入设备参与的,我们回调设备的event(),即dev->event(dev,type,code,value),若需要handler处理的,我们使用input_pass_event(dev,type,code,value)。关于input_pass_event(),我们重点看下:

点击(此处)折叠或打开

  1. static void input_pass_event(struct input_dev *dev,
  2.                                  unsigned int type, unsigned int code, int value)
  3. {
  4.          struct input_handle *handle;
  5.  
  6.          rcu_read_lock();
  7.  
  8.          handle = rcu_dereference(dev->grab);
  9.          if (handle)
  10.                    handle->handler->event(handle, type, code, value);
  11.          else
  12.                    list_for_each_entry_rcu(handle, &dev->h_list, d_node)
  13.                             if (handle->open)
  14.                                      handle->handler->event(handle,type, code, value);
  15.          rcu_read_unlock();
  16. }
    这段代码我们仔细看看,它根据获得的handle值进行执行,这里grab的类型是input_handle,若具体的handle已存在则直接调用handler的event,否则遍历整个input_dev的h_list上的handle成员,如果handle被打开,则调用与输入设备相对应的handler的event。
    input_pass_event()中最后会调用handler的event(),handler中绑定了具体的connect()的终极执行者为evdev_event(),所以最终将跳转到evdev_event()执行,再然后根据具体判断跳转到evdev_pass_event(),看看此函数都做了些什么:

点击(此处)折叠或打开

  1. static void evdev_pass_event(struct evdev_client *client,struct input_event *event)
  2. {
  3.  
  4.  spin_lock(&client->buffer_lock);
  5.  
  6.  client->buffer[client->head++] = *event;
  7.  
  8.  client->head &= EVDEV_BUFFER_SIZE - 1;
  9.  spin_unlock(&client->buffer_lock);

  10.  kill_fasync(&client->fasync, SIGIO, POLL_IN);
  11. }
    我们可以清楚的看到,具体的事件被存放在buffer中,而将head加1操作,这里的加1预示报告事件的操作完成,至此一个事件就完成了,返回调用的系统中(一般是一个中断的完成),根据head值,知道hend!=tail了,直接唤醒等待队列进行操作。这里的操作就是具体的我们定义的input_handler中的fops,此fops的类型为file_operations,它里面提供了evdev_read,供我们的app来read。至此事件处理告一段落。上面是input子系统重要的一些实现code,下面再从上至下做一个宏观的总结。

阅读(460) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~