全部博文(306)
分类: LINUX
2010-04-10 11:02:18
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
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));
}