> 文档中心 > OpenHarmony HDF框架

OpenHarmony HDF框架

原文:

品读鸿蒙HDF架构(一)|解读鸿蒙源码【图文】_mb607022e25a607_51CTO博客https://blog.51cto.com/u_15162069/2902613

1.铺垫一下

 系统一启动,会运行到SystemInit(),其中会调用DeviceManagerStart()启动与HDF相关的部分:

 【vendor/hisi/hi35xx/hi3516dv300/module_init/src/System_init.c】

void SystemInit(void){    . . . . . .#ifdef LOSCFG_DRIVERS_HDF    if (DeviceManagerStart()) { PRINT_WARN("No drivers need load by hdf manager!");    }#endif    . . . . . .}

2.1启动DeviceManager

 【drivers/hdf/lite/manager/src/Devmgr_service_start.c】

int DeviceManagerStart(){    struct IDevmgrService *instance = DevmgrServiceGetInstance();    if (instance == NULL || instance->StartService == NULL) {        HDF_LOGE("Device manager start failed, service instance is null!");        return HDF_FAILURE;    }    struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE, DEV_MGR_NODE_PERM);    if (ioService != NULL) {        static struct HdfIoDispatcher dispatcher = {            .Dispatch = DeviceManagerDispatch,        };        ioService->dispatcher = &dispatcher;        ioService->target = (struct HdfObject )&instance->object;    }    return instance->StartService(instance);}

 简单地说,要启动DeviceManager服务,就得先获取一个DevmgrService实例,然后调用它的StartService(),又因为DevmgrService继承于IDevmgrService,所以可以强制转换成IDevmgrService。

2.1.1获取DevmgrService单例 

获取实例时,其实用到了HDF机制提供的一个对象管理器,相关代码如下: 

【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】 

struct IDevmgrService *DevmgrServiceGetInstance(){    static struct IDevmgrService *instance = NULL;  // 注意是static的,表示是个静态单例    if (instance == NULL) {        instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);    }    return instance;}

以后我们会看到,这个HdfObjectManagerGetObject()会在多个地方调用,以便获取不同的HDF对象。说起来也简单,HDF机制里有一张表,记录着该如何创建、释放一些重要的HDF对象,该表格为g_liteObjectCreators:
【drivers/hdf/lite/manager/src/Devlite_object_config.c】

static const struct HdfObjectCreator g_liteObjectCreators[]

基于读到的代码,我们可以画出这个表格:

HDF类型ID 创建函数 释放函数
HDF_OBJECT_ID_DEVMGR_SERVICE DevmgrServiceCreate DevmgrServiceRelease
HDF_OBJECT_ID_DEVSVC_MANAGER DevSvcManagerCreate DevSvcManagerRelease
HDF_OBJECT_ID_DEVHOST_SERVICE DevHostServiceCreate DevHostServiceRelease
HDF_OBJECT_ID_DRIVER_INSTALLER DriverInstallerCreate NULL
HDF_OBJECT_ID_DRIVER_LOADER HdfDriverLoaderCreate NULL
HDF_OBJECT_ID_DEVICE HdfDeviceCreate HdfDeviceRelease
HDF_OBJECT_ID_DEVICE_TOKEN HdfDeviceTokenCreate HdfDeviceTokenRelease
HDF_OBJECT_ID_DEVICE_SERVICE DeviceNodeExtCreate DeviceNodeExtRelease

概念还是比较简单的,如果系统中的DevmgrService单例对象已经存在,就使用之。否则就利用HDF对象管理器创建一个DevmgrService对象。对于HDF对象管理器而言,不同类型的HDF对象,需要用到不同的创建函数,所以要查一下上表。比如DevmgrService对应的创建函数就是DevmgrServiceCreate(),该函数代码如下:
【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

struct HdfObject *DevmgrServiceCreate(){    static bool isDevMgrServiceInit = false;    static struct DevmgrService devmgrServiceInstance;    if (!isDevMgrServiceInit) {        if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {            return NULL;        }        isDevMgrServiceInit = true;    }    return (struct HdfObject )&devmgrServiceInstance;   // ???HdfObject,有小问题!}

在“创建”时,如果发现是首次创建,则调用一个类似构造函数的DevmgrServiceConstruct()函数,来初始化对象里的函数表。这种做法是用C语言实现面向对象概念的常用做法。不过,此处的代码有一个小bug,即最后那个强制转换,从目前看到的代码来说,DevmgrService间接继承于HdfDeviceObject,而HdfDeviceObject并不继承于HdfObject,所以是不应该这样强制转换的,除非HdfDeviceObject的第一个成员从“IDeviceIoService*”改为“IDeviceIoService”,我估计最早的代码就是IDeviceIoService,后来因为某些原因,变成了指针形式,至于以后具体该怎么修正,这个就让鸿蒙的工程师去费脑筋吧。DevmgrService的构造函数如下:
【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

static bool DevmgrServiceConstruct(struct DevmgrService *inst){    if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {        HDF_LOGE("%s mutex init failed", __func__);        return false;    }    struct IDevmgrService *devMgrSvcIf = (struct IDevmgrService *)inst;    if (devMgrSvcIf != NULL) {        devMgrSvcIf->AttachDevice      = DevmgrServiceAttachDevice;        devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;        devMgrSvcIf->StartService      = DevmgrServiceStartService;        devMgrSvcIf->AcquireWakeLock  = DevmgrServiceAcquireWakeLock;        devMgrSvcIf->ReleaseWakeLock  = DevmgrServiceReleaseWakeLock;        HdfSListInit(&inst->hosts);    }    return true;}

2.1.2HdfIoServiceBind()

启动DeviceManager时,第二个重要的动作是调用HdfIoServiceBind(): 

struct HdfIoService *ioService = HdfIoServiceBind(DEV_MGR_NODE, DEV_MGR_NODE_PERM);

这一步在做什么呢?我们可以这样理解,DevmgrService作为一个核心的系统服务,我们希望能像访问虚文件系统的文件那样打开它,并进一步向它传递诸如AttachDevice、StartServie......这样的语义。这些语义最终会执行到上面列举的DevmgrServiceAttachDevice、DevmgrServiceStartService等函数。

我们不必列举太多代码,下面是我绘制的一张关于DeviceManagerStart()的调用关系示意图,可供参考:

