platform总线设备实验

红色字体部分与一般字符设备创建,提供应用层面的接口有关。

黑色字体部分则是 platform总线设备相关

内核版本为 4.x


上面是一个platform总线的设备,关于led的一个驱动程序。

大概结构就是通过总线,设备,驱动的设备驱动模型来管理设备,然后再通过字符设备创建的过程来向应用层提供接口,不知道这样做是否有点罗索与重复,但是目前的理解就是还不太到家。

通过probe函数实现应用层接口

remove可以用来取消应用层接口


然后还有使用goto的优点,假如在driver注册失败,那么你不仅要注销driver还要注销device,这个时候用goto就可以很清晰的而且使代码不产生冗余的情况下完成这份工作。


大致的原理是:

在Device添加的函数里面会调用与Driver和Bus相匹配的函数 例如Probe与 Match等。

由此联想到热插拔的可实现的方案(当然只是猜想 不过应该是可行的):

一个模块负责 时刻检测底层的I/O的改变以确定是否有设备加入,这时候这个模块就需要探测这个设备的属性,完成设备注册。这个应该是最底层驱动,负责将设备接入内核,添加Kobject(Device)

在Kobject的添加或者说注册的函数中就会调用一些函数(uevent之类的)来告诉用户有新设备插入,这个时候filter什么的就可以截获并决定是否告诉用户新设备是否插入,以此便实现了热插拔。

所以Bus与Driver就是负责了这个层面的一些事项,而cdev的添加是为了统一文件系统的接口,实现上层应用的调用。

贴上源代码 ( 做了什么事情呢?主要是统一了设备驱动中 上层与下层 的设备模型 ):


#include <linux/module.h>

#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/fs.h>


MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Anfo");

void pfDev_release(struct device* dev){

}

struct resource pfDev_resource={
    .start=(resource_size_t)0x7F008800,
    .end=(resource_size_t)0x7F00880C,
    .flags=IORESOURCE_MEM,
};

struct platform_device pfDev={
    .name="s3c6410_led",
    .id=-1,//auto allocated
    .num_resources=1,
    .resource=&pfDev_resource,
    .dev={
        .release=pfDev_release,
    },
};

/*
    ----------------------------------------------------------
    app led
*/
#define LED_NAME "led"
#define LED_MAJOR 120
#define LED_MINOR 0
#define LED_DEVT MKDEV(LED_MAJOR,LED_MINOR)

static int led_open(struct inode* ind,struct file* filp){
    return 0;
}

static int led_release(struct inode* ind,struct file* filp){
    return 0;
}

struct file_operations led_fops={
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_release,
};
struct class* led_class;
int pfDrv_probe(struct platform_device* pdev){
    //register the led to app
    //register the device num
    if(register_chrdev(LED_MAJOR,LED_NAME,&led_fops))
    {
        printk("----register_chrdev error!\n");
        goto register_chrdev_error;
    }
    printk("----register_chrdev success\n");
    led_class=class_create(THIS_MODULE,LED_NAME);
    if(IS_ERR(led_class))
    {
        printk("----class_create error!\n");
        goto class_create_error;        
    }
    printk("----class_create success\n");
    device_create(led_class,NULL,LED_DEVT,NULL,LED_NAME);//return struct device*
    printk("----device_create success\n");
    
    //
    printk("pfDrv_probe success\n");
    return 0;
class_create_error:
    class_destroy(led_class);
register_chrdev_error:
    unregister_chrdev(LED_MAJOR,LED_NAME);
    return -1;
}
int pfDrv_remove(struct platform_device* pdev){
    unregister_chrdev(LED_MAJOR,LED_NAME);
    printk("----unregister_chrdev success!\n");

    device_destroy(led_class,LED_DEVT);
    printk("----device_destroy success\n");
    
    class_destroy(led_class);
    printk("----class_destroy success\n");
    printk("pfDrv_remove success\n");
    return 0;
}

/*------------------------------------------------------*/
struct platform_driver pfDrv={
    .probe=pfDrv_probe,
    .remove=pfDrv_remove,
    .driver={
        .name="s3c6410_led",
        .owner=THIS_MODULE,
    },
};

int __init PfDevMod_init(void){
    printk("PfDevMod_init begin\n");
    if(platform_device_register(&pfDev))
    {
        printk("platform_device_register error!\n");
        goto device_register_error;
    }
    printk("platform_device_register success!\n");
    if(platform_driver_register(&pfDrv))
    {
        printk("platform_driver_register error!\n");
        goto driver_register_error;
    }
    printk("platform_driver_register success!\n");
    suc:
    return 0;
driver_register_error:
    platform_driver_unregister(&pfDrv);
device_register_error:
    platform_device_unregister(&pfDev);
    return -1;
}

void __exit PfDevMod_exit(void){
    printk("PfDevMod_exit begin\n");
    platform_device_unregister(&pfDev);
    printk("platform_device_unregister success!\n");
    platform_driver_unregister(&pfDrv);
    printk("platform_driver_unregister success!\n");
}

module_init(PfDevMod_init);
module_exit(PfDevMod_exit) ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值