Article Directory
The role and framework of the input subsystem
- What is an input device
- Key/keyboard
- mouse
- touchscreen (touch screen): gt811, ft56xx
- joystick joystick
- When there are multiple input devices that need to be driven, if the input subsystem is not considered
- gt811
device number, file creation, hardware initialization, realization of fop, blocking, hardware initialization (I2C, etc.) - ft56xx
device number, file creation, hardware initialization, realization of fop, blocking, hardware initialization (I2C, etc.).
- The common point of multiple input devices :
get data (hardware operation)------- differentiation and
report to the user (xxx_read, copy_to_user, blocking)------ multiple input devices in common
, there are some differences There are also some general-purpose
kernels that will consider, write the general code well, and leave the differentiated code to the driver - Designed as an input subsystem: It makes the programming of application programmers and driver programmers simple and unified
- Compatible with all input devices
- Unified programming drive method (to achieve differentiated hardware operation)
- Unified application operation interface: /dev/input/event0,event1, open("/dev/input/event0,event1"), read(fd,struct input_event) : struct input_event buff can be considered as a unified data packet
frame
- Framework: The driver is divided into three layers: the
input core layer and the input handler layer. The kernel's own code, the driver engineer only needs to
program in the input device device layer: in the input device device layer
How to program the input subsystem
- The programming method of the input subsystem—learn the simple way of developing the input subsystem
- Prerequisite: input core layer code and input handler layer code must have /drivers/input/input.c in the kernel
//core layer code
/drivers/input/evdev.c //event handler - 在make menuconfig中
Device Drivers—>
Input device support—>
Generic input layer
Event interface //input handler层 evdev.c
Programming steps:
(1) Allocate an input device object
(2) Initialize the input device object
(3) Register the input device object
- Report data
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
Parameter 1: The data
reported by the current input device Parameter 2: The type of data reported is EV_KEY, EV_ABS
Parameter 3: What is the specific data: KEY_POWER
Parameter 4: What is the value
- Data read in user space: unified data packet
struct input_event
{
struct timeval time; //时间戳
__u16 type; //数据类型
__u16 code; //具体数据是什么
__s32 value; //值是什么
}
- Code example
#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");
User space application:
#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;
}