linux下如何模拟按键输入和模拟鼠标.docx
- 文档编号:27247247
- 上传时间:2023-06-28
- 格式:DOCX
- 页数:16
- 大小:21.81KB
linux下如何模拟按键输入和模拟鼠标.docx
《linux下如何模拟按键输入和模拟鼠标.docx》由会员分享,可在线阅读,更多相关《linux下如何模拟按键输入和模拟鼠标.docx(16页珍藏版)》请在冰豆网上搜索。
linux下如何模拟按键输入和模拟鼠标
linux下如何模拟按键输入和模拟鼠标
查看/dev/input/eventX是什么类型的事件,cat/proc/bus/input/devices
设备有着自己特殊的按键键码,我需要将一些标准的按键,比如0-9,X-Z等模拟成标准按键,比如KEY_0,KEY-Z等,所以需要用到按键模拟,具体方法就是操作/dev/input/event1文件,向它写入个input_event结构体就可以模拟按键的输入了。
linux/input.h中有定义,这个文件还定义了标准按键的编码等
structinput_event{
structtimevaltime;//按键时间
__u16type;//类型,在下面有定义
__u16code;//要模拟成什么按键
__s32value;//是按下还是释放
};
code:
事件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.代码植0~127为键盘上的按键代码,0x110~0x116为鼠标上按键代码,其中0x110(BTN_LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_MIDDLE)为鼠标中键.其它代码含义请参看include/linux/input.h文件.如果事件的类型代码是EV_REL,code值表示轨迹的类型.如指示鼠标的X轴方向REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y(代码为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08).
type:
EV_KEY,键盘
EV_REL,相对坐标
EV_ABS,绝对坐标
value:
事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;如果事件的类型代码是EV_REL,value的正数值和负数值分别代表两个不同方向的值.
/*
*Eventtypes
*/
#defineEV_SYN0x00
#defineEV_KEY0x01//按键
#defineEV_REL0x02//相对坐标(轨迹球)
#defineEV_ABS0x03//绝对坐标
#defineEV_MSC0x04//其他
#defineEV_SW0x05
#defineEV_LED0x11//LED
#defineEV_SND0x12//声音
#defineEV_REP0x14//repeat
#defineEV_FF0x15
#defineEV_PWR0x16
#defineEV_FF_STATUS0x17
#defineEV_MAX0x1f
#defineEV_CNT(EV_MAX+1)
1。
模拟按键输入
//其中0表示释放,1按键按下,2表示一直按下
//0forEV_KEYforrelease,1forkeypressand2forautorepeat.
voidsimulate_key(intfd,intvalue)
{
structinput_eventevent;
event.type=EV_KEY;
//event.code=KEY_0;//要模拟成什么按键
event.value=value;//是按下还是释放按键或者重复
gettimeofday(&event.time,0);
if(write(fd,&event,sizeof(event))<0){
dprintk("simulatekeyerror~~~\n");
return;
}
}
2。
模拟鼠标输入(轨迹球)
voidsimulate_mouse(intfd,charbuf[4])
{
intrel_x,rel_y;
staticstructinput_eventevent,ev;
//buf[0],buf[2],小于0则为左移,大于0则为右移
//buf[1],buf[3],小于0则为下移,大于0则为上移
dprintk("MOUSETOUCH:
x1=%d,y1=%d,x2=%d,y2=%d\n",buf[0],buf[1],buf[2],buf[3]);
rel_x=(buf[0]+buf[2])/2;
rel_y=-(buf[1]+buf[3])/2;//和我们的鼠标是相反的方向,所以取反
event.type=EV_REL;
event.code=REL_X;
event.value=rel_x;
gettimeofday(&event.time,0);
if(write(fd,&event,sizeof(event))!
=sizeof(event))
dprintk("rel_xerror~~~:
%s\n",strerror(errno));
event.code=REL_Y;
event.value=rel_y;
gettimeofday(&event.time,0);
if(write(fd,&event,sizeof(event))!
=sizeof(event))
dprintk("rel_yerror~~~:
%s\n",strerror(errno));
//一定要刷新空的
write(fd,&ev,sizeof(ev));
}
鼠标和键盘文件打开方法:
intfd_kbd;///dev/input/event1
intfd_mouse;//dev/input/mouse2
fd_kbd=open("/dev/input/event1",O_RDWR);
if(fd_kbd<=0){
printf("erroropenkeyboard:
%s\n",strerror(errno));
return-1;
}
fd_mouse=open("/dev/input/event3",O_RDWR);//如果不行的话,那试试/dev/input/mice
if(fd_mouse<=0){
printf("erroropenmouse:
%s\n",strerror(errno));
return-2;
}
}
/dev/input/mice是鼠标的抽象,代表的是鼠标,也许是/dev/input/mouse,/dev/input/mouse1,或者空,
这个文件一直会存在。
这里你也许会问,我怎么知道/dev/input/eventX这些事件到底是什么事件阿,是鼠标还是键盘或者别的,
eventX代表的是所有输入设备(input核心)的事件,比如按键按下,或者鼠标移动,或者游戏遥控器等等,
在系统查看的方法是cat/proc/bus/input/devices就可以看到每个eventX是什么设备的事件了。
PS:
在GTK中用的话,可以参考下gtk_main_do_event这个函数
staticvoidsimulate_key(GtkWidget*window,intkeyval,intpress)
{
GdkEvent*event;
GdkEventTypetype;
if(press)
type=GDK_KEY_PRESS;
else
type=GDK_KEY_RELEASE;
event=gdk_event_new(type);
//event->key.send_event=TRUE;
event->key.window=window->window;//一定要设置为主窗口
event->key.keyval=keyval;
//FIXME:
一定要加上这个,要不然容易出错
g_object_ref(event->key.window);
gdk_threads_enter();
//FIXME:
记得用这个来发送事件
gtk_main_do_event(event);
gdk_threads_leave();
gdk_event_free(event);
}
kernel里input模块
input_dev结构:
structinput_dev{
void*private;
constchar*name;
constchar*phys;
constchar*uniq;
structinput_idid;
/*
*根据各种输入信号的类型来建立类型为unsignedlong的数组,
*数组的每1bit代表一种信号类型,
*内核中会对其进行置位或清位操作来表示时间的发生和被处理.
*/
unsignedlongevbit[NBITS(EV_MAX)];
unsignedlongkeybit[NBITS(KEY_MAX)];
unsignedlongrelbit[NBITS(REL_MAX)];
unsignedlongabsbit[NBITS(ABS_MAX)];
unsignedlongmscbit[NBITS(MSC_MAX)];
unsignedlongledbit[NBITS(LED_MAX)];
unsignedlongsndbit[NBITS(SND_MAX)];
unsignedlongffbit[NBITS(FF_MAX)];
unsignedlongswbit[NBITS(SW_MAX)];
.........................................
};
/**
*input_set_capability-markdeviceascapableofacertainevent
*@dev:
devicethatiscapableofemittingoracceptingevent
*@type:
typeoftheevent(EV_KEY,EV_REL,etc...)
*@code:
eventcode
*
*Inadditiontosettingupcorrespondingbitinappropriatecapability
*bitmapthefunctionalsoadjustsdev->evbit.
*/
/*记录本设备对于哪些事件感兴趣(对其进行处理)*/
voidinput_set_capability(structinput_dev*dev,unsignedinttype,unsignedintcode)
{
switch(type){
caseEV_KEY:
__set_bit(code,dev->keybit);//比如按键,应该对哪些键值的按键进行处理(对于其它按键不予理睬)
break;
caseEV_REL:
__set_bit(code,dev->relbit);
break;
caseEV_ABS:
__set_bit(code,dev->absbit);
break;
caseEV_MSC:
__set_bit(code,dev->mscbit);
break;
caseEV_SW:
__set_bit(code,dev->swbit);
break;
caseEV_LED:
__set_bit(code,dev->ledbit);
break;
caseEV_SND:
__set_bit(code,dev->sndbit);
break;
caseEV_FF:
__set_bit(code,dev->ffbit);
break;
default:
printk(KERN_ERR
"input_set_capability:
unknowntype%u(code%u)\n",
type,code);
dump_stack();
return;
}
__set_bit(type,dev->evbit);//感觉和前面重复了(前面一经配置过一次了)
}
EXPORT_SYMBOL(input_set_capability);
staticirqreturn_tgpio_keys_isr(intirq,void*dev_id)
{
inti;
structplatform_device*pdev=dev_id;
structgpio_keys_platform_data*pdata=pdev->dev.platform_data;
structinput_dev*input=platform_get_drvdata(pdev);
for(i=0;i
structgpio_keys_button*button=&pdata->buttons[i];
intgpio=button->gpio;
if(irq==gpio_to_irq(gpio)){//判断哪个键被按了?
unsignedinttype=button->type?
:
EV_KEY;
intstate=(gpio_get_value(gpio)?
1:
0)^button->active_low;//记录按键状态
input_event(input,type,button->code,!
!
state);//汇报输入事件
input_sync(input);//等待输入事件处理完成
}
}
returnIRQ_HANDLED;
}
/*
*input_event()-reportnewinputevent
*@dev:
devicethatgeneratedtheevent
*@type:
typeoftheevent
*@code:
eventcode
*@value:
valueoftheevent
*
*Thisfunctionshouldbeusedbydriversimplementingvariousinputdevices
*Seealsoinput_inject_event()
*/
voidinput_event(structinput_dev*dev,unsignedinttype,unsignedintcode,intvalue)
{
structinput_handle*handle;
if(type>EV_MAX||!
test_bit(type,dev->evbit))//首先判断该事件类型是否有效且为该设备所接受
return;
add_input_randomness(type,code,value);
switch(type){
caseEV_SYN:
switch(code){
caseSYN_CONFIG:
if(dev->event)
dev->event(dev,type,code,value);
break;
caseSYN_REPORT:
if(dev->sync)
return;
dev->sync=1;
break;
}
break;
caseEV_KEY:
/*
*这里需要满足几个条件:
*1:
键值有效(不超出定义的键值的有效范围)
*2:
键值为设备所能接受(属于该设备所拥有的键值范围)
*3:
按键状态改变了
*/
if(code>KEY_MAX||!
test_bit(code,dev->keybit)||!
!
test_bit(code,dev->key)==value)
return;
if(value==2)
break;
change_bit(code,dev->key);//改变对应按键的状态
/*如果你希望按键未释放的时候不断汇报按键事件的话需要以下这个(在简单的gpio_keys驱动中不需要这个,暂时不去分析)*/
if(test_bit(EV_REP,dev->evbit)&&dev->rep[REP_PERIOD]&&dev->rep[REP_DELAY]&&dev->timer.data&&value){
dev->repeat_key=code;
mod_timer(&dev->timer,jiffies+msecs_to_jiffies(dev->rep[REP_DELAY]));
}
break;
........................................................
if(type!
=EV_SYN)
dev->sync=0;
if(dev->grab)
dev->grab->handler->event(dev->grab,type,code,value);
else
/*
*循环调用所有处理该设备的handle(event,mouse,ts,joy等),
*如果有进程打开了这些handle(进行读写),则调用其对应的event接口向气汇报该输入事件.
*/
list_for_each_entry(handle,&dev->h_list,d_node)
if(handle->open)
handle->handler->event(handle,type,code,value);
}
EXPORT_SYMBOL(input_event);
event层对于input层报告的这个键盘输入事件的处理:
drivers/input/evdev.c:
staticstructinput_handlerevdev_handler={
.event= evdev_event,
.connect= evdev_connect,
.disconnect= evdev_disconnect,
.fops= &evdev_fops,
.minor= EVDEV_MINOR_BASE,
.name= "evdev",
.id_table= evdev_ids,
};
Linux有自己的input子系统,可以统一管理鼠标和键盘事件。
基于输入子系统实现的uinput可以方便的在用户空间模拟鼠标和键盘事件。
当然,也可以自己造轮子,做一个字符设备接收用户输入,根据输入,投递input事件。
还有一种方式就是直接往evnent里写入数据,都可以达到控制鼠标键盘的功能。
本篇文章就是演示直接写入event的方法。
linux/input.h中有定义,这个文件还定义了标准按键的编码等
structinput_event{
structtimevaltime; //按键时间
__u16type;//类型,在下面有定义
__u16code;//要模拟成什么按键
__s32value;//是按下还是释放
};
code:
事件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.代码植0~127为键盘上的按键代码,0x110~0x116为鼠标上按键代码,其中0x110(BTN_LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_MIDDLE)为鼠标中键.其它代码含义请参看include/linux
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux 如何 模拟 按键 输入 鼠标