Linux 输入设备 自定义键盘 input输入子系统 gpio

您所在的位置:网站首页 LINUX驱动系统 Linux 输入设备 自定义键盘 input输入子系统 gpio

Linux 输入设备 自定义键盘 input输入子系统 gpio

2024-07-11 16:35| 来源: 网络整理| 查看: 265

文章目录 前言查看include/uapi/linux/input.h设备树添加make menuconfig驱动编译ko模块查看驱动运行状态查看/proc/bus/input/devices设备查看dev/input 按键测试hexdump应用程序 过程中问题及解决方法常见问题按键硬件注意

前言

设计板需要提供六个按键进行人机交互,起初准备使用CH455G键盘扫描芯片,设计键盘电路

在这里插入图片描述

随着旋转编码器Linux内核驱动的调试成功

Linux 输入设备调试详解(零基础开发)Rotary_Encoder旋转编码器模块(EC11)通用GPIO为例 挂载input输入子系统

对于更加简单,参考资料更加多的按键输入,可以尝试使用Linux内核驱动来解决,减少外围电路的设计负担,以及调试i2c的痛苦

有了之前调试旋转编码器的经验,这次也是信心十足,但整个过程还是花费了三天左右的时间,并且中间犯了一个常识性错误

查看include/uapi/linux/input.h

对于按键,先准备好input.h文件

include/uapi/linux/input.h

在这里插入图片描述 在这里插入图片描述

设备树添加

要使用Linux 内核自带的按键驱动程序很简单, 只需要根据Documentation/devicetree/bindings/input/gpio-keys.txt 这个文件在设备树中添加指定的设备节点即可,节点要求如下:

①、节点名字为“gpio-keys”。

②、gpio-keys 节点的compatible 属性值一定要设置为“gpio-keys”。

③、所有的KEY 都是gpio-keys 的子节点,每个子节点可以用如下属性描述自己: gpios:KEY 所连接的GPIO 信息。 interrupts:KEY 所使用GPIO 中断信息,不是必须的,可以不写。 label:KEY 名字 linux,code:KEY 要模拟的按键,也就是示例代码58.1.2.4 中的这些按键。

④、如果按键要支持连按的话要加入autorepeat。

在设备树中添加所需

gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = ; autorepeat; key-up { label = "key-up"; gpios = ; gpio-key,wakeup; linux,code = ; // 103 }; key-down { label = "key-down"; gpios = ; gpio-key,wakeup; linux,code = ; // 108 }; key-left { label = "key-left"; gpios = ; gpio-key,wakeup; linux,code = ; // 105 }; key-right { label = "key-right"; // gpios = ; // MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 // gpios = ; // MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 gpios = ; // MX6QDL_PAD_EIM_A18__GPIO2_IO20 gpio-key,wakeup; linux,code = ; // 106 }; key-enter { label = "key-enter"; // gpios = ; // MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 // gpios = ; // MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 gpios = ; // MX6QDL_PAD_EIM_A20__GPIO2_IO18 gpio-key,wakeup; linux,code = ; // 28 }; key-esc { label = "key-esc"; // gpios = ; // MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 // gpios = ; // MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 gpios = ; // MX6QDL_PAD_EIM_A21__GPIO2_IO17 gpio-key,wakeup; linux,code = ; // 1 }; /*EC11按键添加*/ key-ec11 { label = "key-ec11"; gpios = ; // MX6QDL_PAD_EIM_A16__GPIO2_IO22 gpio-key,wakeup; linux,code = ; // 2 }; };

注意:KEY 按键信息,名字设置为“key-enter”,对于这个按键linux,code = ;,也就是回车键,效果和键盘上的回车键一样。KEY_ENTER的宏定义就在之前所说include/uapi/linux/input.h中

添加pinctrl子系统信息

pinctrl_gpio_keys: gpio_keysgrp { fsl,pins = ; };

保存,编译dtb

make dtbs -32

在这里插入图片描述 在输出信息中可以看到,生成了我需要的imx6q-c-sabresd.dtb设备树文件

make menuconfig驱动 make menuconfig

搜索到了我们需要的普通GPIO的按键驱动 在这里插入图片描述

-> Device Drivers -> Input device support -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y]) -> Keyboards (INPUT_KEYBOARD [=y]) ->GPIO Buttons

在这里插入图片描述 选中以后就会在.config 文件中出现“CONFIG_KEYBOARD_GPIO=y”这一行,Linux 内核就会根据这一行来将KEY 驱动文件编译进Linux 内核。Linux 内核自带的KEY 驱动文件为drivers/input/keyboard/gpiokeys.c,gpio_keys.c 采用了platform 驱动框架,在KEY 驱动上使用了input 子系统实现。

nano drivers/input/keyboard/gpio_keys.c

在这里插入图片描述 找到了驱动,按照调试内核驱动的老规矩,首先我们在内核驱动中先不开启gpio-keys驱动,而是提取出来编译成ko模块进行测试

所以在make menuconfig 找到驱动的位置后,取消掉驱动,然后编译,生成zImage文件

现在就可以把dtb文件和zImage文件烧录进板子了

编译ko模块

在编译驱动之前,先给驱动加上各种printk打印信息 在这里插入图片描述 处理完驱动,然后编写makefile

# ,%%%%%%%%, # ,%%/\%%%%/\%% # ,%%%\c''''J/%%% # %. %%%%/ o o \%%% # `%%. %%%% |%%% # `%% `%%%%(__Y__)%%' # // ;%%%%`\-/%%%' # (( / `%%%%%%%' # \\ .' | # \\ / \ | | # \\/ ) | | # \ /_ | |__ # (____________))))))) 攻城狮 # 调试驱动和应用程序用Makefile # 编译模块 # 开发板Linux内核的实际路径 # KDIR变量 KDIR:=/work/linux-4.1.15 # 获取当前目录 PWD:=$(shell pwd) # obj-m表示将 chrdevbase.c这个文件 编译为 name.ko模块。 obj-m += gpio_keys.o # 编译成模块 all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean

大功告成,执行make,编译成ko模块 在这里插入图片描述 发送到板子

scp gpio_keys.ko [email protected]:/work

在这里插入图片描述 在这里插入图片描述

查看驱动运行状态

运行ko文件 在这里插入图片描述 没有任何错误,非常的完美,运气非常的不错

但是为了谨慎,还是要查看驱动的加载情况

查看/proc/bus/input/devices设备

查看/proc/bus/input/devices

nano /proc/bus/input/devices

可以看到我们gpio-keys 在这里插入图片描述

查看dev/input

在input节点下,可以看到我们的event2 在这里插入图片描述 从驱动加载情况上来看,驱动正常运行,没有问题

按键测试

这里测试按键的输入有好多种方法,这里列举几个

hexdump hexdump /dev/input/event2

可以看到信号的输入,但是没有办法直观的判断是哪个按键的 在这里插入图片描述

应用程序

这里有一个简单的应用程序

// _ooOoo_ // // o8888888o // // 88" . "88 // // (| ^_^ |) // // O\ = /O // // ____/`---'\____ // // .' \\| |// `. // // / \\||| : |||// \ // // / _||||| -:- |||||- \ // // | | \\\ - /// | | // // | \_| ''\---/'' | | // // \ .-\__ `-` ___/-. / // // ___`. .' /--.--\ `. . ___ // // ."" '< `.___\__/___.' >'"". // // | | : `- \`.;`\ _ /`;.`/ - ` : | | // // \ \ `-. \_ __\ /__ _/ .-` / / // // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // 佛祖保佑 永不宕机 永无BUG // #include #include #include #include #include #include #include int main(int argc, char *argv[]) { struct input_event in_ev = {0}; int fd = -1; /* 校验传参 */ if (2 != argc) { fprintf(stderr, "usage: %s \n", argv[0]); exit(-1); } /* 打开文件 */ if (0 > (fd = open(argv[1], O_RDONLY))) { perror("open error"); exit(-1); } for ( ; ; ) { /* 循环读取数据 */ if (sizeof(struct input_event) != read(fd, &in_ev, sizeof(struct input_event))) { perror("read error"); exit(-1); } printf("type:%d code:%d value:%d\n", in_ev.type, in_ev.code, in_ev.value); } }

执行交叉编译

$CC gpio_key_app.c -o gpio_key_app

在这里插入图片描述

通过网络发送到板子上

scp gpio_key_app [email protected]:/work

在这里插入图片描述 运行应用程序

./gpio_key_app /dev/input/event2

按动我们的按键,就可以看到按键的数据 在这里插入图片描述 为了可以更直观一些,可以使用这个应用程序

#include #include #include #include #include #define NOKEY 0 int main() { int keys_fd; char ret[2]; struct input_event t; char *dev; setvbuf(stdout, (char *)NULL, _IONBF, 0);//disable stdio out buffer; // dev = getenv("KEYPAD_DEV"); keys_fd = open("/dev/input/keypad", O_RDONLY); if(keys_fd


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3