欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android 使用uinput模拟输入设备的方法

程序员文章站 2023-11-14 08:58:16
在google remote中,android接收端接收socket发来的ir code,然后将ir code模拟出来发给系统处理,这就是google remote接收端的...

在google remote中,android接收端接收socket发来的ir code,然后将ir code模拟出来发给系统处理,这就是google remote接收端的原理。

系统端怎样模拟input event呢?
方法一:通过instrumentation.sendkeydownupsync 实现,简单使用但是问题在于sendkeydownupsync发出的event,无法运行到
interceptkeybeforedispatching,也就无法正常作用 home,vol...
方法二:通过uinput桥接;原理是利用内核现有的uinput驱动,通过内核驱动uinput来发送input event,而且还容易使用kl,kcm 客制化;


  经过比较方法二较优,下面就就给出方法二的测试代码...
  1、main函数,setup_uinput_device 完成设备的注册,然后创建一个线程 virtualinputdev_eventthread,该线程重复发出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函数,完成设备注册;可以看到是直接打开uinput节点,设置了虚拟设备的name,verdor,product,bustype,
   最后通过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、线程 virtualinputdev_eventthread,只是重复发key,发key是通过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 写event到uinput节点

复制代码 代码如下:

  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));
}