[punctual atom linux serial] Chapter 17 input device application programming - extracted from [punctual atom] I.MX6U embedded Linux C application programming guide V1.1

1) Experimental platform: punctual atom alpha Linux development board
2) Platform purchase address: https://item.taobao.com/item.htm?id=603672744434
2) Full set of experimental source code + manual + video download address: http://www.openedv.com/thread-300792-1-1.html
3) Students interested in punctual atomic Linux can add group discussion: 935446741
4) pay attention to the official account of the dot atom and get updated information.

Chapter 17 input device application programming

This chapter studies the application programming of input devices. First, you should know what input devices are? Input devices are actually devices that can generate input events, which are called input devices. Common input devices include mouse, keyboard, touch screen, buttons, etc. they can generate input events and generate input data to the computer system.
For the application programming of the input device, it is mainly to obtain the data reported by the input device and the current state of the input device, such as obtaining the X-axis and Y-axis position information of the current touch point of the touch screen and whether the touch screen is currently pressed or released.
This chapter will discuss the following topics.
 what is an input device;
 how to read the data of the input device;
 how to analyze the data obtained from the input device;
 how keys and touch screen devices analyze data.

18.1 introduction to input equipment programming
18.1. 1 what is an input device
Let's first understand what input devices are (also known as input devices). Common input devices include mouse, keyboard, touch screen, remote control, computer drawing board, etc. users interact with the system through input devices.
18.1.2input subsystem
It can be seen from the above introduction that there are many types of input devices, and the data reported by each device is different. How can the Linux system manage it? In order to manage these input devices uniformly, Linux system implements a framework that is compatible with all input devices. Then this framework is the input subsystem. The driver developer develops the driver of the input device based on the input subsystem. The input subsystem can shield the difference of hardware and provide a set of unified interface to the application layer.
The input devices registered successfully based on the input subsystem will generate corresponding device nodes (device files) in the / dev/input directory. The data reported by the input devices can be obtained by reading these device nodes.
18.1. 3 process of reading data
If we want to read the data of the touch screen, assuming that the device node corresponding to the touch screen device is / dev/input/event0, the data reading process is as follows:
① . the application opens the / dev/input/event0 device file;
② . the application initiates a read operation (for example, calling read). If there is no data readable, it will enter sleep (when I/O is blocked);
③ . when there is data readable, the application will be awakened, and the read operation will obtain the data return;
④ . the application program parses the read data.
When no data is readable, The program will go to sleep (that is, blocking). For example, when an application reads the touch screen, we do not touch the touch screen at present, so naturally there is no data readability; when we touch the touch screen with our fingers, there is data readability, and the application will wake up and successfully read the data. The same is true for other input devices. When there is no data readability, the application will enter the sleep state, Of course, what we are talking about here is that in the blocking I/O mode, it will be awakened when there is data readable.
18.1. 4 how does the application parse data
First of all, we need to know that the application opens the device file of the input device and initiates a read operation to it. What kind of data is obtained by this read operation? In fact, each read operation obtains a struct input_event structure type data, which is defined in < Linux / input h> In the header file, it is defined as follows:
Example code 18.1 1 struct input_ Event structure

struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

The time member variable in the structure is a variable of struct timeval type. The structure has been introduced to you earlier. Each input event is struct input_event contains its occurrence time, which is described by the variable time of struct timeout type. The time parameter is usually not very important, while the other three member variables type, code and value are more important.
 type: type is used to describe what kind of events have occurred. The input event types supported by the Linux system are as follows:

/*
 * Event types
 */

#define EV_SYN 			 0x00 		// Synchronous events, used to separate events
#define EV_KEY 			 0x01 		// Key event
#define EV_REL 			 0x02 		// Relative displacement events (such as mouse)
#define EV_ABS 			 0x03 		// Absolute displacement events (e.g. touch screen)
#define EV_MSC 			 0x04 		// Other miscellaneous
#define EV_SW			0x05
#define EV_LED			0x11
#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)

These macro definitions are also in < Linux / input h> Header file, so the header file needs to be included in the application; An input device can usually generate many different types of events. For example, when the mouse clicks a key (left, right, or other keys on the mouse), it will report a key event, and when the mouse is moved, it will report a relative displacement event.
 Code: code indicates which specific event under this type of event, and each event type has A corresponding series of events. Different event types contain different events. For example, for key events, there are many keys on A keyboard, such as letters A, B, C, D or numbers 1, 2, 3, 4, etc. each different key will correspond to A specific event, as shown below:

