使用/dev/uinput的简要介绍(含demo程序)【转】

转自:https://blog.csdn.net/zhongkunjia/article/details/75142699

uinput机制有2个很大的优点:

1) 不用自己写驱动(比如弄个红外遥控器、车载线控)。

2) 创建/dev/input/eventX节点,在用户态下向/dev/input/eventX写入事件,即可模拟键盘、鼠标等的事件输入。


操作流程:

1)打开UInput Device

2)设置UInput Device

3)写入设备信息

4)创建Input Device

5*)向Input Device发送Event

具体的demo代码如下:

//uinput-demo.c

 

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <fcntl.h>  
  5. #include <string.h>  
  6. #include <linux/uinput.h>  
  7. #include <linux/input.h>  
  8.   
  9.   
  10. #define KEY_CUSTOM_UP 0x20  
  11. #define KEY_CUSTOM_DOWN 0x30  
  12.   
  13.   
  14. static struct uinput_user_dev uinput_dev;  
  15. static int uinput_fd;  
  16.   
  17. int creat_user_uinput(void);  
  18. int report_key(unsigned int type, unsigned int keycode, unsigned int value);  
  19.   
  20.   
  21. int main(int argc, char *argv[])  
  22. {  
  23.     int ret = 0;  
  24.     ret = creat_user_uinput();  
  25.     if(ret < 0){  
  26.         printf("%s:%d ", __func__, __LINE__);  
  27.         return -1;//error process.  
  28.     }  
  29.       
  30.     sleep(10);// help you to 'hexdump -C /dev/input/event[X]' for test.  
  31.       
  32.     report_key(EV_KEY, KEY_A, 1);// Report BUTTON A CLICK - PRESS event  
  33.     report_key(EV_KEY, KEY_A, 0);// Report BUTTON A CLICK - RELEASE event  
  34.       
  35.     report_key(EV_KEY, KEY_CUSTOM_UP, 12);  
  36.     report_key(EV_KEY, KEY_CUSTOM_UP, 0);  
  37.       
  38.     sleep(5);  
  39.     close(uinput_fd);  
  40.     return 0;  
  41. }  
  42.   
  43.   
  44. int creat_user_uinput(void)  
  45. {  
  46.     int i;  
  47.     int ret = 0;  
  48.   
  49.     uinput_fd = open("/dev/uinput", O_RDWR | O_NDELAY);  
  50.     if(uinput_fd < 0){  
  51.         printf("%s:%d ", __func__, __LINE__);  
  52.         return -1;//error process.  
  53.     }  
  54.       
  55.     //to set uinput dev  
  56.     memset(&uinput_dev, 0, sizeof(struct uinput_user_dev));  
  57.     snprintf(uinput_dev.name, UINPUT_MAX_NAME_SIZE, "uinput-custom-dev");  
  58.     uinput_dev.id.version = 1;  
  59.     uinput_dev.id.bustype = BUS_VIRTUAL;  
  60.       
  61.     ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN);  
  62.     ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);  
  63.     ioctl(uinput_fd, UI_SET_EVBIT, EV_MSC);  
  64.       
  65.     for(i = 0; i < 256; i++){  
  66.         ioctl(uinput_fd, UI_SET_KEYBIT, i);  
  67.     }  
  68.     ioctl(uinput_fd, UI_SET_MSCBIT, KEY_CUSTOM_UP);  
  69.     ioctl(uinput_fd, UI_SET_MSCBIT, KEY_CUSTOM_DOWN);  
  70.       
  71.     ret = write(uinput_fd, &uinput_dev, sizeof(struct uinput_user_dev));  
  72.     if(ret < 0){  
  73.         printf("%s:%d ", __func__, __LINE__);  
  74.         return ret;//error process.  
  75.     }  
  76.       
  77.     ret = ioctl(uinput_fd, UI_DEV_CREATE);  
  78.     if(ret < 0){  
  79.         printf("%s:%d ", __func__, __LINE__);  
  80.         close(uinput_fd);  
  81.         return ret;//error process.  
  82.     }  
  83. }  
  84.   
  85. int report_key(unsigned int type, unsigned int keycode, unsigned int value)  
  86. {  
  87.     struct input_event key_event;  
  88.     int ret;  
  89.       
  90.     memset(&key_event, 0, sizeof(struct input_event));  
  91.       
  92.     gettimeofday(&key_event.time, NULL);  
  93.     key_event.type = type;  
  94.     key_event.code = keycode;  
  95.     key_event.value = value;  
  96.     ret = write(uinput_fd, &key_event, sizeof(struct input_event));  
  97.     if(ret < 0){  
  98.         printf("%s:%d ", __func__, __LINE__);  
  99.         return ret;//error process.  
  100.     }  
  101.       
  102.     gettimeofday(&key_event.time, NULL);  
  103.     key_event.type = EV_SYN;  
  104.     key_event.code = SYN_REPORT;  
  105.     key_event.value = 0;//event status sync  
  106.     ret = write(uinput_fd, &key_event, sizeof(struct input_event));  
  107.     if(ret < 0){  
  108.         printf("%s:%d ", __func__, __LINE__);  
  109.         return ret;//error process.  
  110.     }  
  111.       
  112.     return 0;  
  113. }  

编译方法:

root@ubuntu:/home/ubuntu/Documents# gcc uinput-demo.c -o uinput-demo
root@ubuntu:/home/ubuntu/Documents# ls
uinput-demo  uinput-demo.c
root@ubuntu:/home/ubuntu/Documents# ./uinput-demo     ------执行时要用root用户登入才行

这时,在开个终端,切换到:root@ubuntu:/dev/input#

执行hexdump -C event5  ------event5是创建uinput时生成的节点

10秒到后,显示结果:

root@ubuntu:/dev/input# hexdump -C event5
00000000  bd 5e 69 59 aa fd 05 00  01 00 1e 00 01 00 00 00  |.^iY............|
00000010  bd 5e 69 59 aa fd 05 00  00 00 00 00 00 00 00 00  |.^iY............|
00000020  bd 5e 69 59 d7 fd 05 00  01 00 1e 00 00 00 00 00  |.^iY............|
00000030  bd 5e 69 59 d7 fd 05 00  00 00 00 00 00 00 00 00  |.^iY............|
00000040  bd 5e 69 59 db fd 05 00  01 00 20 00 0c 00 00 00  |.^iY...... .....|
00000050  bd 5e 69 59 db fd 05 00  00 00 00 00 00 00 00 00  |.^iY............|
00000060  bd 5e 69 59 dd fd 05 00  01 00 20 00 00 00 00 00  |.^iY...... .....|
00000070  bd 5e 69 59 dd fd 05 00  00 00 00 00 00 00 00 00  |.^iY............|
adhexdump: event5: 没有那个设备
00000080
root@ubuntu:/dev/input# 

也可以打开记事本,再次执行:

root@ubuntu:/home/ubuntu/Documents# ./uinput-demo

10秒到后,就会在记事本里输入:ad。

 

这样,就可以通过应用程序的执行模拟鼠标、键盘等的输入事件。

原文地址:https://www.cnblogs.com/sky-heaven/p/9098982.html