Linux驱动之输入子系统
2016-06-19 23:07
495 查看
一. 概述
1. 输入子系统的概念
输入子系统是对分散的、多种不同类别的输入设备(键盘、鼠标、触摸屏、加速计、跟踪球、操纵杆等)进行统一处理的驱动程序。
2. 输入子系统的优点
抽象底层形态各异的硬件(鼠标,键盘,触摸屏,游戏杆等)输入设备,为上层提供了统一的操作接口。
二. 输入子系统的分层结构
1.三层结构
事件驱动层:负责和应用程序的接口。 核心层: 提供事件驱动层和设备驱动层所需的函数接口 设备驱动层:负责和底层设备驱动通信
2.层次框架图
三. 设备驱动
1. 设备驱动的数据结构
对于系统的每个输入设备硬件,在输入子系统都要实现一个设备驱动。每个设备驱动都由input_dev的数据结构描述,部分成员定义如:
struct input_dev{ const char *name; const char *phys; const char *uniq; struct input_id id; unsigned longevbit[BITS_TO_LONGS(EV_CNT)]; unsigned longkeybit[BITS_TO_LONGS(KEY_CNT)]; }
name: 该成员的设备驱动名字。但与对于的设备文件名无任何关系。
id : 该成员的输入设备身份。
evbit :该成员会产生的输入事件类型。事件类型定义如下:
1. #define EV_SYN 0x00 /*表示设备支持所有的事件*/ 2. #define EV_KEY 0x01 /*键盘或者按键,表示一个键码*/ 3. #define EV_REL 0x02 /*鼠标设备,表示一个相对的光标位置结果*/ 4. #define EV_ABS 0x03 /*手写板产生的值,其是一个绝对整数值*/ 5. #define EV_MSC 0x04 /*其他类型*/ 6. #define EV_LED 0x11 /*LED灯设备*/ 7. #define EV_SND 0x12 /*蜂鸣器,输入声音*/ 8. #define EV_REP 0x14 /*允许重复按键类型*/ 9. #define EV_PWR 0x16 /*电源管理事件*/
把指定的位置1,可以使用set_bit()函数:
set_bit( EV_KEY, input_dev->evbit);
keybit : 当设备驱动可以产生按键事件时,keybit成员表示设备驱动支持按键的键值。键值的定义:
#define KEY_RESERVED 0 #define KEY_ESC 1 #define KEY_1 2 #define KEY_2 3 ......
2. 注册/注销设备驱动
当一个input_dev结构体被初始化完成后,就可以调用input_register_device()函数注册到输入子系统:
int input_register_device(struct input_dev *);
注销:
void input_unregister_device(struct input_dev *);
3. 报告按键值
void input_report_key(struct input_dev*dev,unsigned int code,int value);
value : 1为按下,0为提起;
4. 提交同步事件,防止数据混乱
void input_sync(struct input_dev *dev);
四. 驱动实现
1. 驱动函数event_drv.c
/* * event_drv.c * * Program: Key input event * * Author: Lin Xubin */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/irq.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <linux/input.h> #include <linux/interrupt.h> struct input_dev *key_event_dev; typedef struct { int irq; char *devname; unsigned int gpio_pin; unsigned int key_val; }KeyEvent_TypeDef; KeyEvent_TypeDef KeyEvent[4]={ {IRQ_EINT0, "S2", S3C2410_GPF0, KEY_A}, {IRQ_EINT2, "S3", S3C2410_GPF2, KEY_B}, {IRQ_EINT11, "S4", S3C2410_GPG3, KEY_C}, {IRQ_EINT19, "S5", S3C2410_GPG11, KEY_D}, }; static irqreturn_t key_drv_irq(int irq,void *dev_id) { KeyEvent_TypeDef *KeyPin = (KeyEvent_TypeDef *)dev_id; static int PinState; PinState = s3c2410_gpio_getpin(KeyPin->gpio_pin); if(PinState) { input_event(key_event_dev, EV_KEY, KeyPin->key_val, 1); input_sync(key_event_dev); } else { input_event(key_event_dev, EV_KEY, KeyPin->key_val, 0); input_sync(key_event_dev); } return IRQ_RETVAL(IRQ_HANDLED); } int key_drv_init(void) { int i; key_event_dev = input_allocate_device(); //分配input_dev结构体 set_bit(EV_KEY, key_event_dev->evbit); //按键事件 for(i=0; i<4; i++) { set_bit(KeyEvent[i].key_val , key_event_dev->keybit); } input_register_device(key_event_dev); //注册input事件 for(i=0; i<4; i++) { request_irq(KeyEvent[i].irq , key_drv_irq, IRQT_BOTHEDGE, KeyEvent[i].devname, &KeyEvent[i]); } return 0; } void key_drv_exit(void) { int i; for(i=0; i<4; i++) { free_irq(KeyEvent[i].irq, &KeyEvent[i]); } input_unregister_device(key_event_dev); input_free_device(key_event_dev); } module_init(key_drv_init); module_exit(key_drv_exit); MODULE_LICENSE("GPL");
2. 应用测试程序 event_drv_test.c
/* * event_drv_test.c * * Author: Lin Xubin */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <poll.h> #include <signal.h> #include <unistd.h> #include <linux/input.h> int main(char argc, char *argv[]) { int fd,val; struct input_event key_event_val; fd = open("/dev/event1", O_RDWR); if(fd < 0) { printf("open device failed\n"); return 0; } while(1) { val = read(fd,&key_event_val, sizeof(struct input_event)); if( val < 0) { printf("read input err\n"); return 0; } switch(val) printf("%d,%d,%d\n", key_event_val.type, key_event_val.code, key_event_val.value); } }
相关文章推荐
- 通过ulimit改善系统性能
- 最新嵌入式开发经典高清视频教程免费下载
- 在CF卡上建立文件系统和安装引导加载程序
- ARM如何入门
- 嵌入式ARM系统实战开发(编程模型、指令系统、程序设计、混合编程、驱动开发)视频教程
- [arm 驱动]Linux输入子系统分析
- [arm 驱动]input 子系统架构总结
- 2012-2013年(第五届)中国嵌入式开发从业人员大调查正式启动
- xshell中文显示乱码
- 求嵌入式研发精英 两枚!!
- VMware的配置及ubuntu10.04 tftp 与嵌入式开发板的连接设置
- CSDN我来了,专注于车载mv导航产品开发。
- 导航开发基础篇章
- 为何不伸手
- stm32中断服务函数的机制
- pc寄存器与可寻址空间
- 静态字符串模式匹配模板库
- 交叉工具链
- Makefile工具
- 嵌入式开发数据库SqlCe和SQLite性能比较