bus, device, driver之间是怎么一回事,继续

分类: LINUX

继续上一篇。整理虚拟总线的代码部分:
   1.将挂在总线上的设备及驱动的数据各定义成一个结构体;
   2.将设备及驱动的注册,注销部分各自模块化并导出;
   3.初始化match函数指针。

下面是虚拟总线的代码:

#include <linux/module.h>
#include <linux/init.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/io.h>

#include "bus.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zl");

int zl_match(struct device * dev, struct device_driver * drv);

struct bus_type zl_bus = {
    .name = "zlbus",
    .match = zl_match,
};

int zl_device_register(struct zl_device *dev)
{
    dev->dev.bus = &zl_bus;    
    //strcpy(dev->dev.bus_id, dev->name); //2.6.13

    dev->dev.init_name = dev->name; //2.6.36

    device_register(&dev->dev);
    return 0;
}
EXPORT_SYMBOL(zl_device_register);

int zl_device_unregister(struct zl_device *dev)
{
    device_unregister(&dev->dev);
    return 0;
}
EXPORT_SYMBOL(zl_device_unregister);

int zl_driver_register(struct zl_driver *drv)
{
    drv->drv.bus = &zl_bus;

    driver_register(&drv->drv);
    return 0;
}
EXPORT_SYMBOL(zl_driver_register);

int zl_driver_unregister(struct zl_driver *drv)
{
    driver_unregister(&drv->drv);
    return 0;
}
EXPORT_SYMBOL(zl_driver_unregister);

//------------------------------------------
int zl_match(struct device * dev, struct device_driver * drv)
{
    struct zl_device *zldev;
    struct zl_driver *zldrv;

    printk("zl_match.\n");

    zldev = container_of(dev, struct zl_device, dev);
    zldrv = container_of(drv, struct zl_driver, drv);
    
    if ((zldev->idVendor == zldrv->idVendor) && (zldev->idProduct == zldrv->idProduct)) {
        return 1;
    }
    return 0;
}

int test_init(void)
{
    int ret = 0;

    bus_register(&zl_bus);

    return ret;
}

void test_exit(void)
{
    bus_unregister(&zl_bus);
}

module_init(test_init);
module_exit(test_exit);

其中的match函数在插入设备或驱动模块时会执行。具体是比较两组数字,一般是厂商及其产品代号。若能匹配,说明设备和相应驱动对上号了,这时会执行驱动代码中的probe指向的函数。

相应头文件:

#ifndef _BUS_Header_
#define _BUS_Header_

#include <linux/device.h>

struct zl_device {
    int idVendor, idProduct; 

    unsigned long phys;
    int irq;
    char *name;

    struct device dev;
};

struct zl_driver {
    int idVendor, idProduct;

    struct device_driver drv;
};

int zl_device_register(struct zl_device *dev);
int zl_device_unregister(struct zl_device *dev);
int zl_driver_register(struct zl_driver *drv);
int zl_driver_unregister(struct zl_driver *drv);

#endif /* _BUS_Header_ */



接在zl_bus虚拟总线下的一个设备的代码也有变化,下面是相应代码:

#include <linux/module.h>
#include <linux/init.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <asm/io.h>

#include "bus.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zl");

void zl_device_release(struct device * dev)
{
    printk("device release.\n");
}

struct zl_device zl_device_struct = { 
    .idVendor = 0x1234,
    .idProduct = 0x5678,

    .name = "zldevice",
    .dev = { 
        .release = zl_device_release,
    }, 
};

int test_init(void)
{
    int ret = 0;

    zl_device_register(&zl_device_struct);
    
    return ret;
}

void test_exit(void)
{
    zl_device_unregister(&zl_device_struct);
}

module_init(test_init);
module_exit(test_exit);


下面是接在zl_bus虚拟总线下的驱动的代码:

#include <linux/module.h>
#include <linux/init.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/device.h>

#include "bus.h"

#include <asm/io.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zl");

int zl_probe(struct device * dev)
{
    printk("driver probe.\n");

    return 0;
}

int zl_remove(struct device * dev)
{
    printk("driver remove.\n");
    return 0;
}

struct zl_driver zl_driver_struct = {
    .idVendor = 0x1234,
    .idProduct = 0x5678,

    .drv = {    
        .name = "zldevice",

        .probe = zl_probe,
        .remove = zl_remove,
    },
};

int test_init(void)
{
    int ret = 0;

    zl_driver_register(&zl_driver_struct);
    return ret;
}

void test_exit(void)
{
    zl_driver_unregister(&zl_driver_struct);
}

module_init(test_init);
module_exit(test_exit);

match指向的函数如果返回1,表明设备驱动对上号了,就会执行probe指向的函数,进行设备正常工作必要的初始化动作。remove指向的函数与probe函数执行相反的动作。

插入以上三个模块后,
    1.在/sys/bus/zlbus/drivers目录下有zldriver生成
    2.在/sys/bus/zlbus/device目录下有zldevice生成
在match函数返回1的情况下:
    a./sys/bus/zlbus/drivers/zldriver下有driver,其中有zldevice
    b./sys/bus/zlbus/devices/zldevice下有device,其中有zldriver
     即设备与驱动匹配成功。
若match函数返回0,则上述a,b不成立。

回到上一篇中,没有初始化match函数指针。也有上述a,b的情况发生
     即同一总线上的设备与驱动在没有match的情况下默认是匹配成功的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值