uinput

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <errno.h>
  7. #include <linux/input.h>
  8. #include <linux/uinput.h>


  9. void usage(void)
  10. {
  11.     printf(" Usage : keyboard <kye number> [key number...]\n");
  12.     printf(" keyboard 29 56 32 /* CTRL + ALT +D */\n");
  13.     printf(" keyboard 125 32 /* WIN +D */\n");
  14.     printf("/* Types of key number are defined in /usr/include/linux/input.h */\n");

  15.     return;
  16. }

  17. /* Setup the uinput device */
  18. int setup_uinput_device(int fd)
  19. {
  20.     struct uinput_user_dev uidev;    // uInput device structure

  21.     memset(&uidev, 0, sizeof(struct uinput_user_dev));    // Intialize the uInput device to NULL
  22.     snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-keyboard");
  23.     uidev.id.bustype = BUS_USB;
  24.     uidev.id.vendor = 0x1;
  25.     uidev.id.product = 0x1;
  26.     uidev.id.version = 1;
  27.     // Setup the driver I/O channels
  28.     ioctl(fd, UI_SET_EVBIT, EV_KEY);
  29.     ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
  30.     for (int i = 0; i < 256; i++) {
  31.         ioctl(fd, UI_SET_KEYBIT, i);
  32.     }
  33.     ioctl(fd, UI_SET_EVBIT, EV_REL);
  34.     ioctl(fd, UI_SET_RELBIT, REL_X);
  35.     ioctl(fd, UI_SET_RELBIT, REL_Y);

  36.     /* Create input device into input sub-system */
  37.     write(fd, &uidev, sizeof(struct uinput_user_dev));
  38.     if (ioctl(fd, UI_DEV_CREATE) < 0) {
  39.         printf("error: create uinput device\n");
  40.         return -1;
  41.     }

  42.     return 0;
  43. }

  44. void uinput_key(int fd, int keycode, int keyvalue)
  45. {
  46.     struct input_event ev;            // Input device structure

  47.     memset(&ev, 0, sizeof(struct input_event));
  48.     gettimeofday(&ev.time, NULL);
  49.     ev.type = EV_KEY;
  50.     ev.code = keycode;
  51.     ev.value = keyvalue;
  52.     if (write(fd, &ev, sizeof(struct input_event)) < 0) {
  53.         printf("uinput key error\n");
  54.         return;
  55.     } else {
  56.         printf("uinput key %d, %d\n", keycode, keyvalue);
  57.     }

  58.     return;
  59. }

  60. void uinput_key_end(int fd)
  61. {
  62.     struct input_event ev;            // Input device structure

  63.     memset(&ev, 0, sizeof(struct input_event));
  64.     ev.type = EV_SYN;
  65.     ev.code = 0;
  66.     ev.value = 0;
  67.     write(fd, &ev, sizeof(struct input_event));

  68.     return;
  69. }

  70. //check the key is control key
  71. int check_valid_control_key(int key)
  72. {
  73.     int ret = 0;
  74.     int control_key[] = {29, 42, 54, 56, 97, 100, 125, 126};
  75.     int len = sizeof(control_key) / sizeof(control_key[0]);

  76.     for (int i = 0; i < len; i++) {
  77.         if (control_key[i] == key) {
  78.             ret = 1;
  79.             break;
  80.         }
  81.     }

  82.     return ret;
  83. }

  84. int main(int argc, char *argv[])
  85. {
  86.     int fd = -1;
  87.     int key;
  88.     int i;
  89.     
  90.     if (argc <= 1) {
  91.         usage();
  92.         return -1;
  93.     }

  94.     fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);    // Open the input device
  95.     if (fd < 0) {
  96.         printf("error: open /dev/uinput\n");
  97.         return -1;
  98.     }

  99.     setup_uinput_device(fd);

  100.     sleep(1);

  101.     for (= 1; i < argc; i++) {
  102.         key = atoi(argv[i]);
  103.         uinput_key(fd, key, 1);
  104.         if (check_valid_control_key(key) == 0) {
  105.             uinput_key(fd,key, 0);
  106.         }
  107.     }

  108.     for (= 1; i < argc; i++) {
  109.         key = atoi(argv[i]);
  110.         if (check_valid_control_key(key) == 1) {
  111.             uinput_key(fd,key, 0);
  112.         }
  113.     }

  114.     uinput_key_end(fd);
  115.     if (ioctl(fd, UI_DEV_DESTROY) < 0) {
  116.         printf("error: ioctl");
  117.         return -1;
  118.     }

  119.     close(fd);
  120.     fd = -1;

  121.     return 0;
  122. }
