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