您的位置:首页 > 其它

内核设备驱动API之device_add

2018-03-21 11:05 176 查看
int device_add(struct device *dev)用于添加一个设备到linux的设备数
其源码分析如下:
int device_add(struct device *dev)
{
struct device *parent;
struct kobject *kobj;
struct class_interface *class_intf;
int error = -EINVAL;
struct kobject *glue_dir = NULL;
#得到这个设备
dev = get_device(dev);
if (!dev)
goto done;
#检查设备是否有私有的初始化函数
if (!dev->p) {
error = device_private_init(dev);
if (error)
goto done;
}

/*
* for statically allocated devices, which should all be converted
* some day, we need to initialize the name. We prevent reading back
* the name, and force the use of dev_name()
*/
#设置device的name 我们平时通过cat 看到的device的name就是在这里设定的
if (dev->init_name) {
dev_set_name(dev, "%s", dev->init_name);
dev->init_name = NULL;
}

/* subsystems can specify simple device enumeration */
#如果没有指定device的init_name 就用bus 中的dev_name和dev id来组成device name
if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
#如果前两部都没有成功设置device name则退出
if (!dev_name(dev)) {
error = -EINVAL;
goto name_error;
}
#通过dmesg 可以看到下面打印出的name
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
#获得这个设备的父设备
parent = get_device(dev->parent);
kobj = get_device_parent(dev, parent);
if (kobj)
dev->kobj.parent = kobj;

/* use parent numa_node */
#子设备会复用父设备的numa 节点
if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
set_dev_node(dev, dev_to_node(parent));

/* first, register with generic layer. */
/* we require the name to be set before, and pass NULL */
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
if (error) {
glue_dir = get_glue_dir(dev);
goto Error;
}

/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
#新建attr_uevent
error = device_create_file(dev, &dev_attr_uevent);
if (error)
goto attrError;
#建立symbol link
error = device_add_class_symlinks(dev);
if (error)
goto SymlinkError;
#添加attr
error = device_add_attrs(dev);
if (error)
goto AttrsError;
#在bus中添加这个device
error = bus_add_device(dev);
if (error)
goto BusError;
#在power manager中增加这个设备
error = dpm_sysfs_add(dev);
if (error)
goto DPMError;
device_pm_add(dev);
#在sys中增加入口
if (MAJOR(dev->devt)) {
error = device_create_file(dev, &dev_attr_dev);
if (error)
goto DevAttrError;

error = device_create_sys_dev_entry(dev);
if (error)
goto SysEntryError;

devtmpfs_create_node(dev);
}

/* Notify clients of device addition.  This call must come
* after dpm_sysfs_add() and before kobject_uevent().
*/
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
#向user space 发送uevent 命令
kobject_uevent(&dev->kobj, KOBJ_ADD);
#开始bus的probe 过程
bus_probe_device(dev);
#如果这个设备有父设备,则将这个device 添加到父设备的klist中
if (parent)
klist_add_tail(&dev->p->knode_parent,
&parent->p->klist_children);
#如果这个device属于某个class,也添加到父设备的对应的class 对应klist中
if (dev->class) {
mutex_lock(&dev->class->p->mutex);
/* tie the class to the device */
klist_add_tail(&dev->knode_class,
&dev->class->p->klist_devices);

/* notify any interfaces that the device is here */
list_for_each_entry(class_intf,
&dev->class->p->interfaces, node)
if (class_intf->add_dev)
class_intf->add_dev(dev, class_intf);
mutex_unlock(&dev->class->p->mutex);
}
done:
put_device(dev);
return error;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: