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

2019-07-13 06:00发布

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

4. 键盘设备示例代码


执行结果如下:

5. 鼠标设备示例代码

执行结果如下:

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 "); return -1; } fd_mouse = open("/dev/input/event2", O_RDWR); if(fd_mouse <= 0) { printf("Can not open mouse input file "); 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); }