Input under Linux system application programming combat

Author: Yang Yuan Xin (also our campus agency)

Authorized public reproduced in numbers embedded development circles, slightly modified.

What is the input subsystem? No matter what operating system, there is a program for managing a variety of input devices, which is an input device? For example, the touch screen on the computer keyboard, mouse, smart phone, keys. All input devices. Then the operating system how to manage these input devices? Here to explain the most common Linux operating system.

In the Linux kernel, there are many subsystem for managing many devices, such as display systems, input subsystem, audio subsystem, power management subsystem, clock management subsystem and so on, in this section we focus on the input subsystem.

Input subsystem is implemented in the kernel, as the device to be accessed frequently (e.g., serial, ps / 2, usb, etc.) by a specific hardware interface, these hardware protection and management by the kernel interfaces. Kernel to user to export a fixed set of hardware-independent input API, for user space programs.

In the Linux input subsystem manages three points, namely: input core (core input system), drivers (input layer system drive) and event handlers (input layer system events), you may feel too abstract, look Figure 4-5-9 clear.

7526403-b375b120fd7c7957
Here Insert Picture Description

First from the perspective of application knowledge input subsystem, we can see the corresponding equipment from the following file.

Open Linux terminal, enter the command cat / proc / bus / input / devices can see something like the following.

I: Bus=0003 Vendor=046d Product=c018 Version=0111
N: Name=" USB Optical Mouse"
P: Phys=usb-0000:00:1d.1-2/input0
S: Sysfs=/class/input/input24
U: Uniq=
H: Handlers=mouse1 event2
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=103

These devices are mainly used to describe the input file subsystem registered in the device, there may be a mouse, a keyboard, a touch screen, a gravity sensor, a temperature sensor, etc., when the write driver, the input device is registered by the device provided by the kernel associated interface, This information will be saved to the corresponding file.

So, how to input an input device subsystem description of it?

Linux system provides us with the relevant operating system input header file:

include <linux/input.h>

In this paper, can be found in this structure:

//用于描述一个输入事件
struct input_event {
    struct timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};

Here we see input_event nested structure further another structure struct timeval time;

Explanation first struct timeval time, which is defined in the following time.h

struct timeval
{
__time_t tv_sec;        /* Seconds. */
__suseconds_t tv_usec;    /*Microseconds. */
};

Wherein, when creating the tv_sec Epoch is a struct timeval number of seconds, as the number of microseconds tv_usec, i.e. behind the second fraction.

The type field is of an event type of report, e.g., a key press or button press, relative motion (such as a mobile mouse) or the absolute motion (such as a mobile joystick);

code field tells you what a key or axes in the operation;

value field devices now tell you what the state or movement yes.

There are three main events: the relative event (such as a mouse), absolute event (such as a touch screen), keyboard events.

Such as a mouse, we move the mouse when the mouse is a relative event, the type of the type that is underlying reporting events to a user relative event type, code represented is the coordinates of the current position of the mouse X or Y with respect to the, value that is, relative to the current position shifted much.

Event type (type) in input.h classified as follows:

 /*
  * Event types
  */
 #define EV_SYN            0x00     //同步事件,就是将结果上报给系统的过程
 #define EV_KEY            0x01     //按键事件
 #define EV_REL            0x02     //相对事件
 #define EV_ABS            0x03     //绝对事件
 本节,我们来实现一个input控制鼠标的应用程序。所以还会用到以下事件:
 /*
 * Relative axes
 */
//在这里,我们暂时只会用REL_X和REL_Y这两个参数
#define REL_X            0x00    //相对X坐标
#define REL_Y            0x01    //相对Y坐标

We can use the cat command to test the current mouse event in the end node belongs to which event, as shown in Figure 4-5-10:


7526403-82e18208ff264ec9.jpg
Here Insert Picture Description

