linux驱动之输入子系统

原创 2017年03月03日 11:35:04

输入子系统框架,把内核打开 搜索input.c

输入子系统的代码在/driver/input目录下面 最上一层,我们称它为核心层

要看一个驱动程序我们应该从他的入口函数开始看


有一行:err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),INPUT_MAX_CHAR_DEVICES, "input");//注册字符设备,以前是我们自己写的,现在这套代码里面已经有了


在 2.4 的内核我们使用 register_chrdev(0, "hello", &hello_fops) 来进行字符设备设备节点的分配,这种方式每一个主设备号只能存放一种设备,它们使用相同的 file_operation 结构体,也就是说内核最多支持 256 个字符设备驱动程序。

在 2.6 的内核之后,新增了一个 register_chrdev_region 函数,它支持将同一个主设备号下的次设备号进行分段,每一段供给一个字符设备驱动程序使用,使得资源利用率大大提升,同时,2.6 的内核保留了原有的 register_chrdev 方法。在 2.6 的内核中这两种方法都会调用


下一层是evdev.c,keyboard.c mousedev.c


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

他们向上注册input_register_handler 向input.c 

可以看下这个evdev_handler这个里面有什么东西


这里面有个fops


handler是个纯软件的 handler处理


还一个层,设备层

设备层向input.c注册input_register_device  上面是纯软件的东西,这里就代表硬件


这个handler能不能处理这个device呢 ,这里肯定会有个联系 我们先看一下这个handler

这里有个.id_table= evdev_ids,就是表示支持哪一些设备

当你注册handler和注册设备的时候,他们会比较一下,看看这个handler能不能支持这个设备


在这里可以看出来,如果能够支持的话就会调用这个connect函数

搜索input_register_device会发现各种外设如鼠标什么的都调用了这个函数

我们input_register_device这个主要做了什么事情,大概看一眼

list_add_tail(&dev->node, &input_dev_list);会把device结构体放到链表里面去


list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);

handler也会有一个链表,对这个链表里面的每一项都调用input_attach_handler(dev, handler);这个函数会根据input_handler的id_tabler判断能否支持这个input_dev。


我们来看看另外一边input_register_handler这里面做了什么事情

list_add_tail(&handler->node, &input_handler_list);//放到一个链表里面去

list_for_each_entry(dev, &input_dev_list, node)//对于每个input_device调用input_attach_handler
input_attach_handler(dev, handler);这个函数会根据input_handler的id_tabler判断能否支持这个input_dev。


来看看input_attach_handler这个函数

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
const struct input_device_id *id;
int error;


id = input_match_device(handler, dev);//根据这个handler的id_table和输入设备比较一下,看看能不能支持,是否匹配


if (!id)
return -ENODEV;


error = handler->connect(handler, dev, id);//如果可以的话调用handler里面的connect函数
if (error && error != -ENODEV)
pr_err("failed to attach handler %s to device %s, error: %d\n",
      handler->name, kobject_name(&dev->dev.kobj), error);


return error;
}

注册input_dev和input_handler时,会两两比较左边的input_dev和右边的input_handler

根据input_handler的id_table判断这个input_handler能否支持这个input_dev

如果能支持,则调用input_handler的connect函数建立“连接”


怎么建立连接的

我们来看看 

evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);这里分配一个evdev结构体,分配了一个input_handle,注意没有r,跟之前相比没有r,

然后来设置它

evdev->handle.dev = input_get_device(dev);指向左边的input_device结构体
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler; 指向右边的input_handler结构体
evdev->handle.private = evdev;


evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;


error = input_register_handle(&evdev->handle);//然后注册这个handle


然后我们进去看一看这个函数

if (handler->filter)
list_add_rcu(&handle->d_node, &dev->h_list); 
else
list_add_tail_rcu(&handle->d_node, &dev->h_list); 把这个handle放到一个输入设备的链表里面


list_add_tail_rcu(&handle->h_node, &handler->h_list); 把这个handle放到handler的链表里面



连接的时候构造一个input_handle 里面有个dev指向输入设备,里面有个handler指向handler



input_devie里面有个h_list, handler也有一个h_list

这两个h_list都指向这个handle 所以我们device可以通过这个h_list找到这个handle,又可以通过这个handle找到这个handler,反过来也是一样的


所以怎么建立连接总结起来就是

1.分配一个input_handle结构体

2.input_handle.dev=input_dev;//指向input_device

    input_handle.handler=input_handler;//指向input_handler

3.注册

注册里面干了什么事了 就是input_handler->h_list =&input_handle

input_device>h_list =&input_handle


所以我们handler可以通过h_list找到input_handle input_handle里面有个input_handle.handler = handler;可以找到handler 反过来一样的



我们拿按键驱动来举例子

