【Linux系统编程应用】 Linux Input子系统(一)

1. 什么是输入子系统 ?
输入子系统是 Linux内核用于管理各种输入设备 (键盘,鼠标,遥控杆,书写板等等 )的部分,用户通过输入子系统进行内核,命令行,图形接口之间的交换。输入子系统在内核里实现,因为设备经常要通过特定的硬件接口被访问 (例如串口, ps/2, usb等等 ),这些硬件接口由内核保护和管理。内核给用户导出一套固定的硬件无关的 input API,供用户空间程序使用。

 

2. 理解内核内部实现

输入子系统分为三块: input core, drivers和 event handlers。他们之间的关系如图 1所示。正常的路径是从底层硬件到驱动,从驱动到 input core,从 input core到 event handler,从 event handler到 user space。此外,还存在一个返回路径 (return path)。返回路径允许给一个键盘设置 LED,给一个 force feedback joystick提供 motion commands。路径的两个方向(指从内核到用户的方向和从用户到内核的方向)使用相同的event定义和不同的 type identifier。


3. 相关结构体

[root@uplooking ~]# vim /usr/include/linux/input.h 

/*
 * The event structure itself
 */
struct input_event {
	struct timeval time;	输入事件时间;
	__u16 type;				类型;	
	__u16 code;				按键值:		
	__s32 value;			按键状态:
};



type类型可以设置为如下:

/*
 * Event types
 */

#define EV_SYN          0x00		//表示设备所支持所有的事件
#define EV_KEY          0x01		//按键
#define EV_REL          0x02		//鼠标事件 相对坐标
#define EV_ABS          0x03		//手写板事件 绝对坐标
#define EV_MSC          0x04		//其他类型
#define EV_SW           0x05
#define EV_LED          0x11		//LED灯设备
#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



code:事件代码
事件的代码。如果事件的类型代码是EV_KEY,该代码code为设备键盘代码,代码值0~127为键盘上的按键代码, 0x110~0x116 为鼠标上按键代码,其中0x110(BTN_ LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_ MIDDLE)为鼠标中键。其它代码含义请参看include/linux /input.h文件。如果事件的类型代码是EV_REL,code值表示轨迹的类型。如指示鼠标的X轴方向 REL_X (代码为0x00),指示鼠标的Y轴方向REL_Y(代码为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08)。
*
 * Keys and buttons
 */

#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
#define KEY_6			7
#define KEY_7			8
#define KEY_8			9
#define KEY_9			10
#define KEY_0			11
#define KEY_MINUS		12
#define KEY_EQUAL		13
#define KEY_BACKSPACE		14
#define KEY_TAB			15
#define KEY_Q			16
#define KEY_W			17
#define KEY_E			18
#define KEY_R			19
#define KEY_T			20
#define KEY_Y			21
#define KEY_U			22
#define KEY_I			23
#define KEY_O			24
#define KEY_P			25
#define KEY_LEFTBRACE		26
#define KEY_RIGHTBRACE		27
#define KEY_ENTER		28
#define KEY_LEFTCTRL		29
#define KEY_A			30
#define KEY_S			31
#define KEY_D			32
#define KEY_F			33
#define KEY_G			34
#define KEY_H			35
#define KEY_J			36
#define KEY_K			37
#define KEY_L			38
#define KEY_SEMICOLON		39
#define KEY_APOSTROPHE		40
#define KEY_GRAVE		41
#define KEY_LEFTSHIFT		42
#define KEY_BACKSLASH		43
#define KEY_Z			44
#define KEY_X			45
#define KEY_C			46
#define KEY_V			47
#define KEY_B			48
#define KEY_N			49
#define KEY_M			50
#define KEY_COMMA		51
#define KEY_DOT			52
#define KEY_SLASH		53
#define KEY_RIGHTSHIFT		54
#define KEY_KPASTERISK		55
#define KEY_LEFTALT		56
#define KEY_SPACE		57
#define KEY_CAPSLOCK		58
#define KEY_F1			59
#define KEY_F2			60
#define KEY_F3			61
#define KEY_F4			62
#define KEY_F5			63
#define KEY_F6			64
#define KEY_F7			65
#define KEY_F8			66
#define KEY_F9			67
#define KEY_F10			68
#define KEY_NUMLOCK		69
#define KEY_SCROLLLOCK		70
#define KEY_KP7			71
#define KEY_KP8			72
#define KEY_KP9			73
#define KEY_KPMINUS		74
#define KEY_KP4			75
#define KEY_KP5			76
#define KEY_KP6			77
#define KEY_KPPLUS		78
#define KEY_KP1			79
#define KEY_KP2			80
#define KEY_KP3			81
#define KEY_KP0			82
#define KEY_KPDOT		83