 图中已经明确注明,DevmgrService在虚文件系统里对应的路径应该是“/dev/dev_mgr”,而上面调用HdfIoServiceBind()后,实际上建立了一个文件系统的inode节点,示意图如下:

 HdfVNodeAdapter的target在最后赋值为(struct HdfObject*)&instance->object,说到底其实就是指向了DevmgrService。

2.1.3执行DevmgrService的StartService

    接下来是启动DeviceManager的第三步,调用instance->StartService(),这一步其实是在调用DevmgreviceStartService()函数。
【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

int DevmgrServiceStartService(struct IDevmgrService *inst){    struct DevmgrService *dmService = (struct DevmgrService *)inst;    if (dmService == NULL) {        HDF_LOGE("Start device manager service failed, dmService is null");        return HDF_FAILURE;    }    return DevmgrServiceStartDeviceHosts(dmService);}

主要就是在调用一个DevmgrServiceStartDeviceHosts()函数。这个函数应该算是个重量级函数,它会负责建立起DevmgrService内部主要的数据结构。我们先绘制一下该函数第一层次的调用关系,如下图:

在进一步深入代码细节之前,我们最好先大概说明一下。在鸿蒙HDF架构里,有一个“设备Host”的概念,根据官方的文档,我们大概可以知道,一个Host用于整合若干业务相近的设备,这个原则被称为相似相容原则。为了实现这个原则,HDF构造了一系列数据结构,我们列举一下:
1)HdfHostInfo
2)DevHostServiceClnt
3)DevHostService
4)HdfDevice
5)HdfDeviceNode
. . . . . .

我们当然没必要在一篇文档里列出所有的数据结构,只需先明白:
1)设备管理服务(DevmgrService)内部可以管理若干Host;
2)每个Host内部可以整合若干业务相近的设备;
3)每个Host可以拆分成两个部分:DevHostServiceClnt 和 DevHostService;
4)每个DevHostService可以添加多个设备;

从上面的调用关系图中,我们可以看到DevmgrServiceStartDeviceHosts()函数的主要行为是:
1)先获取一个驱动安装器(单例)对象;
2)解析系统配置信息,将其转换成一个以HdfHostInfo为表项的列表,这个就对应着系统里所有的host;
3)遍历这张HdfHostInfo列表,为每个HdfHostInfo节点创建一个对应的DevHostServiceClnt对象;
4)新创建的DevHostServiceClnt节点会被插入DevmgrService的hosts列表中;
5)针对每个HdfHostInfo节点,利用刚刚获取的驱动安装器具体启动该host。