#define KEY_RESERVED		0
#define KEY_ESC 			 one 			// ESC key
#define KEY_ one 			 two 			// Number 1 key
#define KEY_ two 			 three 			// Number 2 key
#define KEY_TAB 			 fifteen 			// Tab key
#define KEY_Q 			 sixteen 			// Letter Q key
#define KEY_W 			 seventeen 			// Letter W key
#define KEY_E 			 eighteen 			// Letter e key
#define KEY_R 			 nineteen 			// Letter R key
......
Relative displacement event code value
#define REL_X 			 0x00 	// X axis
#define REL_Y 			 0x01 	// Y axis
#define REL_Z 			 0x02 	// Z axis
#define REL_RX			0x03
#define REL_RY			0x04
#define REL_RZ			0x05
#define REL_HWHEEL		0x06
#define REL_DIAL		0x07
#define REL_WHEEL		0x08
#define REL_MISC		0x09
#define REL_MAX			0x0f
#define REL_CNT			(REL_MAX+1)

code value of absolute displacement event
For example, for touch screen devices, a touch point has X-axis coordinates and Y-axis coordinates, and even a touch point has pressure value and other information. Each kind of information will correspond to a specific event, that is, code value.

#define ABS_X 			 0x00 		// X axis
#define ABS_Y 			 0x01 		// Y axis
#define ABS_Z 			 0x02 		// Z axis
#define ABS_RX			0x03
#define ABS_RY			0x04
#define ABS_RZ			0x05
#define ABS_THROTTLE		0x06
#define ABS_RUDDER		0x07
#define ABS_WHEEL		0x08
#define ABS_GAS			0x09
#define ABS_BRAKE		0x0a
#define ABS_HAT0X		0x10
#define ABS_HAT0Y		0x11
#define ABS_HAT1X		0x12
#define ABS_HAT1Y		0x13
#define ABS_HAT2X		0x14
#define ABS_HAT2Y		0x15
#define ABS_HAT3X		0x16
#define ABS_HAT3Y		0x17
#define ABS_PRESSURE		0x18
#define ABS_DISTANCE		0x19
#define ABS_TILT_X		0x1a
#define ABS_TILT_Y		0x1b
#define ABS_TOOL_WIDTH		0x1c
......

In addition to those listed above, there are many more. You can browse < Linux / input h> Header files (these macros are actually defined in the input event codes. H header file, which is included in < Linux / input. H >), these specific events will be introduced later.
 value: value represents the event value, and the interpretation of value changes with the change of code type. For example, for key events, if code indicates key 1, then value equal to 1 indicates that key 1 is pressed, value equal to 0 indicates that key 1 is released, and if value equal to 2 indicates that the key is pressed for a long time. For example, in an absolute displacement event, if code represents the X-axis coordinate ABS_ 10. Then the value value indicates the position of the touch point in the X-axis coordinate. Therefore, the interpretation of value value depends on different code types!
Separation and synchronization between events
We mentioned the synchronization event EV above_ SYN is used to separate different events and realize synchronous operation. When an application reads data from an input device, only one struct input can be read at a time_ Event type data. For example, for the touch screen, a touch point will report the X-axis coordinate position, Y-axis coordinate position, and possibly the pressure value. In this case, the application needs to perform three read operations to read all the data reported by a touch point; This is only the case of a single touch point. If the touch screen device supports multi-point touch and there are multiple touch points on the touch screen at the same time, the data of all touch points needs to be read out in the program, which is considered complete.
So how does the application know that the complete data has been read? In fact, it is realized through synchronization events. After the driver reports the complete data (such as X-axis, Y-axis and pressure of the touch point), a synchronization event will be reported to inform the application that the data has been completed and synchronized.
Synchronization event types also contain many different events, that is, code values, as shown below:

/*
 * Synchronization events.
 */

#define SYN_REPORT		0
#define SYN_CONFIG		1
#define SYN_MT_REPORT		2
#define SYN_DROPPED		3
#define SYN_MAX			0xf
#define SYN_CNT			(SYN_MAX+1)

