zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

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

2023-06-13 09:15:15 时间

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

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


 经过比较方法二较优,下面就就给出方法二的测试代码...
 1、main函数,setup_uinput_device完成设备的注册,然后创建一个线程VirtualInputDev_EventThread,该线程重复发出keycode;

复制代码代码如下:


 intmain()
{


 printf("Enterprocess!!!!\n");

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

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

   //Coverityserverneedsettoignorethis.
   while(1){
       usleep(1000000); //sleep1second
   }

   free(pKpdData);
   pKpdData=0;

   //Destroythedevice
   ioctl(uinp_fd,UI_DEV_DESTROY);

   close(uinp_fd);
   return0;
}

2、setup_uinput_device函数,完成设备注册;可以看到是直接打开uinput节点,设置了虚拟设备的name,verdor,product,bustype,
  最后通过ioctl(uinp_fd,UI_DEV_CREATE)注册设备

复制代码代码如下:


  intsetup_uinput_device(stVirtualInputDevData*mstVirtualInputDevData)
{
   structuinput_user_devuinp;//uInputdevicestructure
   inti;

   //Opentheinputdevice
   uinp_fd=open("/dev/uinput",O_WRONLY|O_NDELAY);
   if(uinp_fd==0){
       printf("Unabletoopen/dev/uinput\n");
       return-1;
   }

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

   //Createinputdeviceintoinputsub-system
   if(write(uinp_fd,&uinp,sizeof(uinp))!=sizeof(uinp)){
       printf("Firstwritereturnedfail.\n");
       return-1;
   }

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

   return1;
}

3、线程VirtualInputDev_EventThread,只是重复发key,发key是通过write_event_to_device来完成的

复制代码代码如下:
  staticvoid*VirtualInputDev_EventThread(void*driver_data)
{

   unsignedcharu8Keycode,i=umin_keycode;

   while(1){
       u8Keycode=0xff;

       /*sleepanintervaltime*/
       usleep(2000000);//sleep5s
       /*filleventtouinputdevice.*/
       write_event_to_device(i++,0);
  if(i==4){
  i=0;
  }
  printf("virtualinputdevthread...\n");
  //i%=umax_keycode;
   }

   printf("virtualinputdevthreaddied\n");
   pthread_exit(0);
   return0;
}

4、write_event_to_device写event到uinput节点

复制代码代码如下:
 voidwrite_event_to_device(unsignedcharu8KeyCode,unsignedcharu8Repeat)
{
   structinput_eventevent;//Inputdevicestructure
   structtimespecs;
   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));
}