刚開始学习linux这门课就被分配编写一个设备的input子系统驱动。这对我的确有点困难。只是实际的操作中发现困难远比我想象的要大的多。本以为依照老师课上的步骤就行非常快的完毕这项任务。后来发现是我想多了。

刚一開始我就陷入了一个困境,理不清究竟input子系统驱动哪些是我须要做的哪些是系统已经为我们完毕的。为此花费了我一个星期的时间才真正的从这个困惑里走出来。当然后边还有非常多其它的困难这里我就不多说了,以下我就来总结一下input子系统学习的过程。

首先我们要清楚input子系统分为几层,各层都有些什么,以及各自的功能

一、input子系统分层


input子系统分为三层如图所看到的。须要强调的是我们须要做的仅仅是完毕设备驱动层的编程。这一点困惑了我一个星期。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhaGFpY2Fv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">


1.1 设备驱动层
提供驱动层对详细输入设备硬件寄存器的读写问以及将底层硬件对用户输入訪问的响应转换为标准的输入事件,再通过事件核心层提交给事件处理层;设备驱动层完毕详细硬件设备驱动的实现。

这一层中包括一个input_dev结构体,它是用来描写叙述一个设备的信息的。

包括了对设备的各项设置及操作函数。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hhaGFpY2Fv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



1.2 事件核心层
输入子系统的核心部分,负责初始化和管理整个输入子系统,它对设备驱动层提供输入设备的注冊和初始化函数完毕输入设备在事件核心层的注冊;同一时候它也对事件处理层提供接口函数以完毕事件处理层设备在事件核心层的注冊;建立设备驱动层的输入设备和事件处理层设备之间的关联。

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


1.3 事件处理层
为用户空间的应用程序提供统一訪问设备的接口和驱动层提交来的事件处理。

使设备驱动部分不再关心对设备文件的操作而仅仅需关心对各硬件寄存器的操作和提交的输入事件就可以 。

这一层包括了input_handler结构体,它是作为事件处理器相应用程序的接口。



input子系统的三层分别各自拥有一个结构体,驱动功能的实现就是这三个结构体连接传递信息的过程。


到底这三个结构体怎样实现连接,在总结完input子系统驱动实现的整个过程之后在整体描写叙述。

二、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子系统驱动学习之中的一个的更多相关文章

  1. input子系统驱动

    input子系统驱动 框架分析 核心层 文件为:/drivers/input/input.c: 首先找到入口函数为**static int __init input_init(void)**,在该函数 ...

  2. netty深入学习之中的一个: 入门篇

    netty深入学习之中的一个: 入门篇 本文代码下载: http://download.csdn.net/detail/cheungmine/8497549 1)Netty是什么 Netty是Java ...

  3. Linux Framebuffer驱动剖析之中的一个—软件需求

    嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2 ...

  4. Python 学习之中的一个:在Mac OS X下基于Sublime Text搭建开发平台包括numpy,scipy

    1 前言 Python有许多IDE能够用,官方自己也带了一个,Eclipse也能够. 但我在使用各种IDE之后,发现用Sublime Text是最好用的一个.因此.我都是用Sublime Text来编 ...

  5. mysql学习之中的一个:mysql安装

    我用的时mac系统,本来想在mac系统上装一个,可是发现mac系统始终无法用password登入到本机server,很奇怪的问题(在stackflow上看了些回复,也没有找到原因),最后仅仅好装到虚拟 ...

  6. Java并发学习之中的一个——线程的创建

    本文是学习网络上的文章时的总结,感谢大家无私的分享. 1.与每一个Java语言中的元素一样,线程是对象.在Java中,我们有两种方式创建线程: a.通过直接继承thread类,然后覆盖run方法. b ...

  7. Scapy基础学习之中的一个

    关于Scapy Scapy的是一个强大的交互式数据包处理程序(使用python编写). 它可以伪造或者解码大量的网络协议数据包,可以发送.捕捉.匹配请求和回复包等等.它可以非常easy地处理一些典型操 ...

  8. Linux驱动学习(编写一个最简单的模块)

    在Linux中想做驱动开发,那么一定要先熟悉module的使用和编写 一.什么是module 从名字上看就是模块的意思,我个人的理解就是一个一个的小程序,可以进行动态的安装和卸载,而在这里面就实现一些 ...

  9. 嵌入式Linux驱动案例之中的一个

    前几天解决一个嵌入式Linux驱动问题,做为一个案例进行记录. 本案例是一个CPU通过LocalBus总线訪问外围一个设备,详细设备是一个DSP器件.在实际应用中,性能要求非常高,对数据訪问速度提出比 ...

随机推荐

  1. 了解MySQL的字符集

    在数据库中,字符乱码属于常见.多发问题.鉴于本人水平顶多只能归于不入流之类,写这篇文章时内心诚惶诚恐,实在担心误导大家.内容仅供参考,若有错误,请各位及时指出,我也好学习提高! MySQL的字符集有4 ...

  2. mysql数据的操作

    一.插入数据记录 1.插入完整数据记录 INSERT INTO table_name VALUES(value1,value2......valuen); 2.插入数据记录的一部分 INSERT IN ...

  3. [转]linux之ps命令

    转自:http://www.cnblogs.com/peida/archive/2012/12/19/2824418.html Linux中的ps命令是Process Status的缩写.ps命令用来 ...

  4. Elasticsearch之CURL命令的HEAD

    如果只想检查一些文档是否存在,我们可以使用HEAD来替代GET方法,这样就只会返回HTTP头文件. [hadoop@master elasticsearch-]$ curl -i XHEAD http ...

  5. ionic2\ionic3 自定义弹窗

    ionic2及ionic3没有了popup及 其templateUrl属性 那我们如何对弹窗里加入自定义元素 从而达到自定义弹窗样式 那么就可以通过写h5页面来实现 自定义弹窗效果: 写个H5的弹窗及 ...

  6. echarts交叉关系图二

    echarts关系图表,此图是坐标关系图,此图用的随机坐标,此图可以拖拽,更方便整理关系, 引入echarts.js就可以实现 代码: var graph={ //这是数据项目中一般都是获取到的 no ...

  7. IO编程——复制一个文件中的内容到另一个文件

    public class TestIO { public static void main(String[] args) { File inputFile = new File("a.txt ...

  8. Luogu P1256 显示图像

    P1256 显示图像 题目描述 古老的显示屏是由N×M个像素(Pixel)点组成的.一个像素点的位置是根据所在行数和列数决定的.例如P(2,1)表示第2行第1列的像素点.那时候,屏幕只能显示黑与白两种 ...

  9. 《零压力学Python》 之 第一章知识点归纳

    第一章(初识Python)知识点归纳 Python是从ABC语言衍生而来的 ABC语言是Guido参与设计的一种教学语言,为非专业编程人员所开发的. Python是荷兰程序员 Guido Van Ro ...

  10. hdu 5170 精度控制

    众所周知,GTY是一位神犇,为了更好的虐场,他从来不写数学作业而是去屠题,他的数学老师非常不爽,但由于GTY每次考试都AK,她也不能说什么,有一天老师在黑板上写了四个数——a,b,c,da,b,c,d ...