前面的例子已经实现platform驱动了,可以将之前的字符设备驱动整合到这个驱动中,实际上我也做了这一步。因为没有什么技术含量,所以忽视它的存在(就不发表出来)。这篇文章是将实现好的基于platform模型的字符设备驱动简化成一个可用的模板。如要实现字符设备,可直接套用此模板。

由于注释写得比较多,不再花笔墨作多余的事了。

/*** @file   foo_drv.c* @author Late Lee <latelee@163.com>* @date   Tue Nov 12 22:21:19 2013* * @brief  platform模型示例* * @note   基于platform模型的字符设备驱动示例,添加自动创建设备文件功能。此部分代码可在init时做,也可在probe中做。*/#include <linux/module.h>
#include <linux/kernel.h>       /**< printk() */
#include <linux/init.h>
#include <linux/platform_device.h>#include <linux/cdev.h>         /**< cdev_* */
#include <linux/fs.h>
#include <asm/uaccess.h>        /**< copy_*_user */#include <linux/types.h>        /**< size_t */
#include <linux/errno.h>        /**< error codes */
#include <linux/string.h>// 避免删掉模块时出现警告
static void foo_dev_release(struct device* dev)
{
//    printk(KERN_NOTICE "do %s case of: Device xxx does not have a release() function, it is broken and must be fixed.\n", __func__);return;
}// platform设备
static struct platform_device foo_device = {.name    = "foo",.id      = -1,.dev     = {//.platform_data = &foo_pdata,.release = &foo_dev_release,},
};#define DEBUG#ifdef DEBUG
/* KERN_INFO */
#define debug(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__)
#else
#define debug(fmt, ...)
#endif#define DEV_NAME "foo"// 指定设备号或自动创建设备号
//#define HAVE_MAJOR
#ifdef HAVE_MAJOR
#define DEVICE_MAJOR 248
#else
#define DEVICE_MAJOR 0
#endif#define FOO_NR_DEVS 1static struct cdev foo_cdev;
static int foo_major = DEVICE_MAJOR;
static int foo_minor = 0;
static int foo_nr_devs = FOO_NR_DEVS;
static dev_t foo_devno;
static struct class* foo_class;static int foo_open(struct inode *inode, struct file *filp)
{//debug("in %s()\n", __func__);//debug("%s() inode: 0x%08x\n", __func__, inode->i_rdev);return 0;
}// close时调用此函数
static int foo_release(struct inode *inode, struct file *filp)
{//debug("in %s()\n", __func__);return 0;
}static ssize_t foo_read(struct file *filp, char *buf, size_t count, loff_t *f_ops)
{int ret = 0;return ret;
}static ssize_t foo_write(struct file *filp, const char *buf, size_t count, loff_t *f_ops)
{int ret = 0;return ret;
}static int foo_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
// 2.6.36及以上版本使用下列函数
// static long foo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{return 0;
}static struct file_operations foo_fops = {.owner   = THIS_MODULE,.open    = foo_open,.release = foo_release,.read    = foo_read,.write   = foo_write,.ioctl   = foo_ioctl,
//2.6.36及以上版本使用下列接口
//    .unlocked_ioctl   = foo_ioctl,
};static int foo_remove(struct platform_device *dev)
{unregister_chrdev_region(foo_devno, 1);cdev_del(&foo_cdev);device_destroy(foo_class, foo_devno);class_destroy(foo_class);//printk(KERN_NOTICE "remove...\n");return 0;
}static int foo_probe(struct platform_device *dev)
{int ret = 0;// 初始化,关联文件操作结构体cdev_init(&foo_cdev, &foo_fops);foo_cdev.owner = THIS_MODULE;if (foo_major){foo_devno = MKDEV(foo_major, foo_minor);ret = register_chrdev_region(foo_devno, foo_nr_devs, DEV_NAME);}else{ret = alloc_chrdev_region(&foo_devno, foo_minor, foo_nr_devs, DEV_NAME); /* get devno */foo_major = MAJOR(foo_devno); /* get major */}if (ret < 0){dev_err(&foo_device.dev, "can't get major %d\n", foo_major);return -EINVAL;}ret = cdev_add(&foo_cdev, foo_devno, 1);if (ret < 0){dev_err(&foo_device.dev, "cdev_add failure!\n");return -EINVAL;}// 自动创建/dev下的节点,名称为DEV_NAMEfoo_class = class_create(THIS_MODULE, DEV_NAME);if (IS_ERR(foo_class)){dev_err(&foo_device.dev, "failed to create class.\n");return -EINVAL;}device_create(foo_class, NULL, foo_devno, NULL, DEV_NAME);dev_info(&foo_device.dev, "Register /dev/%s ok: major: %d minor: %d devno: 0x%08x\n", DEV_NAME, foo_major, foo_minor, foo_devno);return ret;
}// driver
static struct platform_driver foo_driver = {.probe        = foo_probe,.remove        = foo_remove,.driver        = {.name        = "foo",.owner        = THIS_MODULE,},
};static int __init foo_drv_init(void)
{int ret = 0;// 先注册设备(适用于静态定义设备结构体)ret = platform_device_register(&foo_device);if (ret){dev_err(&foo_device.dev, "platform_device_register failed!\n");return ret;}// 再注册驱动ret = platform_driver_register(&foo_driver);if (ret){dev_err(&foo_device.dev, "platform_driver_register failed!\n");return ret;}dev_info(&foo_device.dev, "Init %s OK!\n", DEV_NAME);return ret;
}static void __exit foo_drv_exit(void)
{// 先卸载驱动platform_driver_unregister(&foo_driver);// 再卸载设备platform_device_unregister(&foo_device);
}module_init(foo_drv_init);
module_exit(foo_drv_exit);MODULE_AUTHOR("Late Lee");
MODULE_DESCRIPTION("Simple platform driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:foo");

