Android device 注册、添加、管理


注册:函数调用

以音频设备注册为例,音频声卡初始化

代码目录:kernel/sound/soc/xxxx.c

  1. static int __init audio_card_init(void)  
  2. {  
  3.     int ret =0;   
  4.     xxxx_snd_device = platform_device_alloc("soc-audio", -1);  
  5.     if (!xxxx_snd_device) {  
  6.           ret = -ENOMEM;  
  7.           return ret;  
  8.     }  
  9.     platform_set_drvdata(xxxx_snd_device, &xxxx_snd_devdata);  
  10.     xxxx_snd_devdata.dev = &xxxx_snd_device->dev;  
  11.     ret = platform_device_add(xxxx_snd_device);  
  12.     if (ret) {  
  13.         platform_device_put(rk2818_snd_device);  
  14.     }  
  15.     return ret;  
  16. }  

平台注册

代码目录:kernel/drivers/base/platform.c

  1. /** 
  2.  * platform_device_add - add a platform device to device hierarchy 
  3.  * @pdev: platform device we're adding 
  4.  * 
  5.  * This is part 2 of platform_device_register(), though may be called 
  6.  * separately _iff_ pdev was allocated by platform_device_alloc(). 
  7.  */  
  8. int platform_device_add(struct platform_device *pdev)  
  9. {  
  10.     int i, ret = 0;  
  11.   
  12.     if (!pdev)  
  13.         return -EINVAL;  
  14.   
  15.     if (!pdev->dev.parent)  
  16.         pdev->dev.parent = &platform_bus;  
  17.   
  18.     pdev->dev.bus = &platform_bus_type;  
  19.   
  20.     if (pdev->id != -1)  
  21.         dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);  
  22.     else  
  23.         dev_set_name(&pdev->dev, "%s", pdev->name);  
  24.   
  25.     for (i = 0; i < pdev->num_resources; i++) {  
  26.         struct resource *p, *r = &pdev->resource[i];  
  27.   
  28.         if (r->name == NULL)  
  29.             r->name = dev_name(&pdev->dev);  
  30.   
  31.         p = r->parent;  
  32.         if (!p) {  
  33.             if (resource_type(r) == IORESOURCE_MEM)  
  34.                 p = &iomem_resource;  
  35.             else if (resource_type(r) == IORESOURCE_IO)  
  36.                 p = &ioport_resource;  
  37.         }  
  38.   
  39.         if (p && insert_resource(p, r)) {  
  40.             printk(KERN_ERR  
  41.                    "%s: failed to claim resource %d\n",  
  42.                    dev_name(&pdev->dev), i);  
  43.             ret = -EBUSY;  
  44.             goto failed;  
  45.         }  
  46.     }  
  47.   
  48.     pr_debug("Registering platform device '%s'. Parent at %s\n",  
  49.          dev_name(&pdev->dev), dev_name(pdev->dev.parent));  
  50.   
  51.     ret = device_add(&pdev->dev);  
  52.     if (ret == 0)  
  53.         return ret;  
  54.   
  55.  failed:  
  56.     while (--i >= 0) {  
  57.         struct resource *r = &pdev->resource[i];  
  58.         unsigned long type = resource_type(r);  
  59.   
  60.         if (type == IORESOURCE_MEM || type == IORESOURCE_IO)  
  61.             release_resource(r);  
  62.     }  
  63.   
  64.     return ret;  
  65. }  
  66. EXPORT_SYMBOL_GPL(platform_device_add);  

设备添加 www.bkjia.com

