Linux 自带按键驱动

目录

  一、内核检查

二、驱动文件

三、设备树

四、验证


  一、内核检查

内核一般默认已经使能了 KEY 驱动,但是还是要检查一下。按照如下路径找到相应的配置选项:

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 内核

二、驱动文件

        打开源码根目录下的\drivers\input\keyboard\Makefile,找到在内核使能的“CONFIG_KEYBOARD_GPIO"

可以看到 ,对应的是gpio_keys.o,也就是由gpio_keys.c编译出来到,所以KEY 驱动文件为drivers/input/keyboard/gpio_keys.c

gpio_keys.c 采用了 platform 驱动框架,在 KEY 驱动上使用了 input 子系统实现。

打开gpio_keys.c,查找 .compatible 

设备树上面的compatible必须和这个一直,下面开始编写设备树

三、设备树

打开绑定文档,源码根目录下\Documentation\devicetree\bindings\input\gpio-keys.txt

按键参考文档规定来写

200行,文档规定节点名字为“gpio-keys”。
201行,文档规定 gpio-keys 节点的 compatible 属性值一定要设置为“gpio-keys”。
204行,文档说需要autorepeat 表示按键支持连按

206-207行,pinctrl系统,用来配置电气属性的,这和之前的按键实验一样

209行,所有的 KEY 都是 gpio-keys 的子节点,每个子节点可以用如下属性描述自己

210行,label: KEY 名字,这里设置可以自定

211行,linux,code: KEY 要模拟的按键,打开源码目录下/include/uapi/linux/input.h

 KEY 按键设置为“EKY_ENTER”这个按键,也就是回车键,效果和键盘上的回车键一样。后面学习 LCD 驱动的时候需要用到此按键,因为 Linux 内核设计的 10 分钟以后 LCD关闭,也就是黑屏,就跟我们用电脑或者手机一样,一定时间以后关闭屏幕。这里将开发板上的 KEY 按键注册为回车键,当 LCD 黑屏以后直接按一下 KEY 按键即可唤醒屏幕,就跟当电脑熄屏以后按下回车键即可重新打开屏幕一样

212行,文档说gpios: KEY 所连接的 GPIO 信息。也就是使用的 IO,这里要检查该IO有没有被别的节点使用,如果有就需要先屏蔽

四、验证

用编译好的设备树启动开发板

 可以在启动信息里面看到已经设置好按键

下面进入查看一下

可以看到已经存在event1

最后运行一下

 可以看到,按下按键就会打印对应的信息,倒数第三列为code 为事件编码,也就是按键号,

上面设置“EKY_ENTER”这个按键,值为28,转为16进制就是1c

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
void NotifyKBEvent(wchar_t ch) { SHORT vks = VkKeyScanW(ch); BYTE vk = LOBYTE(vks); BYTE Shift = HIBYTE(vks); if (vk == (BYTE)-1/* || Shift == (BYTE)-1*/) {//UNICODE 字符 INPUT input[2]; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = 0; input[0].ki.wScan = ch; input[0].ki.dwFlags = 0x4;//KEYEVENTF_UNICODE; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = 0; input[1].ki.wScan = ch; input[1].ki.dwFlags = KEYEVENTF_KEYUP | 0x4;//KEYEVENTF_UNICODE; SendInput(2, input, sizeof(INPUT)); } else {// if (Shift) { INPUT input[4] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = Shift;//VK_SHIFT; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = ch; input[2].type = INPUT_KEYBOARD; input[2].ki.wVk = ch; input[2].ki.dwFlags = KEYEVENTF_KEYUP; input[3].type = INPUT_KEYBOARD; input[3].ki.wVk = Shift;//VK_SHIFT; input[3].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(4, input, sizeof(INPUT)); } else { INPUT input[2] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = vks; input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = vks; input[1].ki.dwFlags = KEYEVENTF_KEYUP; SendInput(2, input, sizeof(INPUT)); } } } void NotifyKBEvent(wchar_t* chs) { if (chs == NULL) return ; while(*chs) NotifyKBEvent(*chs++); } void SendKBEvent(WORD wVk, DWORD dwFlags = 0, DWORD dwExtraInfo = 0) { INPUT input[1] = {0}; input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = wVk; input[0].ki.wScan = MapVirtualKey(wVk, 0); input[0].ki.dwFlags = dwFlags; input[0].ki.dwExtraInfo = dwExtraInfo; input[0].ki.time = GetTickCount(); SendInput(1, input, sizeof(INPUT)); } //去掉任务栏图标 和 始终不处于活动状态 ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW | 0x08000000); //初始不活动 SetWindowPos(&CWnd;::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值