163 basic concepts of input subsystem

Posted by youngloopy on Sat, 06 Nov 2021 06:17:43 +0100

I

  • Unified management of external input devices, such as:
    Key
    keyboard
    mouse
    touch screen

...

User space interface

  • /dev/input/event0/1/2/...
  • /dev/input/mouse0/1/2 /... (mouse)
  • /dev/input/sj0/1/2/...
  • ...

Hierarchical model

Core layer

Create input device class
Distribute events to different event processors according to the type of input device

Event processing layer

Includes various event handlers
Provide the operation interface of specific devices and create specific device files for input devices (input_dev structure). Therefore, we do not need to create device files for these input devices. The corresponding event processor of the event processing layer will create specific device files for us.

General purpose event processor (drivers/input/evdev.c), most used
Mouse event handler (drivers/input/mousedev.c)
Rocker event processor (drivers/input/joydev.c)
...

Create input device class

input_init() function

drivers/input/input.c
This function runs automatically after the system starts

static int __init input_init(void)
{
	int err;
	// Register an input device class. See the following for details
	// After registration, a new directory will be generated: / sys/class/input
	err = class_register(&input_class);
	if (err) {
		pr_err("unable to register input_dev class\n");
		return err;
	}
	...
	// Application equipment No
	// Parameter 1 starting equipment number, parameter 2 number of secondary equipment numbers, parameter 3 name
	err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
				     INPUT_MAX_CHAR_DEVICES, "input");
	if (err) {
		pr_err("unable to register char major %d", INPUT_MAJOR);
		goto fail2;
	}

	return 0;

 fail2:	input_proc_exit();
 fail1:	class_unregister(&input_class);
	return err;
}

input_class definition

drivers/input/input.c

struct class input_class = {
	.name		= "input",
	.devnode	= input_devnode,
};

INPUT_MAJOR definition

include/uapi/linux/major.h

#define INPUT_MAJOR  13

INPUT_MAX_CHAR_DEVICES definition

drivers/input/input.c

#define INPUT_MAX_CHAR_DEVICES		1024

input_dev structure

Identify an input device
include/linux/input.h

struct input_dev {
	// Device name
	const char *name;
	const char *phys;
	const char *uniq;
	// Save the attributes of the input device, support the manufacturer and version number, and match the input device with the specific event processor through this member
	struct input_id id;

	unsigned long propbit[BITS_TO_LONGS(INPUT_PROP_CNT)];
	// Record which input events are supported by the input device
	unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
	// Key events, which specific key types are supported
	unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
	// Relative coordinate time, specifying the supported relative coordinate type
	unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
	// Absolute coordinate event, specifying the absolute coordinate type supported
	unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
	unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
	unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
	unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
	unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
	unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
	...
	int (*open)(struct input_dev *dev);
	void (*close)(struct input_dev *dev);
	int (*flush)(struct input_dev *dev, struct file *file);
	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
	...
	// inherit
	struct device dev;

	struct list_head	h_list;
	struct list_head	node;

	unsigned int num_vals;
	unsigned int max_vals;
	struct input_value *vals;

	bool devres_managed;
};
  • Name: enter the device name

  • id: enter the matching information between the device and the event processor

  • evbit: Specifies the supported event types

    • Synchronization event, key event, coordinate event
  • keybit: Specifies the supported key value types

    • key1,key2...
  • relbit: Specifies the relative coordinate type supported

    • x-axis, y-axis, z-axis, pulley
  • absbit: Specifies the absolute coordinate type supported

    • x-axis, y-axis, z-axis, pulley

Event type

include/linux/input.h

// Synchronization event
#define EV_SYN			0x00
// Key event
#define EV_KEY			0x01
// Relative coordinate event
#define EV_REL			0x02
// Absolute coordinate event
#define EV_ABS			0x03
...
#define EV_CNT			(EV_MAX+1)

Key value type

include/linux/input.h

#define KEY_RESERVED		0
#define KEY_ESC			1
#define KEY_1			2
#define KEY_2			3
#define KEY_3			4
#define KEY_4			5
#define KEY_5			6
...

Register / destroy input devices

Assignment, registration, cancellation, release

input_allocate_device() function

drivers/input/input.c

Allocate and initially initialize input_dev struct variable

struct input_dev *input_allocate_device(void)

input_register_device() function

drivers/input/input.c

Register the input device with the system

int input_register_device(struct input_dev *dev)

Return value:
0: successful
-1: Fail

input_unregister_device() function

drivers/input/input.c

Log off the input device to the system

void input_unregister_device(struct input_dev *dev)

input_free_device() function

drivers/input/input.c

Release input_dev struct variable

void input_free_device(struct input_dev *dev)

Report input events

input_event() function

drivers/input/input.c

General event reporting interface

void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
  • dev
    Input device for reporting information

  • Type: the specific input event type reported
    Key input type: EV_KEY
    Coordinate input type: EV_REL,EV_ABS
    Special type: EV_SYN
    Synchronization event: notifies user space programs to receive messages
    ...

  • code
    Record specific events in the input event type
    When a key input type event occurs on the keyboard, record which value of the keyboard is pressed
    ...

  • Value: the corresponding value of the specific event
    Press the key, and the value is 1; When the key is released, the value is 0
    ...

input_report_key() function

include/linux/input.h

Key event special reporting interface

static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_KEY, code, !!value);
}

input_report_rel() function

include/linux/input.h

Special reporting interface for relative coordinate events

static inline void input_report_rel(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_REL, code, value);
}

input_report_abs() function

include/linux/input.h

Special reporting interface for absolute coordinate events

static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
{
	input_event(dev, EV_ABS, code, value);
}

input_sync() function

include/linux/input.h

Special reporting interface for synchronization events
The special events reported above, such as key, rel, key, etc., are not reported immediately.
Instead, the data is temporarily stored in a circular queue buffer until input is called_ Sync, will notify the user space to read the data in the circular queue buffer

static inline void input_sync(struct input_dev *dev)
{
	input_event(dev, EV_SYN, SYN_REPORT, 0);
}

Topics: Embedded system