我们应用程序来读,最终会导致相应的handler里面的里面的fops里面的read函数被调用

我们拿evdev_read来说明




有休眠就有唤醒,那么被谁唤醒呢,被谁唤醒不好找,那我们来搜索evdev->wait这个东西,

结果可以发现在.event= evdev_event,这个里面唤醒 从这个单词就可以知道它是发生了某些事件



那么问题有来了,被它唤醒,但是这个东西又是被谁调用

我们可以猜测应该是硬件相关的代码,应该是input_device这一层调用的

有个例子比较好,搜索gpio_keys.c这个,这只是一个例子



如此可以看出 在设备的中断服务程序里面,确定事件是什么,然后调用相应的input_handler的event处理函数

实际上这就是我们的核心 input_event就是用来上报事件的

void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value) 这个函数有个参数是input_device

函数里有个成员是input_handler


list_for_each_entry(handle,&dev->h_list,d_node)

if(handle->open)

handle->handler->event(handle,type,code,value);



怎么写一个符合输入子系统框架的驱动程序

1.分配一个input_dev结构体

2.设置

3.注册

4.硬件相关的代码,比如中断服务程序上报事件











linux设备驱动那点事儿之输入子系统理论篇

 Linux输入子系统(Input Subsystem) 1.1.input子系统概述 输入设备(如按键,键盘,触摸屏,鼠标等)是典型的字符设备,其一般的工作机制是低层在按键,触...
  • Liuqz2009
  • Liuqz2009
  • 2016年03月03日 14:46
  • 770

linux驱动之输入子系统概念

以前的博文介绍linux驱动程序的时候一直遵循以下步骤: 确定主设备号定义一个file_operation结构,填充函数如:open  write  read poll等设备注册入口函数出口函数 以...
  • a912293097
  • a912293097
  • 2014年12月24日 23:00
  • 1669

我对linux驱动 输入子系统的理解

前言:学习驱动有一段时间了,之前所学习的驱动都是驱动最原始的写法,也移植过很多驱动,然而并没有对内核自带的驱动进行深入的了解,于是出于好奇,就认真的学习了一下内核自带的驱动,我发现之前所学习的驱动都是...
  • zouleideboke
  • zouleideboke
  • 2017年04月24日 22:40
  • 620

Linux驱动之输入子系统框架

好记性不如烂笔头,整理一下笔记~ Linux驱动之输入子系统框架 输入子系统将该类驱动划分为3部分 1、核心层 input.c 2、设备层 Gpio_keys.c ... 3、事件处理层 Evd...
  • lizuobin2
  • lizuobin2
  • 2016年05月26日 17:06
  • 6176

Linux输入子系统框架分析及输入设备驱动编程

Linux输入子系统框架linux输入子系统(linux input subsystem)从上到下由三层实现,分别为:输入子系统事件驱动程序层(EventHandler)、输入子系统核心层(Input...
  • were0415
  • were0415
  • 2016年11月29日 16:22
  • 635

linux驱动之输入子系统

对于驱动开发者来说,对按键 触摸屏 鼠标等设备分别进行文件操作显得很繁琐,他们具有一些相同的规律,即内核负责记录数据,应用负责读取数据,因此,内核开发者为了简化驱动开发者的工作,特地创造了输入子系统。...
  • fffffcccccv
  • fffffcccccv
  • 2015年07月06日 20:35
  • 429

linux驱动之--输入子系统

输入子系统模型 构建出口入口函数 module_init(simple_input_dev_init); module_exit(simple_input_dev_exit); MODULE_L...
  • zhanglz314159
  • zhanglz314159
  • 2016年05月18日 14:22
  • 71

Linux驱动之input输入子系统

input输入子系统在实际项目中用的也比较多,按键,触摸屏,鼠标,键盘等,用来实现内核层和应用层数据之间的传递,这里得说明不只有input,还有copy_to_user等,利用input的好处是我们用...
  • qq_21792169
  • qq_21792169
  • 2015年09月14日 13:06
  • 3339

Linux驱动之输入子系统

输入子系统的概念 输入子系统是对分散的、多种不同类别的输入设备(键盘、鼠标、触摸屏、加速计、跟踪球、操纵杆等)进行统一处理的驱动程序。 2. 输入子系统的优点 抽象底层形态各异的硬...
  • flyoung1994
  • flyoung1994
  • 2016年06月19日 23:07
  • 158

Linux驱动子系统之输入子系统

[内容概要] 介绍了input-subsystem的三个组成部分,并对主要结构体和函数进行了分析以及它们如何关联。 [概述] 内核的输入子系统是对分散的、多种不同类别的输入设...
  • beckdon
  • beckdon
  • 2016年02月26日 20:54
  • 350
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux驱动之输入子系统
举报原因:
原因补充:

(最多只允许输入30个字)