Chinaunix首页 | 论坛 | 博客
  • 博客访问: 251543
  • 博文数量: 52
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1538
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-24 07:45
个人简介

生活就像海洋,只有意志坚强的人,才能到达彼岸。

文章存档

2013年(52)

分类: LINUX

2013-09-03 15:52:41

一、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);//同步




点击(此处)折叠或打开

  1. /*实例分析*/
  2. /*在按键中断中报告事件*/

  3. static void button_interrupt(int irq,void *dummy,struct pt_regs *fp)
  4. {
  5.     input_report_key(&button_dev,BTN_0,inb(BUTTON_PORT0));
  6.     input_report_key(&button_dev,BTN_1,inb(BYTTON_PORT1));
  7.     input_sync(&button_dev);
  8. }

  9. static int __init button_init(void)
  10. {
  11.     /*申请中断*/
  12.     if(request_irq(BUTTON_IRQ,button_interrupt,0,"button",NULL))
  13.         return -EBUSY;

  14.     set_bit(EV_KEY,button_dev.evbit);//支持EV_KEY事件
  15.     set_bit(BTN_0,button_dev.keybit);//设备支持两个键
  16.     set_bit(BTN_1,button_dev/keybit);
  17.     input_register_device(&button_dev);//注册input设备
  18. }


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