android 使用uinput模拟输入设备


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


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值