【Linux驱动】Linux 按键驱动开发指南

Linux 按键驱动开发指南

1、按键驱动开发基础

1.1. 按键驱动类型

Linux下的按键驱动主要有两种实现方式:

  • 输入子系统驱动:最常用,通过input子系统上报按键事件

  • 字符设备驱动:较少用,需要自己实现文件操作接口

1.2. 输入子系统框架

推荐使用input子系统实现按键驱动,主要组件:

  • input_register_device() - 注册输入设备

  • input_report_key() - 上报按键事件

  • input_sync() - 同步事件

2、设备树配置

2.1. 基本按键节点配置

复制代码
/ {
    gpio-keys {
        compatible = "gpio-keys";
        #address-cells = <1>;
        #size-cells = <0>;
        
        button@1 {
            label = "Power Button";
            linux,code = <KEY_POWER>;  // 按键编码,定义在include/uapi/linux/input-event-codes.h
            gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; // 使用的GPIO,低电平有效
            debounce-interval = <20>;  // 消抖时间(ms)
        };
    };
};

【linux驱动】【设备树】按键设备树讲解

2.2. 关键属性说明

  • compatible: 必须包含"gpio-keys"
  • linux,code: 按键键值,如KEY_POWER、KEY_VOLUMEUP等
  • gpios: 指定GPIO控制器、引脚和有效电平
  • debounce-interval: 硬件消抖时间

3、驱动代码实现

3.1. 基本驱动框架

c 复制代码
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>

struct gpio_key_data {
    struct gpio_desc *gpiod;
    int code;
    int irq;
};

struct gpio_key_drvdata {
    struct input_dev *input;
    struct gpio_key_data *data;
    int n_buttons;
};

static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
    struct gpio_key_data *key_data = dev_id;
    struct gpio_key_drvdata *ddata = container_of(key_data, struct gpio_key_drvdata, data);
    int state = gpiod_get_value(key_data->gpiod);
    
    input_report_key(ddata->input, key_data->code, !state);
    input_sync(ddata->input);
    
    return IRQ_HANDLED;
}

static int gpio_key_probe(struct platform_device *pdev)
{
    // 驱动初始化代码
    // 1. 分配input设备
    // 2. 解析设备树获取按键信息
    // 3. 申请GPIO和中断
    // 4. 注册input设备
    // ...
}

static const struct of_device_id gpio_key_of_match[] = {
    { .compatible = "gpio-keys", },
    { },
};
MODULE_DEVICE_TABLE(of, gpio_key_of_match);

static struct platform_driver gpio_key_driver = {
    .probe = gpio_key_probe,
    .driver = {
        .name = "gpio-keys",
        .of_match_table = gpio_key_of_match,
    },
};
module_platform_driver(gpio_key_driver);

4、应用层使用按键驱动

4.1. 通过input子系统访问

按键驱动注册后会在/dev/input/下生成设备节点,如event0

4.2. 读取按键事件示例代码

c 复制代码
#include <stdio.h>
#include <linux/input.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    int fd = open("/dev/input/event0", O_RDONLY);
    struct input_event ev;
    
    while(1) {
        read(fd, &ev, sizeof(ev));
        if(ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2) {
            printf("Key %d %s\n", ev.code, 
                  ev.value ? "pressed" : "released");
        }
    }
    
    close(fd);
    return 0;
}

4.3. 使用工具测试

  • evtest: 通用输入设备测试工具
  • cat /proc/bus/input/devices: 查看已注册的输入设备

5、调试与问题排查

5.1 检查设备树是否正确加载:

powershell 复制代码
ls /proc/device-tree/gpio-keys/

5.2 查看GPIO状态:

powershell 复制代码
cat /sys/kernel/debug/gpio

5.3 检查中断是否注册:

powershell 复制代码
cat /proc/interrupts

5.4 查看input设备信息:

powershell 复制代码
cat /proc/bus/input/devices
相关推荐
Escalating_xu几秒前
【Linux mmap 文件映射】从虚拟地址到页缓存:读写文件、匿名映射与极简 malloc
linux·缓存
Zixhy7 分钟前
Boost 库实现异步高并发服务器
linux·服务器·c++
阿明69 分钟前
基础编辑工具使用【Linux】
linux·运维·服务器
Tinyundg9 分钟前
关于Termux的基本使用——安卓手机爆改Linux服务器?
linux·运维·服务器·智能手机·个人开发
鱼很腾apoc23 分钟前
【Linux】第15期 讲解IP网络层核心原理与机制
linux·服务器·网络协议·学习·tcp/ip·ip·网络层
zx_7414848126 分钟前
【Linux入门】常用基本命令(一)——帮助、文件目录操作、时间日期与用户组管理
linux·服务器
AutumnWind042038 分钟前
【Shell 知识速查表】
linux
风哥2号44 分钟前
数据库教程FGMT04‑生产环境Linux+Oracle19c RAC集群安装配置与项目实战
linux·数据库
qetfw1 小时前
Debian Postfix + Dovecot 基础配置:DNS、Maildir、IMAP 与邮件队列验证
linux·服务器·网络·debian
吴声子夜歌1 小时前
Shell脚本——数组
linux·运维·shell