您的位置:首页 > 运维架构 > Linux

Linux下面一个简单的虚拟platform驱动

2016-03-17 14:21 519 查看
/* 
 * 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

[cpp] view
plain copy

#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:

[html] view
plain copy

### 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  

from: http://blog.csdn.net/yao_guet/article/details/7067068
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: