Linux下面一个简单的虚拟platform驱动
2011-12-13 15:36
387 查看
/*
* Yao.GUET
* http://blog.csdn.net/Yao_GUET
* Linux下面一个简单的虚拟platform驱动
*/
在Linux之中,约定如果设备不属于任何的总线,则可以把它注册为虚拟的platform设备。
下面就简单来学习一下一个简单的platform设备是怎么创建出来的。
一般注册platform驱动的步骤是:
1,platform_device_create注册一个设备
2,platform_driver_create注册一个驱动。
static struct platform_driver chrdev_platform_driver = {
.probe = chrdev_probe,
.remove = chrdev_remove,
.driver = {
.name = CHRDEV_NAME,
.owner = THIS_MODULE,
},
};
static struct platform_device chrdev_platform_device = {
.name = CHRDEV_NAME,
.id = 0,
.dev = {
}
};
platform_device和platform_driver的名字必须一致
然后在chrdev_probe中完成注册一个字符设备。一般注册字符设备的流程如下:
1,alloc_chrdev_region分配一个未使用的设备号
2,cdev_init和cdev_add使用(1)分配到的设备号添加一个字符设备
如果到这里就结束了,我们就需要使用分配到的设备号手动去建立/dev下面的设备节点,,,
在这里可以使用class_create和device_create让udev deamon自动为我们创建设备节点
3,class_create(THIS_MODULE, "chrdev");
4,device_create(chrdev_class, NULL, chrdev_devno, NULL, "chrdev");
当使用insmod把模块加载到系统之后,就会在/dev下面自动创建名为"chrdev"的设备节点,模块名字应该尽量跟注册驱动的名字一致,不然可能会遇到不可测的问题。
源文件:chrdev.c
Makefile:
* Yao.GUET
* http://blog.csdn.net/Yao_GUET
* Linux下面一个简单的虚拟platform驱动
*/
在Linux之中,约定如果设备不属于任何的总线,则可以把它注册为虚拟的platform设备。
下面就简单来学习一下一个简单的platform设备是怎么创建出来的。
一般注册platform驱动的步骤是:
1,platform_device_create注册一个设备
2,platform_driver_create注册一个驱动。
static struct platform_driver chrdev_platform_driver = {
.probe = chrdev_probe,
.remove = chrdev_remove,
.driver = {
.name = CHRDEV_NAME,
.owner = THIS_MODULE,
},
};
static struct platform_device chrdev_platform_device = {
.name = CHRDEV_NAME,
.id = 0,
.dev = {
}
};
platform_device和platform_driver的名字必须一致
然后在chrdev_probe中完成注册一个字符设备。一般注册字符设备的流程如下:
1,alloc_chrdev_region分配一个未使用的设备号
2,cdev_init和cdev_add使用(1)分配到的设备号添加一个字符设备
如果到这里就结束了,我们就需要使用分配到的设备号手动去建立/dev下面的设备节点,,,
在这里可以使用class_create和device_create让udev deamon自动为我们创建设备节点
3,class_create(THIS_MODULE, "chrdev");
4,device_create(chrdev_class, NULL, chrdev_devno, NULL, "chrdev");
当使用insmod把模块加载到系统之后,就会在/dev下面自动创建名为"chrdev"的设备节点,模块名字应该尽量跟注册驱动的名字一致,不然可能会遇到不可测的问题。
源文件:chrdev.c
#include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/cdev.h> #include <linux/fs.h> //////////////////////////////////////////////////////////////////////////////// /* * Yao.GUET * http://blog.csdn.net/Yao_GUET * a simple platform character driver */ //////////////////////////////////////////////////////////////////////////////// MODULE_LICENSE("Dual BSD/GPL"); //////////////////////////////////////////////////////////////////////////////// static int chrdev_open(struct inode *inode, struct file *file) { printk(KERN_ALERT "chrdev open!\n"); return 0; } static int chrdev_release(struct inode *inode, struct file *file) { printk(KERN_ALERT "chrdev release!\n"); return 0; } static int chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { printk(KERN_ALERT "chrdev release!\n"); return 0; } // Kernel interface static struct file_operations chrdev_fops = { .owner = THIS_MODULE, .ioctl = chrdev_ioctl, .open = chrdev_open, .release = chrdev_release, }; #define CHRDEV_NAME "chrdev" // driver interface static struct class *chrdev_class = NULL; static struct device *chrdev_device = NULL; static dev_t chrdev_devno; static struct cdev chrdev_cdev; static int chrdev_probe(struct platform_device *dev) { int ret = 0, err = 0; printk(KERN_ALERT "chrdev probe!\n"); // alloc character device number ret = alloc_chrdev_region(&chrdev_devno, 0, 1, CHRDEV_NAME); if (ret) { printk(KERN_ALERT " alloc_chrdev_region failed!\n"); goto PROBE_ERR; } printk(KERN_ALERT " major:%d minor:%d\n", MAJOR(chrdev_devno), MINOR(chrdev_devno)); cdev_init(&chrdev_cdev, &chrdev_fops); chrdev_cdev.owner = THIS_MODULE; // add a character device err = cdev_add(&chrdev_cdev, chrdev_devno, 1); if (err) { printk(KERN_ALERT " cdev_add failed!\n"); goto PROBE_ERR; } // create the device class chrdev_class = class_create(THIS_MODULE, CHRDEV_NAME); if (IS_ERR(chrdev_class)) { printk(KERN_ALERT " class_create failed!\n"); goto PROBE_ERR; } // create the device node in /dev chrdev_device = device_create(chrdev_class, NULL, chrdev_devno, NULL, CHRDEV_NAME); if (NULL == chrdev_device) { printk(KERN_ALERT " device_create failed!\n"); goto PROBE_ERR; } printk(KERN_ALERT " chrdev probe ok!\n"); return 0; PROBE_ERR: if (err) cdev_del(&chrdev_cdev); if (ret) unregister_chrdev_region(chrdev_devno, 1); return -1; } static int chrdev_remove (struct platform_device *dev) { printk(KERN_ALERT " chrdev remove!\n"); cdev_del(&chrdev_cdev); unregister_chrdev_region(chrdev_devno, 1); device_destroy(chrdev_class, chrdev_devno); class_destroy(chrdev_class); return 0; } // platform_device and platform_driver must has a same name! // or it will not work normally static struct platform_driver chrdev_platform_driver = { .probe = chrdev_probe, .remove = chrdev_remove, .driver = { .name = CHRDEV_NAME, .owner = THIS_MODULE, }, }; static struct platform_device chrdev_platform_device = { .name = CHRDEV_NAME, .id = 0, .dev = { } }; static __init int chrdev_init(void) { int ret = 0; printk(KERN_ALERT "chrdev init!\n"); ret = platform_device_register(&chrdev_platform_device); if (ret) { printk(KERN_ALERT " platform_device_register failed!\n"); return ret; } ret = platform_driver_register(&chrdev_platform_driver); if (ret) { printk(KERN_ALERT " platform_driver_register failed!\n"); return ret; } printk(KERN_ALERT " chrdev_init ok!\n"); return ret; } static __exit void chrdev_exit(void) { printk(KERN_ALERT "chrdev exit!\n"); platform_driver_unregister(&chrdev_platform_driver); } module_init(chrdev_init); module_exit(chrdev_exit);
Makefile:
### Makefile obj-m := chrdev.o KERNEL_DIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
相关文章推荐
- Linux下面一个简单的虚拟platform驱动
- [linux driver]驱动模型中为什么用一个虚拟的platform_bus/device?
- Linux下面一个简单的虚拟platform驱动
- Linux下面一个简单的虚拟platform驱动
- 如何写一个简单的linux驱动
- linux 一个简单的字符设备驱动例子
- 一个简单的linux系统下的5*5的键盘驱动
- Ubuntu下面的一个简单的C++程序——My first C++ demo in Linux
- Linux总线驱动-01: 一个简单的示例
- 一个简单的Linux驱动示例
- 编译和安装linux内核2.6.x,一个简单的内核驱动测试
- Linux 网卡驱动学习(一)(分析一个虚拟硬件的网络驱动例子)
- 一个简单的Linux驱动
- Linux驱动学习(编写一个最简单的模块)
- Linux 网卡驱动学习(一)(分析一个虚拟硬件的网络驱动样例)
- 一个最简单的Linux 2.6内核驱动模块
- Linux虚拟总线platform驱动框架之地址对齐省内存
- linux下面一个简单ps的实现
- Linux 网卡驱动学习(一)(分析一个虚拟硬件的网络驱动例子)
- 一个简单的Linux字符驱动