以前写的一些输入设备的驱动都是采用字符设备处理的。问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的、不同类别的输入设备进行统一的驱动,所以才出现了输入子系统。

输入子系统引入的好处:

(1)统一了物理形态各异的相似的输入设备的处理功能。例如,各种鼠标,不论PS/2、USB、还是蓝牙,都被同样处理。

(2)提供了用于分发输入报告给用户应用程序的简单的事件(event)接口。你的驱动不必创建、管理/dev节点以及相关的访问方法。因此它能够很方便的调用输入API以发送鼠标移动、键盘按键,或触摸事件给用户空间。X windows这样的应用程序能够无缝地运行于输入子系统提供的event接口之上。

(3)抽取出了输入驱动的通用部分,简化了驱动,并提供了一致性。例如,输入子系统提供了一个底层驱动(成为serio)的集合,支持对串口和键盘控制器等硬件输入的访问。

子系统包括一前一后运行的两类驱动:输入事件(event)驱动和输入设备(device)驱动。

输入事件驱动负责和应用程序的接口;

而输入设备驱动负责和底层输入设备的通信。

输入事件驱动和输入设备驱动都可以利用输入子系统的高效、可重用的核心提供的服务。

而我们需要实现的就是输入设备驱动。

首先在linux内核源代码的drivers/input/input.c中就是输入子系统,它的file_operation中只有一个open函数。而在open函数中却对file_operation结构体进行了重新指定,从而实现read、write等其他功能。

驱动程序代码:

#include <linux/module.h>
#include <linux/version.h> #include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <asm/gpio.h> struct pin_desc *pin_timer;
static struct timer_list keys_timer; static struct input_dev *keys_dev;
struct pin_desc{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
}; struct pin_desc pins_desc[] = {
{ IRQ_EINT0, "key1", S3C2410_GPF0, KEY_L },
{ IRQ_EINT2, "key2", S3C2410_GPF2, KEY_S },
{ IRQ_EINT11, "key3", S3C2410_GPG3, KEY_ENTER },
{ IRQ_EINT19, "key4", S3C2410_GPG11,KEY_LEFTSHIFT }, }; static irqreturn_t keys_irq(int irq, void *dev_id)
{
pin_timer = (struct pin_desc *)dev_id;
mod_timer(&keys_timer, jiffies+HZ/ );
return IRQ_HANDLED; } static void keys_timer_fun(unsigned long t)
{
struct pin_desc *pindesc = (struct pin_desc *)pin_timer;
unsigned int pinval;
if( !pindesc )
return ;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval)
{
input_event(keys_dev,EV_KEY,pindesc->key_val,); /* 有事件产生时上报事件 */
input_sync(keys_dev);
}
else
{
input_event(keys_dev,EV_KEY,pindesc->key_val,); /* 有事件产生时上报事件 */
input_sync(keys_dev);
}
} static int key_init(void)
{
int i;
/* 分配一个input_dev结构体*/
keys_dev = input_allocate_device();
if (!keys_dev)
return -ENOMEM; /*设置*/
set_bit(EV_KEY, keys_dev->evbit);
set_bit(EV_REP, keys_dev->evbit); set_bit(KEY_L,keys_dev->keybit);
set_bit(KEY_S,keys_dev->keybit);
set_bit(KEY_ENTER,keys_dev->keybit);
set_bit(KEY_LEFTSHIFT,keys_dev->keybit);
/*注册*/
input_register_device(keys_dev);
/*硬件相关的操作*/
for(i=;i<;i++)
{
request_irq( pins_desc[i].irq, keys_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i] );
}
init_timer(&keys_timer);
keys_timer.function = keys_timer_fun;
keys_timer.expires = ;
add_timer(&keys_timer);
return ;
}
static void key_exit(void)
{
int i;
for( i=; i<; i++ )
{
free_irq( pins_desc[i].irq, &pins_desc[i] );
}
del_timer(&keys_timer);
input_unregister_device(keys_dev);
printk("key Module exit\n");
} module_init( key_init );
module_exit( key_exit );
MODULE_LICENSE("GPL");

会在/dev/目录下对一个event设备。

测试:

运行 cat /dev/tty1

sd

嵌入式Linux驱动学习之路(十六)输入子系统的更多相关文章

  1. 嵌入式Linux驱动学习之路(十八)LCD驱动

    驱动代码: /************************************************************************* > File Name: lcd ...

  2. 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖

    在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...

  3. 嵌入式Linux驱动学习之路(十四)按键驱动-同步、互斥、阻塞

    目的:同一个时刻,只能有一个应用程序打开我们的驱动程序. ①原子操作: v = ATOMIC_INIT( i )  定义原子变量v并初始化为i atomic_read(v)        返回原子变量 ...

  4. 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制

    实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...

  5. 嵌入式Linux驱动学习之路(十)字符设备驱动-my_led

    首先贴上代码: 字符设备驱动代码: /** *file name: led.c */#include <linux/sched.h> #include <linux/signal.h ...

  6. 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试

    触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...

  7. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  8. 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序

    基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...

  9. 嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序

    一.协议栈层次对比 设备无关层到驱动层的体系结构 1).网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过 ...

随机推荐

  1. patch 打补丁,和diff 生成制作补丁

    一.diff 命令: diff命令就是比较两个文件的差异,然后生成差异文件,即补丁文件. 参数:diff --help获得,最常用的 1.-N --new-file 在比较时,如果没有就拿一个空的文件 ...

  2. No.006:ZigZag Conversion

    问题: The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows l ...

  3. 对hashmap,hashset,hashtable的理解

    1.首先先理一下java的集合关系,Collection和Map接口是所有集合接口的根结点,其他集合都直接或者间接的实现了他们中的一个:collection下有:list(元素可重复)和set(不可重 ...

  4. java中 try return finally return

    finally块里面的代码一般都是会执行的,除非执行 System.exit(int),停止虚拟机,断电. 1.若try代码块里面有return ,假设要return 的值 是A,A为基本类型或者被f ...

  5. maven 间接依赖的jar自动引入

    很多时候,我们引用的第三方jar需要一些其他的第三方jar,这个时候默认情况下,间接需要依赖的第三方jar是不会自动被引入的,如果希望这些额外的三方jar被自动引入,则在Maven仓库中除了提交jar ...

  6. 事件流之事件冒泡与事件捕获<JavaScript高级程序设计>学习笔记

    1.事件流 浏览器开发团队遇到一个很有意思问题:页面的那一部分会拥有特定的事件? 对于理解这个问题您可以想象画在一张纸上的一组同心圆,如果你把手指放在圆心上,那么你的手指指向的其实不是一个圆,而是纸上 ...

  7. 前端Demo常用库文件链接

    <!doctype html><html><head> <meta charset="UTF-8"> <title>前端 ...

  8. 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(三)显示地图坐标系模块

    config.xml文件的配置如下: <widget left="3" bottom="3" config="widgets/Coordinat ...

  9. iOS 常用三方类库整理

    iOS 常用三方类库整理 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址:https://gi ...

  10. 【转】Jsduck一个纯净的前端文档生成神器

    让前端程序更具可维护性,是一个老生常谈的问题,大多数时候我们都关注于应用层面的代码可维护性,如:OO.模块化.MVC,编码规范.可扩展和复用性,但这都是属于设计层面需要考虑的事情,可维护性还应包含另一 ...