N22 key驱动

一、platform自动匹配

  1. 定义一个 platform_driver,告诉内核:我是一个正规驱动
  2. 内核会自动去设备树里找匹配的硬件(compatible)
  3. 找到后自动调用 probe 函数
  4. probe 里:
    • 读取设备树地址
    • ioremap 映射寄存器
    • 注册 misc 设备
  5. 设备拔掉 → remove
  6. 驱动卸载 → 自动清理
  7. 应用层通过 /dev/led 控制亮灭

它是标准 Linux 驱动结构,内核统一管理。

内核自动匹配,只看 compatible,不关心路径。

这是 Linux 驱动最核心思想:驱动与设备分离。
copy_to_user:内核 → 用户

copy_from_user:用户 → 内核

cs 复制代码
字符串替换
:%s/led/key/g

二、key驱动(linux/of_irq.h)

cs 复制代码
#include <linux/init.h>
#include <linux/printk.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/export.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/of_irq.h>
#include <linux/wait.h>
#include <linux/sched.h>

#define DEV_NAME "key"
static unsigned int irq_key_num;
#define key_ON 0
#define key_OFF 1
static int arg = 100;
static wait_queue_head_t wq;
static int condition;

static irqreturn_t key_irq_handler(int dev_num, void * dev)
{
	condition = 1;
	wake_up_interruptible(&wq);
	printk("dev_num = %d  dev = %d\n", dev_num, *(int *)dev);
	return IRQ_HANDLED;
}

static int open(struct inode * node, struct file * file)
{
	printk("key  open...\n");
	return 0;
}

static ssize_t read(struct file * file, char __user * buf, size_t len, loff_t * offset)
{
	condition = 0;
	wait_event_interruptible(wq, condition);
	//copy_to_user();
	printk("key  read...\n");
	return 0;
}

static int close(struct inode * node, struct file * file)
{
	printk("key  close...\n");
	return 0;
}

static struct file_operations fops = 
{
	.owner = THIS_MODULE,
	.open = open,
	.read = read,
	.release = close
};

static struct miscdevice misc = 
{
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEV_NAME,
	.fops = &fops
};

static int probe(struct platform_device * pdev)
{
	struct device_node * pnode;

	int ret = misc_register(&misc);
	if(IS_ERR_VALUE(ret))
		goto err_misc;

	pnode = of_find_node_by_path("/pt_key");
	if(IS_ERR(pnode))
	{
		ret = PTR_ERR(pnode);
		goto err_find_node;
	}

	irq_key_num = irq_of_parse_and_map(pnode, 0);
	if(irq_key_num < 0)
	{
		ret = irq_key_num;
		goto err_of_parse;
	}

	ret = request_irq(irq_key_num, key_irq_handler, IRQF_TRIGGER_FALLING, "key_irq", &arg);
	if(ret < 0)
		goto err_request_irq;

	init_waitqueue_head(&wq);

    printk("probe   key misc_register    ##############\n");
    return 0;

err_request_irq:
	disable_irq(irq_key_num);
	free_irq(irq_key_num, &arg);
	printk("key err_request_irq\n");
err_of_parse:
	printk("key err_of_parse\n");
err_find_node:
	printk("of_find_node_by_path  err\n");
err_misc:
	printk("key  probe faikey  ret = %d\n", ret);
	misc_deregister(&misc);
	return ret;
}

static int remove(struct platform_device * pdev)
{
	disable_irq(irq_key_num);
	free_irq(irq_key_num, &arg);
	misc_deregister(&misc);
    printk("remove  key misc_deregister    ##############\n");

	return 0;
}
	
static const struct of_device_id match_table[] = 
{
	[0] = {.compatible = "pt-key"}
};

static struct platform_driver drv = 
{
	.probe = probe,
	.remove = remove,
	.driver = 
	{
		.name = DEV_NAME,
		.of_match_table = match_table
	}
};

static int __init key1_init(void)
{
	int ret = platform_driver_register(&drv);
	if(ret < 0)
		goto err_reg;

	printk("platform_driver_register  ...\n");
	return 0;

err_reg:
	printk("platform_driver_register  faikey ret = %d\n", ret);
	platform_driver_unregister(&drv);
	return ret;
}

static void __exit key1_exit(void)
{
	platform_driver_unregister(&drv);
	printk("platform_driver_unregister  ...\n");
}

module_init(key1_init);
module_exit(key1_exit);
MODULE_LICENSE("GPL");
相关推荐
xiami_world10 小时前
私有化部署协同白板选型指南:从Docker容器化到信创全栈适配的架构实践
运维·人工智能·docker·ai·持续部署
weixin_3077791310 小时前
从脚本执行到智能体协作:AI辅助测试能力的范式重构
运维·开发语言·人工智能·算法·测试用例
Yiyaoshujuku10 小时前
化学谱图数据API接口,数据字段一览!
linux·服务器·前端
__Witheart__10 小时前
make menuconfig 使用全流程
linux·ubuntu·rockchip
2601_9516457810 小时前
Linux 编程语言全解析:C、C++、Python、Go、Rust 谁更强?
linux·python·go·c·编程语言
阿坤带你走近大数据11 小时前
Linux中管道符的作用
java·linux·服务器
Fcy64811 小时前
Linux下 进程信号初识和信号的产生
linux·运维·信号的产生
爱装代码的小瓶子11 小时前
安工大Linux考点分类真题解析(含知识点是试卷原题了)
linux·服务器·网络·c
hweiyu0011 小时前
Linux命令:sudoedit
linux·运维·服务器
qq_1631357511 小时前
Linux 【03-nl命令超详细教程】
linux