我的内核学习笔记3:我的platform驱动模板文件相关推荐

  1. 我的内核学习笔记7:Intel LPC驱动lpc_ich分析

    接触这么久的内核代码,还没有真正分析一个完整的驱动源码,都是零零散散写只言片字.本文就作一个尝试,写一写Linux内核源码分析层面的文章. 本文介绍基于Intel baytrail系列的e3800系列 ...

  2. 我的内核学习笔记12:linux i2c-gpio驱动应用实例

    linux内核的i2c-gpio是使用GPIO模拟I2C协议的驱动,只需要配置2根GPIO即可使用.Linux的I2C子系统比较复杂,笔者暂时还没有研究.本着"实用"的目的,介绍一 ...

  3. 我的内核学习笔记11:linux leds-gpio驱动应用实例

    linux内核的leds-gpio是使用GPIO控制LED的驱动,只要将板子上LED灯对接的GPIO引脚号进行适当的配置,就能使用这个驱动了,十分方便.网上有很多文章分析这个驱动,就不献丑--或者后面 ...

  4. 我的内核学习笔记10:Intel GPIO驱动源码分析

    本文对Intel e3800的GPIO驱动源码进行分析. 一.概述 1.1 内核配置 Intel e3800的GPIO在Linux内核中使用的驱动名为gpio_ich(为了行文方便,将对应的设备称为& ...

  5. Windows x64内核学习笔记(五)—— KPTI(未完待续)

    Windows x64内核学习笔记(五)-- KPTI(未完待续) KPTI 实验一:构造IDT后门并读取Cr3 参考资料 KPTI 描述:KPTI(Kernel page-table isolati ...

  6. Windows x64内核学习笔记(四)—— 9-9-9-9-12分页

    Windows x64内核学习笔记(四)-- 9-9-9-9-12分页 前言 9-9-9-9-12分页 实验一:线性地址转物理地址 页表基址 定位基址 PTE to PXE 实验二:通过页表基址定位各 ...

  7. Windows x64内核学习笔记(三)—— SMEP SMAP

    Windows x64内核学习笔记(三)-- SMEP & SMAP SMEP & SMAP 实验:构造IDT后门 第一步:编译以下代码 第二步:构造IDT后门 第三步:运行程序 第四 ...

  8. Windows x64内核学习笔记(一)—— 环境与配置

    Windows x64内核学习笔记(一)-- 环境与配置 前言 新特性 基础要求 实验环境 Guest Win10配置 问题解决 参考资料 前言 之前,跟着海哥学习了windows内核的一些机制,包括 ...

  9. 操作系统进程学习(Linux 内核学习笔记)

    操作系统进程学习(Linux 内核学习笔记) 进程优先级 并非所有进程都具有相同的重要性.除了大多数我们所熟悉的进程优先级之外,进程还有不同的关键度类别,以满足不同需求.首先进程比较粗糙的划分,进程可 ...

最新文章

  1. 安徽全国计算机缴费,全国计算机等级考试3月报名 安徽首次网上报名缴费
  2. 优化webpack配置
  3. 机器学习:基于关联规则的多标签分类器
  4. python培训中心-想学python,上海Python培训中心哪个好?
  5. linux -- ./configure --prefix 命令
  6. 规模估算失准 软件开发成空中楼阁
  7. 《魔鸟》:上帝可以宽恕,魔鬼却一个都不放过
  8. hibernate3.6.0日志配置
  9. (2)PCIE简介(学无止境)
  10. 判断服务器是虚拟机还是物理机方式
  11. 小米路由器安装Misstar tools 和MIXBOX
  12. 使用Python与Sharepoint进行交互——第1部分
  13. ios 字符加密问题 字符串加密gyb字符返回空
  14. w7测算计算机分级,win7游戏分级系统
  15. 【CRH】列车通过曲线时,曲线半径、超高值与车速的关系
  16. 海康、大华网络摄像机RTSP流接入流媒体实现WEB无插件直播通过视频广场观看实时直播
  17. ViT强势应用 | V2X基于ViT提出了一个具有V2X通信的强大协作感知框架
  18. 基于android的即时通讯APP 聊天APP
  19. 菜鸟学JAVA之——static关键字(静态属性和动态属性的区别)
  20. pytest 第一章 安装与执行用例

热门文章

  1. python变量赋值方式_python变量和变量赋值的几种形式
  2. 俞敏洪回应新东方股价跌破1美元
  3. 恒大集团:网传《关于召开全国恒大财富投资人大会通知》系伪造
  4. 谁给小鹏P5的勇气?
  5. 周一“开小差” 淘宝又崩了
  6. 苹果出来挨打!又一个不配充电器的来了
  7. 抖音起诉腾讯垄断 要求停止封禁并索赔9000万元
  8. 新款iPhone SE并未搭载U1超宽带芯片,后续恐不支持AirTag
  9. 阿里云面向制造业推出防疫复工数字化方案 复工效率提升50%以上
  10. iPhone 12“概念视频”曝光:被恶搞的太惨了