嵌入式Linux input

前言

这是前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

微信公众号

欢迎扫描关注我的微信公众号, 及时获取最新文章:
在这里插入图片描述

发布了203 篇原创文章 · 获赞 105 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/weifengdq/article/details/104921059