The synchronization event reported is usually the first SYN_REPORT (code value), and the value value is usually 0. For synchronous events, the application usually does not need to care which specific colleague event it is. Just know that type is equal to EV_SYN, which means the data is complete.
18.2 write a program to read the data of the input device
The path corresponding to the source code of this routine is: development board CD - > 11, Linux C application programming routine source code - > 18_ input->read_ input. c.
According to the previous introduction, we write a simple sample code for testing. The sample code is as follows:
Example code 18.2 1 read data from input device

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc, char *argv[])
{
    struct input_event in_ev = {0};
    int fd = -1;

    /* Check transmission parameters */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
        exit(-1);
    }

    /* Open file */
    if (0 > (fd = open(argv[1], O_RDONLY))) {
        perror("open error");
        exit(-1);
    }

    for ( ; ; ) {

        /* Loop read data */
        if (sizeof(struct input_event) !=
            read(fd, &in_ev, sizeof(struct input_event))) {
            perror("read error");
            exit(-1);
        }

        printf("type:%d code:%d value:%d\n",
                in_ev.type, in_ev.code, in_ev.value);
    }
}

When you execute a program, you need to import parameters. This parameter is the corresponding device node (device file) of the input device. In the program, the parameter will be checked. In the program, first call the open() function to open the device file, then call the read() function in the for loop to read the file, and store the read data in struct input_. Event in the structure object, and then print out each member variable in the structure object. Note that the blocking I/O mode is used in the program to read the device file, so the read call will be blocked when there is no data readable, and will be awakened when there is data readable!
Use the cross compilation tool to compile the above code to obtain the executable testApp:

Figure 18.2 1 compile sample code
18.3 testing on the development board
Copy the executable file testApp compiled in the previous section to the root file system of the development board, for example, to the home directory of the Linux system of the development board:

Figure 18.3 1 copy the testApp file to the development board home directory
There is a user key KEY0 on the alpha Linux development board, which is a typical input device, as shown in the following figure:

Figure 18.3 2 user key KEY0
The key is a GPIO key provided to the user. The underlying driver is implemented based on the Linux input subsystem. Therefore, the device node of the key device exists in the / dev/input directory. Which device node can be used? 13.1 The method described in Section 1 is not repeated here! You can also see by viewing the / proc/bus/input/devices file. Viewing this file can obtain the relevant information of all input devices registered in the system, as shown below:

Figure 18.3 3 view the / proc/bus/input/devices file
It should be noted that when the key KEY0 is pressed, The underlying driver will report the key event (EV_KEY), and the corresponding event is KEY_VOLUMEDOWN (that is, the VOLUMEDOWN key on the keyboard. It seems that there is no such key on the ordinary keyboard, and there is such a key on the keyboard of the notebook). The code value of this event is equal to 114. You can compare the < Linux / input. H > header file to find it. This is already configured by the factory system of the alpha development board.
Next, we use this key to test, execute the following commands (the device node corresponding to the development board key KEY0 used by the author in the test is / dev/input/event2), and then press and release the KEY0 key:

Figure 18.3 4 test
In the first line, type is equal to 1, indicating that the key event EV is reported_ Key, code equals 114, which is the key mentioned above_ The volumedown key, with value equal to 1, means that it is pressed, so the whole first line means KEY_VOLUMEDOWN is pressed.
In the second line, type is equal to 0, indicating that the synchronization event EV is reported_ Syn indicates that the previously reported data is complete, because there are only two states for the key: press and release, so as long as the EV is obtained_ The value of the key event indicates that the data is complete.
In the third line, type is equal to 1, indicating the key event, code is equal to 114 and value is equal to 0, so it indicates the KEY_VOLUMEDOWN is released.
In the fourth line, a synchronization event is reported.
Therefore, the printing information in the above four lines is the data reported by the underlying driver when the KEY0 key on the development board is pressed and released.
Let's try to press and hold key 0, as shown below:

