android USES uinput to simulate the method of the input device

  • 2020-05-19 05:53:51
  • OfStack

In google remote, the android receiver receives IR CODE from socket, and then simulates IR CODE to the system for processing. This is the principle of google remote receiver.

How does the system side simulate input event?
Method 1: Instrumentation.sendKeyDownUpSync, simple to use, but the problem is that event, issued by sendKeyDownUpSync, does not work
interceptKeyBeforeDispatching, HOME, VOL...
Method 2: bridge through uinput; The principle is to use the existing uinput driver of the kernel to send input event through the kernel driver uinput, and it is also easy to use kl,kcm customization;


After comparing method 2 better, the test code of method 2 is given below...
1, main function, setup_uinput_device complete the device registration, and then create a thread VirtualInputDev_EventThread, the thread repeatedly issued keycode;


  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 the uinput node is opened directly, and name, verdor, product, bustype of the virtual device is set.
Finally, the device is registered via ioctl(uinp_fd, UI_DEV_CREATE)


   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(uinp.name, "virtualinputdev", sizeof(uinp.name)-1);
    uinp.id.vendor = 0x1341;
    uinp.id.product = 0x0001;
    uinp.id.bustype = 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, just sends key repeatedly, and sends key through write_event_to_device


   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


  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(&event.time, 0);
    event.type = EV_KEY;
    event.code = u8KeyCode;
    event.value = 1;
    write(uinp_fd, &event, sizeof(event));
    memset(&event, 0x00, sizeof(event));
    gettimeofday(&event.time, 0);
    event.type = EV_KEY;
    event.code = u8KeyCode;
    event.value = 0;
    write(uinp_fd, &event, sizeof(event));
    memset(&event, 0x00, sizeof(event));
    gettimeofday(&event.time, 0);
    event.type = EV_SYN;
    event.code = SYN_REPORT;
    event.value = 0;
    write(uinp_fd, &event, sizeof(event));
}


Related articles: