分类: LINUX
2013-09-07 18:39:04
/****************************************************输入子系统****************************************************************/
/*
* 输入设备(如按键、键盘、触摸屏、鼠标等)是典型的字符设备,其一般的工作机理是底层在按键、触摸屏等动作发生时产生一个中断(或驱动通过timer定时查询),然后
*CPU通过SPI、IIC或外部存储器总线读取键值、坐标等数据,放入一个缓冲区,字符设备驱动管理缓冲区,而驱动的read接口让用户可以读取键值、坐标等数据。
* 显然,在这些工作中,只是中断、读键值或坐标值是设备相关的,而输入事件的缓冲区管理以及字符设备驱动的file_operations接口则对输入设备是通用的,基于此,
*内核设计了输入子系统。
*
*相关结构和接口函数在input.h、input.c
*/
#include
//输入设备结构:
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_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)];
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, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);KEY_L
struct ff_device *ff;
unsigned int repeat_key;
struct timer_list timer;
int sync;
int abs[ABS_MAX + 1];
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_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
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;
int going_away;
struct device dev;
struct list_head h_list;
struct list_head node;
};
//所有的输入事件,内部都用统一的input_event结构来描述:
struct input_event {
struct timeval time; /* 事件发生的事件 */
__u16 type; //事件的类型(按键类事件、位移类事件等等)
__u16 code; //事件的值
__s32 value; //1表示事件发生,0表示事件未发生
};
//分配与释放:
struct input_dev *xxx_dev;
struct input_dev *input_allocate_device(void); //分配一个输入设备即分配input_dev 结构体,表征一个输入设备
void input_free_device(struct input_dev *dev); //释放一个输入设备即释放input_dev 结构体,
1:注意释放设备必须要在其他资源释放了并且在设备注销了之后,要不然会产生段错误
//注册与注销:
int __must_check input_register_device(struct input_dev *dev); //注册一个输入设备
void input_unregister_device(struct input_dev *dev); //注销一个输入设备
//设置能产生的事件:
set_bit(nr,p); //设置能产生哪类事件及该类事件中能产生哪些事件
//nr为事件类型或哪些事件(比如:EV_KEY、KEY_L等)
//p为事件类型,在上面的struct input_dev结构中定义(比如evbit)。驱动程序在模块加载函数中告知input子系统它支持哪些事件
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); //设置此输入设备可告知的事件
//报告输入事件接口:
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); //报告指定type、code的输入事件,type在input.h中定义
void input_report_key(struct input_dev *dev, unsigned int code, int value); //报告键值
void input_report_rel(struct input_dev *dev, unsigned int code, int value); //报告相对坐标
void input_report_abs(struct input_dev *dev, unsigned int code, int value); //报告绝对坐标
void input_sync(struct input_dev *dev); //报告同步事件,说明以上的事件是一组事件
//一般的输入子系统驱动程序流程:
1:分配一个input_dev结构体
2:设置结构体成员(能产生哪类事件以及产生该类事件中的哪些事件等)
3:注册
4:硬件相关的代码,在其中上报事件
/****************************************************end**********************************************************************/