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)
{
未完待续,,,,
}
本人新手,,欢迎指导,真诚感谢。。。