天天看點

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;
}
           

繼續閱讀