Figure 18.3 5. Press and hold the key KEY0
It can be seen that when the key event is reported, the corresponding value is equal to 2, indicating the long press status.
Next, let's review the sample code 17.2 1. Modify without directly printing struct input_ Each member variable in the event data structure, but by analyzing these data, judge whether the key is currently pressed, released or long pressed, and print the results. The modified code is as follows:
The path corresponding to the source code of this routine is: development board CD - > 11, Linux C application programming routine source code - > 18_ input->read_ key. c.
Example code 18.3 1 judge the current state of key 0

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc, char *argv[])
{
    struct input_event in_ev = {0};
    int fd = -1;
    int value = -1;

    /* Check transmission parameters */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
        exit(-1);
    }

    /* Open file */
    if (0 > (fd = open(argv[1], O_RDONLY))) {
        perror("open error");
        exit(-1);
    }

    for ( ; ; ) {

        /* Loop read data */
        if (sizeof(struct input_event) !=
            read(fd, &in_ev, sizeof(struct input_event))) {
            perror("read error");
            exit(-1);
        }

        switch (in_ev.type) {
        case EV_KEY:    //Key event
            if (KEY_VOLUMEDOWN == in_ev.code)
                value = in_ev.value;
            break;

        case EV_SYN:    //Synchronization event
            switch (value) {
            case 0:
                printf("Key release\n");
                break;
            case 1:
                printf("Press the key\n");
                break;
            case 2:
                printf("Press and hold the key\n");
                break;
            }

            value = -1;
            break;
        }
    }
}

In the above program, the read data is not directly printed, but the data is analyzed to judge the current state of key KEY0. When the key event is reported, the value value is saved. When the synchronization event is reported, it means that the reported data is complete. Then, it is judged whether the value value is equal to 0, 1 or 2, so as to judge whether the current state of key 0 is released, pressed or long pressed.
Compile the above code and copy it to the development board home directory for testing:

Figure 18.3 6 test results
18.4 reading touch screen data
This section describes how to analyze the data reported by the touch screen device. The touch screen device is an absolute displacement device that can report absolute displacement events. The absolute displacement events that can be reported are as follows:

#define ABS_X 			 0x00 	// X-axis coordinates
#define ABS_Y 			 0x01 	// Y position 
#define ABS_Z 			 0x02 	// Z-axis coordinates
#define ABS_RX			0x03
#define ABS_RY			0x04
#define ABS_RZ			0x05
#define ABS_THROTTLE		0x06
#define ABS_RUDDER		0x07
#define ABS_WHEEL		0x08
#define ABS_GAS			0x09
#define ABS_BRAKE		0x0a
#define ABS_HAT0X		0x10
#define ABS_HAT0Y		0x11
#define ABS_HAT1X		0x12
#define ABS_HAT1Y		0x13
#define ABS_HAT2X		0x14
#define ABS_HAT2Y		0x15
#define ABS_HAT3X		0x16
#define ABS_HAT3Y		0x17
#define ABS_PRESSURE 		 0x18 	// Press pressure
#define ABS_DISTANCE		0x19
#define ABS_TILT_X		0x1a
#define ABS_TILT_Y		0x1b
#define ABS_TOOL_WIDTH		0x1c

#define ABS_VOLUME		0x20

#define ABS_MISC		0x28

#define ABS_MT_SLOT		0x2f	/* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR	0x30	/* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR	0x31	/* Minor axis (omit if circular) */
#define ABS_MT_WIDTH_MAJOR	0x32	/* Major axis of approaching ellipse */
#define ABS_MT_WIDTH_MINOR	0x33	/* Minor axis (omit if circular) */
#define ABS_MT_ORIENTATION	0x34	/* Ellipse orientation */
#define ABS_MT_POSITION_X 	 0x35 	/*  Center X touch position */ 	// X-axis coordinates
#define ABS_MT_POSITION_Y 	 0x36 	/*  Center Y touch position */ 	// Y position 
#define ABS_MT_TOOL_TYPE	0x37	/* Type of touching device */
#define ABS_MT_BLOB_ID		0x38	/* Group a set of packets as a blob */
#define ABS_MT_TRACKING_ID	0x39	/* Unique ID of initiated contact */
#define ABS_MT_PRESSURE 		 0x3a 	/*  Pressure on contact area */ 	// Press pressure
#define ABS_MT_DISTANCE		0x3b	/* Contact hover distance */
#define ABS_MT_TOOL_X		0x3c	/* Center X tool position */
#define ABS_MT_TOOL_Y		0x3d	/* Center Y tool position */


#define ABS_MAX			0x3f
#define ABS_CNT			(ABS_MAX+1)