2.1.3.1获取驱动安装器

现在我们详细看上图中调用的关键函数。
installer = DriverInstallerGetInstance();
先拿到一个驱动安装器。

struct IDriverInstaller *DriverInstallerGetInstance(){    static struct IDriverInstaller *installer = NULL;    if (installer == NULL) {        installer = (struct IDriverInstaller *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DRIVER_INSTALLER);    }    return installer;}

 又看到HdfObjectManagerGetObject(),于是我们查前文那张表,可以找到驱动安装器对应的创建函数是DriverInstallerCreate():
【drivers/hdf/frameworks/core/manager/src/Hdf_driver_installer.c】

struct HdfObject *DriverInstallerCreate(void){    static bool isDriverInstInit = false;    static struct DriverInstaller driverInstaller;    if (!isDriverInstInit) {        DriverInstallerConstruct(&driverInstaller);        isDriverInstInit = true;    }    return (struct HdfObject *)&driverInstaller;}

用的是一个单例的DriverInstaller对象。

2.1.3.2获取HdfHostInfo列表

启动所有hosts的第二步,是获取一个HdfHostInfo列表:
HdfAttributeManagerGetHostList(&hostList)
我们摘选该函数的主要句子,如下:
【drivers/hdf/lite/manager/src/Hdf_attribute_manager.c】

bool HdfAttributeManagerGetHostList(struct HdfSList *hostList){    . . . . . .    hdfManagerNode = GetHdfManagerNode(HcsGetRootNode());    . . . . . .    hostNode = hdfManagerNode->child;    while (hostNode != NULL) {        struct HdfHostInfo *hostInfo = HdfHostInfoNewInstance();        . . . . . .        if (!GetHostInfo(hostNode, hostInfo)) {            HdfHostInfoFreeInstance(hostInfo);            hostInfo = NULL;            hostNode = hostNode->sibling;            continue;        }        hostInfo->hostId = hostId;        if (!HdfSListAddOrder(hostList, &hostInfo->node, HdfHostListCompare)) {            HdfHostInfoFreeInstance(hostInfo);            hostInfo = NULL;            hostNode = hostNode->sibling;            continue;        }        hostId++;        hostNode = hostNode->sibling;    }    return true;}

我们稍微扩展一点知识来说明一下。在鸿蒙系统中,有一些系统级的配置文件,叫做HCS文件。系统可以利用类似hc-gen这样的工具,根据配置文件生成二进制码。当HDF启动时,它会将二进制信息传给DriverConfig模块。该模块会将二进制码转换成配置树,并向开发者提供API去查询这棵树。

配置树的根节点是g_hcsTreeRoot,节点类型为DeviceResourceNode。这棵配置树里有一个特殊的节点,具有“hdf_manager”属性,上面代码中调用GetHdfManagerNode()一句,就是在获取这个特殊节点。接着,上面的代码里会尝试遍历该节点的所有child,并将每个child的信息整理进一个HdfHostInfo对象里。注意此时就会给HdfHostInfo分派一个hostId了,这个hostId后续还会用到。所有读出的HdfHostInfo节点会按照其内记录的优先级进行排序,并连成一个列表,优先级越高越靠近表头。

2.1.3.3遍历HdfHostInfo列表

得到HdfHostInfo列表后,紧接着就会尝试遍历这张表。因为每个HdfHostInfo节点代表的就是一个host,所以每读取一个HdfHostInfo,就会对应地生成一个DevHostServiceClnt对象。这些生成的DevHostServiceClnt都会插入到DevmgrService的hosts列表中。

每读取一个HdfHostInfo信息后,就会利用驱动安装器,启动对应的host。
 

 2.1.3.4启动host

启动host的动作是installer->StartDeviceHost()一步,它的调用关系如下: 

大家还记得前文我说过,每个Host可以拆分成两个部分:DevHostServiceClnt 和 DevHostService。这个就体现在上面的调用关系里。

StartDeviceHost一开始就会创建一个DevHostService对象,
【drivers/hdf/frameworks/core/manager/src/Hdf_driver_installer.c】

static int DriverInstallerStartDeviceHost(uint32_t devHostId, const char *devHostName){    struct IDevHostService *hostServiceIf = DevHostServiceNewInstance(devHostId, devHostName);    if ((hostServiceIf == NULL) || (hostServiceIf->StartService == NULL)) {        HDF_LOGE("hostServiceIf or hostServiceIf->StartService is null");        return HDF_FAILURE;    }    int ret = hostServiceIf->StartService(hostServiceIf);    if (ret != HDF_SUCCESS) {        HDF_LOGE("Start host service failed, ret is: %d", ret);        DevHostServiceFreeInstance(hostServiceIf);    }    return ret;}

随后调用的StartService,实际上对应DevHostServiceStartService()函数:
【drivers/hdf/frameworks/core/host/src/Devhost_service.c】

static int DevHostServiceStartService(struct IDevHostService *service){    struct DevHostService *hostService = (struct DevHostService*)service;    if (hostService == NULL) {        HDF_LOGE("Start device service failed, hostService is null");        return HDF_FAILURE;    }    return DevmgrServiceClntAttachDeviceHost(hostService->hostId, service);}

此处调用的DevmgrServiceClntAttachDeviceHost()函数,内部涉及的内容挺多,我打算在下一篇文档里再细说。现在我们已经对“启动DeviceManager”的流程有了一点初步的认识,为了便于理解里面host的部分,我们画一张示意图总结一下,绘图如下:

我们已经知道,一个Host对应一个DevHostServiceClnt和一个DevHostService,很明显主要行为都包含在后者内部。当后者启动时,会执行到DriverInstallerStartDeviceHost(),该函数又会调用DevHostServiceStartServie(),这些内容在前面都说过。

我们不用去想太多调用细节,反正说起来就是要让一个DevHostServiceClnt和一个DevHostService“挂接”(attach)起来,挂接的动作里会进一步在DevHostService里安装设备驱动。这个挂接动作具体对应的函数就是DevmgrServiceClntAttachDeviceHost()。在上一篇文章里,我们没有展开讲这个函数,现在就从它说起。为了便于阅读,我将挂接动作的调用顺序先绘制出来,如下图所示:

 1.挂接device Host

我用黄色框表达了DevmgrServiceClntAttachDeviceHost()一步,该函数代码截选如下:
【drivers/hdf/frameworks/core/host/src/Devmgr_service_clnt.c】

int DevmgrServiceClntAttachDeviceHost(uint16_t hostId, struct IDevHostService *hostService){    struct IDevmgrService *devMgrSvcIf = NULL;    . . . . . .    devMgrSvcIf = inst->devMgrSvcIf;    . . . . . .    // 实际调用的是DevmgrServiceAttachDeviceHost()    return devMgrSvcIf->AttachDeviceHost(devMgrSvcIf, hostId, hostService);}

 最后一句实际调用的是DevmgrServiceAttachDeviceHost(),代码截选如下:
【drivers/hdf/frameworks/core/manager/src/Devmgr_service.c】

static int DevmgrServiceAttachDeviceHost(    struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService){    struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);    . . . . . .    hostClnt->deviceInfos = HdfAttributeManagerGetDeviceList(hostClnt->hostId, hostClnt->hostName);    . . . . . .    hostClnt->hostService = hostService;    return DevHostServiceClntInstallDriver(hostClnt);}

首先,遍历DevmgrService的hosts列表,根据hostId找到对应的DevHostServiceClnt对象,并给该DevHostServiceClnt对象的deviceInfos域和hostService域赋值,然后调用重头戏DevHostServiceClntInstallDriver()。

在获取这个host范畴的所有device信息时,也是去查询上一篇文章提到的配置树,树节点的类型为DeviceResourceNode,只不过上一次系统是去查找具有“hdf_manager”属性的节点,而此次是查找名字为hostName的节点,这个节点里包含着若干设备的信息,现在这些设备信息会被组织成一个HdfDeviceInfo链表。最终形成下面图中的结构:

1.1安装host范畴内的设备驱动

1.1.1在每个host的DevHostService里添加设备

Attach动作的最后一步就是安装驱动啦,我们看一下这个DevHostServiceClntInstallDriver()函数:
【drivers/hdf/frameworks/core/manager/src/Devhost_service_clnt.c】

