Device 与 platform device的不同(一)[通俗易懂]

Device 与 platform device的不同(一)[通俗易懂]Device与platformdevice在注册方法上有所不同。Device注册有两步,platformdevice注册也有两步,它们第一步相同,都是initialize设备,但第二步有所不同,Device是直接调用device_add()函数来add设备,而platformdevice则调用platform_device_add()函数。实际上,platfo

大家好,又见面了,我是你们的朋友全栈君。

Device 与 platform device 在注册方法上有所不同。

Device 注册有两步,platform device注册也有两步,它们第一步相同,都是initialize设备,

但第二步有所不同,Device是直接调用device_add()函数来add设备,而platform device则调用platform_device_add()函数。

实际上,platform_device_add()里面也嵌套了device_add()函数(红色部分),不过在device_add()被调用之前,platform device要先注册它的resources。

就是下面蓝色的部分。

 

 >>>>>>>>>>>>>>>>>>>> device的注册 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 void device_register(struct device *dev)

{

device_initialize(dev);

return device_add(dev);

}

>>>>>>>>>>>>>>>>>>>>>>device_register的第一步, 初始化device>>>>>>>>>>>>>>>>>>>>

void device_initialize(struct device *dev)

{

     dev->kobj.kset = device_kset;

     kboject_init(&dev->kobj, &device_ktype);

     INIT_LIST_HEAD(&dev->dma_pools);

     mutex_init(&dev->mutex);

     lockdep_set_novalidate_class(&dev->mutex);

     spin_lock_init(&dev->devres_lock);

     INIT_LIST_HEAD(&dev->devres_head);

     device_pm_init(dev);

     set_dev_node(dev, -1);

}

>>>>>>>>备注: struct device_private *p;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

struct device_private {             //hold the private to the driver core portions of the device structure

      struct klist klist_children;             //containing all children of this device

      struct klist_node knode_parent;   //node in sibling list

      struct klist_node knode_driver;   //node in driver list

      struct klist_node knode_bus;    //node in bus list

      void *driver_data;       //private pointer for driver specific info.

      struct device *device;        //pointer back to the struct class that this structure is associated with

};  //  Nothing outside of the driver core should ever touch these fields.

 

>>>>>>>>>>>>>>>>> device_register的第二步, 添加device>>>>>>>>>>>>>>>>>>>>>>>>> 

int device_add(struct device *dev)

{

    struct device *parent =NULL;

    struct class_interface *class_intf;

    int error = -EINVAL;

     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() */

   if(dev->init_name){

         dev_set_name(dev, “%s”, dev->init_name);

         dev->init_name =NULL;

   }

    if(!dev_name(dev)){

         error = – EINVAL;

         goto name_error;

     }

     pr_debug(“device: ‘%s’ : %s\n”, dev_name(dev), __func__);

     parent = getdevce(dev->parent);

     setup_parent(dev, parent);

     /*use paent numa_node*/

     if(parent)

               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 = kboject_add(&dev->kobj, dev->kobj.parent, NULL);

     if(error)

               goto Error;

     //notify platform of device entry

     if(platform_notify)

                 platform_notify(dev);

     erro = device_create_file(dev, &uevent_attr);

     if(error)

               goto attrError;

      if(MAJOR(dev->devt)){

              error = device_create_file(dev, &devt_attr);

              if(error)

                         goto ueventattrError;

              error = device_create_sys_dev_entry(dev);

              if(error)

                        goto devtattrError;

             devtmpfs_create_node(dev);

     }

     error = device_add_class_symlinks(dev);

     if(error)

             goto SymlinkError;

     error = device_add_attrs(dev);

     if(error)

            goto AttrsError;

     error = bus_add_device(dev);

     if(error)

            goto BusError;

     error = dpm_sysfs_add(dev);

      if(error)

            goto DPMError;

      device_pm_add(dev);

     / /Notify clients of device addtion. This call must come after dpm_sysf_add() and before kobject_uevent().

    if(dev->bus)

           blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);

    kobject_uevent(&dev->kobj, KOBJ_ADD);

    bus_probe_device(dev);

    if(parent)

              klist_add_tail(&dev->p->knode_parent, &parent->p->klist_children);

    if(dev->class){

              mutex_lock(&dev->class->p->class_mutex);

              //tie the class to the device

             klist_add_tail(&dev->knode_class, &dev->class->p->class_devices);

             list_for_each_entry(class_intf, &dev->class->p->class_interfaces, node);

             if(class_intf->add_dev)

                     class_intf->add_dev(dev, class_intf);

            mutex_unlock(&dev->class->class_mutex);

     }

 

done:

          put_device(dev);

          return error;

DPMError:

          bus_remove_device(dev);

BusError:

          device_remove_attrs(dev);

AttrsError:

          device_remove_class_syslinks(dev);

SymlinkError:

          if(MAJOR(dev->devt))

                        devtmpfs_delete_node(dev);

          if(MAJOR(dev->devt))

                        device_remover_file(dev, &devt_attr);

ueventattrError:

          device_remove_file(dev, &uevent_attr);

attrError:

          kobject_uevent(&dev->kobj, KOBJ_REMOVE);

          kobject_del(&dev->kobj);

Error:

          cleanup_device_parent(dev);

          if(parent)

                 put_device(parent);

name_error:

           kfree(dev->p);

           dev-> = NULL;

           goto done;

}

>>>>>>>>>>>>>>> platform_device 的注册>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

// platform_device_register – add a platform-level device   @pdev: platform device we’re adding

int platform_device_register(struct platform_device *pdev)

{

             device_initialize(&pdev->dev);          //第一步与device完全相同

             return platform_device_add(pdev);

}

 

>>>>>>>>>>>>>>>>>>>platform_device_add()>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

int platform_device_add(struct platform_device *pdev)

{

        int i, ret = 0;

        if(!pdev)

                   return -EINVAL;

        if(!pdev->dev.parent)

                  pdev->dev.parent = &platform_bus;

        pdev->dev.bus = &platform_bus_type;

        if(pdev->id != -1)

                  dev_set_name(&pdev->dev, “%s.%d”, pdev->name, pdev->id);

       else

                 dev_set_name(&pdev->dev, “%s”, pdev->name);

        for( i = -; i < pdev->num_resources; i++){

                 struct resource *p, *r = &pdev->resource[i];

                 if( r->name == NULL )

                               r->name = dev_name(&pdev->dev);

                 r->name = dev_name(&pdev->dev);

                 p = r->parent;

                 if(!p){

                              if(resource_type(r) == IORESOURCE_MEM)

                                            p = &iomem_resource;

                              else if (resource_type(r) == IORESOURCE_IO)

                                           p = &ioport_resource;

                }

                 if( p && insert_resource(p, r)){

                             printk(KERN_ERR “%s: failed to claim resource %d\n”, dev_name(&pdev->dev), i);

                             ret = -EBUSY;

                             goto failed;

                 }

       }

       pr_debug(“Registering platform device ‘%s’. Parent at %s\n”, dev_name(&pdev->dev), dev_name(pdev->dev.parent));

       ret = device_add(&pdev->dev);

       if(ret == 0)

                  return ret;

failed:

       while( –i>=0){

                 struct resource *r = &pdev->resource[i];

                 unsigned long type = resouce_type(r);

                 if(type==IORESOURCE_MEM)||type==IORESOURCE_IO)

                              release_resource(r);

        }

        return ret;

}

}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163792.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • hostapd.conf详细

    hostapd.conf详细#####hostapdconfigurationfile###############################################Emptylinesandlinesstartingwith#areignored#APnetdevicename(without’ap’postfix,i.e.,wlan0useswlan0a…

    2022年5月22日
    186
  • Linux学习——基础命令、搜索命令、压缩解压命令

    Linux学习——基础命令、搜索命令、压缩解压命令学习Linux要掌握一些简单的常用的一些命令,下面就是Linux的一命令的介绍。

    2022年2月26日
    44
  • toast弹窗教程_toast提示是什么

    toast弹窗教程_toast提示是什么2.3.1 反编译APK安装包首先,需要从网上下载样本安装包,这里使用的样本是哒哒文件助手,读者可以从安卓市场下载。在反编译APK之前,还需要从网上下载第三方模拟器,如夜神、雷电等模拟器。安装下载好的样本,运行看一下效果,大概了解一下该APK实现的相关功能,如图2.6所示,该界面就是程序入口界面。                   图2.6…

    2022年9月15日
    2
  • AMD CPU安装Intel HAXM

    AMD CPU安装Intel HAXM1.2.找到安装目录(我的安装目录:F:\Android\SDK\extras\google\Android_Emulator_Hypervisor_Driver)下的这个文件:silent_install,右击该文件选择“以管理员运行”,即可。…

    2022年6月28日
    83
  • git如何退出vim_git提交的命令

    git如何退出vim_git提交的命令有很多方法:退出Vi当编辑完文件,准备退出Vi返回到shell时,可以使用以下几种方法之一。在命令模式中,连按两次大写字母Z,若当前编辑的文件曾被修改过,则Vi保存该文件后退出,返回到shell;若当前编辑的文件没被修改过,则Vi直接退出,返回到shell。在末行模式下,输入命令:wVi保存当前编辑文件,但并不退出,而是继续等待用户输入命令。在使用

    2022年8月24日
    5
  • 小程序uv访客怎么刷_微信小程序获取访客数据-使用攻略

    小程序uv访客怎么刷_微信小程序获取访客数据-使用攻略一、使用场景企业希望有更多机会获取微信小程序访客的数据,以便精准快速地和客户取得联系、把握并转化商机。二、如何获取微信访客数据2.1可设置在特定场景下,触发授权请求,获取访客的微信头像昵称或手机号。如果访客已经授权了微信头像昵称或手机号后,则不会再要求访客授权。(注:获取手机号功能需要先授权“非个人”主体的微信小程序才可使用。)2.2授权请求分为两种:引导授权、强制授权。引导授权:显示弹窗,引…

    2022年9月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号