Linux advanced character driver input subsystem

The role and framework of the input subsystem

  • What is an input device
  1. Key/keyboard
  2. mouse
  3. touchscreen (touch screen): gt811, ft56xx
  4. joystick joystick
  • When there are multiple input devices that need to be driven, if the input subsystem is not considered
  1. gt811
    device number, file creation, hardware initialization, realization of fop, blocking, hardware initialization (I2C, etc.)
  2. 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
  1. Compatible with all input devices
  2. Unified programming drive method (to achieve differentiated hardware operation)
  3. 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
    Insert picture description here
    Insert picture description here
    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—>
    Insert picture description here
    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;
}

Guess you like

Origin blog.csdn.net/qq_41782149/article/details/99701533