Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1297990
  • 博文数量: 168
  • 博客积分: 2124
  • 博客等级: 大尉
  • 技术积分: 2590
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-16 23:51
文章分类

全部博文(168)

文章存档

2014年(6)

2013年(74)

2012年(71)

2011年(17)

分类: LINUX

2012-08-09 15:18:40

输入设备(按键、键盘、触摸屏、鼠标)是典型的字符设备,工作机理是底层
在按键、触摸等动作发生时产生一个中断(或驱动timer定时查询),然后CPU
通过SPI、I2C或外部存储器总线读取键值,坐标等数据。
输入核心层提供了底层输入设备驱动程序所需的API,如分配/释放一个输入设备
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
input_allocate_device()返回的是1个input_dev的结构体,此结构体用于表征1个输入设备
注册/注销输入设备用的接口
input_register_device(struct input_dev *);
void input_unregister_device(struct input_dev *);
报告输入事件的接口,指定type, code, value
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);


input通用数据结构
1. input_dev是input设备基本的设备结构,每个input驱动程序必须分配初始化这样一个结构
include/linux/input.h
struct input_dev {
const char *name; //设备名称
const char *phys;//设备在系统的物理路径
const char *uniq;//统一的ID
struct input_id id;//设备ID


unsigned long evbit[BITS_TO_LONGS(EV_CNT)];//事件
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];//按键
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];//相对设备
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];//绝对设备
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];//杂项设备
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];//LED
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];//声音设备
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];//强制反馈设备
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];//开关设备


unsigned int keycodemax;//按键码的最大值
unsigned int keycodesize;//按键码的大小
void *keycode;//按键码
int (*setkeycode)(struct input_dev *dev,
 unsigned int scancode, unsigned int keycode);
int (*getkeycode)(struct input_dev *dev,
 unsigned int scancode, unsigned int *keycode);


struct ff_device *ff;


unsigned int repeat_key;
struct timer_list timer;


int sync;


int abs[ABS_CNT];
int rep[REP_MAX + 1];


unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];


int absmax[ABS_CNT];
int absmin[ABS_CNT];
int absfuzz[ABS_CNT];
int absflat[ABS_CNT];
int absres[ABS_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 *grab;


spinlock_t event_lock;
struct mutex mutex;


unsigned int users;
bool going_away;


struct device dev;


struct list_headh_list;
struct list_headnode;
};


2. input_event 驱动层向input子系统核心报告事件的函数。
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value);
 
不同设备内容的报告均是通过input_event函数来完成的,选择使用了不同参数而已
@type:类型(EV_KEY键盘,EV_REL相对,EV_ABS绝对)
@code:编码(事件代码,如键盘代码)
@value:值(EV_KEY当按键按下时值为1,松开时值为0,如果事件为EV_REL,value的正
数值和负数值分别代表两个不同的方向)


键盘keyboard属于按键设备EV_KEY
轨迹属于相对设备EV_REL
触模屏属于绝对设备EV_ABS


3. 分配并初始化input_dev
input_allocate_device()


4. 向内核注册一个input设备
input_register_device()


5. input驱动流程
1)定义input设备结构
struct input_dev *input;
2)分配并初始化input_dev接构
input = input_allocate_device();
input->name = "gpio-keys";
input->phys = "gpio-keys/input0";
input->id.bustype = BUS_HOST;
input->id.vendor  = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
3) 记录本设备对于哪些事件感兴趣(对其进行处理)input_set_capability();
定义/drivers/input/input.c
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
input_set_capability(input, EV_KEY, 101);


4)向内核注册一个input设备
input_register_device(input);


5)记录按键状态
int state = (gpio_get_value((S3C64XX_GPN(0)) ? 1 : 0) ^ 1 ;


6)汇报输入事件
input_event(input, EV_KEY, 101, !!state);


7)等待输入事件处理完成
input_sync(input);


8)注销一个input设备
input_unregister_device(input);

转自
阅读(895) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~