因为公司智能终端放置在外面,有一个像ATM机器一样的密码键盘.原本是作为银行卡密码输入确认的。
现在为了方便维护,一些简单的系统操作,就利用这个密码键盘来调用编写好的sh脚本。
但是因为终端机并没有插键盘,所以没有输入设备,这个时候只能利用与密码键盘通讯的支付程序,向系统发送按键指令。
所以,用到了uinput虚拟输入驱动,简单的说:用它可以在用户空间实现输入设备,向系统中注入输入事件。
下面,是我写好的输入按键的程序。
1.将下面的代码保存成 keyinput.c
2.编译:
$ gcc keyinput.c -o keyinput
3.加载 uinput驱动
$ sudo modprobe uinput
$ lsmod |grep uinput
4.将编译好的文件放到/usr/sbin/中
$ sudo cp keyinput /usr/sbin/
$ sudo chmod 755 /usr/sbin/keyinput
5.示例:向Linux桌面系统发送CTRL+ALT+D 清屏蔽指令
$ keyinput 29 56 32
6.keyinput 参数说明:后面跟着的参数全是ASCII码,对应的键盘ASCII码在 /usr/include/linux/input.h 中可以查询。
/*//////////////////////////////////////////
// Simulated keyboard input program //
// by:0x001 //
//////////////////////////////////////////*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#define die(str, args...) do {
perror(str);
exit(EXIT_FAILURE);
} while(0)
int fd;
struct uinput_user_dev uidev; // uInput device structure
struct input_event ev; // Input device structure
/* Setup the uinput device */
void setup_uinput_device()
{
int i=0;
// Open the input device
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fd < 0)
die("error: open /dev/uinput");
memset(&uidev, 0, sizeof(uidev)); // Intialize the uInput device to NULL
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-Openkk");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
// Setup the driver I/O channels
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
for (i=0; i < 256; i++) {
ioctl(fd, UI_SET_KEYBIT, i);
}
ioctl(fd, UI_SET_EVBIT, EV_REL);
ioctl(fd, UI_SET_RELBIT, REL_X);
ioctl(fd, UI_SET_RELBIT, REL_Y);
/* Create input device into input sub-system */
write(fd, &uidev, sizeof(uidev));
if(ioctl(fd, UI_DEV_CREATE) < 0)
die("error: create uinput device");
}
// Simulated keyboard input
void simulate_key(int keycode, int keyvalue)
{
memset(&ev, 0, sizeof(struct input_event));
gettimeofday(&ev.time, NULL);
ev.type = EV_KEY;
ev.code = keycode;
ev.value = keyvalue;
if(write(fd, &ev, sizeof(struct input_event)) < 0)
{
printf("simulate key errorn");
return;
}else{
printf("simulate key %d, %dn", keycode, keyvalue);
}
}
void simulate_key_end()
{
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_SYN;
ev.code = 0;
ev.value = 0;
write(fd, &ev, sizeof(struct input_event));
}
// check the key is control key
int check_valid_control_key(int key)
{
int control_key[] = {29,42,54,56,97,100,125,126};
int len = sizeof(control_key) / sizeof(control_key[0]);
int i;
int ret = 0;
for ( i = 0; i < len; i++)
{
if (control_key[i] == key)
{
ret = 1;
break;
}
}
return ret;
}
int main(int argc, char *argv[])
{
if (argc <=1)
{
printf("n /*//////////////////////////////////////////n");
printf(" // Simulated keyboard input program //n");
printf(" // by:0x001 //n");
printf(" //////////////////////////////////////////*/nn");
printf(" Usage : keyinput <kye number> [key number...]n");
printf(" keyinput 29 56 32 /* CTRL + ALT +D */n");
printf(" keyinput 125 32 /* WIN +D */nn");
printf(" /* Types of key number are defined in /usr/include/linux/input.h */nn");
printf(" /* tools need to load the kernel module: uinput */nn");
printf(" /* $ sudo modprobe uinput */nn");
return 0;
}
setup_uinput_device();
sleep(1);
int key;
int i;
for (i=1; i < argc; i++)
{
key = atoi(argv[i]);
simulate_key(key,1);
if (check_valid_control_key(key) == 0)
{
simulate_key(key,0);
}
}
for (i=1; i < argc; i++)
{
key = atoi(argv[i]);
if (check_valid_control_key(key) == 1)
{
simulate_key(key,0);
}
}
simulate_key_end();
if(ioctl(fd, UI_DEV_DESTROY) < 0)
die("error: ioctl");
close(fd);
return 0;
}