• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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