韦东山视频实验之Input子系统分析之二

应用程序如何read?

Input子系统分析之一讲过应用程序去open,那么如何read呢?

搜遍input.c 也没有提供read的函数,有一个可惜不是;那read在哪里定义的呢?想到可能在evdev.c里定义的,先看下他的初始化模块

仍以evdev.c (drivers/input/evdev.c)为基础进行说明:

static int __init evdev_init(void)
{
 return input_register_handler(&evdev_handler);
}

上文说过input_register_handler 就是在这里调用的,下面来看一下传入的参数evdev_handler,定义如下

static struct input_handler evdev_handler = {
 .event  = evdev_event,
 .connect = evdev_connect,
 .disconnect = evdev_disconnect,
 .fops  = &evdev_fops,
 .minor  = EVDEV_MINOR_BASE,
 .name  = "evdev",
 .id_table = evdev_ids,
};

看到这里面有一个fops操作集合,默认用evdev_fops填充的,猜想肯定是在这里面

static const struct file_operations evdev_fops = {
 .owner  = THIS_MODULE,
 .read  = evdev_read,
 .write  = evdev_write,
 .poll  = evdev_poll,
 .open  = evdev_open,
 .release = evdev_release,
...
 .fasync  = evdev_fasync,
 ...
};

看看在这个函数里面如何read的??

if (client->head == client->tail && evdev->exist &&
     (file->f_flags & O_NONBLOCK))
  return -EAGAIN;

 // wake up wait queue
 retval = wait_event_interruptible(evdev->wait,
  client->head != client->tail || !evdev->exist);
 if (retval)
  return retval;

整个就是有数据可读,就是按键按下,直接执行下面的,否则休眠

 while (retval + input_event_size() <= count &&
        evdev_fetch_next_event(client, &event))

{

  if (input_event_to_user(buffer + retval, &event))
   return -EFAULT;

  retval += input_event_size();
 }

这里面有点疑问retval+input_event_size() 没理解??而且retval是wait_event_interruptible返回的,奥明白了

只有retal=0才会跳到这里,如果休眠的话肯定返回了,那就是有数据可读,其实这个就转换为input_event_size()<=count

似乎有点多此一举,其实不是的,下面有的,利用它读剩余事件。

先看下input_event_size(),这个函数是得到sizeof(struct input_event),而input_event是什么呢?

struct input_event {
 struct timeval time;
 __u16 type;
 __u16 code;
 __s32 value;
};

就是它!没错,平时发送的事件就是它,就是用它来传送的

evdev_fetch_next_event(client, &event)是用来取出里面的event事件的,这个函数里面会指定处理的最大事件数量为64

#define EVDEV_BUFFER_SIZE 64

  *event = client->buffer[client->tail++];
  client->tail &= EVDEV_BUFFER_SIZE - 1;

接着就调用input_event_to_user(buffer + retval, &event)函数,发送到用户空间

这里面调用的方式不一样,处理也不一样,这个函数最终会调用copy_to_user(buffer, event, sizeof(struct input_event)),不再陈述

上面牵涉到一个问题在哪里唤醒刚才休眠的队列?

在本文家搜素这个wait队列,有两处提供唤醒,一处是evdev_hangup函数,另一处是evdev_event,而后面一处正是我们需要的

这个evdev_event如何被调用?

一般大家能猜到的就是中断服务程序,下面进入一般都是驱动提供的服务程序里,使用input_event函数,这个函数里面会调用下面的函数

input_handle_event(dev, type, code, value);

进入此函数,看一下这个函数怎么实现的?这个肯定是讲键盘有关的事件进行上传,在后面会进行陈述

 

自此全部完结,肯定还没有搞懂怎么回事??其实这样的,

你先讲模块放入内核编译,或者insmod此input模块后,就已经将input_dev注册进去了,而且注册了中断之类的

而handler之类的大部分框架底层已帮我们实现好了,接下来看下应用程序

 int buttons_fd;
 int key_value, i=0, count;

 struct input_event ev_key;
 buttons_fd = open("/dev/event0", O_RDWR);

 while(1)
 {
  count = read(buttons_fd, &ev_key, sizeof(struct input_event));
  for(i=0; i<(int)count/sizeof(struct input_event); i++)
  {
   //对每一个事件的处理
  }

 }
 close(buttons_fd);

1. 应用程序打开input设备,并在read处阻塞(前面有调用具体的函数),然后就等待中断的触发,

2. 当按下按钮时就触发了中断,中断里面调用input_event去上传按键事件,最终调用input_pass_event,如何处理的??敬请期待

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值