SoFunction
Updated on 2025-03-01

Android method to simulate input device using uinput

In Google remote, the Android receiver receives the IR CODE sent from the socket, and then simulates the IR CODE and sends it to the system for processing. This is the principle of the Google remote receiver.

How to simulate input event on the system side?
Method 1: Implemented through , simple use , but the problem is that the event sent by sendKeyDownUpSync cannot be run to
interceptKeyBeforeDispatching, it will not work normally. HOME, VOL...
Method 2: bridging through uinput; the principle is to use the kernel's existing uinput driver to send input event through the kernel driver uinput, and it is also easy to customize using kl and kcm;


After comparing the advantages of Method 2, we will give the test code for Method 2...
1. Main function, setup_uinput_device completes the device registration, and then creates a thread VirtualInputDev_EventThread, which repeatedly issues keycode;

Copy the codeThe code is as follows:

  int main()
{


 printf("Enter process !!!! \n");

    stVirtualInputDevData *pKpdData = (stVirtualInputDevData*) malloc(sizeof(stVirtualInputDevData));
   pKpdData->min_keycode = umin_keycode;
   pKpdData->max_keycode = umax_keycode;
    if (setup_uinput_device(pKpdData) < 0) {
        printf("Unable to find uInput device\n");
        free(pKpdData);
        return -1;
    }

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (0 != pthread_create(&keypad_EventThreadId, &attr, VirtualInputDev_EventThread, (void *)0)) {
        printf("Create KeypadEventThread Failed!!\n");
        exit(1);
    }

    // Coverity server need set to ignore this.
    while (1) {
        usleep(1000000);  // sleep 1 second
    }

    free(pKpdData);
    pKpdData = 0;

    // Destroy the device
    ioctl(uinp_fd, UI_DEV_DESTROY);

    close(uinp_fd);
    return 0;
}

2. Setup_uinput_device function to complete the device registration; you can see that it is to directly open the uinput node and set the name, verdor, product, and bustype of the virtual device.
Finally, register the device through ioctl(uinp_fd, UI_DEV_CREATE)

Copy the codeThe code is as follows:

   int setup_uinput_device(stVirtualInputDevData* mstVirtualInputDevData)
{
    struct uinput_user_dev uinp; // uInput device structure
    int i;

    // Open the input device
    uinp_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
    if (uinp_fd == 0) {
        printf("Unable to open /dev/uinput\n");
        return -1;
    }

    // Intialize the uInput device to NULL
    memset(&uinp, 0x00, sizeof(uinp));
    strncpy(, "virtualinputdev", sizeof()-1);
    = 0x1341;
    = 0x0001;
    = BUS_VIRTUAL;

    // Keyboard
    ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
    for (i = mstVirtualInputDevData->min_keycode; i < mstVirtualInputDevData->max_keycode; i++) {
        ioctl(uinp_fd, UI_SET_KEYBIT, i);
    }

    // Create input device into input sub-system
    if (write(uinp_fd, &uinp, sizeof(uinp)) != sizeof(uinp)) {
        printf("First write returned fail.\n");
        return -1;
    }

    if (ioctl(uinp_fd, UI_DEV_CREATE)) {
        printf("ioctl UI_DEV_CREATE returned fail.\n");
        return -1;
    }

    return 1;
}

3. Thread VirtualInputDev_EventThread is just a repetition of keys. The key is completed through write_event_to_device.

Copy the codeThe code is as follows:

   static void* VirtualInputDev_EventThread(void *driver_data)
{

    unsigned char u8Keycode,i=umin_keycode;

    while (1) {
        u8Keycode = 0xff;

        /* sleep an interval time */
        usleep(2000000);//sleep 5 s
        /* fill event to uinput device. */
        write_event_to_device(i++, 0);
  if(i==4){
  i = 0;
  }
  printf ("virtualinputdev thread ...\n");
  //i %= umax_keycode;
    }

    printf ("virtualinputdev thread died\n");
    pthread_exit(0);
    return 0;
}

4. Write_event_to_device Write event to uinput node

Copy the codeThe code is as follows:

  void write_event_to_device(unsigned char u8KeyCode, unsigned char u8Repeat)
{
    struct input_event event; // Input device structure
    struct timespec s;
    s.tv_nsec = 5000000L;
    s.tv_sec = 0;

    memset(&event, 0x00, sizeof(event));
    gettimeofday(&, 0);
    = EV_KEY;
    = u8KeyCode;
    = 1;
    write(uinp_fd, &event, sizeof(event));

    memset(&event, 0x00, sizeof(event));
    gettimeofday(&, 0);
    = EV_KEY;
    = u8KeyCode;
    = 0;
    write(uinp_fd, &event, sizeof(event));

    memset(&event, 0x00, sizeof(event));
    gettimeofday(&, 0);
    = EV_SYN;
    = SYN_REPORT;
    = 0;
    write(uinp_fd, &event, sizeof(event));
}