嵌入式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()函数发送数据,并通过 ...
随机推荐
- 转载:《TypeScript 中文入门教程》 3、接口
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 介绍 TypeScript的核心原则之一是对值所具有的shape进行类型检查. 它有时 ...
- 转载:《TypeScript 中文入门教程》 2、枚举
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 由于第一章节是我翻译的,而且与他的版本不一致,导致第一章节有枚举这部分,而他的第二章节 ...
- mybatis中的#和$的区别(转)
#相当于对数据 加上 双引号,$相当于直接显示数据 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sq ...
- java web学习总结(十五) -------------------JSP基础语法
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- MongoDB分片(sharding)
1.概念 分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程.有时也用分区(partitioning)来表示这个概念.将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存 ...
- 解决服务器SID引起虚拟机不能加入AD域用户,无法远程登录的问题
最近在公司搭建AD域控制器,发现无法在计算机真正添加域用户,也就是添加的用户虽然可以在本地登录,但是无法远程登录,尝试多种方法都无法解决,而最终原因居然是虚拟机导致的服务器的SID冲突.本文记录下该问 ...
- Jsp静态包含和动态包含的区别
1 <%@include file="xxx.jsp"%>为jsp中的编译指令,其文件的包含是发生在jsp向servlet转换的时期,而<jsp:include ...
- CSS笔记之伪类与伪元素
伪类分为两种:UI伪类 与 结构化伪类 UI伪类:a:link{} a:hover{} a:active{} a:visited{} input[type='text']:focus{} ...
- AlloyRenderingEngine开门大吉
快速入口 不读文章可以直接拐向这里: github:https://github.com/AlloyTeam/AlloyRenderingEngine website:http://alloyteam ...
- js => ES6一个新的函数写法
今天在网上参观到一个写法,返回字符串个个字母的个数 var arr='aaabbccaa'; var info = arr.split('').reduce((p, k) => (p[k]++ ...