按键中断,input上报demo
文章目录前言代码前言通过gpio的物理按键中断上报一个input事件代码#includelinux/module.h#includelinux/errno.h#includelinux/miscdevice.h#includelinux/kernel.h#includelinux/major.h#includelinux/mutex.h#includelinux/init.h#includelinux/device.h#includelinux/gpio/consumer.h#includelinux/platform_device.h#includelinux/of_gpio.h#includelinux/of_irq.h#includelinux/interrupt.h#includelinux/irq.h#includelinux/delay.h#includelinux/input.h#includelinux/workqueue.h#defineOWNER_NAMEkk_gpio_key#defineIRQ_NAMEkk_vak/** * 私有数据 */structem_gpio_key{intgpio_pin;//pin脚intgpio_irq;//中断号structworkqueue_struct*work_queue;//工作队列structwork_structwork;//类似标识的东西与key_worker关联起来structinput_dev*input_dev;//input接口};/* 工作处理函数 */staticvoidwork_handler(structwork_struct*work){structem_gpio_key*em_keycontainer_of(work,structem_gpio_key,work);intvalue;printk(%s start \n,__func__);//20ms消抖mdelay(20);valuegpio_get_value(em_key-gpio_pin);printk(%s value %d \n,__func__,value);if(value1){//按键松开input_report_key(em_key-input_dev,KEY_VOICECOMMAND,0);input_sync(em_key-input_dev);}elseif(value0){//按键按下input_report_key(em_key-input_dev,KEY_VOICECOMMAND,1);input_sync(em_key-input_dev);}//重新使能中断enable_irq(em_key-gpio_irq);printk(%s end \n,__func__);}/** * 按键按下触发的中断处理 */staticirqreturn_tgpio_key_isr(intirq,void*data){structem_gpio_key*em_keydata;printk(%s start \n,__func__);//关闭中断防止中断嵌套disable_irq_nosync(em_key-gpio_irq);queue_work(em_key-work_queue,em_key-work);printk(%s end \n,__func__);returnIRQ_HANDLED;}/* * 1.中断申请用于获取中断 * 2.创建工作队列用于处理耗时的操作 * 3.创建input用于上报KEY_VOICECOMMAND按下及抬起 */staticintgpio_key_probe(structplatform_device*pdev){intret;structdevice_node*nodepdev-dev.of_node;structem_gpio_key*em_key;structinput_dev*input_dev;printk(%s start \n,__func__);//给私有数据 分配内存em_keydevm_kzalloc(pdev-dev,sizeof(structem_gpio_key),GFP_KERNEL);if(!em_key){ret-ENOMEM;gotodevm_kzalloc_error;}//获取gpio pin脚em_key-gpio_pinof_get_named_gpio(node,irq-gpio,0);if(!gpio_is_valid(em_key-gpio_pin)){printk(%s gpio_pin:%d is invalid\n,__func__,em_key-gpio_pin);ret-EINVAL;gotoof_error;}/** * 中断创建 *///申请gpio引脚retdevm_gpio_request_one(pdev-dev,em_key-gpio_pin,GPIOF_IN,em_key_irq_gpio);if(ret){printk(%s em_gpio_key.gpio_pin:%d request failed \n,__func__,em_key-gpio_pin);gotorequest_error;}else{printk(%s em_gpio_key.gpio_pin:%d request succeed \n,__func__,em_key-gpio_pin);}//获得gpio中断号em_key-gpio_irqgpio_to_irq(em_key-gpio_pin);if(!em_key-gpio_irq){printk(%s .gpio_pin:%d get irq num:%d failed \n,__func__,em_key-gpio_pin,em_key-gpio_irq);gototo_irq_error;}else{printk(%s .gpio_pin:%d get irq num:%d succeed \n,__func__,em_key-gpio_pin,em_key-gpio_irq);}//根据irq申请中断retdevm_request_threaded_irq(pdev-dev,em_key-gpio_irq,NULL,gpio_key_isr,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_ONESHOT,emdoor-vak,em_key);if(ret0){printk(%s irq num:%d request failed, ret %d \n,__func__,em_key-gpio_irq,ret);gotoirq_error;}//使用工作队列处理中断这里为了及时处理中断单独创建一个em_key-work_queuecreate_workqueue(my_workqueue);if(!em_key-work_queue){printk(KERN_ERR%s Workqueue demo: Failed to create workqueue\n,__func__);return-ENOMEM;}INIT_WORK(em_key-work,work_handler);//把这个数据设置为device的私有数据dev_set_drvdata(pdev-dev,em_key);/** * input创建 */input_devinput_allocate_device();if(!input_dev){printk(%s Failed to allocate memory for input device,__func__);ret-ENOMEM;gotoinput_allocate_error;}input_dev-dev.parentpdev-dev;input_dev-namekk-input;input_dev-id.bustypeBUS_VIRTUAL;__set_bit(EV_SYN,input_dev-evbit);//同步事件__set_bit(EV_KEY,input_dev-evbit);//按键事件__set_bit(EV_REP,input_dev-evbit);//重复事件__set_bit(KEY_VOICECOMMAND,input_dev-keybit);//设置产生哪些按键值retinput_register_device(input_dev);if(ret){printk(%s Input device registration failed,__func__);gotoinput_register_error;}//把这个数据设置为input_dev的私有数据dev_set_drvdata(input_dev-dev,em_key);//将这个input设备接口存起来em_key-input_devinput_dev;enable_irq(em_key-gpio_irq);printk(%s end \n,__func__);return0;input_allocate_error:irq_error:to_irq_error:request_error:of_error:devm_kzalloc_error:returnret;input_register_error:input_free_device(input_dev);input_devNULL;returnret;}staticintgpio_key_remove(structplatform_device*pdev){structem_gpio_key*em_key;intret;//probe中开辟的私有数据内存需要释放em_keydev_get_drvdata(pdev-dev);if(IS_ERR(em_key)){retPTR_ERR(em_key);printk(KERN_ERR %s remove error!\n,__func__);}flush_workqueue(em_key-work_queue);destroy_workqueue(em_key-work_queue);input_unregister_device(em_key-input_dev);input_free_device(em_key-input_dev);input_set_drvdata(em_key-input_dev,NULL);dev_set_drvdata(pdev-dev,NULL);return0;}staticconststructof_device_idgpio_key[]{{.compatiblekk-vak},{},};/* 1. 定义platform_driver */staticstructplatform_drivergpio_keys_driver{.probegpio_key_probe,.removegpio_key_remove,.driver{.nameOWNER_NAME,.of_match_tablegpio_key,},};/* 2. 在入口函数注册platform_driver */staticint__initgpio_key_init(void){interr;printk(%s %s line %d\n,__FILE__,__FUNCTION__,__LINE__);errplatform_driver_register(gpio_keys_driver);returnerr;}/* 3. 有入口函数就应该有出口函数卸载驱动程序时就会去调用这个出口函数 * 卸载platform_driver */staticvoid__exitgpio_key_exit(void){printk(%s %s line %d\n,__FILE__,__FUNCTION__,__LINE__);platform_driver_unregister(gpio_keys_driver);}module_init(gpio_key_init);module_exit(gpio_key_exit);MODULE_LICENSE(GPL);设备树kk_key:kk_key{compatiblekk-vak;statusokay;irq-gpiopio320;};如果没有上拉中断脚会出现不断触发中断的现象需要内部上拉这个中断脚这里是MTK 引脚的配置就不在设备树里做相关的电气属性配置