int DevHostServiceClntInstallDriver(struct DevHostServiceClnt *hostClnt){    . . . . . .    struct HdfSListIterator it;    struct HdfDeviceInfo *deviceInfo = NULL;    struct IDevHostService *devHostSvcIf = NULL;    . . . . . .    devHostSvcIf = (struct IDevHostService *)hostClnt->hostService;    . . . . . .    HdfSListIteratorInit(&it, hostClnt->deviceInfos);    while (HdfSListIteratorHasNext(&it)) {        deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&it);        if ((deviceInfo == NULL) || (deviceInfo->preload != DEVICE_PRELOAD_ENABLE)) {            continue;        } // 实际调用的是 DevHostServiceAddDevice()        ret = devHostSvcIf->AddDevice(devHostSvcIf, deviceInfo);        . . . . . .    }    return HDF_SUCCESS;}

其实就是遍历一下该host范畴内的所有HdfDeviceInfo节点,如果节点的preload是“使能”的,就执行对应的AddDevice操作,即DevHostServiceAddDevice()函数,其代码截选如下:
【drivers/hdf/frameworks/core/host/src/Devhost_service.c】

static int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo){    int ret = HDF_FAILURE;    struct HdfDevice *device = NULL;    struct HdfDeviceNode *devNode = NULL;    struct DevHostService *hostService = (struct DevHostService *)inst;    struct IDriverLoader *driverLoader =  HdfDriverLoaderGetInstance();    . . . . . .    device = DevHostServiceGetDevice(hostService, deviceInfo->deviceId);    . . . . . .    // 实际调用的是 HdfDriverLoaderLoadNode()    devNode = driverLoader->LoadNode(driverLoader, deviceInfo);    . . . . . .    devNode->hostService = hostService;    // 实际调用的是 HdfDeviceAttach()    ret = device->super.Attach(&device->super, devNode);    . . . . . .    return HDF_SUCCESS;    . . . . . .}

在这个函数里,先调用DevHostServiceGetDevice()尝试从DevHostService的devices列表里查找与deviceId匹配的节点,如果找不到就创建一个新HdfDevice节点,并插入该列表。

 当然,一开始devices列表是个空列表,此时只会创建新节点。反正经此一步,我们一般可以拿到一个可用的HdfDevice对象。接着利用驱动加载器加载一个和deviceInfo匹配的HdfDeviceNode节点。最后还需把得到的HdfDevice和HdfDeviceNode挂接起来。

1.1.1.1加载HdfDeviceNode

加载HdfDeviceNode的动作实际上是HdfDriverLoaderLoadNode(),代码截选如下:
【drivers/hdf/frameworks/core/host/src/Hdf_driver_loader.c】 

static struct HdfDeviceNode *HdfDriverLoaderLoadNode(    struct IDriverLoader *loader, const struct HdfDeviceInfo *deviceInfo){    struct HdfDriverEntry *driverEntry = NULL;    struct HdfDeviceNode *devNode = NULL;    . . . . . .    // 实际调用的是 HdfDriverLoaderGetDriverEntry()    driverEntry = loader->GetDriverEntry(deviceInfo);    . . . . . .    devNode = HdfDeviceNodeNewInstance();    . . . . . .    devNode->driverEntry = driverEntry;    devNode->deviceInfo = deviceInfo;    devNode->deviceObject.property = HcsGetNodeByMatchAttr(HcsGetRootNode(),     deviceInfo->deviceMatchAttr);    . . . . . .    if ((deviceInfo->policy == SERVICE_POLICY_PUBLIC) || (deviceInfo->policy == SERVICE_POLICY_CAPACITY)) {        . . . . . .        if (driverEntry->Bind(&devNode->deviceObject) != 0) {            HDF_LOGE("bind driver failed");            HdfDeviceNodeFreeInstance(devNode);            return NULL;        }    }    return devNode;}

HdfDeviceNode的定义如下:
【drivers/hdf/frameworks/core/host/include/Hdf_device_node.h】

struct HdfDeviceNode {    struct IDeviceNode super;    struct HdfSListNode entry;    struct PowerStateToken *powerToken;    struct DevHostService *hostService;    struct HdfDeviceObject deviceObject;    struct IHdfDeviceToken *token;    struct HdfDriverEntry *driverEntry;    const struct HdfDeviceInfo *deviceInfo;};

可以看到,驱动加载器在创建HdfDeviceNode节点时,还是有一些工作要做的:
1)得加载相应设备的驱动程序入口,最终体现为HdfDriverEntry;
2)创建一个HdfDeviceNode对象,经过研究,我们可以看到最终创建的其实是HdfDeviceNode的派生类(DeviceNodeExt)对象;
3)把HdfDeviceNode节点和设备驱动程序绑定起来;

