input子系统

1.何为输入设备
Linux 系统下把键盘、鼠标、触摸屏、游戏句柄等等
设备都当做是输入设备
2.linux中输入设备的编程模型
struct input_event
3.input子系统简介
input子系统分4个部分:应用层 + input event + input core + 硬件驱动
在这里插入图片描述


input设备应用层编程实践
1.应用层操作驱动有2条路:/dev目录下的设备文件,/sys目录下的属性文件
2.input子系统用的/dev目录下的设备文件,具体一般都是在 /dev/input/eventn
3.用cat命令来确认某个设备文件名对应哪个具体设备。我在自己的ubuntu中实测的键盘是event1,而鼠标是event3.
4.struct input_event是给应用层的标准接口:
struct input_event {
struct timeval time;
__u16 type; 类型
__u16 code; 编码
__s32 value; 值
};
5.Event types:事件类型,有如下:
#define EV_SYN 0x00 同步事件,在应用层和驱动层做信息同步的
#define EV_KEY 0x01 按键事件(键盘和按键)
#define EV_REL 0x02 相对坐标事件,用于鼠标
#define EV_ABS 0x03 绝对坐标事件,用于摇杆、触摸屏
#define EV_MSC 0x04 其它
#define EV_SW 0x05 二进制的开关状态事件
#define EV_LED 0x11 LED灯事件
#define EV_SND 0x12 声音事件
#define EV_REP 0x14 重复按键事件
#define EV_FF 0x15 受力事件
#define EV_PWR 0x16 电源事件
#define EV_FF_STATUS 0x17 受力状态事件
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
在这里插入图片描述
6.我们打开一个键盘设备,按下m键得到如下的打印 一次按下弹起打印了6包数据 如下:
第1包数据说明:type = 0x4属于EV_MSC其他事件,code = 0x4说明属于EV_MSC事件中的MSC_SCAN事件,50说明扫描到的值是:KEY_M
type = 0x4
code = 0x4
value = 0x32=50

第2包数据说明:type = 0x1属于EV_KEY事件,code = 50说明属于KEY_M,value = 0x1表示按下
type = 0x1
code = 0x32
value = 0x1

第3包数据说明:同步包,在应用层和驱动层做信息同步,标识一个独立的事件的发生,它后一组的打印就是一个事件的发生
type = 0x0
code = 0x0
value = 0x0

第4包数据说明:type = 0x4属于EV_MSC其他事件,code = 0x4说明属于EV_MSC事件中的MSC_SCAN事件,50说明扫描到的值是:KEY_M
type = 0x4 EV_MSC事件
code = 0x4 MSC_SCAN子事件
value = 0x32 对应的是 KEY_M

第5包数据说明:type = 0x1属于EV_KEY事件,code = 50说明属于KEY_M,value = 0x0表示弹起
type = 0x1
code = 0x32
value = 0x0

第6包数据说明:同步包
type = 0x0
code = 0x0
value = 0x0
总结一下:所以一个按键按下到弹起,发了6包数据,依次是:扫描事件、KEY事件、同步事件、扫描事件、KEY事件、同步事件
鼠标上的按键是属于KEY事件的。


input子系统架构分析
1.input子系统分为三层
(1)最上层:输入事件驱动层,evdev.c和mousedev.c和joydev.c属于这一层
(2)中间层:输入核心层,input.c属于这一层
(3)最下层:输入设备驱动层,drivers/input/xxx 文件夹下
2.input类设备驱动开发方法
(1)输入事件驱动层和输入核心层不需要动,只需要编写设备驱动层
(2)设备驱动层编写的接口和调用模式已定义好,驱动工程师的核心工作量是对具体输入设备硬件的操作和性能调优。


输入核心层源码分析
1.在drivers/input/input.c中:input_init函数中
class_register:注册input类
input_proc_init:proc文件系统中的初始化
register_chrdev:注册字符设备驱动,MAJOR=13
2.核心层给设备驱动层的接口函数:
(1)input_allocate_device:动态分配struct input_dev结构体的内存
(2)input_set_capability:设置哪个事件的哪个值
(3)input_register_device:注册input device设备
填充struct input_dev结构体来注册input device。
3.handler和device的匹配,input_attach_handler在input_register_device和函数input_register_handler中被调用,因为我们一般不会去调用input_register_handler这个函数,所以我们写了驱动之后,就是在函数input_register_device来完成匹配和连接的。
input_attach_handler
调用:
input_match_device 匹配device和handler
调用:
handler->connect(handler, dev, id) 连接device和handler
4.handler、handle、input_dev这三个会联系起来,构成handler可以找到dev,dev也可以找到handler的框架。
5.事件驱动层的接口函数
input_register_handler
input_register_handle
6.input_handler结构体:
struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*match)(struct input_handler *handler, struct input_dev *dev);
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void (*start)(struct input_handle *handle);
const struct file_operations *fops;
int minor;
const char *name;
const struct input_device_id *id_table;
struct list_head h_list;
struct list_head node;
};
6.handler和dev的连接,使用struct evdev 中的handle来进行连接的。
7.evdev_event :当硬件有事件上传将调用


重要:
8.我们如何知道bsp中有没有实现我们按键驱动的代码?
cat /dev/input/eventn, 然后按按键,看是否有反应。
也就是把所有的event cat一遍,看按按键是否有反应。
实验证明,当我们cat event0的时候,按按键的时候,是有反应的,所以我们按键的驱动对应的是event0.
9.我们如何判断哪个文件是对应的我们的驱动文件?
一个简单的办法:进入drivers/input/keyboard目录下面,ls -l *.o,看哪个文件被编译进了内核,实验证明,atkbd.c编译进去内核。那么atkbd.c对应的就是我们的驱动文件?可以我们实际查看之后,发现不是这个文件。
10.那么我们怎么样找源码?进入/sys/class/input/event0/device,发现有很多的属性文件,其中有一个name,我们cat name = s3c-button,那么我们就可以根据s3c-button去查找了。
11.最后我们发现是在:arch/arm/mach-s5pv210/button-x210.c中。


分析:button-x210.c文件
(1)gpio_request
(2)input_allocate_device
(3)input_register_device
(4)timer
注意timer的使用:

  1. init_timer(&timer); 初始化
    timer.function = s3cbutton_timer_handler; 绑定任务函数
    timer.expires = jiffies + (HZ/100); 多久后触发timer,执行绑定函数
    add_timer(&timer); 添加timer
    2.在任务处理函数中:
    mod_timer(&timer,jiffies + HZ/100);
    3.timer绑定的任务,是一次执行的,若要让它循环执行,要使用mod_timer(&timer,jiffies + HZ/100);添加下次触发的时间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值