【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
相关推荐
夜听莺儿鸣3 小时前
502-003_Linux 中断与异常(一):从Linux角度理解中断与异常
linux·中断与异常·linux中断
杨云龙UP3 小时前
TDengine 3.4.2.8 Community 三节点三副本生产集群部署实战(DNode/MNode/taosAdapter/Explorer)
大数据·linux·运维·数据库·tdengine·时序库
向成科技4 小时前
XC3576H工控主板|深度适配Ubuntu 26.04 LTS,释放边缘AI与工业开发新潜能
linux·人工智能·ubuntu·机器人·硬件·主板·边缘ai
Fcy6485 小时前
Linux下 进程间关系与守护进程
linux·运维·服务器·守护进程
码农小韩5 小时前
Linux驱动理论(二)——Linux字符设备驱动
linux·嵌入式软件开发·linux操作系统·linux应用开发·linux驱动理论
well06125 小时前
Linux粘滞位与Makefile机制深度解析
linux·运维·服务器
再写一行代码就下班6 小时前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
额额额对了6 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
子木HAPPY阳VIP6 小时前
Ubuntu 关闭防火墙操作步骤
linux·运维·ubuntu
王振超wzc6 小时前
嵌入式开发环境搭建--WM软件安装,Ubuntu操作系统安装
linux·运维·ubuntu