#define KEY_ZENKAKUHANKAKU	85
#define KEY_102ND		86
#define KEY_F11			87
#define KEY_F12			88
#define KEY_RO			89
#define KEY_KATAKANA		90
#define KEY_HIRAGANA		91
#define KEY_HENKAN		92
#define KEY_KATAKANAHIRAGANA	93
#define KEY_MUHENKAN		94
#define KEY_KPJPCOMMA		95
#define KEY_KPENTER		96
#define KEY_RIGHTCTRL		97
#define KEY_KPSLASH		98
#define KEY_SYSRQ		99
#define KEY_RIGHTALT		100
#define KEY_LINEFEED		101
#define KEY_HOME		102
#define KEY_UP			103
#define KEY_PAGEUP		104
#define KEY_LEFT		105
#define KEY_RIGHT		106
#define KEY_END			107
#define KEY_DOWN		108
#define KEY_PAGEDOWN		109
#define KEY_INSERT		110
#define KEY_DELETE		111
#define KEY_MACRO		112
#define KEY_MUTE		113
#define KEY_VOLUMEDOWN		114
#define KEY_VOLUMEUP		115
#define KEY_POWER		116
#define KEY_KPEQUAL		117
#define KEY_KPPLUSMINUS		118
#define KEY_PAUSE		119

#define KEY_KPCOMMA		121
#define KEY_HANGEUL		122
#define KEY_HANGUEL		KEY_HANGEUL
#define KEY_HANJA		123
#define KEY_YEN			124
#define KEY_LEFTMETA		125
#define KEY_RIGHTMETA		126
#define KEY_COMPOSE		127

鼠标相关的值

#define BTN_MOUSE		0x110
#define BTN_LEFT		0x110
#define BTN_RIGHT		0x111
#define BTN_MIDDLE		0x112
#define BTN_SIDE		0x113
#define BTN_EXTRA		0x114
#define BTN_FORWARD		0x115
#define BTN_BACK		0x116
#define BTN_TASK		0x117


相对坐标

Type为EV_REL时,code表示操作的是哪个坐标轴,如:REL_X,REL_Y。(因为鼠标有x,y两个轴向,所以一次鼠标移动,会产生两个input_event)
*
 * Relative axes
 */

#define REL_X			0x00
#define REL_Y			0x01
#define REL_Z			0x02
#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
value:根据Type的不同而含义不同。
例如:
Type为EV_KEY时,value: 0表示按键抬起。1表示按键按下。(4表示持续按下等?)。
Type为EV_REL时,value: 表明移动的值和方向(正负值)。
Type为EV_ABS时,code表示绝对位置。


4. 键盘设备示例代码

【Linux系统编程应用】 Linux Input子系统(一)_第1张图片


执行结果如下:

【Linux系统编程应用】 Linux Input子系统(一)_第2张图片


5. 鼠标设备示例代码

【Linux系统编程应用】 Linux Input子系统(一)_第3张图片


执行结果如下:

【Linux系统编程应用】 Linux Input子系统(一)_第4张图片


6. 模拟鼠标和按键的示例代码

#include 
#include 
#include 
#include 
#include 

//按键模拟,按键包含按下和松开两个环节

void simulate_key(int fd, int kval)
{

         struct input_event event;
         gettimeofday(&event.time, 0);

       //按下kval键
         event.type = EV_KEY;
         event.value = 1;
         event.code = kval;
         write(fd, &event, sizeof(event));
       //同步,也就是把它报告给系统
         event.type = EV_SYN;
         event.value = 0;
         event.code = SYN_REPORT;
         write(fd, &event, sizeof(event));

         memset(&event, 0, sizeof(event));
         gettimeofday(&event.time, 0);
         //松开kval键
        event.type = EV_KEY;
         event.value = 0;
         event.code = kval;
         write(fd, &event, sizeof(event));

       //同步,也就是把它报告给系统
       event.type = EV_SYN;
       event.value = 0;
       event.code = SYN_REPORT;
       write(fd, &event, sizeof(event));
}

//鼠标移动模拟
void simulate_mouse(int fd, int rel_x, int rel_y)
{
    struct input_event event;
    gettimeofday(&event.time, 0);
    //x轴坐标的相对位移
    event.type = EV_REL;
    event.value = rel_x;
    event.code = REL_X;
    write(fd, &event, sizeof(event));

    //y轴坐标的相对位移

    event.type = EV_REL;
    event.value = rel_y;
    event.code = REL_Y;
    write(fd, &event, sizeof(event));
    //同步
    event.type = EV_SYN;
    event.value = 0;
    event.code = SYN_REPORT;
    write(fd, &event, sizeof(event));

}

int main(int argc, char **argv)
{
         int fd_mouse = -1;
         int fd_kbd = -1;
         int i = 0;

         fd_kbd = open("/dev/input/event3", O_RDWR);
         if(fd_kbd <= 0)
         {
                   printf("Can not open keyboard input file\n");
                   return -1;
         }

         fd_mouse = open("/dev/input/event2", O_RDWR);
        if(fd_mouse <= 0)
        {
                printf("Can not open mouse input file\n");
                return -1;
        }   

         for (i = 0; i < 50; i++)
         {
                   simulate_key(fd_mouse, BTN_LEFT);  //模拟按下鼠标左键
                   //if (i % 3 == 0)
                   //      simulate_key(fd_kbd, KEY_A);  //模拟按下键盘A键
                  //模拟鼠标相对上次x和y轴相应移动10个像素
                  //simulate_mouse(fd_mouse, 10, 10);                  
                   sleep(3);
         }
         close(fd_kbd);
         close(fd_mouse);
}


你可能感兴趣的:(Linux系统网络编程,Linux环境高级编程)