Just switch to / dev / input, find the corresponding event node, and then use cat eventx (event node), and then move the mouse you can see the data printed matter, but the data we obviously can not read, but you can use the test the program will read out the value of the mouse.

Next, we write a program mouse.c take a look at how to read mouse events,

 #include <stdio.h>
 #include <linux/input.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <fcntl.h>
 /*
 struct input_event {
         struct timeval time;
         __u16 type;
        __u16 code;
        __s32 value;
};
*/
/*
Event types
#define EV_SYN                  0x00
#define EV_KEY                  0x01
#define EV_REL                  0x02
#define EV_ABS                  0x03
*/
/*
 Relative axes
#define REL_X                   0x00
#define REL_Y                   0x01
#define REL_Z                   0x02
#define REL_MAX                 0x0f
#define REL_CNT                 (REL_MAX+1)
*/
//event8  mouse
//event9  keyboard
int main(void)
{
    //1、定义一个结构体变量用来描述input事件
    struct input_event event_mouse ;
    //2、打开input设备的事件节点我的电脑对应的鼠标事件的节点是event3
//读者的电脑的设备节点可能和我的不一样,可以使用cat命令去获取,然后
//不断尝试
    int fd = open("/dev/input/event4",O_RDWR);
    int value ;
    int type ;
    int buffer[10]={0};
    if(-1 == fd){
        printf("open mouse event fair!\n");
        return -1 ;
    }   
    while(1){
        //3、读事件
       read(fd ,&event_mouse ,sizeof(event_mouse));
        //4、判断事件类型,并打印键码
        switch(event_mouse.type){
            //同步事件
            case EV_SYN:
                printf("sync!\n");
                 break ;
            case EV_REL:
            //鼠标事件,XY相对位移
            //code表示相对位移X或者Y,当判断是X时,打印X的相对位移value
            //当判断是Y时,打印Y的相对位移value
            if(event_mouse.code == REL_X){ 
                 printf("event_mouse.code_X:%d\n",event_mouse.code);    
                 printf("event_mouse.value_X:%d\n",event_mouse.value);  
            }
            if(event_mouse.code == REL_Y){
                 printf("event_mouse.code_Y:%d\n",event_mouse.code);    
                printf("event_mouse.value_Y:%d\n",event_mouse.value);  
           }
            defalut:
           break ;
       }
    }   
    return 0 ;
}

Operation result, as shown in FIG 4-5-11.


7526403-e76c148ab954050a.jpg
Here Insert Picture Description

As we continue to move the mouse, the values ​​will be printed.

Please think about a problem, since we can move the mouse print values ​​that can not be able to write a program to automatically control the mouse to move it? Certainly, let's write a program to make their own mouse to draw a square on the code:

 #include <stdio.h>
 #include <linux/input.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <fcntl.h>
 
 //event8  mouse
 //event9  keyboard
 int main(void)
{
    //1、定义一个结构体变量用来描述input事件
    struct input_event event_mouse ;
   //2、打开input设备的事件节点  我的电脑鼠标事件的节点是event3
    int fd = open("/dev/input/event3",O_RDWR);
    int value ;
    int type ;
    int i ;
    int buffer[10]={0};
    if(-1 == fd){
        printf("open mouse event fair!\n");
        return -1 ;
    }   
    while(1){
        //3、写事件
        for(i = 0 ; i < 20 ; i++){
           event_mouse.type = EV_REL ; 
           event_mouse.code = REL_X ;
           event_mouse.value = i ;  
           write(fd,&event_mouse,sizeof(event_mouse));         
           event_mouse.code = 0 ;
           event_mouse.value = 0;
           event_mouse.type = EV_SYN ;
           write(fd,&event_mouse,sizeof(event_mouse));         
           usleep(50000);
        }
        for(i = 0 ; i < 20 ; i++){
           event_mouse.type = EV_REL ; 
           event_mouse.code = REL_Y ;
           event_mouse.value = i ;  
           write(fd,&event_mouse,sizeof(event_mouse));         
           event_mouse.code = 0 ; 
           event_mouse.value = 0 ;
           event_mouse.type = EV_SYN ;
           write(fd,&event_mouse,sizeof(event_mouse));         
           usleep(50000);
        }
        for(i = 0 ; i > -20 ; i--){
           event_mouse.type = EV_REL ; 
           event_mouse.code = REL_X ;
           event_mouse.value = i ;  
           write(fd,&event_mouse,sizeof(event_mouse));         
           event_mouse.code = 0 ;
           event_mouse.value = 0;
           event_mouse.type = EV_SYN ;
           write(fd,&event_mouse,sizeof(event_mouse));         
           usleep(50000);
        }
        for(i = 0 ; i > -20 ; i--){
           event_mouse.type = EV_REL ; 
           event_mouse.code = REL_Y ;
           event_mouse.value = i ;  
           write(fd,&event_mouse,sizeof(event_mouse));         
           event_mouse.code = 0 ; 
           event_mouse.value = 0 ;
           event_mouse.type = EV_SYN ;
           write(fd,&event_mouse,sizeof(event_mouse));         
           usleep(50000);
        }

    }   
    return 0 ;
}

