Linux设备驱动子系统第三弹 - Input

http://blog.csdn.net/qianjin0703/article/details/6025673

1. 总论

2. 导航

3. 实例

 3.1 键盘

 3.2 触摸屏


1. 总论

  Input子系统为一些常用的小规模数据传输的设备提供统一的数据上报系统,把数据以统一的格式上传到用户空间。适用于Input子系统的设备有摇杆、鼠标、键盘、触摸屏,Misc等。

  

 

2. 导航

   Input子系统配置步骤如下,

  1. 申请和初始化input设备
  2. 设置input与设备相关的bit位
  3. 注册input设备
  4. 上报数据

2.1 申请和初始化input设备 input_allocate_device();

  设备的数据结构里存放一个struct input_dev类型的结构,用于存放input设备。该结构定义于/include/linux/input.c,

2.2 设置input与设备相关的bit位

linux为input的设备提供以上不同类型的事件,每一类事件比如keybit[],其中的每一位代表一个事件,比如按键的上、下、左、右等。

驱动程序里只要对设备相关的事件设置对应的bit位即可。

2.3 注册input设备   input_register_device(input_dev);

2.4 上报数据 input_report_xxx(input_dev, code, value)

 

   驱动程序将设备数据value通过input_report_xxx()的方式上报给input核心层,核心层完成将数据从内核空间上传到用户空间。

   xxx表示事件的类型,比如键盘事件就是input_report_key(), code代表按键的类型(由input系统定义),value代表该按键的状态(通过驱动得到数据);触摸屏事件就是input_report_abs(),code代表触摸的类型(由input系统定义),比如压力,或者x轴,y轴,value代表压力值或坐标值(通过驱动得到数据)。

 

下面进入input核心层,看看数据具体是如何上报的,以input_report_key()为例,

最终调用了回调函数handle->handler->event(); 注意到handle这个数据结构,它是struct input_dev里的一个成员,而struct input_dev在设备驱动初始化的时候被唯一地申请并注册,这里的handle就是用来指代这个input设备,即键盘,这样,回调函数handle->handler->event()就可以通过这个handle找到指定的键盘设备。

struct evdev *evdev里存放的就是通过handle从底层得到的设备驱动的数据结构

struct evdev_client *client为最终用户空间可以访问的数据结构,其中存放了事件类型type,数据类型code和数据数值value。

下图为一个上层应用的例子,

 

 

3. 实例

 3.1 键盘

 

1)橙色部分为系统初始化后得到的platform_device结构的数据,包括,键盘控制器的物理地址,中断号,以及键盘矩阵对应的键值等。

2)蓝色部分就是通过input子系统注册的键盘设备驱动,分别完成了上文提到的1,2,3步,即申请input,设置input相关bit,注册input。

注意到粉红色的代码所实现的,就把把键盘矩阵对应的键值(按键类型code)申报到input子系统中相对应的bit位中,具体地,

如图所示,确认键的矩阵坐标(0,0),左键对应的矩阵坐标(2,0),

首先,系统初始化时对这些矩阵坐标配置键值(按键类型code),(0,0)配置为confirm,(2,0)配置为left,然后把键值存放到platform_device里,接着,驱动程序提取键值,并将其赋给input系统中相对应的位,这些位定义于/include/linux/input.h。

3)绿色部分就是上文提到的第4步-上报数据。

当有键按下或者弹起,驱动程序引发中断函数,即键盘扫描函数。

通过键盘控制器的寄存器得到按下或弹起键的矩阵坐标(row, col),再由坐标得到相对应的键值(按键类型code),最后由input_report_key(input, code, value)完成数据的上报。注意上报完数据后要用input_sync()同步。

 

 3.2 触摸屏

1)橙色部分为系统初始化后得到的platform_device结构的数据,主要为芯片上的引脚申请GPIO口,电路图如下图所示,

2)蓝色部分就是通过input子系统注册的触摸屏设备驱动,即申请input,设置input相关bit,注册input设备。这里主要设置了触摸屏的压力pressure以及坐标轴X,Y事件。

3)上报数据。

触摸笔按下产生中断,触发中断处理函数,唤醒一个读取和解析触摸屏坐标数据的线程(之所以使用线程,是因为读取和解析数据的开销比较大),最终通过input子系统上报坐标值。同样,用input_sync()同步。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在开发输入子系统设备驱动时,通常遵循以下步骤: 1. 包含必要的头文件:在驱动程序的源文件中,你需要包含一些必要的头文件,例如`linux/input.h`、`linux/module.h`、`linux/init.h`等。 2. 定义驱动模块:使用`module_init`宏定义一个初始化函数,用来加载驱动程序。例如: ```c static int __init myinput_init(void) { // 驱动初始化逻辑 return 0; } module_init(myinput_init); ``` 3. 注册输入设备:在初始化函数中,你需要创建一个输入设备并进行注册。你可以使用`input_allocate_device`函数分配一个输入设备结构体,并设置一些属性,例如设备名称、支持的事件类型等。然后,使用`input_register_device`函数注册输入设备。例如: ```c static int __init myinput_init(void) { struct input_dev *myinput_dev; myinput_dev = input_allocate_device(); if (!myinput_dev) { pr_err("Failed to allocate input device\n"); return -ENOMEM; } // 设置设备名称、支持的事件类型等 input_register_device(myinput_dev); return 0; } ``` 4. 处理输入事件:注册完输入设备后,你需要实现一个中断处理函数或者定时器处理函数,用来处理输入事件。当触发输入事件时,驱动程序会调用该函数进行处理。你可以使用`input_report_*`系列函数上报输入事件,例如鼠标移动、按键按下等。例如: ```c static irqreturn_t myinput_interrupt(int irq, void *dev_id) { // 处理输入事件的逻辑 input_report_key(myinput_dev, KEY_A, 1); // 模拟按下 A 键 input_sync(myinput_dev); // 同步输入事件 return IRQ_HANDLED; } ``` 这只是一个简单的示例,实际的输入子系统设备驱动可能还需要处理更多的细节和特定的硬件接口。更详细的编写方法和实现细节可以参考Linux内核源码中的驱动示例和相关文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值