1 /*
2 * Copyright (c) 2020-2021 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
DevmgrServiceDynamicDevInfoFound(const char * svcName,struct DevHostServiceClnt ** targetHostClnt,struct HdfDeviceInfo ** targetDeviceInfo)23 static bool DevmgrServiceDynamicDevInfoFound(
24 const char *svcName, struct DevHostServiceClnt **targetHostClnt, struct HdfDeviceInfo **targetDeviceInfo)
25 {
26 struct HdfSListIterator itDeviceInfo;
27 struct HdfDeviceInfo *deviceInfo = NULL;
28 struct DevHostServiceClnt *hostClnt = NULL;
29 struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
30 if (devMgrSvc == NULL) {
31 return false;
32 }
33
34 DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
35 HdfSListIteratorInit(&itDeviceInfo, &hostClnt->dynamicDevInfos);
36 while (HdfSListIteratorHasNext(&itDeviceInfo)) {
37 deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
38 if (strcmp(deviceInfo->svcName, svcName) == 0) {
39 *targetDeviceInfo = deviceInfo;
40 *targetHostClnt = hostClnt;
41 return true;
42 }
43 }
44 }
45
46 return false;
47 }
48
49 #define WAIT_HOST_SLEEP_TIME 1 // ms
50 #define WAIT_HOST_SLEEP_CNT 300
DevmgrServiceStartHostProcess(struct DevHostServiceClnt * hostClnt,bool sync)51 static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bool sync)
52 {
53 int waitCount = WAIT_HOST_SLEEP_CNT;
54 struct IDriverInstaller *installer = DriverInstallerGetInstance();
55 if (installer == NULL || installer->StartDeviceHost == NULL) {
56 HDF_LOGE("invalid installer");
57 return HDF_FAILURE;
58 }
59
60 hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName);
61 if (hostClnt->hostPid == HDF_FAILURE) {
62 HDF_LOGW("failed to start device host(%s, %u)", hostClnt->hostName, hostClnt->hostId);
63 return HDF_FAILURE;
64 }
65 hostClnt->stopFlag = false;
66 if (!sync) {
67 return HDF_SUCCESS;
68 }
69
70 while (hostClnt->hostService == NULL && waitCount > 0) {
71 OsalMSleep(WAIT_HOST_SLEEP_TIME);
72 waitCount--;
73 }
74
75 if (waitCount <= 0) {
76 HDF_LOGE("wait host(%s, %d) attach timeout", hostClnt->hostName, hostClnt->hostId);
77 return HDF_ERR_TIMEOUT;
78 }
79
80 return HDF_SUCCESS;
81 }
82
DevmgrServiceLoadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)83 static int DevmgrServiceLoadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
84 {
85 struct HdfDeviceInfo *deviceInfo = NULL;
86 struct DevHostServiceClnt *hostClnt = NULL;
87 (void)devMgrSvc;
88
89 if (serviceName == NULL) {
90 return HDF_ERR_INVALID_PARAM;
91 }
92
93 if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo)) {
94 HDF_LOGE("device %s not in configed device list", serviceName);
95 return HDF_DEV_ERR_NO_DEVICE;
96 }
97
98 if (deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
99 HDF_LOGE("device %s not an dynamic load device", serviceName);
100 return HDF_DEV_ERR_NORANGE;
101 }
102
103 if (hostClnt->hostPid < 0 && DevmgrServiceStartHostProcess(hostClnt, true) != HDF_SUCCESS) {
104 HDF_LOGW("failed to start device host(%s, %u)", hostClnt->hostName, hostClnt->hostId);
105 return HDF_FAILURE;
106 }
107
108 if (hostClnt->hostService == NULL) {
109 return HDF_FAILURE;
110 }
111
112 return hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
113 }
114
DevmgrServiceStopHost(struct DevHostServiceClnt * hostClnt)115 static int DevmgrServiceStopHost(struct DevHostServiceClnt *hostClnt)
116 {
117 struct IDriverInstaller *installer = DriverInstallerGetInstance();
118 if (installer == NULL || installer->StopDeviceHost == NULL) {
119 HDF_LOGE("invalid installer");
120 return HDF_FAILURE;
121 }
122 installer->StopDeviceHost(hostClnt->hostId, hostClnt->hostName);
123 hostClnt->stopFlag = true;
124 return HDF_SUCCESS;
125 }
126
DevmgrServiceUnloadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)127 static int DevmgrServiceUnloadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
128 {
129 struct HdfDeviceInfo *deviceInfo = NULL;
130 struct DevHostServiceClnt *hostClnt = NULL;
131 bool isHostEmpty = false;
132 int ret;
133 (void)devMgrSvc;
134
135 if (serviceName == NULL) {
136 return HDF_ERR_INVALID_PARAM;
137 }
138
139 if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo) ||
140 deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
141 HDF_LOGE("device %s not in configed dynamic device list", serviceName);
142 return HDF_DEV_ERR_NO_DEVICE;
143 }
144
145 if (hostClnt->hostService == NULL) {
146 return HDF_FAILURE;
147 }
148 ret = hostClnt->hostService->DelDevice(hostClnt->hostService, deviceInfo->deviceId);
149 if (ret != HDF_SUCCESS) {
150 HDF_LOGI("%{public}s:unload service %{public}s delDevice failed", __func__, serviceName);
151 return ret;
152 }
153
154 isHostEmpty = HdfSListIsEmpty(&hostClnt->devices);
155 if (!isHostEmpty) {
156 HDF_LOGI("%{public}s host %{public}s devices is not empty", __func__, hostClnt->hostName);
157 return HDF_SUCCESS;
158 }
159 return DevmgrServiceStopHost(hostClnt);
160 }
161
DevmgrServiceLoadLeftDriver(struct DevmgrService * devMgrSvc)162 int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc)
163 {
164 int32_t ret;
165 struct HdfSListIterator itDeviceInfo;
166 struct HdfDeviceInfo *deviceInfo = NULL;
167 struct DevHostServiceClnt *hostClnt = NULL;
168 if (devMgrSvc == NULL) {
169 return HDF_FAILURE;
170 }
171
172 DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
173 HdfSListIteratorInit(&itDeviceInfo, &hostClnt->unloadDevInfos);
174 while (HdfSListIteratorHasNext(&itDeviceInfo)) {
175 deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
176 if (deviceInfo->preload == DEVICE_PRELOAD_ENABLE_STEP2) {
177 ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
178 if (ret != HDF_SUCCESS) {
179 HDF_LOGE("%s:failed to load driver %s", __func__, deviceInfo->moduleName);
180 continue;
181 }
182 HdfSListIteratorRemove(&itDeviceInfo);
183 }
184 }
185 }
186 return HDF_SUCCESS;
187 }
188
DevmgrServiceFindDeviceHost(struct IDevmgrService * inst,uint16_t hostId)189 static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrService *inst, uint16_t hostId)
190 {
191 struct DevHostServiceClnt *hostClnt = NULL;
192 struct DevmgrService *dmService = (struct DevmgrService *)inst;
193 if (dmService == NULL) {
194 HDF_LOGE("failed to find device host, dmService is null");
195 return NULL;
196 }
197
198 DLIST_FOR_EACH_ENTRY(hostClnt, &dmService->hosts, struct DevHostServiceClnt, node) {
199 if (hostClnt->hostId == hostId) {
200 return hostClnt;
201 }
202 }
203 HDF_LOGE("cannot find host %u", hostId);
204 return NULL;
205 }
206
DevmgrServiceAttachDevice(struct IDevmgrService * inst,struct IHdfDeviceToken * token)207 static int DevmgrServiceAttachDevice(struct IDevmgrService *inst, struct IHdfDeviceToken *token)
208 {
209 struct DevHostServiceClnt *hostClnt = NULL;
210 struct DeviceTokenClnt *tokenClnt = NULL;
211
212 hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(token->devid));
213 if (hostClnt == NULL) {
214 HDF_LOGE("failed to attach device, hostClnt is null");
215 return HDF_FAILURE;
216 }
217 tokenClnt = DeviceTokenClntNewInstance(token);
218 if (tokenClnt == NULL) {
219 HDF_LOGE("failed to attach device, tokenClnt is null");
220 return HDF_FAILURE;
221 }
222
223 HdfSListAdd(&hostClnt->devices, &tokenClnt->node);
224 return HDF_SUCCESS;
225 }
226
HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode * tokenNode,uint32_t devid)227 static bool HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode *tokenNode, uint32_t devid)
228 {
229 struct DeviceTokenClnt *tokenClnt = CONTAINER_OF(tokenNode, struct DeviceTokenClnt, node);
230 return tokenClnt->tokenIf->devid == devid;
231 }
232
DevmgrServiceDetachDevice(struct IDevmgrService * inst,devid_t devid)233 static int DevmgrServiceDetachDevice(struct IDevmgrService *inst, devid_t devid)
234 {
235 struct DevHostServiceClnt *hostClnt = NULL;
236 struct DeviceTokenClnt *tokenClnt = NULL;
237 struct HdfSListNode *tokenClntNode = NULL;
238
239 hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(devid));
240 if (hostClnt == NULL) {
241 HDF_LOGE("failed to attach device, hostClnt is null");
242 return HDF_FAILURE;
243 }
244 tokenClntNode = HdfSListSearch(&hostClnt->devices, devid, HdfSListHostSearchDeviceTokenComparer);
245 if (tokenClntNode == NULL) {
246 HDF_LOGE("devmgr detach device %x not found", devid);
247 return HDF_DEV_ERR_NO_DEVICE;
248 }
249 tokenClnt = CONTAINER_OF(tokenClntNode, struct DeviceTokenClnt, node);
250 HdfSListRemove(&hostClnt->devices, &tokenClnt->node);
251 return HDF_SUCCESS;
252 }
253
DevmgrServiceAttachDeviceHost(struct IDevmgrService * inst,uint16_t hostId,struct IDevHostService * hostService)254 static int DevmgrServiceAttachDeviceHost(
255 struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)
256 {
257 struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
258 if (hostClnt == NULL) {
259 HDF_LOGE("failed to attach device host, hostClnt is null");
260 return HDF_FAILURE;
261 }
262 if (hostService == NULL) {
263 HDF_LOGE("failed to attach device host, hostService is null");
264 return HDF_FAILURE;
265 }
266
267 hostClnt->hostService = hostService;
268 return DevHostServiceClntInstallDriver(hostClnt);
269 }
270
DevmgrServiceStartDeviceHost(struct DevmgrService * devmgr,struct HdfHostInfo * hostAttr)271 static int DevmgrServiceStartDeviceHost(struct DevmgrService *devmgr, struct HdfHostInfo *hostAttr)
272 {
273 struct DevHostServiceClnt *hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);
274 if (hostClnt == NULL) {
275 HDF_LOGW("failed to create new device host client");
276 return HDF_FAILURE;
277 }
278
279 if (HdfAttributeManagerGetDeviceList(hostClnt) != HDF_SUCCESS) {
280 HDF_LOGW("failed to get device list for host %s", hostClnt->hostName);
281 return HDF_FAILURE;
282 }
283
284 DListInsertTail(&hostClnt->node, &devmgr->hosts);
285
286 // not start the host which only have dynamic deivces
287 if (HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
288 return HDF_SUCCESS;
289 }
290
291 if (DevmgrServiceStartHostProcess(hostClnt, false) != HDF_SUCCESS) {
292 HDF_LOGW("failed to start device host, host id is %u", hostAttr->hostId);
293 DListRemove(&hostClnt->node);
294 DevHostServiceClntFreeInstance(hostClnt);
295 return HDF_FAILURE;
296 }
297 return HDF_SUCCESS;
298 }
299
DevmgrServiceStartDeviceHosts(struct DevmgrService * inst)300 static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst)
301 {
302 int ret;
303 struct HdfSList hostList;
304 struct HdfSListIterator it;
305 struct HdfHostInfo *hostAttr = NULL;
306
307 HdfSListInit(&hostList);
308 if (!HdfAttributeManagerGetHostList(&hostList)) {
309 HDF_LOGW("%s: host list is null", __func__);
310 return HDF_SUCCESS;
311 }
312 HdfSListIteratorInit(&it, &hostList);
313 while (HdfSListIteratorHasNext(&it)) {
314 hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);
315 ret = DevmgrServiceStartDeviceHost(inst, hostAttr);
316 if (ret != HDF_SUCCESS) {
317 HDF_LOGW("%s failed to start device host, host id is %u, host name is '%s'", __func__, hostAttr->hostId,
318 hostAttr->hostName);
319 }
320 }
321 HdfSListFlush(&hostList, HdfHostInfoDelete);
322 return HDF_SUCCESS;
323 }
324
DevmgrServiceStartService(struct IDevmgrService * inst)325 int DevmgrServiceStartService(struct IDevmgrService *inst)
326 {
327 int ret;
328 struct DevmgrService *dmService = (struct DevmgrService *)inst;
329 if (dmService == NULL) {
330 HDF_LOGE("failed to start device manager service, dmService is null");
331 return HDF_FAILURE;
332 }
333
334 ret = DevSvcManagerStartService();
335 HDF_LOGI("start svcmgr result %d", ret);
336
337 return DevmgrServiceStartDeviceHosts(dmService);
338 }
339
DevmgrServicePowerStateChange(struct IDevmgrService * devmgrService,enum HdfPowerState powerState)340 int DevmgrServicePowerStateChange(struct IDevmgrService *devmgrService, enum HdfPowerState powerState)
341 {
342 struct DevHostServiceClnt *hostClient = NULL;
343 struct DevmgrService *devmgr = NULL;
344 int result = HDF_SUCCESS;
345
346 if (devmgrService == NULL) {
347 return HDF_ERR_INVALID_OBJECT;
348 }
349
350 if (!IsValidPowerState(powerState)) {
351 HDF_LOGE("%s:invalid power event %u", __func__, powerState);
352 return HDF_ERR_INVALID_PARAM;
353 }
354 devmgr = CONTAINER_OF(devmgrService, struct DevmgrService, super);
355
356 if (IsPowerWakeState(powerState)) {
357 HDF_LOGI("%s:wake state %u", __func__, powerState);
358 DLIST_FOR_EACH_ENTRY(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
359 if (hostClient->hostService != NULL) {
360 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
361 result = HDF_FAILURE;
362 }
363 }
364 }
365 } else {
366 HDF_LOGI("%s:suspend state %u", __func__, powerState);
367 DLIST_FOR_EACH_ENTRY_REVERSE(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
368 if (hostClient->hostService != NULL) {
369 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
370 result = HDF_FAILURE;
371 }
372 }
373 }
374 }
375
376 return result;
377 }
378
DevmgrServiceConstruct(struct DevmgrService * inst)379 bool DevmgrServiceConstruct(struct DevmgrService *inst)
380 {
381 struct IDevmgrService *devMgrSvcIf = NULL;
382 if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {
383 HDF_LOGE("%s:failed to mutex init ", __func__);
384 return false;
385 }
386 devMgrSvcIf = (struct IDevmgrService *)inst;
387 if (devMgrSvcIf != NULL) {
388 devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;
389 devMgrSvcIf->DetachDevice = DevmgrServiceDetachDevice;
390 devMgrSvcIf->LoadDevice = DevmgrServiceLoadDevice;
391 devMgrSvcIf->UnloadDevice = DevmgrServiceUnloadDevice;
392 devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;
393 devMgrSvcIf->StartService = DevmgrServiceStartService;
394 devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;
395 DListHeadInit(&inst->hosts);
396 return true;
397 } else {
398 return false;
399 }
400 }
401
DevmgrServiceCreate(void)402 struct HdfObject *DevmgrServiceCreate(void)
403 {
404 static bool isDevMgrServiceInit = false;
405 static struct DevmgrService devmgrServiceInstance;
406 if (!isDevMgrServiceInit) {
407 if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {
408 return NULL;
409 }
410 isDevMgrServiceInit = true;
411 }
412 return (struct HdfObject *)&devmgrServiceInstance;
413 }
414
DevmgrServiceGetInstance(void)415 struct IDevmgrService *DevmgrServiceGetInstance(void)
416 {
417 static struct IDevmgrService *instance = NULL;
418 if (instance == NULL) {
419 instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);
420 }
421 return instance;
422 }
423
DevmgrServiceRelease(struct HdfObject * object)424 void DevmgrServiceRelease(struct HdfObject *object)
425 {
426 struct DevmgrService *devmgrService = (struct DevmgrService *)object;
427 struct DevHostServiceClnt *hostClnt = NULL;
428 struct DevHostServiceClnt *hostClntTmp = NULL;
429 if (devmgrService == NULL) {
430 return;
431 }
432 DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &devmgrService->hosts, struct DevHostServiceClnt, node) {
433 DListRemove(&hostClnt->node);
434 DevHostServiceClntDelete(hostClnt);
435 }
436
437 OsalMutexDestroy(&devmgrService->devMgrMutex);
438 }
439