Readers implementation of the results independently verified.

Next we write a story: get the coordinate value in the capacitive screen Tiny4412 platform.

Touch-screen coordinate values ​​of reported incidents is absolutely event, that is, the coordinates of the touch point X and Y will report an absolute coordinate (X, Y) within the scope of the resolution of the screen.

So for reporting the type (type) as follows: EV_ABS

For the following code:

Relative to the X:

ABS_MT_POSITION_X

Relative to the Y:

ABS_MT_POSITION_Y

I used an application to get the screen resolution, a resolution that is 480 wide, 800 high.

First, when writing this program, I went through to Android adb root directory, then getevent -p found in the Events node of the touch screen is event0, but also know that the touch screen is an absolute event, as follows:


7526403-d86eed36f874570f
Here Insert Picture Description

Next, I created the following directory under Android5.0 source external directory: Getft5x0x_Test

There are the following two files in this directory:

Android.mk and Get_ft5x0x_tp.c

(1) look at the Android.mk

 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := eng
 LOCAL_SHARED_LIBRARIES += libcutils libutils
 #LOCAL_STATIC_LIBRARIES += libz libstdc++ libpng libvtpng
 LOCAL_STATIC_LIBRARIES += libz libstdc++ libpng
 
 LOCAL_SRC_FILES := Get_ft5x0x_tp.c
 LOCAL_MODULE := ft5x0x_tp
 include $(BUILD_EXECUTABLE)

(2)Get_ft5x0x_tp.c

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <dirent.h>
#include <inttypes.h>
#include <errno.h>
//ft5x0x_ts触摸屏事件初始化
18int touch_fd = -1 ;
19int ft5x0x_ts__init(void)
{
    touch_fd = open("/dev/input/event0", O_RDONLY);
    if (touch_fd < 0)
    {
        printf("open /dev/input/event0 failed\n");
        return -1;
    }
    return 0;
}

//获取ft5x0x_ts触摸屏上的坐标点
int Get_ft5x0x_ts_postion(int *x, int *y)
{
    int touch_ret = -1 ;    
    //1、定义一个结构体变量用来描述ft5x0x触摸屏事件  
    struct input_event ft5x0x_ts ;  

    //2、读事件  
    touch_ret = read(touch_fd ,&ft5x0x_ts ,sizeof(ft5x0x_ts));  
    if(touch_ret < 0){
    printf("read touch fair!\n");
    }
    //3、判断事件类型
    switch(ft5x0x_ts.type)
    {  
    case EV_SYN:  
             break ;  
        case EV_ABS:  
             if(ft5x0x_ts.code == ABS_MT_POSITION_X){   
        *x = ft5x0x_ts.value ;
            }  
             if(ft5x0x_ts.code == ABS_MT_POSITION_Y){  
        *y = ft5x0x_ts.value ;
             }  
        defalut:  
        break ;  
    }         
    return 0;
}


int main(int argc, char **argv)
{
    int tp_ret ;
    int ft5x0x_x = 0;
    int ft5x0x_y = 0; 
    tp_ret = ft5x0x_ts__init();
    if(-1 == tp_ret){
    printf("tp init fair!\n");
    return -1 ;
    }
    printf("tp init success!\n");
    while(1)
    {    //获取屏幕上的绝对坐标点
     Get_ft5x0x_ts_postion(&ft5x0x_x,&ft5x0x_y);
     printf("ft5x0x_x:%d     ft5x0x_y:%d\n",ft5x0x_x,ft5x0x_y);
     usleep(100);
    }    
    return 0;
}

After the preparation and Android.mk C, switch to Android root directory, compiled with the command Get_ft5x0x_tp.c

(Be sure to perform source and lunch two steps before using the command mmm)

root@morixinguan:/work/android-5.0.2# source build/envsetup.sh 
including device/samsung/manta/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including device/friendly-arm/tiny4412/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/asus/deb/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including sdk/bash_completion/adb.bash
root@morixinguan:/work/android-5.0.2# lunch 

You're building on Linux

Lunch menu... pick a combo:
     . aosp_arm-eng
     . aosp_arm64-eng
     . aosp_mips-eng
     . aosp_mips64-eng
     . aosp_x86-eng
     . aosp_x86_64-eng
     . aosp_manta-userdebug
     . aosp_shamu-userdebug
     . full_tiny4412-userdebug
     . full_tiny4412-eng
     . mini_emulator_x86_64-userdebug
     . m_e_arm-userdebug
     . mini_emulator_mips-userdebug
     . mini_emulator_arm64-userdebug
     . mini_emulator_x86-userdebug
     . aosp_deb-userdebug
     . full_fugu-userdebug
     . aosp_fugu-userdebug
     . aosp_grouper-userdebug
     . aosp_tilapia-userdebug
     . aosp_flo-userdebug
     . aosp_hammerhead-userdebug
     . aosp_mako-userdebug

Which would you like? [aosp_arm-eng] 20

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.0.2
TARGET_PRODUCT=aosp_tilapia
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=cortex-a9
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.8.0-46-generic-x86_64-with-Ubuntu-16.04-xenial
HOST_BUILD_TYPE=release
BUILD_ID=LRX22G
OUT_DIR=out
====================

root@morixinguan:/work/android-5.0.2# 

Next, the compiler:

mmm external/Getft5x0x_Test/

Then we see the following display:


7526403-4440554f1ddb8209
Here Insert Picture Description

This binary generate absolute path to the directory is out, we need ft5x0x_tp file, the name which is above the corresponding Android.mk inside:

LOCAL_MODULE := ft5x0x_tp

Install: out / target / product / tiny4412 / system / bin / ft5x0x_tp
copy this file to the current directory:

cp out/target/product/tiny4412/system/bin/ft5x0x_tp .

Then, the connection with the USB cable tiny4412 development board, then adb ft5x0x_tp push command to the system / bin / directory, which is a command of Android root file system, a lot of commands in this directory.

(If this is not adb, can be installed apt-get install adb)

After adb push completed, and then switch to the adb shell root

Execution ft5x0x_tp.bin, then touch touch screen, so that the coordinate values ​​is printed out.

7526403-17634034c28737b0
Here Insert Picture Description

ps: Wei Dongshan two video input subsystem of the drive mechanism to write and explain very clearly, there is need to look

                                       --END--

Public concern Pak asked Technologies (ID: baiwenkeji) the first time to read embedded dry.
Technical exchanges plus personal prestige 13,266,630,429, verify: Jane books

Guess you like

Origin blog.csdn.net/weixin_34216107/article/details/90974558