ABS is commonly used_ X,ABS_Y,ABS_PRESSURE,ABS_MT_POSITION_X,ABS_MT_POSITION_Y,ABS_ MT_ Press: the last three events with MT are usually used in devices that support multi touch. The touch screen used with alpha development board supports 5 touch points, and the 10.1-inch screen even supports up to 10 touch points. If you need to obtain the setting information of multiple touch points in the application, you need to capture the ABS reported by the device_ MT_ POSITION_ X,ABS_MT_POSITION_Y event, get the value corresponding to the event.
In addition to reporting absolute displacement events, the touch screen can also report key events. When our fingers click or release from the touch screen, the underlying driver will report key events, and the corresponding key event is BTN_ Touch (code equals 0x14a), the value corresponding to the BTN_TOUCH event reported when pressed is equal to 1, and the value is equal to 0 when released; sliding on the touch screen will not report the BTN_TOUCH event.
The following example code demonstrates how to read a single touch point, including the x-axis coordinate position and y-axis coordinate position of the touch point. Read the x-axis coordinate position and y-axis coordinate position of a single touch point, and only capture the ABS reported by the equipment_ X,ABS_Y event, just get the corresponding value data!
The path corresponding to the source code of this routine is: development board CD - > 11, Linux C application programming routine source code - > 18_ input->read_ ts.c.
Example code 18.4 1 read touch screen data

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc, char *argv[])
{
    struct input_event in_ev = {0};
    int x_val, y_val, key_val;
    int fd = -1;

    /* Check transmission parameters */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
        exit(-1);
    }

    /* Open file */
    if (0 > (fd = open(argv[1], O_RDONLY))) {
        perror("open error");
        exit(-1);
    }

    x_val = y_val = key_val = -1;
    for ( ; ; ) {

        /* Loop read data */
        if (sizeof(struct input_event) !=
            read(fd, &in_ev, sizeof(struct input_event))) {
            perror("read error");
            exit(-1);
        }

        switch (in_ev.type) {
        case EV_KEY:    //Key event
            if (BTN_TOUCH == in_ev.code)
                key_val = in_ev.value;  //Save BTN_ value of touch
            break;

        case EV_ABS:    //Absolute displacement event
            if (ABS_X == in_ev.code)    //X axis
                x_val = in_ev.value;    //Save X coordinate position
            else if (ABS_Y == in_ev.code)//Y axis
                y_val = in_ev.value;    //Save Y coordinate position
            break;

        case EV_SYN:    //Synchronization event
            if (1 == key_val)   //Press
                printf("Press, X=%d Y=%d\n", x_val, y_val);
            else if (0 == key_val)
                printf("release\n");
            else
                printf("X=%d Y=%d\n", x_val, y_val);

            key_val = -1;
            break;
        }
    }
}

In the program, the parameters are first verified, and the device file path is passed into the program by passing parameters. Then, open() is called to open the file, the device file is read in the for loop, and the read data is stored in struct input_event data structure. Analyze the read data in the switch... case statement to determine the reported BTN_TOUCH event, judge whether the touch screen is pressed or released, and capture ABS_X and ABS_ If the Y event obtains the corresponding value variable, the x-axis coordinate position and y-axis coordinate position of the touch point can be obtained.
Hardware connection
The factory system of alpha I.MX6U development board supports a variety of LCD screens with different resolutions, including 4.3-inch 480272, 4.3-inch 800480, 7-inch 800480, 7-inch 1024600 and 10.1-inch 1280 * 800. Before starting the development board, the LCD screen needs to be connected to the LCD interface of the development board through a flexible cable. After the development board is connected with the LCD screen, power on the development board to run the factory burning system of the development board.

Figure 18.4 1 hardware connection
The touch screen and LCD panel are bonded together, that is, the touch screen is directly pasted on the LCD screen. We can directly touch and slide the touch screen installed on the LCD screen through fingers or other objects that can be touched.
For the convenience of testing, you can exit the GUI application of the factory system. How to exit? Click the screen to enter the setting page. You can see that there is an exit button option under this page. Click directly!
Compile test
Use the cross compilation tool to compile the sample code 17.4 1 copy it to the development board home directory and execute the program (the device node corresponding to the development board touch screen used by the author is / dev/input/event1). After the program is executed, you can touch, release and slide the touch screen, and the serial port terminal will print out the corresponding information:

Figure 18.4 2 test results
When the finger clicks the touch screen, it will print "press, x = XXX, y = YYY". When it is released, it will print "release". When the finger slides on the touch screen, it will only print coordinate information. You can test by yourself. If you don't understand the code, you can compare the test results.

Keywords: Linux

Added by MJH Mike on Sat, 25 Dec 2021 21:18:51 +0200