相关新闻

PCIe寄存器深度解析:从硬件能力到驱动调试的实战指南

PCIe寄存器深度解析:从硬件能力到驱动调试的实战指南

1. 项目概述与核心价值搞硬件驱动或者嵌入式系统开发,尤其是涉及到高速总线通信的,PCIe(Peripheral Component Interconnect Express)绝对是一个绕不开的坎。它早已不是PC主板上那个插显卡的插槽那么简单,在服务器、存…

2026/10/21 1:56:16 阅读更多 →
GitHub热门项目分析方法与技术趋势解读

GitHub热门项目分析方法与技术趋势解读

1. GitHub 热门项目解析方法论作为开发者日常获取技术灵感和工具的重要渠道,GitHub Trending 榜单每周都会涌现出值得关注的新项目。要系统性地分析这些热门项目,我总结了一套行之有效的四步分析法:1.1 数据采集与清洗首先通过 GitHub API 获…

2026/10/19 7:59:34 阅读更多 →
Codebase Memory MCP:AI编程辅助工具中的代码知识图谱技术

Codebase Memory MCP:AI编程辅助工具中的代码知识图谱技术

1. 项目概述:Codebase Memory MCP的革新意义在AI编程辅助工具领域,我们正面临一个关键瓶颈:大模型处理代码库时的token消耗问题。传统方式下,AI代理需要反复读取整个代码文件来理解项目结构,这不仅效率低下&#xff0c…

