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