Chinaunix首页 | 论坛 | 博客
  • 博客访问: 390296
  • 博文数量: 83
  • 博客积分: 1650
  • 博客等级: 上尉
  • 技术积分: 861
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-18 18:22
文章分类
文章存档

2021年(1)

2016年(1)

2015年(2)

2014年(3)

2013年(12)

2012年(16)

2011年(18)

2010年(30)

分类: LINUX

2013-09-10 16:37:28


/****************************************************输入子系统****************************************************************/
/*
 *   输入设备(如按键、键盘、触摸屏、鼠标等)是典型的字符设备,其一般的工作机理是底层在按键、触摸屏等动作发生时产生一个中断(或驱动通过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**********************************************************************/

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