代码目录:kernel/drivers/base/core.c

  1. /** 
  2.  * device_add - add device to device hierarchy. 
  3.  * @dev: device. 
  4.  * 
  5.  * This is part 2 of device_register(), though may be called 
  6.  * separately _iff_ device_initialize() has been called separately. 
  7.  * 
  8.  * This adds @dev to the kobject hierarchy via kobject_add(), adds it 
  9.  * to the global and sibling lists for the device, then 
  10.  * adds it to the other relevant subsystems of the driver model. 
  11.  * 
  12.  * NOTE: _Never_ directly free @dev after calling this function, even 
  13.  * if it returned an error! Always use put_device() to give up your 
  14.  * reference instead. 
  15.  */  
  16. int device_add(struct device *dev)  
  17. {  
  18.     struct device *parent = NULL;  
  19.     struct class_interface *class_intf;  
  20.     int error = -EINVAL;  
  21.   
  22.     dev = get_device(dev);  
  23.     if (!dev)  
  24.         goto done;  
  25.   
  26.     if (!dev->p) {  
  27.         error = device_private_init(dev);  
  28.         if (error)  
  29.             goto done;  
  30.     }  
  31.   
  32.     /* 
  33.      * for statically allocated devices, which should all be converted 
  34.      * some day, we need to initialize the name. We prevent reading back 
  35.      * the name, and force the use of dev_name() 
  36.      */  
  37.     if (dev->init_name) {  
  38.         dev_set_name(dev, "%s", dev->init_name);  
  39.         dev->init_name = NULL;  
  40.     }  
  41.   
  42.     if (!dev_name(dev))  
  43.         goto name_error;  
  44.   
  45.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);  
  46.   
  47.     parent = get_device(dev->parent);  
  48.     setup_parent(dev, parent);  
  49.   
  50.     /* use parent numa_node */  
  51.     if (parent)  
  52.         set_dev_node(dev, dev_to_node(parent));  
  53.   
  54.     /* first, register with generic layer. */  
  55.     /* we require the name to be set before, and pass NULL */  
  56.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);  
  57.     if (error)  
  58.         goto Error;  
  59.   
  60.     /* notify platform of device entry */  
  61.     if (platform_notify)  
  62.         platform_notify(dev);  
  63.   
  64.     error = device_create_file(dev, &uevent_attr);  
  65.     if (error)  
  66.         goto attrError;  
  67.   
  68.     if (MAJOR(dev->devt)) {  
  69.         error = device_create_file(dev, &devt_attr);  
  70.         if (error)  
  71.             goto ueventattrError;  
  72.   
  73.         error = device_create_sys_dev_entry(dev);  
  74.         if (error)  
  75.             goto devtattrError;  
  76.   
  77.         devtmpfs_create_node(dev);  
  78.     }  
  79.   
  80.     error = device_add_class_symlinks(dev);  
  81.     if (error)  
  82.         goto SymlinkError;  
  83.     error = device_add_attrs(dev);  
  84.     if (error)  
  85.         goto AttrsError;  
  86.     error = bus_add_device(dev);  
  87.     if (error)  
  88.         goto BusError;  
  89.     error = dpm_sysfs_add(dev);  
  90.     if (error)  
  91.         goto DPMError;  
  92.     device_pm_add(dev);  
  93.   
  94.     /* Notify clients of device addition.  This call must come 
  95.      * after dpm_sysf_add() and before kobject_uevent(). 
  96.      */  
  97.     if (dev->bus)  
  98.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  99.                          BUS_NOTIFY_ADD_DEVICE, dev);  
  100.   
  101.     kobject_uevent(&dev->kobj, KOBJ_ADD);  
  102.     bus_probe_device(dev);  
  103.     if (parent)  
  104.         klist_add_tail(&dev->p->knode_parent,  
  105.                    &parent->p->klist_children);  
  106.   
  107.     if (dev->class) {  
  108.         mutex_lock(&dev->class->p->class_mutex);  
  109.         /* tie the class to the device */  
  110.         klist_add_tail(&dev->knode_class,  
  111.                    &dev->class->p->class_devices);  
  112.   
  113.         /* notify any interfaces that the device is here */  
  114.         list_for_each_entry(class_intf,  
  115.                     &dev->class->p->class_interfaces, node)  
  116.             if (class_intf->add_dev)  
  117.                 class_intf->add_dev(dev, class_intf);  
  118.         mutex_unlock(&dev->class->p->class_mutex);  
  119.     }  
  120. done:  
  121.     put_device(dev);  
  122.     return error;  
  123.  DPMError:  
  124.     bus_remove_device(dev);  
  125.  BusError:  
  126.     device_remove_attrs(dev);  
  127.  AttrsError:  
  128.     device_remove_class_symlinks(dev);  
  129.  SymlinkError:  
  130.     if (MAJOR(dev->devt))  
  131.         device_remove_sys_dev_entry(dev);  
  132.  devtattrError:  
  133.     if (MAJOR(dev->devt))  
  134.         device_remove_file(dev, &devt_attr);  
  135.  ueventattrError:  
  136.     device_remove_file(dev, &uevent_attr);  
  137.  attrError:  
  138.     kobject_uevent(&dev->kobj, KOBJ_REMOVE);  
  139.     kobject_del(&dev->kobj);  
  140.  Error:  
  141.     cleanup_device_parent(dev);  
  142.     if (parent)  
  143.         put_device(parent);  
  144. name_error:  
  145.     kfree(dev->p);  
  146.     dev->p = NULL;  
  147.     goto done;  
  148. }  

设备添加到电源管理链表中

代码目录:kernel/drivers/base/main.c

  1. /** 
  2.  * device_pm_add - Add a device to the PM core's list of active devices. 
  3.  * @dev: Device to add to the list. 
  4.  */  
  5. void device_pm_add(struct device *dev)  
  6. {  
  7.     pr_debug("PM: Adding info for %s:%s\n",  
  8.          dev->bus ? dev->bus->name : "No Bus",  
  9.          kobject_name(&dev->kobj));  
  10.     mutex_lock(&dpm_list_mtx);  
  11.     if (dev->parent) {  
  12.         if (dev->parent->power.status >= DPM_SUSPENDING)  
  13.             dev_warn(dev, "parent %s should not be sleeping\n",  
  14.                  dev_name(dev->parent));  
  15.     } else if (transition_started) {  
  16.         /* 
  17.          * We refuse to register parentless devices while a PM 
  18.          * transition is in progress in order to avoid leaving them 
  19.          * unhandled down the road 
  20.          */  
  21.         dev_WARN(dev, "Parentless device registered during a PM transaction\n");  
  22.     }  
  23.   
  24.     list_add_tail(&dev->power.entry, &dpm_list);  
  25.     mutex_unlock(&dpm_list_mtx);  
  26. }  

综上,设备挂到电源管理的函数调用关系是(依次往下调用)

audio_card_init (函数类型包含__init 初始化调用)

platform_device_add

device_add

device_pm_add

list_add_tail(最直接的链表添加操作)

  • 1
  • 2
  • 下一页

相关内容