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