2026/10/20 13:22:54 阅读更多 →

最新新闻

SSM+Vue教学资源库系统开发实战:从上传审核到在线预览

SSM+Vue教学资源库系统开发实战:从上传审核到在线预览

1. 起因:教学资源乱成一锅粥,才决定动手做这个库先交代一下背景。我们这边是搞创客教育的团队,课程横跨图形化编程、开源硬件、3D建模几个方向,老师和助教加起来十几号人,积累的教案、课件、代码示例、电路图、视频素材…

2026/10/21 1:55:36 阅读更多 →
使用 TypeScript 集成 Azure App Configuration:集中配置、Feature Flags 与动态刷新的完整实战指南

使用 TypeScript 集成 Azure App Configuration:集中配置、Feature Flags 与动态刷新的完整实战指南

AI 技能AI 插件人工智能 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600 agentic skills. Includes CLI, local MCP, c…

2026/10/21 1:55:36 阅读更多 →
戴森球计划工厂蓝图免费仓库:7000+张蓝图放下就能跑

戴森球计划工厂蓝图免费仓库:7000+张蓝图放下就能跑

戴森球计划工厂蓝图免费仓库:7000张蓝图放下就能跑 【免费下载链接】FactoryBluePrints 游戏戴森球计划的**工厂**蓝图仓库 项目地址: https://gitcode.com/GitHub_Trending/fa/FactoryBluePrints 玩《戴森球计划》,多数人都会卡死在开局那半小时…

2026/10/21 1:55:36 阅读更多 →
如何在未越狱 iPhone 上玩 Windows PC 游戏:Madeira iOS 模拟器完整教程

如何在未越狱 iPhone 上玩 Windows PC 游戏:Madeira iOS 模拟器完整教程

如何在未越狱 iPhone 上玩 Windows PC 游戏:Madeira iOS 模拟器完整教程 【免费下载链接】Madeira Run x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT 项目地址: https://gitcode.com/GitHub_Trending/mad/Madeira Madeira 是一款跑在未越…

2026/10/21 1:55:36 阅读更多 →
wifit3 WPA 握手嗅探:5 个蹲守窗口,几分钟抓下 4-way

wifit3 WPA 握手嗅探:5 个蹲守窗口,几分钟抓下 4-way

wifit3 WPA 握手嗅探:5 个蹲守窗口,几分钟抓下 4-way 【免费下载链接】wifit3 Wifite but USB-only & cross-platform. 项目地址: https://gitcode.com/GitHub_Trending/wi/wifit3 wifit3 是一款 USB 网卡审计工具,WPA 握手嗅探是它的默认常驻状态。蹲一…

2026/10/21 1:55:36 阅读更多 →
Docker网络完全指南:从命名空间、网桥到Overlay跨主机通信

Docker网络完全指南:从命名空间、网桥到Overlay跨主机通信

1. 为什么网络是容器化应用最容易翻车的地方先从一个非常典型的场景说起。某团队开发了一个微服务Demo,容器里跑着前端、后端、数据库三个进程,本地开发时一切正常。结果一到部署环境,前端服务就是连不上后端接口,后端日志里全是连…

2026/10/21 1:54:35 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →