【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
相关推荐
HLC++9 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室10 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy12 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕13 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫14 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生14 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1116 小时前
linux基础IO
linux·运维·服务器
BelongPanda18 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯18 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983418 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器