1.1.1.1.1获取驱动入口

驱动加载器获取HdfDriverEntry的实际动作是HdfDriverLoaderGetDriverEntry():
【drivers/hdf/lite/manager/src/Lite_driver_loader.c】

struct HdfDriverEntry *HdfDriverLoaderGetDriverEntry(const struct HdfDeviceInfo *deviceInfo){    int count = (int) (((uint8_t *)(HDF_DRIVER_END()) - (uint8_t *)(HDF_DRIVER_BEGIN())) / sizeof(size_t));    size_t *addrBegin = (size_t*)(HDF_DRIVER_BEGIN());    if ((deviceInfo == NULL) || (deviceInfo->moduleName == NULL) || (deviceInfo->svcName == NULL)) { HDF_LOGE("Hdf get device entry failed, input deviceInfo is NULL!"); return NULL;    }    for (int i = 0; i moduleName, driverEntry->moduleName) == 0) {     return driverEntry; } addrBegin++;    }    HDF_LOGE("Hdf get %s device entry failed!", deviceInfo->svcName);    return NULL;}

其中,HdfDriverEntry的定义如下:
【drivers/hdf/frameworks/include/core/Hdf_device_desc.h】

struct HdfDriverEntry {    int32_t moduleVersion;    const char *moduleName;    int32_t (*Bind)(struct HdfDeviceObject *deviceObject);    int32_t (*Init)(struct HdfDeviceObject *deviceObject);    void (*Release)(struct HdfDeviceObject *deviceObject);};

现在我们来解释一下,HdfDriverLoaderGetDriverEntry()到底在干什么。我们设想,HDF会先加载需要的所有驱动程序,每个驱动程序内部都会构造一个HdfDriverEntry对象,而且会填好那个Bind域,这其实就是在填写一个回调函数指针,当然,也只有驱动程序自己知道该填写哪个函数指针。

HDF会把加载的所有驱动的HdfDriverEntry对象的起始地址汇总起来,形成一个类似地址数组的东西,这个数组的第一项的地址对应上面代码中的HDF_DRIVER_BEGIN(),最后一项的地址对应HDF_DRIVER_END()(最后一项不填内容)。示意图如下:
 

获取驱动入口时,就是在遍历这个指针数组,查询与moduleName匹配的节点。

1.1.1.1.2 创建HdfDeviceNode对象

接着尝试创建HdfDeviceNode对象,此时调用的HdfDeviceNodeNewInstance()函数如下:
【drivers/hdf/frameworks/core/host/src/Hdf_device_node.c】

struct HdfDeviceNode *HdfDeviceNodeNewInstance(){    return (struct HdfDeviceNode *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE_SERVICE);}

又需要去查我们熟悉的对象创建表(g_liteObjectCreators),最终查到会调用DeviceNodeExtCreate():
【drivers/hdf/lite/manager/src/Hdf_device_node_ext.c】

struct HdfObject *DeviceNodeExtCreate(){    struct DeviceNodeExt *instance =        (struct DeviceNodeExt *)OsalMemCalloc(sizeof(struct DeviceNodeExt));    if (instance != NULL) {        DeviceNodeExtConstruct(instance);        instance->ioService = NULL;    }    return (struct HdfObject *)instance;}

可以看到,实际创建的是一个DeviceNodeExt对象。DeviceNodeExt继承于HdfDeviceNode,定义如下:
【drivers/hdf/lite/include/manager/Hdf_device_node_ext.h】

struct DeviceNodeExt {    struct HdfDeviceNode super;    struct HdfIoService *ioService;};

其构造函数如下:
【drivers/hdf/lite/manager/src/Hdf_device_node_ext.c】

static void DeviceNodeExtConstruct(struct DeviceNodeExt *inst){    struct IDeviceNode *nodeIf = (struct IDeviceNode *)inst;    if (nodeIf != NULL) {        HdfDeviceNodeConstruct(&inst->super);        nodeIf->PublishService = DeviceNodeExtPublishService;    }}

注意,它修改了继承来的PublishService域,将函数指针设为DeviceNodeExtPublishService了。

