文章目录
输入子系统的作用和框架
- 什么是输入设备
- 按键/keyboard
- mouse
- touchscreen(触摸屏):gt811,ft56xx
- joystick 游戏杆
- 有多个输入设备需要驱动的时候,假如不考虑输入子系统
- gt811
设备号,创建文件,硬件初始化,实现fop,阻塞,硬件初始化(I2C等) - ft56xx
设备号,创建文件,硬件初始化,实现fop,阻塞,硬件初始化(I2C等).
- 多个输入设备的共同点:
获取到数据(硬件操作)-------差异化
上报给用户(xxx_read,copy_to_user,阻塞)------通用
多个输入设备,有部分差异,也有部分通用
内核会考虑,将通用代码编写好,将差异化代码留给驱动工程师 - 设计成输入子系统:使得应用编程人员和驱动编程人员编程的时候变得简单统一
- 兼容所有的输入设备
- 统一的编程驱动方法(实现差异化的硬件操作)
- 统一的应用操作接口:/dev/input/event0,event1, open("/dev/input/event0,event1"),read(fd,struct input_event) :struct input_event buff 可以认为是一个统一的数据包
框架
- 框架:驱动分为三层
input core层和input handler层内核自带的代码,驱动工程师只需要在input device 设备层编程
编程:在input device 设备层
输入子系统的编程方式
- 输入子系统的编程方式—学会简单的输入子系统的开发方式
- 前提:input 核心层代码 和 input handler 层代码需要在内核中必须有
/drivers/input/input.c //核心层代码
/drivers/input/evdev.c //event handler - 在make menuconfig中
Device Drivers—>
Input device support—>
Generic input layer
Event interface //input handler层 evdev.c
程序编写步骤:
(1)分配一个 input device 对象
(2)初始化 input device 对象
(3)注册 input device 对象
- 上报数据
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
参数1:当前input device 上报数据
参数2:上报的是那种数据类型 EV_KEY,EV_ABS
参数3:具体数据时什么:KEY_POWER
参数4:值是什么
- 用户空间读到的数据:统一的数据包
struct input_event
{
struct timeval time; //时间戳
__u16 type; //数据类型
__u16 code; //具体数据是什么
__s32 value; //值是什么
}
- 代码实例
#include<linux/init.h>
#include<linux/module.h>
#include<linux/input.h>
struct input_dev *inputdev;
static int __init simple_input_init(void)
{
//编写输入子系统代码
/*
*(1)分配一个 input device 对象
*(2)初始化 input device 对象
*(3)注册 input device 对象
* */
int ret;
inputdev = input_allocate_device();
if(inputdev == NULL)
{
printk(KERN_ERR "input allocate device error\n");
return -ENOMEM;
}
//当前设备能够产生按键数据
__set_bit(EV_KEY,inputdev->evbit);
//表示当前设备能够产生power按键
__set_bit(KEY_POWER,inputdev->keybit);
ret = input_register_device(inputdev);
if(ret != 0)
{
printk(KERN_ERR "input register device error\n");
goto err_0;
return ret;
}
return 0;
err_0:
input_free_device(inputdev);
return ret;
}
static void __exit simple_input_exit()
{
input_unregister_device(inputdev);
input_free_device(inputdev);
}
module_init(simple_input_init);
module_exit(simple_input_exit);
MODULE_LICENSE("GPL");
用户空间应用程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
int main(void)
{
int fd;
int ret;
struct input_event event;
fd = open("/dev/event0",O_RDWR);
if(fd < 0)
{
perror("open");
exit(1);
}
while(1)
{
ret = read(fd,&event,sizeof(struct input_event));
if(ret < 0)
{
perror("read");
exit(1);
}
if(event.type == EV_KEY)
{
if(event.code == KEY_POWER)
{
if(event.value) //按键按下
{
printf("__APP_USER__:power pressed\n");
}
else //按键抬起
{
printf("__APP_USER__:power up\n");
}
}
}
}
close(fd);
return 0;
}