嵌入式Linux驱动学习之路(十六)输入子系统
以前写的一些输入设备的驱动都是采用字符设备处理的。问题由此而来,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驱动学习之路(十六)输入子系统的更多相关文章
- 嵌入式Linux驱动学习之路(十八)LCD驱动
驱动代码: /************************************************************************* > File Name: lcd ...
- 嵌入式Linux驱动学习之路(十五)按键驱动-定时器防抖
在之前的定时器驱动程序中,我们发现在连续按下按键的时候,正常情况下应该是一次按下对应一次松开.而程序有时候会显示是两次按下,一次松开.这个问题是因为在按下的时候,因为是机械按键,所以电压信号会产生一定 ...
- 嵌入式Linux驱动学习之路(十四)按键驱动-同步、互斥、阻塞
目的:同一个时刻,只能有一个应用程序打开我们的驱动程序. ①原子操作: v = ATOMIC_INIT( i ) 定义原子变量v并初始化为i atomic_read(v) 返回原子变量 ...
- 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制
实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...
- 嵌入式Linux驱动学习之路(十)字符设备驱动-my_led
首先贴上代码: 字符设备驱动代码: /** *file name: led.c */#include <linux/sched.h> #include <linux/signal.h ...
- 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试
触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...
- 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入
字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...
- 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序
基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...
- 嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序
一.协议栈层次对比 设备无关层到驱动层的体系结构 1).网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过 ...
随机推荐
- js中XMLHttpRequest对象实现GET、POST异步传输
js中XMLHttpRequest对象实现GET.POST异步传输 /* * 统一XHR接口 */ function createXHR() { // IE7+,Firefox, Opera, Chr ...
- java基础知识总结(2)
抽象方法的定义语法: 访问修饰符 abstract <返回类型> <方法名>(参数列表): 在语法中:abstract关键字表示该方法被定义为抽象方法 抽象方法和普通方 ...
- jQuery ClockPicker 圆形时钟
ClockPicker.js是一款时钟插件,其实还可以改进,里面的分可以改成短横线. 在线实例 实例预览 jQuery ClockPicker 圆形时钟 使用方法 <div class=&qu ...
- text-align=center 失效原因
text-align属性是针对 内联元素居中得属性设置,对于块状元素使用margin:0 auto;来控制居中: 笔者在设置一个h2标签时设置了text-align:center;但是却始终出现在中间 ...
- angularjs+微信,解决chooseImage不能预览的问题
在wx.chooseImage的success回调中直接进行数据绑定,却在ng-repeat时发现ng-src不加载微信localId的问题,类似wxLocalResource://imageid98 ...
- css(二)
本文是一些作者在长期写代码中总结的常用css查询,写在本博客中,方便以后查询. 1. 颜色属性: color HEX(十六进制色:color: #FFFF00 --> 缩写:#FF0) RG ...
- 微信平台ASPX高级定制开发(一):如何使用C#建立响应微信接入和自动回复的代码
微信平台不解释了,如果不了解的百度一下下,如果不会用微信,请自宫,光盘重启电脑,打开CMD输入Format C:.网上有很多针对企业级的高级定制ASPX开发,写得草草了事,很多男人干事都草草了事,这可 ...
- ListView实现点击事件以及总结
差点吓死我了,好不容易写的博客没有了,还好有自动保存功能,不然我真的是呜呜... ---恢复内容开始--- 开学一个月了,终于可以看见自己的作品雏形了. 从一个小白到现在半年了,觉得日子过得比较充实, ...
- iOS 学习 - 17.Socket
Socket 是应用层与 TCP / IP 协议通信的中间软件抽象层,它是一组接口 TCP:面向连接.传输可靠(保证数据正确性,保证数据顺序).用于传输大量数据(流模式).速度慢,建立连接需要开销 ...
- ASP.NET MVC中Unobtrusive Ajax的妙用
Unobtrusive Javascript有三层含义:一是在HTML代码中不会随意的插入Javsscript代码,只在标签中加一些额外的属性值,然后被引用的脚本文件识别和处理:二是通过脚本文件所增加 ...