前言
這是前4篇:
本篇介紹下input子系統, 用於檢測按鍵輸入, 採用米爾MYS-6ULX板子出廠配置的系統. 主要參考自野火的9. 檢測按鍵輸入(input子系統) .
input子系統
input子系統是Linux對輸入設備提供的統一驅動框架。如按鍵、鍵盤、觸摸屏和鼠標等輸入設備的驅動方式是類似的,當出現按鍵、觸摸等操作時,硬件產生中斷,然後CPU直接讀取引腳電平,或通過SPI、I2C等通訊方式從設備的寄存器讀取具體的按鍵值或觸摸座標,然後把這些信息提交給內核。使用input子系統 驅動的輸入設備可以通過統一的數據結構提交給內核,該數據結構包括輸入的時間、類型、代號以及具體的鍵值或座標,而內則通過/dev/input目錄下的文件接口傳遞給用戶空間。
上篇LED, GPIO的操作在/sys/class/leds
和/sys/class/gpio
, input也有對應的目錄, 如:
root@mys6ull14x14:~# cat /sys/class/input/event2/device/name
gpio-keys
這個對應板子上的用戶按鍵:
假如我們使用的是GPIO子系統框架來編寫按鍵驅動程序,在應用層的操作中,需要使用”/sys/class/gpio/gpio*/direction”文件配置爲輸入方向,然後使用循環讀取”/sys/class/gpio/gpio*/value”文件的值來獲得按鍵的狀態,但由於對value文件的read讀 取操作不會阻塞,所以進程會不停地讀取文件內容來判斷按鍵值,佔用CPU寶貴的運算資源。
在輸入事件檢測的應用中,通常使用主線程直接 循環讀取”/dev/input/event*”設備文件獲取事件的數據結構,然後通過消 息隊列通知其它子線程,從而響應輸入操作。
此處使用的是開發板KEY按鍵 在”/dev/input/by-path”下的鏈接文件名,此處不使用”/dev/input/event*”只是 爲了讓程序不受其它輸入設備而影響了事件編號。
root@mys6ull14x14:~/nfs_share# ls /dev/input/by-path
platform-2040000.tsc-event
platform-20cc000.snvs:snvs-powerkey-event
platform-ci_hdrc.1-usb-0:1.2:1.0-event-mouse
platform-ci_hdrc.1-usb-0:1.2:1.0-mouse
platform-gpio-keys-event
如果cat /dev/input/by-path/platform-gpio-keys-event
, 按下按鍵會發現亂碼, 可以用evtest
檢測:
root@mys6ull14x14:~/nfs_share# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: 20cc000.snvs:snvs-powerkey
/dev/input/event1: iMX6UL TouchScreen Controller
/dev/input/event2: gpio-keys
Select the device event number [0-2]: 2
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100
Input device name: "gpio-keys"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 2 (KEY_1)
Properties:
Testing ... (interrupt to exit)
Event: time 1507355347.797407, type 1 (EV_KEY), code 2 (KEY_1), value 0
Event: time 1507355347.797407, -------------- SYN_REPORT ------------
Event: time 1507355347.977336, type 1 (EV_KEY), code 2 (KEY_1), value 1
Event: time 1507355347.977336, -------------- SYN_REPORT ------------
按鍵檢測C代碼
新建gpio_key.c
:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
const char default_path[] = "/dev/input/by-path/platform-gpio-keys-event";
int main(int argc, char *argv[])
{
int fd;
struct input_event event;
char *path;
printf("This is a input device demo.\n");
path = (char *)default_path;
fd = open(path, O_RDONLY);
if (fd < 0)
{
printf("Fail to open device:%s.\n", path);
exit(1);
}
printf("Test device: %s.\nWaiting for input...\n", path);
while (1)
{
if (read(fd, &event, sizeof(event)) == sizeof(event))
{
//EV_SYN是事件分隔標誌,不打印
if (event.type != EV_SYN)
printf("Event: time %ld.%ld, type %d, code %d,value %d\n",
event.time.tv_sec, event.time.tv_usec,
event.type,
event.code,
event.value);
}
}
close(fd);
return 0;
}
編譯arm-linux-gnueabihf-gcc -o gpio_key gpio_key.c
, NFS掛載後直接在開發板串口終端輸入./gpio_key
運行, 按下按鍵:
root@mys6ull14x14:~/nfs_share/Code/cache# ./gpio_key
This is a input device demo.
Test device: /dev/input/by-path/platform-gpio-keys-event.
Waiting for input...
Event: time 1507358199.167780, type 1, code 2,value 0
Event: time 1507358199.437382, type 1, code 2,value 1
或者改自米爾的例子也大同小異:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
const char key_path[] = "/dev/input/event2";
int main(int argc, char *argv[])
{
int ledn;
char *tmp;
int keys_fd;
struct input_event t;
keys_fd = open(key_path, O_RDONLY);
if (keys_fd <= 0)
{
printf("open %s device error!\n", &key_path);
return 0;
}
printf("Hit any key on board ......\n");
while (1)
{
if (read(keys_fd, &t, sizeof(t)) == sizeof(t))
{
if (t.type == EV_KEY)
{
if (t.value == 0 || t.value == 1)
{
printf("key %d %s\n", t.code, (t.value) ? "Pressed" : "Released");
if (t.code == KEY_ESC)
break;
}
}
}
}
close(keys_fd);
return 0;
}
運行如下:
root@mys6ull14x14:~/nfs_share/Code/cache# ./gpio_key1
Hit any key on board ......
key 2 Released
key 2 Pressed
key 2 Released
key 2 Pressed
微信公衆號
歡迎掃描關注我的微信公衆號, 及時獲取最新文章: