andorid 探测总线设备驱动

__bus_register() //  register a driver-core subsystem

        1)  首先不管是设备还是驱动,都是挂接在某条总线上的,也就是说我们根据总线类型的不同来区分各种设备和驱动。
        2) 从总线注册函数bus_register(struct bus_type *bus)中可以发现,首先申请了一个subsys_private结构体内存。该结构体中包含了三个kset结构,分别是struct kset subsys、struct kset *devices_kset和struct kset *drivers_kset。
        3) subsys是用来向上链接的。
        4) 当发现一个设备或者驱动的时候,对于每一次设备或者驱动注册(设备是被插入了,驱动就是.ko模块被加载),都得分配一个device或者device_drive结构,每一次都需要将device结构挂入drivers或devices(kset结构)链表中,这样才能通过总线找到挂接在这个总线上的所有设备和驱动。这里仅仅将设备和驱动挂接在总线上,并不能表明设备和驱动之间的关系,这样的处理仅仅表明了驱动、设备与总线的关系,它们申明了我现在挂接在这条总线上,以后操作我就通过这条总线。
        5) 总线的目录名为”usb”。也就是说在/sys/bus目录下有一个usb目录,即/sys/bus/usb。内核中有usb总线驱动,__bus_register()就是用来注册总线的,该函数调用完成后,就会在/sys/bus/目录下创建usb目录。


/**********************************************************
/
/
android 探测设备   流程
在kernel/drivers/usb/gadget/android.c 中,
module_init(init)

1, int __init init(void)
{
    INIT_LIST_HEAD(&android_dev_list); //初始化android设备表
    android_dev_count = 0;

    ret = platform_driver_register(&android_platform_driver);

    //static struct platform_driver android_platform_driver = {
    //    .driver = { .name = "android_usb"},
    //    .probe = android_probe,        
    //    .remove = android_remove,
    //    .id_table = android_id_table,
    //};
    
}

2, platform_driver_register(struct platform_driver *drv)

    drv->driver.bus = &platform_bus_type;
    // 在platform_bus_type中,定义了 .match    = platform_match,而这个函数会在匹配设备时调用
    if (drv->probe)
        drv->driver.probe = platform_drv_probe;//在探测到设备时先调用drv->driver.probe,然后再调用 (1  函数中的).probe  
     driver_register(&drv->driver);

    /******************

        1) driver_register()完成挂接驱动至总线及生成设备树的过程。
        2) 首先调用driver_find()函数在总线上查找该驱动是否已经存在,如果存在,退出。
        3) 如果该驱动在总线上不存在,调用bus_add_driver(drv)增加该驱动。
        4) 调用driver_add_groups(drv, drv->groups)函数增加驱动组。

    *******************/

3,int driver_register(struct device_driver *drv)
{
    int ret;
    struct device_driver *other;

    BUG_ON(!drv->bus->p);

    if ((drv->bus->probe && drv->probe) ||   //driver和bus的同名操作函数如果同时存在,会出现警告
        (drv->bus->remove && drv->remove) ||   //并且会优先选用bus的
        (drv->bus->shutdown && drv->shutdown))
        printk(KERN_WARNING "Driver '%s' needs updating - please use "
            "bus_type methods\n", drv->name);

    other = driver_find(drv->name, drv->bus);  //进入bus的driver链表,确认该driver是否已经注册
// 会调用到kset_find_obj (),在函数中,会遍历kset->list ,比较kobject_name(kobject)和指定的name
    if (other) {
        put_driver(other);                //找到了再减少引用计数,并且报错退出
        printk(KERN_ERR "Error: Driver '%s' is already registered, "
            "aborting...\n", drv->name);
        return -EBUSY;
    }

    ret = bus_add_driver(drv); //如果没有注册,那么把该driver加入所在bus,并生成文件夹和链接
    if (ret)
        return ret;
    ret = driver_add_groups(drv, drv->groups);//添加attribute_group
    if (ret)
        bus_remove_driver(drv);
    return ret;
}

4,   int bus_add_driver(struct device_driver *drv)
{
    struct bus_type *bus;
    struct driver_private *priv;
    int error = 0;

    bus = bus_get(drv->bus); //取得其所在bus的指针经,增加对 bus 的引用

    priv = kzalloc(sizeof(*priv), GFP_KERNEL); //开始初始化这个driver的私有成员,这个结构体中存放着kobj相关的数据

    klist_init(&priv->klist_devices, NULL, NULL);//设备操作函数清空,设备链表初始化
    priv->driver = drv;// 反向指向包含其的 drv,以便后续使用
    drv->p = priv;        // 将 priv保存到 device_driver
    priv->kobj.kset = bus->p->drivers_kset;//kset指定到bus下面drivers_kset容器
    error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  "%s", drv->name);
    //建立一个kobject结构体,并初始化,将pri->kobj = &driver_ktype ,最终添加到层次结构和创建属性文件
    if (drv->bus->p->drivers_autoprobe) {//bus的自动匹配如果设置为真,
        error = driver_attach(drv);        //那么到bus的devices上去匹配设备
        if (error)
            goto out_unregister;
    }
    klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);//把driver挂接到bus的driver链表,方便后续快速查找 driver
    module_add_driver(drv->owner, drv);//将driver添加到module模块

    error = driver_create_file(drv, &driver_attr_uevent);//以下添加该driver相关属性文件

    error = driver_add_attrs(bus, drv);//添加 bus 的公有属性文件

    }
    /* 如果配置了”CONFIG_HOTPLUG",则生成“bind”和"unbind”属性文件,可用于手动匹
        配和移除 device与driver 之间的关联 */
    if (!drv->suppress_bind_attrs) {
        error = add_bind_files(drv);

    }

    kobject_uevent(&priv->kobj, KOBJ_ADD);// 通过 uevent 设置几个环境变量并通知用户空间,以便调用程序来完成相关设置
    return 0;

}

5, int driver_attach(struct device_driver *drv)
{
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}


 6,  int bus_for_each_dev(struct bus_type *bus, struct device *start,
             void *data, int (*fn)(struct device *, void *))
{
    struct klist_iter i;
    struct device *dev;
    int error = 0;

    klist_iter_init_node(&bus->p->klist_devices, &i,
                 (start ? &start->p->knode_bus : NULL));// 打开bus->p->klist_devices 链表,从第一个开始准备遍历
    while ((dev = next_device(&i)) && !error) //遍历每个klist->iter 节点,每遍历一个后就进行判断
        error = fn(dev, data); //调用__driver_attach 函数}
7, static int __driver_attach(struct device *dev, void *data)
{
    struct device_driver *drv = data;

    if (!driver_match_device(drv, dev))
    // 调用drv->bus->match(dev, drv),而这个函数指针在在platform_bus_type中,定义的
    //        .match    = platform_match, (见第2个函数)
    // 这个函数会优先判断platform_match_id(pdrv->id_table, pdev) != NULL  如果成立直接返回,    

    //否则会继续判断driver name 是否相等  strcmp(pdev->name, drv->name) == 0
    //如果id和name都不相等,说明这个设备不是我们所要找的,会return 0;继续 6函数中的    。  

     //while循环,直至找到设备或者不存在要找的设备。
        return 0;
    //当找到后,,,,,

    if (!dev->driver)
        driver_probe_device(drv, dev); //这个函数中会调用really_probe()

8,static int really_probe(struct device *dev, struct device_driver *drv)
{
    dev->driver = drv;
    if (driver_sysfs_add(dev))
    //驱动目录下建立一个到设备的同名链接,并且在设备目录下建立一个名为 driver.到驱动的链    接

    if (dev->bus->probe) {
        ret = dev->bus->probe(dev);
    } else if (drv->probe) {
        ret = drv->probe(dev); // 在 platform_driver_register函数中定义的(见 2)
        //  drv->probe =platform_drv_probe

     driver_bound(dev);//调用driver_bound进行绑定  
    }
 

9 ,static int platform_drv_probe(struct device *_dev)
{
    struct platform_driver *drv = to_platform_driver(_dev->driver);
    struct platform_device *dev = to_platform_device(_dev);

    return drv->probe(dev); //(见2)
    //调用android_probe
}



10,static int __devinit android_probe(struct platform_device *pdev)
{
    未完待续,,,,
}


本人新手,,欢迎指导,真诚感谢。。。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值