闲聊linux中的input设备(11) 慢慢打开她的心扉

没错,到目前为止,akm input设备也注册了,evdev handler大叔的全貌也搞明白了,他们的女儿也亭亭玉立了……是不是该干正事的时候了?

好吧,我们就来看看如何来干这份正事:

还是列出那份操作集函数(handler大叔为我们这些笑的最后的弟兄精心准备的泡妹妹大法,不过现实生活中可没有这样的爸爸):

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,

       .unlocked_ioctl      = evdev_ioctl,

#ifdef CONFIG_COMPAT

       .compat_ioctl  = evdev_ioctl_compat,

#endif

       .fasync           = evdev_fasync,

       .flush             = evdev_flush

};

还记得吗?这就是我们精心填表后得到的那个u盾。

要了解evdev,咱先得打开她的心扉,来了解了解她。记得一位情圣曾经说过的一句话:要获得一位美女的好感,要做的第一件事就是能打开她的话匣子,要聊那些她感兴趣的事儿,彻底打开她的心扉,这样她就会对你产生信任感….接着呢?接着就不说了,有兴趣的兄弟可以找我聊聊(研发楼二楼进门就可以看到一个长的不是很搓的瘦瘦哥们)。

好了,在应用层,我们可以通过调用open函数然后转到我们这个操作集函数中的.open  = evdev_open,。是不是很简单。嗯,确实简单的一B。继续,看看具体打开过程:

 

static int evdev_open(struct inode *inode, struct file *file)

{

       1 struct evdev *evdev;

       2 struct evdev_client *client;

       3 int i = iminor(inode) - EVDEV_MINOR_BASE;

       4 int error;

 

       5 if (i >= EVDEV_MINORS)

       6     return -ENODEV;

 

       7 error = mutex_lock_interruptible(&evdev_table_mutex);

       8 if (error)

       9 return error;

       10 evdev = evdev_table[i];

       11 if (evdev)

       12    get_device(&evdev->dev);

       13 mutex_unlock(&evdev_table_mutex);

 

       14 if (!evdev)

       15    return -ENODEV;

 

       16 client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);

       17 if (!client) {

       18    error = -ENOMEM;

       19    goto err_put_evdev;

       20 }

 

       21 spin_lock_init(&client->buffer_lock);

       22 wake_lock_init(&client->wake_lock, WAKE_LOCK_SUSPEND, "evdev");

       23 client->evdev = evdev;

       24 evdev_attach_client(evdev, client);

 

       25 error = evdev_open_device(evdev);

       26 if (error)

       27   goto err_free_client;

 

       28 file->private_data = client;

       29 return 0;

 

30 err_free_client:

       31   evdev_detach_client(evdev, client);

       32  kfree(client);

    33  err_put_evdev:

       34   put_device(&evdev->dev);

       35 return error;

}

俗话说:话说三遍淡如水,再说三遍打驴嘴。相信看过我前面章节的哥们要来读懂这个函数,简直是 a piece of cake。不过还是有几行代码需要提一提:

310两行,第3行:通过设备节点号找到摇篮位置编号;第10行:通过这个摇篮编号找到那个孩子,对了,已经不是孩子了,是个美少女了。

16行,创建struct evdev_client,还记得吗,她是在struct evdev的基础上改造出来的品牌机。再三强调:不是山寨。

24行,进行绑定。

25行,关键的25行,怎么关键了,跟踪进去:

static int evdev_open_device(struct evdev *evdev)

{

       int retval;

 

       retval = mutex_lock_interruptible(&evdev->mutex);

       if (retval)

              return retval;

 

       if (!evdev->exist)

              retval = -ENODEV;

       else if (!evdev->open++) {

              retval = input_open_device(&evdev->handle);

              if (retval)

                     evdev->open--;

       }

 

       mutex_unlock(&evdev->mutex);

       return retval;

}

眼神不是很差的哥们马上会看到,有一行代码加粗了,他就是我们这个函数的核心。就好比小时候老师经常让我们写文章段落大意,找中心句子,如果找不出来,就去操场罚跑步。天生缺乏语言细胞,那时的我步可没少跑,连操场上捡垃圾的大妈都认识我了,偶尔一天侥幸过关没去跑,第二天大妈会说“小娃子,昨天是不是没来上课啊”。估计长不胖的一个重大原因就是小时候语文课上中心句子找少了。搞得现在一看到一堆代码,就想找出那个中心来。

好了继续跟踪进来,看看input_open_device(&evdev->handle)这个中心干了什么事情:

int input_open_device(struct input_handle *handle)

{

       struct input_dev *dev = handle->dev;

       int retval;

 

       retval = mutex_lock_interruptible(&dev->mutex);

       if (retval)

              return retval;

 

       if (dev->going_away) {

              retval = -ENODEV;

              goto out;

       }

 

       handle->open++;

 

       if (!dev->users++ && dev->open)

              retval = dev->open(dev);

 

       if (retval) {

              dev->users--;

              if (!--handle->open) {

                     /*

                      * Make sure we are not delivering any more events

                      * through this handle

                      */

                     synchronize_rcu();

              }

       }

 

 out:

       mutex_unlock(&dev->mutex);

       return retval;

我只能说:兄弟你太有才了,马上又一眼看穿中心句了;对就这里这个加粗部分:

handle->open++;。哥们对它有没有印象,不记得的话,打开第10节,看里面的第一段函数中的加粗部分,就是因为它,我们的数据才得以传递下去……

28 file->private_data = client;把这个client付给文件的私有数据,为什么赋给他,请看下一章节。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值