input子系统驱动学习之中的一个
刚一開始我就陷入了一个困境,理不清究竟input子系统驱动哪些是我须要做的哪些是系统已经为我们完毕的。为此花费了我一个星期的时间才真正的从这个困惑里走出来。当然后边还有非常多其它的困难这里我就不多说了,以下我就来总结一下input子系统学习的过程。
首先我们要清楚input子系统分为几层,各层都有些什么,以及各自的功能
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhaGFpY2Fv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

这一层中包括一个input_dev结构体,它是用来描写叙述一个设备的信息的。
包括了对设备的各项设置及操作函数。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhaGFpY2Fv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

这一层包括一个input_handle结构体。它做为input_dev和input_handler之间的桥梁 ,将handle的list_headd_node加入到handle关联的dev的h_list中, 将handle的list_headh_node加入到handle关联的handler的h_list中。

使设备驱动部分不再关心对设备文件的操作而仅仅需关心对各硬件寄存器的操作和提交的输入事件就可以 。
这一层包括了input_handler结构体,它是作为事件处理器相应用程序的接口。


二、input子系统驱动的实现过程
2.1 分配一个输入设备
struct input_dev *dev;//声明一个输入设备结构体
Struct input_dev
{
const char *name;//输入设备的名称
...
struct input_id id;//输入设备的ID号
...
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//输入设备所支持的事件类型
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//保存设备所支持的事件码
...
//输入设备文件接口操作函数指针
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
struct input_handle __rcu *grab;
struct device dev;// 表示SYS设备模型中的一个设备
struct list_head h_list;//
struct list_head node;
}
dev=input_allocate_device(void);//为声明的结构体分配空间
2.2 驱动支持什么事件
这一步我们能够设置输入设备支持哪些事件类型。以鼠标为例我们能够设置设备支持按键事件和相对坐标事件,在设置完支持的事件类型后还须要设置事件类型的码表,即该事件所包括的子事件。
input_dev->evbit[0] = BIT(EV_KEY); //赋值使输入设备支持按键类型
input_dev->keybit[BITS_TO_LONGS(KEY_CNT)=BIT(BTN_LEFT)| BIT(BTN_RIGHT)|BIT(BTN_MIDDLE); //按键类型的键码,左键、右键、中键
2.3 注冊一个输入设备
这一步调用的是input_register_device()函数。该函数是输入子系统核心层提供的函数。该函数将 input_dev结构体注冊到输入子系统核心中。input_register_device()函数假设注冊失败,必须调用 input_free_device()函数释放分配的input_dev的空间。
假设该函数注冊成功,在卸载函数中应该调用 input_unregister_device()函数来注销输入设备结构体。注冊输入设备的过程就是为输入设备设置默认值,并将其挂在input_dev_list链上,与挂载在 input_handler_list 中的 handler 相匹配。假设匹配成功,就会调用 handler 的 connect函数。
int input_register_device(struct input_dev *dev)。//向input子系统注冊一个新的输入设备
2.4 驱动事件报告
这一步是有设备驱动层向核心层报告发生的事件,比如按键事件。相对坐标事件等。这些事件全都汇总到核心层由核心层统一分配到事件处理层。
input_report_key(dev,BTN_LEFT,value);
实质是函数:input_event(dev,type,value);
2.5 释放和注销设备
这一步用来注销输入设备并清除为该设备分配的空间。
void input_unregister_device(struct input_dev *dev);
void input_free_device(struct input_dev *dev);
通过以上的介绍我们了解了整个input子系统驱动程序的编写流程,以下让我们依据usb鼠标驱动程序来看一看input子系统驱动程序的实现过程。
以下就来说一说三个结构体的连接过程
在我们编写的设备驱动中调用input_register_device()来注冊一个设备。 input_register_device()完毕的主要功能就是初始化一些默认的值,将自己的device结构加入到linux设备模型其中。将input_dev加入到input_dev_list链表中。然后寻找合适的handler与input_handler配对,配对的核心函数是input_attach_handler。
input_attach_handler的主要功能则是调用了两个函数。一个是input_match_device进行配对,一个connect处理配对成功兴许工作。这些函数我们能够在linux内核源代码中进行查看。
对于connect函数,每种事件处理器的实现都有差异,但原理都同样,以事件处理器evdev为例,其connect函数为evdev_connect()。evdev_connect函数做配对后的善后工作,分配一个evdev结构体,并初始化相关成员。evdev结构体中有input_handle结构,在函数evdev_connect()中实现该结构体的初始化并调用 input_register_handle实现注冊。
input_register_handle()就是把一个handle结构体通过d_node链表项。分别链接到input_dev的h_list,input_handler的h_list上。
从而实现了3个结构体的连接。
总结
Input子系统驱动的编写须要我们理清哪些操作是须要我们做的,哪些操作是子系统已经为我们完毕了的。这一点非常重要,唯独我们明确了自己须要做些什么才干让我们更快的学会input子系统程序的编写。在这一个过程中我就走了非常多弯路。起先对input子系统不是太多了解,通过网上查找相关介绍和浏览上课的PPT,我看到了非常多关于input子系统驱动的介绍。 但这些介绍不只包括了我们须要做的并且还包括了系统已经为我们完毕了的。 这给我的学习带来了非常大的困扰,我不明确到底我该从何下手编写一个完整的input子系统设备驱动了。通过一遍又一遍的浏览体会我最终明确了哪些是我须要做的。在这个过程中我也学会了怎样查看linux内核源代码。
input子系统驱动学习之中的一个的更多相关文章
- input子系统驱动
input子系统驱动 框架分析 核心层 文件为:/drivers/input/input.c: 首先找到入口函数为**static int __init input_init(void)**,在该函数 ...
- netty深入学习之中的一个: 入门篇
netty深入学习之中的一个: 入门篇 本文代码下载: http://download.csdn.net/detail/cheungmine/8497549 1)Netty是什么 Netty是Java ...
- Linux Framebuffer驱动剖析之中的一个—软件需求
嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2 ...
- Python 学习之中的一个:在Mac OS X下基于Sublime Text搭建开发平台包括numpy,scipy
1 前言 Python有许多IDE能够用,官方自己也带了一个,Eclipse也能够. 但我在使用各种IDE之后,发现用Sublime Text是最好用的一个.因此.我都是用Sublime Text来编 ...
- mysql学习之中的一个:mysql安装
我用的时mac系统,本来想在mac系统上装一个,可是发现mac系统始终无法用password登入到本机server,很奇怪的问题(在stackflow上看了些回复,也没有找到原因),最后仅仅好装到虚拟 ...
- Java并发学习之中的一个——线程的创建
本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.与每一个Java语言中的元素一样,线程是对象.在Java中,我们有两种方式创建线程: a.通过直接继承thread类,然后覆盖run方法. b ...
- Scapy基础学习之中的一个
关于Scapy Scapy的是一个强大的交互式数据包处理程序(使用python编写). 它可以伪造或者解码大量的网络协议数据包,可以发送.捕捉.匹配请求和回复包等等.它可以非常easy地处理一些典型操 ...
- Linux驱动学习(编写一个最简单的模块)
在Linux中想做驱动开发,那么一定要先熟悉module的使用和编写 一.什么是module 从名字上看就是模块的意思,我个人的理解就是一个一个的小程序,可以进行动态的安装和卸载,而在这里面就实现一些 ...
- 嵌入式Linux驱动案例之中的一个
前几天解决一个嵌入式Linux驱动问题,做为一个案例进行记录. 本案例是一个CPU通过LocalBus总线訪问外围一个设备,详细设备是一个DSP器件.在实际应用中,性能要求非常高,对数据訪问速度提出比 ...
随机推荐
- 聪明的kk --- 搜索超时
二话没说上去搜索 , 果不其然 华丽超时 . #include<stdio.h> #include<string.h> #include<math.h> #incl ...
- Sorting It All Out 拓扑排序+确定点
这一道题的话 数据有一点问题 ........ 例如 不过 还是 能理解一下 试试吧 ......... A<B B<C C<A A<C B<A ...
- Linux-fork()函数详解,附代码注释
// // main.c // Project_C // // Created by LiJinxu on 16/8/13. // Copyright © 2016年 LiJinxu-NEU. All ...
- 转 方法区(method) )、栈区(stack)和堆区(heap)之JVM 内存初学
JAVA的JVM的内存可分为3个区:堆(heap).栈(stack)和方法区(method) 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的目的是得到操作指 ...
- Java&Xml教程(七)使用JDOM修改XML文件内容
JDOM提供了非常灵活的方式操作XML文件,使用JDOM非常简单而且代码简洁可读性强.前面我们学习了如何使用JDOM解析XML文件,本节介绍如何使用JDOM修改XML文件内容. 在这个教程中,我们准备 ...
- 影响ERP成功实施的因素及实施方法
一.影响ERP实施的因素 1.企业自身管理和认识上的问题.在ERP实施过程中没有用变革管理的理念和方法来策划和管理ERP的实施是导致ERP失败的主要原因. ERP作为一种管理工具他的实施本身就是操作手 ...
- highcharts 组合chart
/** *制作 复杂的组合型的 charts * *@param [options] 图表的默认配置 *@dependence jQuery.highcharts *@author wch */ fu ...
- (转)Java任务调度框架Quartz入门教程指南(二) 使用job、trigger、schedule调用定时任务
http://blog.csdn.net/zixiao217/article/details/53044890 读完第一节,我们已经对Quartz有了一个大体的认识,它可以定时帮我们执行一些处理程序, ...
- Memcached 在Linux上的安装
1.安装libevent wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libeve ...
- Sping bean的作用域
单例(Singleton):在整个应用中,只创建bean的一个实例.(默认) 原型(Prototype):每次注入或者通过Sping应用上下文获取的时候,都会创建一个新的bean. 回话(Sessio ...