按键作为用户系统交互的一部分,在嵌入式系统应用中,占有非常重要的地位。Linux内核输入子系统已经对按键提供了良好的驱动支持,只需要实现相应的按键设备即可让按键正常工作。

1、按键设备

按键设备包含了名字、独有的资源等等一些驱动程序的硬件或自定义信息。

通过 platform_add_devices(platform_device_register) 函数将定义的平台设备注册到内核中,用于匹配设备驱动。

内核在 drivers\input\keyboard 目录中实现了 gpio 按键驱动,支持中断方式独立按键驱动、轮询方式独立按键驱动、矩阵扫描按键驱动

笔者的独立按键gpio口不支持外部中断,因此采用按键轮询的方式实现按键驱动。对应的驱动代码为gpio_keys_polled.c,按键设备平台代码如下:

#include <linux/input.h>
#include <linux/gpio_keys.h>

static struct gpio_keys_button home2416_buttons[] = {
    {
        .gpio             = S3C2410_GPC(0),           /* K1 */
        .code             = KEY_F1,
        .desc             = "Button 1",
        .active_low    = 1,
    },
    {
        .gpio             = S3C2410_GPM(0),           /* K2 */
        .code             = KEY_F2,
        .desc             = "Button 2",
        .active_low    = 1,
    },
    {
        .gpio             = S3C2410_GPB(4),           /* K3 */
        .code             = KEY_F3,
        .desc             = "Button 3",
        .active_low    = 1,
    },
};

static struct gpio_keys_platform_data home2416_button_data = {
    .buttons = home2416_buttons,
    .nbuttons = ARRAY_SIZE(home2416_buttons),
    .poll_interval = 50, // 50ms polled
};

static struct platform_device home2416_button_device = {
    .name    =    "gpio-keys-polled",
    .id        =    -1,
    .dev    =    {
        .platform_data    = &home2416_button_data,
    }
};

按键设备使用了按键相关数据结构,应加入相应的头文件。按键轮询间隔一般20hz即可,轮询频率高,占用的cpu资源也比较高。在 static struct platform_device *home2416_devices[] 板级平台设备列表中加入 &home2416_button_device,使按键设备能够注册到内核中

2、内核配置

Linux 配置支持 按键轮询驱动, 选中 Device Drivers->Input device support->Keyboards->Polled GPIO buttons:

09_按键驱动 - 图1

3、按键测试

3.1 查询主设备号

编译内核并启动, 查看主设备号:

#列出目前内核支持的设备:其中第1列为主设备号,第2列为注册名(如果注册成功的话,会在此看到对应的名字)
cat /proc/devices

/proc/devices 简介:
/proc/devices/中的设备是驱动程序生成的,它是通过 insmod 加载到内核的,它可产生一个 major, 供 mknod 作为参数 。
/dev/下的设备是通过 mknod 加载的,用户通过此设备名来访问驱动。

可以知道 input 主设备号为 13。

3.2 查询次设备号

在 /sys/dev/char 中查看按键的主设备号为 13,次设备号为 64:

ls -al /sys/dev/char

09_按键驱动 - 图2

3.3 手动创建设备节点

上面查询出主设备号、次设备号之后,就可以在 dev/ 下面创建设备节点了:
在 /dev/input 目录中创建 event0 按键设备文件:

mkdir /dev/input
mknod /dev/input/event0 c 13 64

用 hexdump 命令测试按键的功能:

09_按键驱动 - 图3

注:
hexdump 是 Linux 下的一个二进制文件查看工具,它可以将二进制文件转换为ASCII、八进制、十进制、十六进制格式进行查看。
指令所在路径:/usr/bin/hexdump

4、应用编程

应用程序可以通过访问 /dev/input/event0 按键设备文件来获取按键的输入。

按键应用测试代码button_test.c如下:

#include "fcntl.h"
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>

int main(void)
{
       intfd;
       structinput_event ev_key;
       fd=open("/dev/input/event0", O_RDWR);
       if(fd < 0) 
       {
              printf("Openfailed\n");
              exit(1);
       }

       while(1) {
              read(fd,&ev_key, sizeof(struct input_event));
              if(ev_key.code != 0) {
                     printf("type:%d,code:%d, value:%d\n", ev_key.type,
ev_key.code, ev_key.value);
              }
       }

       close(fd);
       return0;
}

用arm-linux-gcc静态编译,使之生成arm cpu可执行的指令,并且可脱离任何库独立运行,arm-linux-gcc -static -o button_test button_test.c,生成button_test可执行文件。复制可执行文件到根文件系统,目标板启动后在目录输入./ button_test即可执行。

09_按键驱动 - 图4

5、附录

文件 下载地址
bootloader源码以及使用说明 https://pan.baidu.com/s/1slczwhJ
Qt5.8官网源码 https://pan.baidu.com/s/1eRDJtNs
本系列例程的根文件系统 https://pan.baidu.com/s/1nuGmSqt
opev3.2.0官网源码 https://pan.baidu.com/s/1i5btLGT
yaffs官网源码 https://pan.baidu.com/s/1pLpuHw3
busybox-1.26.2官网源码 https://pan.baidu.com/s/1bpkZynt
tslib官网源码 https://pan.baidu.com/s/1i4EtjfR
mplayer-1.3.0官网源码 https://pan.baidu.com/s/1i5MGRhb
基于S3C2416修改的linux-4.10.10源码 https://pan.baidu.com/s/1sl0fXlr