android使用uinput模拟输入设备的方法
在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来完成的
unsignedcharu8Keycode,i=umin_keycode; while(1){ /*sleepanintervaltime*/ printf("virtualinputdevthreaddied\n"); 4、write_event_to_device写event到uinput节点 memset(&event,0x00,sizeof(event)); memset(&event,0x00,sizeof(event)); memset(&event,0x00,sizeof(event));
staticvoid*VirtualInputDev_EventThread(void*driver_data)
{
u8Keycode=0xff;
usleep(2000000);//sleep5s
/*filleventtouinputdevice.*/
write_event_to_device(i++,0);
if(i==4){
i=0;
}
printf("virtualinputdevthread...\n");
//i%=umax_keycode;
}
pthread_exit(0);
return0;
}
voidwrite_event_to_device(unsignedcharu8KeyCode,unsignedcharu8Repeat)
{
structinput_eventevent;//Inputdevicestructure
structtimespecs;
s.tv_nsec=5000000L;
s.tv_sec=0;
gettimeofday(&event.time,0);
event.type=EV_KEY;
event.code=u8KeyCode;
event.value=1;
write(uinp_fd,&event,sizeof(event));
gettimeofday(&event.time,0);
event.type=EV_KEY;
event.code=u8KeyCode;
event.value=0;
write(uinp_fd,&event,sizeof(event));
gettimeofday(&event.time,0);
event.type=EV_SYN;
event.code=SYN_REPORT;
event.value=0;
write(uinp_fd,&event,sizeof(event));
}相关文章