Linux模拟鼠标和键盘事件

2014-10-05

Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件。 
基于输入子系统 实现的 uinput 可以方便的在用户空间模拟鼠标和键盘事件。 
当然,也可以自己造轮子, 做一个字符设备接收用户输入,根据输入,投递 input 事件。 
还有一种方式就是直接 往 evnent 里写入数据, 都可以达到控制鼠标键盘的功能。

本篇文章就是演示直接写入 event 的方法。 
linux/input.h中有定义,这个文件还定义了标准按键的编码等

struct input_event { 
struct timeval time; //按键时间 
__u16 type; //类型,在下面有定义 
__u16 code; //要模拟成什么按键 
__s32 value;//是按下还是释放 
};

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的正数值和负数值分别代表两个不同方向的值. 
/* 
* Event types 
*/

#define EV_SYN 0x00 
#define EV_KEY 0x01 //按键 
#define EV_REL 0x02 //相对坐标(轨迹球) 
#define EV_ABS 0x03 //绝对坐标 
#define EV_MSC 0x04 //其他 
#define EV_SW 0x05 
#define EV_LED 0x11 //LED 
#define EV_SND 0x12//声音 
#define EV_REP 0x14//repeat 
#define EV_FF 0x15 
#define EV_PWR 0x16 
#define EV_FF_STATUS 0x17 
#define EV_MAX 0x1f 
#define EV_CNT (EV_MAX+1)

下面是一个模拟鼠标和键盘输入的例子:

#include <string.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <linux/input.h> 
#include <linux/uinput.h> 
#include <stdio.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h>

void simulate_key(int fd,int kval) 

struct input_event event; 
event.type = EV_KEY; 
event.value = 1; 
event.code = kval;

gettimeofday(&event.time,0); 
write(fd,&event,sizeof(event)) ;

event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event)); 

memset(&event, 0, sizeof(event)); 
gettimeofday(&event.time, NULL); 
event.type = EV_KEY; 
event.code = kval; 
event.value = 0; 
write(fd, &event, sizeof(event)); 
event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event));

}

void simulate_mouse(int fd) 

struct input_event event; 
memset(&event, 0, sizeof(event)); 
gettimeofday(&event.time, NULL); 
event.type = EV_REL; 
event.code = REL_X; 
event.value = 10; 
write(fd, &event, sizeof(event));

event.type = EV_REL; 
event.code = REL_Y; 
event.value = 10; 
write(fd, &event, sizeof(event));

event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event)); 
}

int main() 

int fd_kbd; 
int fd_mouse; 
fd_kbd = open("/dev/input/event1",O_RDWR); 
if(fd_kbd<=0){ 
printf("error open keyboard:/n"); 
return -1;

}

fd_mouse = open("/dev/input/event2",O_RDWR); 
if(fd_mouse<=0){ 
printf("error open mouse/n"); 
return -2; 
}

int i = 0; 
for(i=0; i< 10; i++) 

simulate_key(fd_kbd, KEY_A + i); 
simulate_mouse(fd_mouse); 
sleep(1); 
}

close(fd_kbd); 

模拟了鼠标和键盘的输入事件。 
关于这里 open 哪个 event , 可以通过 cat /proc/bus/input/devices 
I: Bus=0017 Vendor=0001 Product=0001 Version=0100 
N: Name="Macintosh mouse button emulation" 
P: Phys= 
S: Sysfs=/class/input/input0 
U: Uniq= 
H: Handlers=mouse0 event0 
B: EV=7 
B: KEY=70000 0 0 0 0 0 0 0 0 
B: REL=3

I: Bus=0011 Vendor=0001 Product=0001 Version=ab41 
N: Name="AT Translated Set 2 keyboard" 
P: Phys=isa0060/serio0/input0 
S: Sysfs=/class/input/input1 
U: Uniq= 
H: Handlers=kbd event1 
B: EV=120013 
B: KEY=4 2000000 3803078 f800d001 feffffdf ffefffff ffffffff fffffffe 
B: MSC=10 
B: LED=7

I: Bus=0019 Vendor=0000 Product=0002 Version=0000 
N: Name="Power Button (FF)" 
P: Phys=LNXPWRBN/button/input0 
S: Sysfs=/class/input/input3 
U: Uniq= 
H: Handlers=kbd event3 
B: EV=3 
B: KEY=100000 0 0 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000 
N: Name="Power Button (CM)" 
P: Phys=PNP0C0C/button/input0 
S: Sysfs=/class/input/input4 
U: Uniq= 
H: Handlers=kbd event4 
B: EV=3 
B: KEY=100000 0 0 0

I: Bus=0003 Vendor=046d Product=c018 Version=0111 
N: Name="Logitech USB Optical Mouse" 
P: Phys=usb-0000:00:1d.1-2/input0 
S: Sysfs=/class/input/input24 
U: Uniq= 
H: Handlers=mouse1 event2 
B: EV=7 
B: KEY=70000 0 0 0 0 0 0 0 0 
B: REL=103

我的鼠标是 罗技 的 Logitech USB Optical Mouse, 所以 鼠标是 event2 
下面是一个读取 鼠标和键盘事件的例子: 
#include <stdio.h> 
#include <stdlib.h> 
#include <linux/input.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <errno.h>

static void show_event(struct input_event* event) 

printf("%d %d %d/n", event->type, event->code, event->value);

return; 
}

int main(int argc, char* argv[]) 

struct input_event event = {{0}, 0}; 
const char* file_name = argc == 2 ? argv[1] : "/dev/input/event2";

int fd = open(file_name, O_RDWR);


if(fd > 0) 
{

while(1) 

int ret = read(fd, &event, sizeof(event)); 
if(ret == sizeof(event)) 

show_event(&event); 

else 

break; 


close(fd); 
}

return 0; 
}

很多人对于 如何模拟 CTRL + SPACE 感兴趣, 下面也给个例子,呵呵。 
void simulate_ctrl_space(int fd) 

struct input_event event;

//先发送一个 CTRL 按下去的事件。 
event.type = EV_KEY; 
event.value = 1; 
event.code = KEY_LEFTCTRL; 
gettimeofday(&event.time,0); 
write(fd,&event,sizeof(event)) ;

event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event));

//先发送一个 SPACE 按下去的事件。 
event.type = EV_KEY; 
event.value = 1; 
event.code = KEY_SPACE; 
gettimeofday(&event.time,0); 
write(fd,&event,sizeof(event)) ;

//发送一个 释放 SPACE 的事件 
memset(&event, 0, sizeof(event)); 
gettimeofday(&event.time, NULL); 
event.type = EV_KEY; 
event.code = KEY_SPACE; 
event.value = 0; 
write(fd, &event, sizeof(event));

event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event));


//发送一个 释放 CTRL 的事件 
memset(&event, 0, sizeof(event)); 
gettimeofday(&event.time, NULL); 
event.type = EV_KEY; 
event.code = KEY_LEFTCTRL; 
event.value = 0; 
write(fd, &event, sizeof(event));


event.type = EV_SYN; 
event.code = SYN_REPORT; 
event.value = 0; 
write(fd, &event, sizeof(event));

}

类别:编程相关 | 阅读:1281 | 评论:0 | 标签:c linux

想收藏或者和大家分享这篇好文章→

“Linux模拟鼠标和键盘事件”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

公告

2014年10月4日创建

标签云

最近评论

友情链接