天天看点

Linux应用程序之按键响应

Linux中的按键检测通过循环读取设备文件/dev/input/event[x](其中x可以为0,1,2…)设备文件获取按键事件,一般由主线程循环获取按键事件,然后通过消息队列通知其他子线程,从而做出响应。  

在Linux内核中,按键事件用input_event结构体描述,该结构体在头文件<linux/input.h>中定义,同时该文件还定义了有关按键事件的API函数接口、标准按键编码等。

input_event结构体定义如下:

struct input_event {
	struct timeval time;
	__u16 type;
	__u16 code;
	__s32 value;
};
           

      <linux/input.h>还定义了常用标准按键编码:

#define KEY_RESERVED		0
#define KEY_ESC			1
#define KEY_1			2
#define KEY_2			3
#define KEY_3			4
#define KEY_4			5
#define KEY_5			6
#define KEY_6			7
           

在用户态,我们只需要循环读取设备文件/dev/input/eventx,就可以得到相应的键盘事件,代码如下:

#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>

#define  KEY_EVENT_DEV1_NAME    "/dev/input/event1"

int sysKeyScan(void)
{
	int l_ret = -1;
	int i = 0;
	
	int key_fd  = 0;
	struct input_event key_event  = {0};
	
	key_fd = open(KEY_EVENT_DEV1_NAME, O_RDONLY);
	if(key_fd <= 0)
	{
		printf("---open /dev/input/event1 device error!---\n");
		return l_ret;
	}
	
	while(1)
	{
		l_ret = lseek(key_fd, 0, SEEK_SET);
		l_ret = read(key_fd, &key_event, sizeof(key_event));
		
		if(l_ret)
		{
			if(key_event.type == EV_KEY
				&& (key_event.value == 0 || key_event.value == 1))
			{
				printf("key %d %s\n", key_event.code, (key_event.value) ? "pressed" : "released");
				
				if(key_event.code == KEY_ESC)
				{
					break;
				}
				
			}
		}

	}
	
	close(key_fd);
	
	return l_ret;
	
}

int main(int arg, char *arc[])
{
	printf("---This is a key event test!---\n");
	
	sysKeyScan();
	
	return 0;
}
           

有时候,我们的的Linux内核也可以把不同的按键封装到不同的event中,例如数字键键盘事件通过event1通知用户态,而功能键通过event0通知用户态。此时我们可以使用poll函数来同时监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,直到有键盘事件发生,poll将唤醒睡眠的进程,并执行相应的操作。代码如下:

#include <linux/input.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdint.h>

#define  KEY_EVENT_DEV0_NAME    "/dev/input/event0"
#define  KEY_EVENT_DEV1_NAME    "/dev/input/event1"

int sysKeyScan(void)
{
	int l_ret = -1;
	int i = 0;

	int key_fd[2]  = {0};
	struct pollfd key_fds[2] = {0};
	struct input_event key_event  = {0};

	key_fd[0] = open(KEY_EVENT_DEV0_NAME, O_RDONLY);
	if(key_fd[0] <= 0)
	{
		printf("---open /dev/input/event0 device error!---\n");
		return l_ret;
	}

	key_fd[1] = open(KEY_EVENT_DEV1_NAME, O_RDONLY);
	if(key_fd[1] <= 0)
	{
		printf("---open /dev/input/event1 device error!---\n");
		return l_ret;
	}

	for(i = 0; i < 2; i++)
	{
		key_fds[i].fd = key_fd[i];
		key_fds[i].events = POLLIN;
	}

	while(1)
	{
		l_ret = poll(key_fds, 2, -1);

		for(i = 0; i < 2; i++)
		{
			l_ret = lseek(key_fd[i], 0, SEEK_SET);
			l_ret = read(key_fd[i], &key_event, sizeof(key_event));

			if(l_ret)
			{
				if(key_event.type == EV_KEY
					&& (key_event.value == 0 || key_event.value == 1))
				{

					printf("key value(%d) %s", key_event.code, key_event.value ? "press" : "release");

				}
			}
		}
	}

	close(key_fd[0]);
	close(key_fd[1]);

	return l_ret;

}

int main(int argc, char *argv[])
{
	printf("---This is a key event test!---\n");

	sysKeyScan();

	return 0;
}
           

继续阅读