<think>好的,我现在需要帮助用户了解如何在Linux中使用UInput创建虚拟输入设备。首先,我需要回忆一下UInput的基本概念和用途。UInput是Linux内核的一个模块,允许用户空间程序创建虚拟输入设备,比如模拟键盘、鼠标或游戏手柄。这对于开发需要模拟用户输入的应用程序非常有用,比如自动化测试工具或自定义输入设备。接下来,我需要确认用户的具体需求。用户提到参考了三个引用,但根据我的分析,这些引用主要涉及Android硬件抽象层、中断唤醒和USB设备列表,可能与UInput的直接关联不大。不过,用户的上一个问题涉及Unreal Engine中的输入动作分类,可能现在他们想深入底层,了解Linux下的输入设备模拟。我需要确保回答的结构清晰,分步骤解释UInput的用法。首先,可能需要介绍如何加载uinput内核模块,因为这是使用UInput的前提。然后,说明如何通过C程序与UInput交互,包括打开设备文件、设置设备能力、创建设备以及发送事件。同时,用户可能需要示例代码来更好地理解,所以准备一个简单的键盘事件生成的例子是必要的。另外,用户可能对权限问题有疑问,比如为什么需要root权限或如何配置udev规则,这部分也需要涵盖。安全问题也是需要考虑的,比如虚拟输入设备可能带来的风险,需要提醒用户注意。 在引用部分,用户提供的三个引用中,引用[1]提到getevent命令和加速度计事件,引用[2]涉及驱动程序的挂起和恢复中的中断处理,引用[3]展示lsusb的输出。虽然这些引用可能与输入设备相关,但主要针对Android系统和硬件层面的操作,与UInput的直接关联较弱。因此,在回答中可能不需要直接引用这些内容,但需要确保回答准确,不误导用户。最后,生成的相关问题需要围绕UInput的进阶使用、权限管理、与其他模块的交互以及调试工具,这些能帮助用户进一步探索。同时,要确保使用正确的LaTeX格式,数学表达式和代码块符合要求,并且回答用中文撰写,结构清晰。</think>### UInput在Linux中创建虚拟输入设备的用法指南 UInput是Linux内核提供的用户态输入子系统接口,允许开发者创建**虚拟输入设备**(如键盘、鼠标、游戏手柄等)。其核心原理是通过`/dev/uinput`设备文件与内核交互,实现输入事件的模拟[^1]。 --- #### 一、环境准备与内核模块加载 1. **检查内核支持** 确认内核已启用`CONFIG_INPUT_UINPUT`选项: ```bash $ zgrep CONFIG_INPUT_UINPUT /proc/config.gz ``` 若未启用需重新编译内核或加载模块: ```bash $ sudo modprobe uinput ``` 2. **设备权限设置** 为当前用户添加`uinput`设备访问权限: ```bash $ sudo chmod 666 /dev/uinput ``` 或通过udev规则永久配置: ```bash # /etc/udev/rules.d/99-uinput.rules KERNEL=="uinput", MODE="0666" ``` --- #### 二、核心开发流程 通过C语言实现虚拟键盘的典型步骤如下: 1. **打开UInput设备** ```c int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); ``` 2. **配置设备能力** ```c struct uinput_setup usetup; ioctl(fd, UI_SET_EVBIT, EV_KEY); // 启用按键事件 ioctl(fd, UI_SET_KEYBIT, KEY_A); // 注册A键 memset(&usetup, 0, sizeof(usetup)); usetup.id.bustype = BUS_USB; strcpy(usetup.name, "Virtual Keyboard"); ioctl(fd, UI_DEV_SETUP, &usetup); ``` 3. **创建设备实例** ```c ioctl(fd, UI_DEV_CREATE); ``` 4. **发送输入事件** ```c struct input_event ev; memset(&ev, 0, sizeof(ev)); // 按下A键 ev.type = EV_KEY; ev.code = KEY_A; ev.value = 1; write(fd, &ev, sizeof(ev)); // 同步事件 ev.type = EV_SYN; ev.code = SYN_REPORT; write(fd, &ev, sizeof(ev)); ``` --- #### 三、高级功能实现 1. **组合键模拟** 通过事件序列实现`Ctrl+Alt+Del`: ```c // 按下Ctrl send_key_event(fd, KEY_LEFTCTRL, 1); // 按下Alt send_key_event(fd, KEY_LEFTALT, 1); // 按下Delete send_key_event(fd, KEY_DELETE, 1); // 释放所有按键 send_key_event(fd, KEY_LEFTCTRL, 0); send_key_event(fd, KEY_LEFTALT, 0); send_key_event(fd, KEY_DELETE, 0); ``` 2. **鼠标事件模拟** 配置相对坐标事件: ```c ioctl(fd, UI_SET_EVBIT, EV_REL); // 启用相对坐标 ioctl(fd, UI_SET_RELBIT, REL_X); // X轴移动 ioctl(fd, UI_SET_RELBIT, REL_Y); // Y轴移动 ``` --- #### 四、调试与验证 1. **查看输入设备列表** ```bash $ cat /proc/bus/input/devices ``` 输出示例: ``` I: Bus=0003 Vendor=1234 Product=5678 Version=0001 N: Name="Virtual Keyboard" ``` 2. **实时监控输入事件** 使用`evtest`工具: ```bash $ sudo evtest /dev/input/eventX # X为设备编号 ``` --- #### 五、安全注意事项 - 虚拟输入设备会**绕过物理安全限制**,需严格控制访问权限 - 避免与真实设备产生冲突,可通过`ioctl(fd, UI_SET_PHYS, "virtual/input")`设置物理路径 - 生产环境中建议使用`libevdev`库进行高级封装[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值