我的内核学习笔记3:我的platform驱动模板文件
来源:互联网 发布:mac pro display 编辑:程序博客网 时间:2024/05/17 09:03
前面的例子已经实现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_NAME foo_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;}// driverstatic 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驱动模板文件
- 我的内核学习笔记2:platform设备模型
- 我的内核学习笔记8:多功能设备mfd驱动
- 我的内核学习笔记:环境
- 我的内核学习笔记6:PCI驱动probe的一点认知
- 我的内核学习笔记7:Intel LPC驱动lpc_ich分析
- 我的内核学习笔记9:Intel内部看门狗iTCO_wdt驱动
- 我的内核学习笔记10:Intel GPIO驱动源码分析
- 我的内核学习笔记11:linux leds-gpio驱动应用实例
- 我的内核学习笔记12:linux i2c-gpio驱动应用实例
- 我的内核学习笔记4:sysfs学习
- 我的python学习笔记、写入文件
- 我的内核学习笔记5:proc目录文件创建及读写
- 我的学习内核历程
- 我的学习笔记
- 我的学习笔记
- 我的学习笔记
- 我的内核学习笔记1:字符设备完善
- C/C++ 结构体的一个高级特性 ―― 指定成员的位数
- 关于v$sql_bind_capture 的问题
- hibernate 3.x 常用查询语句
- jni开发 - 使用Memory Analyzer tool(MAT)分析内存泄漏(二)
- C++之 运算符重载
- 我的内核学习笔记3:我的platform驱动模板文件
- 年终复盘,我的2011
- 新浪微博客户端开发之adapter
- 【转载】开发者是如何提升技能水平的
- JSTL--functions及fmt函数的常用方法
- jquery的select美化
- JAVA策略模式(3)之解决具体遇到的一个问题
- Hibernate之使用insert into语句
- Maven之 Dependency & Repository