一、Linux输入子系统
Linux系统提供了input子系统,按键、触摸屏,鼠标等输入型设备都可以利用input接口函数来实现设备驱动。
1>体系结构
输入子系统由驱动层,输入子系统核心层(input Core)和事件处理层(Event Handler)三部分组
成。一个输入事件,如鼠标移动,键盘按键按下,通过Driver->InputCore->Event handler
->userspace的顺序到达用户空间的应用程序。
驱动层:将底层的硬件输入转化为统一事件型式,向输入核心(Input core)汇报。
输入核心层:为驱动提供输入设备注册于操作接口,如:input_register_device;通知事件处理层对
事件进行处理;在/PROC下产生相应的设备信息。
事件处理层:主要作用是和用户空间交互,我们知道Linux在用户空间将所有设备当成文件来处理,
在一般的驱动程序中都有提供fops接口,以及在/dev下生成相应的设备文件nod,而在输入中子系统
中,这些工作都是由事件处理层完成的。
2>设备描述
在Linux内核中,input设备用input_dev结构体描述,使用input子系统实现输入设备驱动的时候,驱
动的核心工作是向系统报告按键、触目屏、键盘、鼠标等输入事件(event,通过input_event结构体
描述),不再需要关心文件操作接口,因为input子系统已经完成了文件操作接口。驱动报告事件经
过inputcore和eventhandler最终到达用户空间。
3>注册输入设备的函数为:
int intput_register_device(struct input_dev *dev)
4>注销输入设备的函数为:
void input_unreegister_device(struct input_dev *dev)
5>驱动实现-事件支持
设备驱动通过set_bit()告诉input子系统它支持哪些事件,哪些按键。
例:set_bit(EV_KEY,button_dev.evbit)
struct input_dev中的成员:
evbit:事件类型;
keybit:按键类型。
事件类型:
EV_RST Reset EV_KEY 按键 EV_REL 相对坐标 EV_ABS 绝对坐标
EV_MSC 其它 EV_LED LED EV_SND 声音 EV_REP Repeat
EV_FF 力反馈
当事件类型为EV_KEY时,还需要指明按键类型:
BTN_LEFT:鼠标左键 BTN_0:数字0键
BTN_RIGHT:鼠标右键 BTN_1:数字1键 BTN_MIDDLE:鼠标右键
6>驱动实现-报告事件
用于报告EV_KEY、EV_REL、和EV_ABS事件的函数分别为:
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)
code:事件的代码。如果事件类型是EV_KEY,该代码则为设备的键盘代码。例如键盘上的按键代码值
为0~127,鼠标按键代码为0x110~0x116,其中0x110(BTN_LEFT)为鼠标左键,0x111(BTN_RIGHT)为
鼠标右键,0x112(BTN_MIDDLE)为鼠标中间。其它代码请参考include/linux/input.h文件
value:事件的值。如果事件的类型是EV_KEY,当按键按下时值为1,松开时值为0。
7>驱动实现-报告结束
input_sync()用于告诉Input Core:此次报告已经结束。
实例:在触摸屏设备驱动中,一次点击的整个报告过程如下:
input_report_abs(input_dev, ABS_X,x);//X坐标
input_report_abs(input_dev,ABS_Y,y); //Y 坐标
input_report_abs(input_dev,ABS_PRESSURE,1);
input_sync(input_dev);//同步
-
/*实例分析*/
-
/*在按键中断中报告事件*/
-
-
static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)
-
{
-
input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));
-
input_report_key(&button_dev,BTN_1,inb(BYTTON_PORT1));
-
input_sync(&button_dev);
-
}
-
-
static int __init button_init(void)
-
{
-
/*申请中断*/
-
if(request_irq(BUTTON_IRQ,button_interrupt,0,"button",NULL))
-
return -EBUSY;
-
-
set_bit(EV_KEY,button_dev.evbit);//支持EV_KEY事件
-
set_bit(BTN_0,button_dev.keybit);//设备支持两个键
-
set_bit(BTN_1,button_dev/keybit);
-
input_register_device(&button_dev);//注册input设备
-
}
阅读(1646) | 评论(0) | 转发(0) |