1 /*
2  * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "devmgr_service.h"
10 #include "devhost_service_clnt.h"
11 #include "device_token_clnt.h"
12 #include "devsvc_manager.h"
13 #include "hdf_attribute_manager.h"
14 #include "hdf_base.h"
15 #include "hdf_driver_installer.h"
16 #include "hdf_host_info.h"
17 #include "hdf_log.h"
18 #include "hdf_object_manager.h"
19 #include "osal_time.h"
20 
21 #define HDF_LOG_TAG devmgr_service
22 #define INVALID_PID (-1)
23 
DevmgrServiceDynamicDevInfoFound(const char * svcName,struct DevHostServiceClnt ** targetHostClnt,struct HdfDeviceInfo ** targetDeviceInfo)24 static bool DevmgrServiceDynamicDevInfoFound(
25     const char *svcName, struct DevHostServiceClnt **targetHostClnt, struct HdfDeviceInfo **targetDeviceInfo)
26 {
27     struct HdfSListIterator itDeviceInfo;
28     struct HdfDeviceInfo *deviceInfo = NULL;
29     struct DevHostServiceClnt *hostClnt = NULL;
30     struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
31     if (devMgrSvc == NULL) {
32         return false;
33     }
34 
35     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
36         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->dynamicDevInfos);
37         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
38             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
39             if (strcmp(deviceInfo->svcName, svcName) == 0) {
40                 *targetDeviceInfo = deviceInfo;
41                 *targetHostClnt = hostClnt;
42                 return true;
43             }
44         }
45     }
46 
47     return false;
48 }
49 
50 #define WAIT_HOST_SLEEP_TIME    2 // ms
51 #define WAIT_HOST_SLEEP_CNT     1000
DevmgrServiceStartHostProcess(struct DevHostServiceClnt * hostClnt,bool sync,bool dynamic)52 static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bool sync, bool dynamic)
53 {
54     int waitCount = WAIT_HOST_SLEEP_CNT;
55     struct IDriverInstaller *installer = DriverInstallerGetInstance();
56     if (installer == NULL || installer->StartDeviceHost == NULL) {
57         HDF_LOGE("invalid installer");
58         return HDF_FAILURE;
59     }
60 
61     hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName, dynamic);
62     if (hostClnt->hostPid == HDF_FAILURE) {
63         HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
64         return HDF_FAILURE;
65     }
66     hostClnt->stopFlag = false;
67     if (!sync) {
68         return HDF_SUCCESS;
69     }
70 
71     while (hostClnt->hostService == NULL && waitCount > 0) {
72         OsalMSleep(WAIT_HOST_SLEEP_TIME);
73         waitCount--;
74     }
75 
76     if (waitCount <= 0) {
77         HDF_LOGE("wait host(%{public}s, %{public}d) attach timeout", hostClnt->hostName, hostClnt->hostId);
78         if (installer->StopDeviceHost != NULL) {
79             installer->StopDeviceHost(hostClnt->hostId, hostClnt->hostName);
80         }
81         hostClnt->hostPid = -1;
82         return HDF_ERR_TIMEOUT;
83     }
84 
85     return HDF_SUCCESS;
86 }
87 
DevmgrServiceLoadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)88 static int DevmgrServiceLoadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
89 {
90     struct HdfDeviceInfo *deviceInfo = NULL;
91     struct DevHostServiceClnt *hostClnt = NULL;
92     bool dynamic = true;
93     int ret;
94     (void)devMgrSvc;
95 
96     if (serviceName == NULL) {
97         return HDF_ERR_INVALID_PARAM;
98     }
99 
100     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo)) {
101         HDF_LOGE("device %{public}s not in configed device list", serviceName);
102         return HDF_DEV_ERR_NO_DEVICE;
103     }
104 
105     if (deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
106         HDF_LOGE("device %{public}s not an dynamic load device", serviceName);
107         return HDF_DEV_ERR_NORANGE;
108     }
109 
110     dynamic = HdfSListIsEmpty(&hostClnt->unloadDevInfos) && !HdfSListIsEmpty(&hostClnt->dynamicDevInfos);
111     OsalMutexLock(&hostClnt->hostLock);
112     if (hostClnt->hostPid < 0) {
113         OsalMutexUnlock(&hostClnt->hostLock);
114         if (DevmgrServiceStartHostProcess(hostClnt, true, dynamic) != HDF_SUCCESS) {
115             HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
116             return HDF_FAILURE;
117         }
118         OsalMutexLock(&hostClnt->hostLock);
119     }
120 
121     if (hostClnt->hostService == NULL || hostClnt->hostService->AddDevice == NULL) {
122         OsalMutexUnlock(&hostClnt->hostLock);
123         HDF_LOGE("%{public}s load %{public}s failed, hostService is null", __func__, serviceName);
124         return HDF_FAILURE;
125     }
126     ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
127     OsalMutexUnlock(&hostClnt->hostLock);
128     if (ret == HDF_SUCCESS) {
129         deviceInfo->status = HDF_SERVICE_USABLE;
130     }
131     return ret;
132 }
133 
DevmgrServiceStopHost(struct DevHostServiceClnt * hostClnt)134 static int DevmgrServiceStopHost(struct DevHostServiceClnt *hostClnt)
135 {
136     struct IDriverInstaller *installer = DriverInstallerGetInstance();
137     if (installer == NULL || installer->StopDeviceHost == NULL) {
138         HDF_LOGE("invalid installer");
139         return HDF_FAILURE;
140     }
141     installer->StopDeviceHost(hostClnt->hostId, hostClnt->hostName);
142     hostClnt->stopFlag = true;
143     return HDF_SUCCESS;
144 }
145 
DevmgrServiceUnloadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)146 static int DevmgrServiceUnloadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
147 {
148     struct HdfDeviceInfo *deviceInfo = NULL;
149     struct DevHostServiceClnt *hostClnt = NULL;
150     int ret;
151     (void)devMgrSvc;
152 
153     if (serviceName == NULL) {
154         return HDF_ERR_INVALID_PARAM;
155     }
156 
157     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo) ||
158         deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
159         HDF_LOGE("device %{public}s not in configed dynamic device list", serviceName);
160         return HDF_DEV_ERR_NO_DEVICE;
161     }
162     OsalMutexLock(&hostClnt->hostLock);
163     if (hostClnt->hostService == NULL || hostClnt->hostService->DelDevice == NULL) {
164         OsalMutexUnlock(&hostClnt->hostLock);
165         HDF_LOGE("%{public}s unload %{public}s failed, hostService is null", __func__, serviceName);
166         return HDF_FAILURE;
167     }
168     ret = hostClnt->hostService->DelDevice(hostClnt->hostService, deviceInfo->deviceId);
169     if (ret != HDF_SUCCESS) {
170         OsalMutexUnlock(&hostClnt->hostLock);
171         HDF_LOGI("%{public}s:unload service %{public}s delDevice failed", __func__, serviceName);
172         return ret;
173     }
174     deviceInfo->status = HDF_SERVICE_UNUSABLE;
175     if (!HdfSListIsEmpty(&hostClnt->devices)) {
176         OsalMutexUnlock(&hostClnt->hostLock);
177         HDF_LOGD("%{public}s host %{public}s devices is not empty", __func__, hostClnt->hostName);
178         return HDF_SUCCESS;
179     }
180     if (!HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
181         OsalMutexUnlock(&hostClnt->hostLock);
182         HDF_LOGD("%{public}s the hdf_devmgr need not to stop automatically started host %{public}s", __func__,
183             hostClnt->hostName);
184         return HDF_SUCCESS;
185     }
186     hostClnt->hostPid = INVALID_PID;
187     hostClnt->hostService = NULL; // old hostService will be recycled in CleanupDiedHostResources
188     HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete);
189     OsalMutexUnlock(&hostClnt->hostLock);
190     ret = DevmgrServiceStopHost(hostClnt);
191 
192     return ret;
193 }
194 
DevmgrServiceLoadLeftDriver(struct DevmgrService * devMgrSvc)195 int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc)
196 {
197     int32_t ret;
198     struct HdfSListIterator itDeviceInfo;
199     struct HdfDeviceInfo *deviceInfo = NULL;
200     struct DevHostServiceClnt *hostClnt = NULL;
201     if (devMgrSvc == NULL) {
202         return HDF_FAILURE;
203     }
204 
205     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
206         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->unloadDevInfos);
207         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
208             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
209             if (deviceInfo->preload == DEVICE_PRELOAD_ENABLE_STEP2) {
210                 ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
211                 if (ret != HDF_SUCCESS) {
212                     HDF_LOGE("%{public}s:failed to load driver %{public}s", __func__, deviceInfo->moduleName);
213                     continue;
214                 }
215                 deviceInfo->status = HDF_SERVICE_USABLE;
216                 HdfSListIteratorRemove(&itDeviceInfo);
217             }
218         }
219     }
220     return HDF_SUCCESS;
221 }
222 
DevmgrServiceFindDeviceHost(struct IDevmgrService * inst,uint16_t hostId)223 static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrService *inst, uint16_t hostId)
224 {
225     struct DevHostServiceClnt *hostClnt = NULL;
226     struct DevmgrService *dmService = (struct DevmgrService *)inst;
227     if (dmService == NULL) {
228         HDF_LOGE("failed to find device host, dmService is null");
229         return NULL;
230     }
231 
232     DLIST_FOR_EACH_ENTRY(hostClnt, &dmService->hosts, struct DevHostServiceClnt, node) {
233         if (hostClnt->hostId == hostId) {
234             return hostClnt;
235         }
236     }
237     HDF_LOGE("cannot find host %{public}u", hostId);
238     return NULL;
239 }
240 
DevmgrServiceAttachDevice(struct IDevmgrService * inst,struct IHdfDeviceToken * token)241 static int DevmgrServiceAttachDevice(struct IDevmgrService *inst, struct IHdfDeviceToken *token)
242 {
243     struct DevHostServiceClnt *hostClnt = NULL;
244     struct DeviceTokenClnt *tokenClnt = NULL;
245 
246     if (token == NULL) {
247         return HDF_FAILURE;
248     }
249     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(token->devid));
250     if (hostClnt == NULL) {
251         HDF_LOGE("failed to attach device, hostClnt is null");
252         return HDF_FAILURE;
253     }
254     tokenClnt = DeviceTokenClntNewInstance(token);
255     if (tokenClnt == NULL) {
256         HDF_LOGE("failed to attach device, tokenClnt is null");
257         return HDF_FAILURE;
258     }
259 
260     HdfSListAdd(&hostClnt->devices, &tokenClnt->node);
261     return HDF_SUCCESS;
262 }
263 
HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode * tokenNode,uint32_t devid)264 static bool HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode *tokenNode, uint32_t devid)
265 {
266     struct DeviceTokenClnt *tokenClnt = CONTAINER_OF(tokenNode, struct DeviceTokenClnt, node);
267     return tokenClnt->tokenIf->devid == devid;
268 }
269 
DevmgrServiceDetachDevice(struct IDevmgrService * inst,devid_t devid)270 static int DevmgrServiceDetachDevice(struct IDevmgrService *inst, devid_t devid)
271 {
272     struct DevHostServiceClnt *hostClnt = NULL;
273     struct DeviceTokenClnt *tokenClnt = NULL;
274     struct HdfSListNode *tokenClntNode = NULL;
275 
276     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(devid));
277     if (hostClnt == NULL) {
278         HDF_LOGE("failed to attach device, hostClnt is null");
279         return HDF_FAILURE;
280     }
281     tokenClntNode = HdfSListSearch(&hostClnt->devices, devid, HdfSListHostSearchDeviceTokenComparer);
282     if (tokenClntNode == NULL) {
283         HDF_LOGE("devmgr detach devic not found");
284         return HDF_DEV_ERR_NO_DEVICE;
285     }
286     tokenClnt = CONTAINER_OF(tokenClntNode, struct DeviceTokenClnt, node);
287     HdfSListRemove(&hostClnt->devices, &tokenClnt->node);
288     return HDF_SUCCESS;
289 }
290 
DevmgrServiceAttachDeviceHost(struct IDevmgrService * inst,uint16_t hostId,struct IDevHostService * hostService)291 static int DevmgrServiceAttachDeviceHost(
292     struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)
293 {
294     struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
295     if (hostClnt == NULL) {
296         HDF_LOGE("failed to attach device host, hostClnt is null");
297         return HDF_FAILURE;
298     }
299     if (hostService == NULL) {
300         HDF_LOGE("failed to attach device host, hostService is null");
301         return HDF_FAILURE;
302     }
303 
304     (void)OsalMutexLock(&hostClnt->hostLock);
305     hostClnt->hostService = hostService;
306     (void)OsalMutexUnlock(&hostClnt->hostLock);
307     return DevHostServiceClntInstallDriver(hostClnt);
308 }
309 
DevmgrServiceStartDeviceHost(struct DevmgrService * devmgr,struct HdfHostInfo * hostAttr)310 static int DevmgrServiceStartDeviceHost(struct DevmgrService *devmgr, struct HdfHostInfo *hostAttr)
311 {
312     struct DevHostServiceClnt *hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);
313     if (hostClnt == NULL) {
314         HDF_LOGW("failed to create new device host client");
315         return HDF_FAILURE;
316     }
317 
318     if (HdfAttributeManagerGetDeviceList(hostClnt) != HDF_SUCCESS) {
319         HDF_LOGW("failed to get device list for host %{public}s", hostClnt->hostName);
320         return HDF_FAILURE;
321     }
322 
323     DListInsertTail(&hostClnt->node, &devmgr->hosts);
324 
325     // not start the host which only have dynamic devices
326     if (HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
327         return HDF_SUCCESS;
328     }
329 
330     if (DevmgrServiceStartHostProcess(hostClnt, false, false) != HDF_SUCCESS) {
331         HDF_LOGW("failed to start device host, host id is %{public}u", hostAttr->hostId);
332         DListRemove(&hostClnt->node);
333         DevHostServiceClntFreeInstance(hostClnt);
334         return HDF_FAILURE;
335     }
336     return HDF_SUCCESS;
337 }
338 
DevmgrServiceStartDeviceHosts(struct DevmgrService * inst)339 static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst)
340 {
341     int ret;
342     struct HdfSList hostList;
343     struct HdfSListIterator it;
344     struct HdfHostInfo *hostAttr = NULL;
345 
346     HdfSListInit(&hostList);
347     if (!HdfAttributeManagerGetHostList(&hostList)) {
348         HDF_LOGW("%{public}s: host list is null", __func__);
349         return HDF_SUCCESS;
350     }
351     HdfSListIteratorInit(&it, &hostList);
352     while (HdfSListIteratorHasNext(&it)) {
353         hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);
354         ret = DevmgrServiceStartDeviceHost(inst, hostAttr);
355         if (ret != HDF_SUCCESS) {
356             HDF_LOGW("%{public}s failed to start device host, host id is %{public}u, host name is '%{public}s'",
357                 __func__, hostAttr->hostId, hostAttr->hostName);
358         }
359     }
360     HdfSListFlush(&hostList, HdfHostInfoDelete);
361     return HDF_SUCCESS;
362 }
363 
DevmgrServiceListAllDevice(struct IDevmgrService * inst,struct HdfSBuf * reply)364 static int32_t DevmgrServiceListAllDevice(struct IDevmgrService *inst, struct HdfSBuf *reply)
365 {
366     struct DevmgrService *devMgrSvc = (struct DevmgrService *)inst;
367     struct DevHostServiceClnt *hostClnt = NULL;
368     struct HdfSListIterator iterator;
369     struct HdfSListNode *node = NULL;
370     const char *name = NULL;
371 
372     if (devMgrSvc == NULL || reply == NULL) {
373         HDF_LOGE("%{public}s failed, parameter is null", __func__);
374         return HDF_FAILURE;
375     }
376 
377     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
378         HdfSbufWriteString(reply, hostClnt->hostName);
379         HdfSbufWriteUint32(reply, hostClnt->hostId);
380         HdfSbufWriteUint32(reply, HdfSListCount(&hostClnt->devices));
381 
382         HdfSListIteratorInit(&iterator, &hostClnt->devices);
383         while (HdfSListIteratorHasNext(&iterator)) {
384             node = HdfSListIteratorNext(&iterator);
385             struct DeviceTokenClnt *tokenClnt = (struct DeviceTokenClnt *)node;
386             if (tokenClnt != NULL && tokenClnt->tokenIf != NULL) {
387                 name = (tokenClnt->tokenIf->deviceName == NULL) ? "" : tokenClnt->tokenIf->deviceName;
388                 HdfSbufWriteString(reply, name);
389                 HdfSbufWriteUint32(reply, tokenClnt->tokenIf->devid);
390                 name = (tokenClnt->tokenIf->servName == NULL) ? "" : tokenClnt->tokenIf->servName;
391                 HdfSbufWriteString(reply, name);
392             } else {
393                 HDF_LOGI("%{public}s host:%{public}s token null", __func__, hostClnt->hostName);
394             }
395         }
396     }
397     return HDF_SUCCESS;
398 }
399 
DevmgrServiceStartService(struct IDevmgrService * inst)400 int DevmgrServiceStartService(struct IDevmgrService *inst)
401 {
402     int ret;
403     struct DevmgrService *dmService = (struct DevmgrService *)inst;
404     if (dmService == NULL) {
405         HDF_LOGE("failed to start device manager service, dmService is null");
406         return HDF_FAILURE;
407     }
408 
409     ret = DevmgrServiceStartDeviceHosts(dmService);
410     int startServiceRet = DevSvcManagerStartService();
411     HDF_LOGI("start svcmgr result %{public}d. Init DeviceHosts info result: %{public}d", startServiceRet, ret);
412     return ret;
413 }
414 
DevmgrServicePowerStateChange(struct IDevmgrService * devmgrService,enum HdfPowerState powerState)415 int DevmgrServicePowerStateChange(struct IDevmgrService *devmgrService, enum HdfPowerState powerState)
416 {
417     struct DevHostServiceClnt *hostClient = NULL;
418     struct DevmgrService *devmgr = NULL;
419     int result = HDF_SUCCESS;
420 
421     if (devmgrService == NULL) {
422         return HDF_ERR_INVALID_OBJECT;
423     }
424 
425     if (!IsValidPowerState(powerState)) {
426         HDF_LOGE("%{public}s:invalid power event %{public}u", __func__, powerState);
427         return HDF_ERR_INVALID_PARAM;
428     }
429     devmgr = CONTAINER_OF(devmgrService, struct DevmgrService, super);
430 
431     if (IsPowerWakeState(powerState)) {
432         HDF_LOGI("%{public}s:wake state %{public}u", __func__, powerState);
433         DLIST_FOR_EACH_ENTRY(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
434             if (hostClient->hostService != NULL) {
435                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
436                     result = HDF_FAILURE;
437                 }
438             }
439         }
440     } else {
441         HDF_LOGI("%{public}s:suspend state %{public}u", __func__, powerState);
442         DLIST_FOR_EACH_ENTRY_REVERSE(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
443             if (hostClient->hostService != NULL) {
444                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
445                     result = HDF_FAILURE;
446                 }
447             }
448         }
449     }
450 
451     return result;
452 }
453 
DevmgrServiceConstruct(struct DevmgrService * inst)454 bool DevmgrServiceConstruct(struct DevmgrService *inst)
455 {
456     if (inst == NULL) {
457         HDF_LOGE("%{public}s:inst is null ", __func__);
458         return false;
459     }
460     struct IDevmgrService *devMgrSvcIf = NULL;
461     if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {
462         HDF_LOGE("%{public}s:failed to mutex init ", __func__);
463         return false;
464     }
465     devMgrSvcIf = (struct IDevmgrService *)inst;
466     if (devMgrSvcIf != NULL) {
467         devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;
468         devMgrSvcIf->DetachDevice = DevmgrServiceDetachDevice;
469         devMgrSvcIf->LoadDevice = DevmgrServiceLoadDevice;
470         devMgrSvcIf->UnloadDevice = DevmgrServiceUnloadDevice;
471         devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;
472         devMgrSvcIf->StartService = DevmgrServiceStartService;
473         devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;
474         devMgrSvcIf->ListAllDevice = DevmgrServiceListAllDevice;
475         DListHeadInit(&inst->hosts);
476         return true;
477     } else {
478         return false;
479     }
480 }
481 
DevmgrServiceCreate(void)482 struct HdfObject *DevmgrServiceCreate(void)
483 {
484     static bool isDevMgrServiceInit = false;
485     static struct DevmgrService devmgrServiceInstance;
486     if (!isDevMgrServiceInit) {
487         if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {
488             return NULL;
489         }
490         isDevMgrServiceInit = true;
491     }
492     return (struct HdfObject *)&devmgrServiceInstance;
493 }
494 
DevmgrServiceGetInstance(void)495 struct IDevmgrService *DevmgrServiceGetInstance(void)
496 {
497     static struct IDevmgrService *instance = NULL;
498     if (instance == NULL) {
499         instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);
500     }
501     return instance;
502 }
503 
DevmgrServiceRelease(struct HdfObject * object)504 void DevmgrServiceRelease(struct HdfObject *object)
505 {
506     struct DevmgrService *devmgrService = (struct DevmgrService *)object;
507     struct DevHostServiceClnt *hostClnt = NULL;
508     struct DevHostServiceClnt *hostClntTmp = NULL;
509     if (devmgrService == NULL) {
510         return;
511     }
512     DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &devmgrService->hosts, struct DevHostServiceClnt, node) {
513         DListRemove(&hostClnt->node);
514         DevHostServiceClntDelete(hostClnt);
515     }
516 
517     OsalMutexDestroy(&devmgrService->devMgrMutex);
518 }
519