HdfDriverLoaderLoadNode()会给DeviceNodeExt的driverEntry域、deviceInfo域、deviceObject.property赋值,那么在进行绑定之前,DeviceNodeExt的示意图大概是这样的:

 1.1.1.1.3 绑定驱动入口

接下来要将刚刚创建的DeviceNodeExt节点和驱动入口绑定起来:

driverEntry->Bind(&devNode->deviceObject)

前文我们已经说了,每个程序会实现自己的Bind动作,而HDF只负责回调Bind。注意,回调时HDF需要传入DeviceNodeExt节点的deviceObject部分的指针,因为需要驱动程序填写其中的域。当然,我们从上图中可以看到,deviceObject部分只剩下service域(IDeviceIoService*)需要填写。那么很明显,一个驱动程序要能被HDF使用,那么它就得包含一个IDeviceIoService对象。IDeviceIoService的定义如下:
【drivers/hdf/frameworks/include/core/Hdf_device_desc.h】
 

struct IDeviceIoService {    struct HdfObject object;    int32_t (*Open)(struct HdfDeviceIoClient *client);    int32_t (*Dispatch)(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,    struct HdfSBuf *reply);    void (*Release)(struct HdfDeviceIoClient *client);};

现在我们可以基于前文示意图,绘制一张DeviceNodeExt和驱动程序绑定后的示意图了,如下图:

 1.1.1.2 挂接HdfDeviceNode

DevHostServiceAddDevice()在加载好DeviceNodeExt之后,调用了一句Attach:

 ret = device->super.Attach(&device->super, devNode);

尝试把HdfDevice节点和DeviceNodeExt联系起来,这一句其实是调用HdfDeviceAttach(),相关代码如下:
【drivers/hdf/frameworks/core/host/include/Hdf_device.h】

struct IHdfDevice {    struct HdfObject object;    int (*Attach)(struct IHdfDevice *, struct HdfDeviceNode *);};struct HdfDevice {    struct IHdfDevice super;    struct HdfSListNode node;    struct HdfSList services;    uint16_t deviceId;    uint16_t hostId;};

【drivers/hdf/frameworks/core/host/src/Hdf_device.c】

static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode){    struct HdfDevice *device = (struct HdfDevice *)devInst;    struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;    . . . . . .    HdfSListAdd(&device->services, &devNode->entry);    // 实际调用的是 HdfDeviceLaunchNode()    return nodeIf->LaunchNode(devNode, devInst);}

代码里先将DeviceNodeExt添加进HdfDevice的services列表里,然后调用了HdfDeviceLaunchNode()。

在HdfDeviceLaunchNode()中,调用驱动程序的 .init 函数,

int HdfDeviceLaunchNode(struct HdfDeviceNode *devNode, struct IHdfDevice *devInst){    ....    if ((driverEntry == NULL) || (driverEntry->Init == NULL)) { HDF_LOGE("deviceEntry or deviceEntry->Init is null"); return HDF_ERR_INVALID_PARAM;    }    int ret = driverEntry->Init(&devNode->deviceObject);/* 调用init函数 */    if (ret != HDF_SUCCESS) { if (driverEntry->Release != NULL) {     driverEntry->Release(&devNode->deviceObject); } return HDF_DEV_ERR_DEV_INIT_FAIL;    }    ...}

在函数DevHostServiceAddDevice()中,对应到驱动程序,会先调用到bind函数,在调用init函数,

static int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo){    ...    /* 在这个函数里面设置了device->super.Attach */    struct IDriverLoader *driverLoader =  HdfDriverLoaderGetInstance();    .../* 这个函数的调用过程会调用到驱动程序的bind函数 */    devNode = driverLoader->LoadNode(driverLoader, deviceInfo);    if (devNode == NULL) { ret = HDF_DEV_ERR_NO_DEVICE_SERVICE; goto error;    }    devNode->hostService = hostService;    /* 这个函数的调用过程会调用到驱动程序的init函数 */    ret = device->super.Attach(&device->super, devNode);    if (ret != HDF_SUCCESS) { goto error;    }    return HDF_SUCCESS;    ...}

我们前文已经说过,HdfDevice节点在之前已经添加进DevHostService的devices列表了,现在它又和DeviceNodeExt联系起来了,再结合前文中的知识,我们可以画一张大一点儿的关系示意图了,如下: