通过http://blog.csdn.net/jklinux/article/details/72570663博文可以得知:
一个输入设备获取到的数据是以struct input_event为单位的。
而且鼠标的相对坐标事件中的type值为EV_REL时, code的值为REL_X时, value的正值表示右移,负值表示左移, 移动量为value
code的值为REL_Y时, value的正值表示下移,负值表示上移,移动量为value
鼠标的按键事件中的type为EV_KEY时, code的值表示左(BTN_LEFT),中(BTN_MIDDLE), 右键(BTN_RIGHT)
value的值表示相应的键是按下或松手
输入事件的数据处理流程:
硬件设备 --> 设备驱动检测硬件并提交数据 <--> linux内核 <---> 系统调用 <--> 用户程序
而且linux里的输入设备驱动除了检测硬件产生相应的事件数据以外,还可以接收用户提交的事件数据(也就是用户程序里填好数据的input_event).
虚拟的输入设备就可以使用这种接口来实现。
如用键盘的方向代替鼠标的移动, 用’l’键代替鼠标的左键, ‘m’代替中键, ‘r’代替右键, ‘q’键退出
代码:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <linux/input.h>
void handle_rel(int dev_fd); //处理坐标事件
int main(int argc, char *argv[])
{
int fd, ch;
struct input_event evt, evt_syn = {EV_SYN};
if (argc < 2)
{
printf("usage: %s mouse_device_file \n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
printf("open %s failed\n", argv[1]);
return 1;
}
system("stty raw -echo"); //用于无须确认键,直接接收用户的按键
while (1)
{
ch = getchar();
if (('q' == ch) || ('Q' == ch))
break;
memset(&evt, 0, sizeof(evt));
evt.type = EV_KEY;
switch (ch)
{
case 'l':
evt.code = BTN_LEFT;
break;
case 'r':
evt.code = BTN_RIGHT;
break;
case 'm':
evt.code = BTN_MIDDLE;
break;
case '\033': //方向键
evt.type = EV_REL;
handle_rel(fd);
break;
}
if ((EV_KEY == evt.type) && evt.code) //按键事件处理
{
evt.value = 1; //按下
write(fd, &evt, sizeof(evt)); //键按下的事件
write(fd, &evt_syn, sizeof(evt_syn)); //提交事件
evt.value = 0;
write(fd, &evt, sizeof(evt)); //键松手的事件
write(fd, &evt_syn, sizeof(evt_syn)); //提交事件
}
}
system("stty -raw echo"); //恢复终端属性
return 0;
}
#define VAL 10 //移动量的单位大小
void handle_rel(int dev_fd)
{
int ch;
struct input_event evt;
evt.type = EV_REL;
ch = getchar();
if ('[' != ch)
return;
ch = getchar();
switch (ch)
{
case 'A': // up
evt.code = REL_Y;
evt.value = -VAL;
break;
case 'B': // down
evt.code = REL_Y;
evt.value = VAL;
break;
case 'C': // right
evt.code = REL_X;
evt.value = VAL;
break;
case 'D': // left
evt.code = REL_X;
evt.value = -VAL;
break;
default:
return;
}
write(dev_fd, &evt, sizeof(evt)); //提交相对坐标事件
memset(&evt, 0, sizeof(evt));
evt.type = EV_SYN;
write(dev_fd, &evt, sizeof(evt)); //提交事件
}
基于上例可以扩展为接收网络传输过来的数据再产生相应的输入事件,即可实现网络输入设备的功能。
另如果系统里没有相应的输入设备, 可以自己写个输入设备驱动用于支持虚拟输入设备功能。