Linux使用uinput实现虚拟鼠标

    最近看了些linux模拟鼠标按键的方法,但是都要从/proc/bus/input/devices中去查看现有的鼠标设备,然后重用该设备,比较麻烦,而且不是很好——可能对应不同硬件要作一定改动。后来学习发现可以让用户态程序利用uinput的输入子系统来创建一个自己的虚拟设备,然后再向我们的这个虚拟设备写入事件,最后证明也能够实现功能。

    我对于Linux算是个入门汉,有些地方理解不够,有什么错误欢迎大家指正。~~


下面是我实现虚拟设备和模拟鼠标移动的代码:

#include <sys/ioctl.h>
#include <linux/uinput.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

#include <errno.h>
#include <stdio.h>
#include <string.h>

#define ALOGE(...) \
        printf(__VA_ARGS__); \
        printf("\n")


#define UINPUT_NAME      "/dev/uinput"
#define VIR_MOUSE_NAME   "DFC Virtual Mouse"

static int device_handler = -1;
static struct uinput_user_dev vir_mouse;

static int install_uinput_mouse_device()
{
    if (device_handler > 0)
    {
        ALOGE("virtual mouse has been installed already.");
        return device_handler;
    }

    //open uinput device
    if ((device_handler = open(UINPUT_NAME, O_WRONLY | O_NDELAY)) <= 0)
    {
        ALOGE("open uinput(%s) failed.", UINPUT_NAME);
        device_handler = -1;
        return device_handler;
    }

    //setup our uinput device of virtual mouse
    memset(&vir_mouse, 0, sizeof(struct uinput_user_dev));
    strncpy(vir_mouse.name, VIR_MOUSE_NAME, UINPUT_MAX_NAME_SIZE);
    vir_mouse.id.version = 4;
    vir_mouse.id.bustype = BUS_USB;

    //if we don't do these register, it seems like not to work
    ioctl(device_handler, UI_SET_EVBIT, EV_KEY);
    for (int i = 0; i < 256; i++)
    {
        ioctl(device_handler, UI_SET_KEYBIT, i);
    }

    //setup mouse coordinate event
    ioctl(device_handler, UI_SET_EVBIT,  EV_REL);
    ioctl(device_handler, UI_SET_RELBIT, REL_X);
    ioctl(device_handler, UI_SET_RELBIT, REL_Y);

    //setup mouse button event
    ioctl(device_handler, UI_SET_KEYBIT, BTN_MOUSE);
    ioctl(device_handler, UI_SET_KEYBIT, BTN_TOUCH);
    ioctl(device_handler, UI_SET_KEYBIT, BTN_LEFT);
    ioctl(device_handler, UI_SET_KEYBIT, BTN_RIGHT);
    ioctl(device_handler, UI_SET_KEYBIT, BTN_MIDDLE);

    //create input device into input subsystem
    write(device_handler, &vir_mouse, sizeof(vir_mouse));
    if (ioctl(device_handler, UI_DEV_CREATE))
    {
        ALOGE("install mouse uinput device failed with error(%s).", strerror(errno));
        close(device_handler);
        device_handler = -1;
    }

    return device_handler;
}

static void uninstall_uinput_mouse_device()
{
    if (device_handler > 0)
    {
        ioctl(device_handler, UI_DEV_DESTROY);
        close(device_handler);
        device_handler = ERROR_DEVICE_HANDLER;
    }
}

void mouse_move(struct data* data)
{
    if (device_handler <= 0)
    {
        install_uinput_mouse_device();
    }

    if (device_handler > 0)
    {
        struct input_event event;
        memset(&event, 0, sizeof(event));

        //x coordinate
        gettimeofday(&event.time, 0);
        event.type = EV_REL;
        event.code = REL_X;
        event.value = data->x;
        write(device_handler, &event, sizeof(event));

        //y coordinate
        event.type  = EV_REL;
        event.code  = REL_Y;
        event.value = data->y;
        write(device_handler, &event, sizeof(event));

        //execute move event
        event.type  = EV_SYN;
        event.code  = SYN_REPORT;
        event.value = 0;
        write(device_handler, &event, sizeof(event));
    }
    else
    {
        ALOGE("invalid device file handler.");
    }
}


下面的代码是测试鼠标移动的代码:

#include <unistd.h>

int main(int argc, char** argv)
{
    struct data data;
    data.x = 2;
    data.y = 2;
    while (1)
    {
        mouse_move(&data);
        sleep(1);
    }

    return 0;
}

然后执行:gcc -o uinput-deamo main.c my_virtual_mouse.c

sudo ./uinput-deamo

我们可以看到鼠标会在每秒移动以下鼠标。查看/proc/bus/input/devices可以看到我们添加的设备。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Linux实现读写HID模拟鼠标可以通过以下步骤来完成: 1. 首先,需要使用hidraw设备来读写HID设备。HID设备在Linux中通常以hidraw设备的形式出现。可以通过以下命令查看系统中的hidraw设备: ```shell ls /dev/hidraw* ``` 2. 打开hidraw设备以进行读写操作。可以使用C语言编写一个程序来打开hidraw设备,并使用read和write函数来读写数据。以下是一个简单的示例程序: ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <linux/hidraw.h> int main() { int fd; char buf[8]; fd = open("/dev/hidraw0", O_RDWR); if (fd < 0) { perror("Unable to open hidraw device"); exit(1); } // 读取数据 if (read(fd, buf, sizeof(buf)) < 0) { perror("Unable to read from hidraw device"); exit(1); } // 写入数据 if (write(fd, buf, sizeof(buf)) < 0) { perror("Unable to write to hidraw device"); exit(1); } close(fd); return 0; } ``` 3. 解析HID报文。HID报文通常是由一系列的字节组成的。根据HID规范,可以解析报文中的每个字节来获取鼠标的相关信息,例如鼠标的坐标、按键状态等。 4. 模拟鼠标操作。根据解析得到的鼠标信息,可以使用X11或者uinput来模拟鼠标操作。X11是Linux下的图形系统,可以使用XTest库来模拟鼠标操作。uinputLinux内核提供的一个虚拟输入设备接口,可以使用uinput库来模拟鼠标操作。 以下是一个使用XTest库来模拟鼠标操作的示例程序: ```c #include <stdio.h> #include <X11/Xlib.h> #include <X11/extensions/XTest.h> int main() { Display *display; Window root; XEvent event; display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Unable to open display\n"); return 1; } root = DefaultRootWindow(display); // 模拟鼠标移动 XTestFakeMotionEvent(display, -1, 100, 100, CurrentTime); // 模拟鼠标点击 XTestFakeButtonEvent(display, 1, True, CurrentTime); XTestFakeButtonEvent(display, 1, False, CurrentTime); XFlush(display); XCloseDisplay(display); return 0; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值