• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "devsvc_manager.h"
10 #include "devmgr_service.h"
11 #include "hdf_base.h"
12 #include "hdf_cstring.h"
13 #include "hdf_device_node.h"
14 #include "hdf_core_log.h"
15 #include "hdf_object_manager.h"
16 #include "hdf_service_record.h"
17 #include "osal_mem.h"
18 
19 #define HDF_LOG_TAG devsvc_manager
20 #define SERVICE_LIST_MAX 16
21 
DevSvcManagerSearchServiceLocked(struct IDevSvcManager * inst,uint32_t serviceKey)22 static struct DevSvcRecord *DevSvcManagerSearchServiceLocked(struct IDevSvcManager *inst, uint32_t serviceKey)
23 {
24     struct DevSvcRecord *record = NULL;
25     struct DevSvcRecord *searchResult = NULL;
26     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
27     if (devSvcManager == NULL) {
28         HDF_LOGE("failed to search service, devSvcManager is null");
29         return NULL;
30     }
31 
32     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
33         if (record->key == serviceKey) {
34             searchResult = record;
35             break;
36         }
37     }
38     return searchResult;
39 }
40 
NotifyServiceStatusLocked(struct DevSvcManager * devSvcManager,const struct DevSvcRecord * record,uint32_t status)41 static void NotifyServiceStatusLocked(
42     struct DevSvcManager *devSvcManager, const struct DevSvcRecord *record, uint32_t status)
43 {
44     struct ServStatListenerHolder *holder = NULL;
45     struct ServStatListenerHolder *tmp = NULL;
46     struct ServiceStatus svcstat = {
47         .deviceClass = record->devClass,
48         .serviceName = record->servName,
49         .status = status,
50         .info = record->servInfo,
51     };
52     HDF_LOGI("notify service status %{public}s, %{public}d", svcstat.serviceName, svcstat.status);
53     DLIST_FOR_EACH_ENTRY_SAFE(holder, tmp, &devSvcManager->svcstatListeners, struct ServStatListenerHolder, node) {
54         if ((holder->listenClass & record->devClass) && holder->NotifyStatus != NULL) {
55             if (holder->NotifyStatus(holder, &svcstat) == HDF_FAILURE) {
56                 DListRemove(&holder->node);
57                 if (holder->Recycle != NULL) {
58                     holder->Recycle(holder);
59                 }
60             }
61         }
62     }
63 }
64 
NotifyServiceStatusOnRegisterLocked(const struct DevSvcManager * devSvcManager,struct ServStatListenerHolder * listenerHolder)65 static void NotifyServiceStatusOnRegisterLocked(
66     const struct DevSvcManager *devSvcManager, struct ServStatListenerHolder *listenerHolder)
67 {
68     struct DevSvcRecord *record = NULL;
69     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
70         if ((listenerHolder->listenClass & record->devClass) == 0) {
71             continue;
72         }
73         struct ServiceStatus svcstat = {
74             .deviceClass = record->devClass,
75             .serviceName = record->servName,
76             .status = SERVIE_STATUS_START,
77             .info = record->servInfo,
78         };
79         if (listenerHolder->NotifyStatus != NULL) {
80             listenerHolder->NotifyStatus(listenerHolder, &svcstat);
81         }
82     }
83 }
84 
DevSvcManagerAddService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)85 int DevSvcManagerAddService(struct IDevSvcManager *inst,
86     struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
87 {
88     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
89     struct DevSvcRecord *record = NULL;
90     if (devSvcManager == NULL || service == NULL || servInfo == NULL || servInfo->servName == NULL) {
91         HDF_LOGE("failed to add service, input param is null");
92         return HDF_FAILURE;
93     }
94     OsalMutexLock(&devSvcManager->mutex);
95     record = DevSvcManagerSearchServiceLocked(inst, HdfStringMakeHashKey(servInfo->servName, 0));
96     if (record != NULL) {
97         // on service died will release old service object
98         record->value = service;
99         OsalMutexUnlock(&devSvcManager->mutex);
100         HDF_LOGI("%{public}s:add service %{public}s exist, only update value", __func__, servInfo->servName);
101         return HDF_SUCCESS;
102     }
103     OsalMutexUnlock(&devSvcManager->mutex);
104     record = DevSvcRecordNewInstance();
105     if (record == NULL) {
106         HDF_LOGE("failed to add service , record is null");
107         return HDF_FAILURE;
108     }
109 
110     record->key = HdfStringMakeHashKey(servInfo->servName, 0);
111     record->value = service;
112     record->devClass = servInfo->devClass;
113     record->devId = servInfo->devId;
114     record->servName = HdfStringCopy(servInfo->servName);
115     record->servInfo = HdfStringCopy(servInfo->servInfo);
116 
117     if (servInfo->interfaceDesc != NULL && strcmp(servInfo->interfaceDesc, "") != 0) {
118         record->interfaceDesc = HdfStringCopy(servInfo->interfaceDesc);
119     }
120     if (record->servName == NULL) {
121         DevSvcRecordFreeInstance(record);
122         return HDF_ERR_MALLOC_FAIL;
123     }
124     OsalMutexLock(&devSvcManager->mutex);
125     DListInsertTail(&record->entry, &devSvcManager->services);
126     NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_START);
127     OsalMutexUnlock(&devSvcManager->mutex);
128     return HDF_SUCCESS;
129 }
130 
DevSvcManagerUpdateService(struct IDevSvcManager * inst,struct HdfDeviceObject * service,const struct HdfServiceInfo * servInfo)131 int DevSvcManagerUpdateService(struct IDevSvcManager *inst,
132     struct HdfDeviceObject *service, const struct HdfServiceInfo *servInfo)
133 {
134     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
135     struct DevSvcRecord *record = NULL;
136     char *servInfoStr = NULL;
137     if (devSvcManager == NULL || service == NULL || servInfo == NULL || servInfo->servName == NULL) {
138         HDF_LOGE("failed to update service, invalid param");
139         return HDF_FAILURE;
140     }
141     OsalMutexLock(&devSvcManager->mutex);
142     record = DevSvcManagerSearchServiceLocked(inst, HdfStringMakeHashKey(servInfo->servName, 0));
143     if (record == NULL) {
144         OsalMutexUnlock(&devSvcManager->mutex);
145         return HDF_DEV_ERR_NO_DEVICE;
146     }
147 
148     if (servInfo->servInfo != NULL) {
149         servInfoStr = HdfStringCopy(servInfo->servInfo);
150         if (servInfoStr == NULL) {
151             OsalMutexUnlock(&devSvcManager->mutex);
152             return HDF_ERR_MALLOC_FAIL;
153         }
154         OsalMemFree((char *)record->servInfo);
155         record->servInfo = servInfoStr;
156     }
157 
158     record->value = service;
159     record->devClass = servInfo->devClass;
160     record->devId = servInfo->devId;
161     NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_CHANGE);
162     OsalMutexUnlock(&devSvcManager->mutex);
163     return HDF_SUCCESS;
164 }
165 
DevSvcManagerSubscribeService(struct IDevSvcManager * inst,const char * svcName,struct SubscriberCallback callBack)166 int DevSvcManagerSubscribeService(struct IDevSvcManager *inst, const char *svcName, struct SubscriberCallback callBack)
167 {
168     struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
169     struct HdfObject *deviceService = NULL;
170     if (inst == NULL || svcName == NULL || devMgrSvc == NULL) {
171         return HDF_FAILURE;
172     }
173 
174     deviceService = DevSvcManagerGetService(inst, svcName);
175     if (deviceService != NULL) {
176         if (callBack.OnServiceConnected != NULL) {
177             callBack.OnServiceConnected(callBack.deviceObject, deviceService);
178         }
179         return HDF_SUCCESS;
180     }
181 
182     return devMgrSvc->super.LoadDevice(&devMgrSvc->super, svcName);
183 }
184 
DevSvcManagerRemoveService(struct IDevSvcManager * inst,const char * svcName,const struct HdfDeviceObject * devObj)185 void DevSvcManagerRemoveService(struct IDevSvcManager *inst, const char *svcName, const struct HdfDeviceObject *devObj)
186 {
187     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
188     struct DevSvcRecord *serviceRecord = NULL;
189     uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
190     bool removeFlag = false;
191 
192     if (svcName == NULL || devSvcManager == NULL) {
193         return;
194     }
195     OsalMutexLock(&devSvcManager->mutex);
196     serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey);
197     if (serviceRecord == NULL) {
198         OsalMutexUnlock(&devSvcManager->mutex);
199         return;
200     }
201     if (devObj == NULL || (uintptr_t)devObj == (uintptr_t)serviceRecord->value) {
202         NotifyServiceStatusLocked(devSvcManager, serviceRecord, SERVIE_STATUS_STOP);
203         DListRemove(&serviceRecord->entry);
204         removeFlag = true;
205     }
206     OsalMutexUnlock(&devSvcManager->mutex);
207 
208     if (removeFlag) {
209         DevSvcRecordFreeInstance(serviceRecord);
210     } else {
211         HDF_LOGI("%{public}s %{public}s device object is out of date", __func__, svcName);
212     }
213 }
214 
DevSvcManagerGetObject(struct IDevSvcManager * inst,const char * svcName)215 struct HdfDeviceObject *DevSvcManagerGetObject(struct IDevSvcManager *inst, const char *svcName)
216 {
217     uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
218     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
219     struct DevSvcRecord *serviceRecord = NULL;
220     struct HdfDeviceObject *deviceObject = NULL;
221     if (svcName == NULL) {
222         HDF_LOGE("Get service failed, svcName is null");
223         return NULL;
224     }
225     OsalMutexLock(&devSvcManager->mutex);
226     serviceRecord = DevSvcManagerSearchServiceLocked(inst, serviceKey);
227     if (serviceRecord != NULL) {
228         deviceObject = serviceRecord->value;
229         OsalMutexUnlock(&devSvcManager->mutex);
230         return deviceObject;
231     }
232     OsalMutexUnlock(&devSvcManager->mutex);
233     return NULL;
234 }
235 
236 // only use for kernel space
DevSvcManagerListService(struct HdfSBuf * serviceNameSet,DeviceClass deviceClass)237 void DevSvcManagerListService(struct HdfSBuf *serviceNameSet, DeviceClass deviceClass)
238 {
239     struct DevSvcRecord *record = NULL;
240     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)DevSvcManagerGetInstance();
241     if (devSvcManager == NULL) {
242         HDF_LOGE("failed to list service, devSvcManager is null");
243         return;
244     }
245 
246     OsalMutexLock(&devSvcManager->mutex);
247     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
248         if (record->devClass == deviceClass) {
249             HdfSbufWriteString(serviceNameSet, record->servName);
250         }
251     }
252     OsalMutexUnlock(&devSvcManager->mutex);
253 }
254 
DevSvcManagerGetService(struct IDevSvcManager * inst,const char * svcName)255 struct HdfObject *DevSvcManagerGetService(struct IDevSvcManager *inst, const char *svcName)
256 {
257     struct HdfDeviceObject *deviceObject = DevSvcManagerGetObject(inst, svcName);
258     if (deviceObject == NULL) {
259         return NULL;
260     }
261     return (struct HdfObject *)deviceObject->service;
262 }
263 
DevSvcManagerListAllService(struct IDevSvcManager * inst,struct HdfSBuf * reply)264 void DevSvcManagerListAllService(struct IDevSvcManager *inst, struct HdfSBuf *reply)
265 {
266     struct DevSvcRecord *record = NULL;
267     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
268     if (devSvcManager == NULL || reply == NULL) {
269         HDF_LOGE("failed to list all service info, parameter is null");
270         return;
271     }
272     OsalMutexLock(&devSvcManager->mutex);
273     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
274         HdfSbufWriteString(reply, record->servName);
275         HdfSbufWriteUint16(reply, record->devClass);
276         HdfSbufWriteUint32(reply, record->devId);
277         HDF_LOGD("%{public}s 0x%{public}x %{public}d", record->servName, record->devId, record->devClass);
278     }
279     OsalMutexUnlock(&devSvcManager->mutex);
280     HDF_LOGI("%{public}s end ", __func__);
281 }
282 
DevSvcManagerListServiceByInterfaceDesc(struct IDevSvcManager * inst,const char * interfaceDesc,struct HdfSBuf * reply)283 int DevSvcManagerListServiceByInterfaceDesc(
284     struct IDevSvcManager *inst, const char *interfaceDesc, struct HdfSBuf *reply)
285 {
286     struct DevSvcRecord *record = NULL;
287     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
288     int status = HDF_SUCCESS;
289     if (devSvcManager == NULL || reply == NULL) {
290         HDF_LOGE("failed to list service collection info, parameter is null");
291         return HDF_ERR_INVALID_PARAM;
292     }
293     const char *serviceNames[SERVICE_LIST_MAX];
294     uint32_t serviceNum = 0;
295     uint32_t i;
296     OsalMutexLock(&devSvcManager->mutex);
297     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
298         if (record->interfaceDesc == NULL) {
299             HDF_LOGD("%{public}s interfacedesc is null", record->servName);
300             continue;
301         }
302         if (serviceNum >= SERVICE_LIST_MAX) {
303             status = HDF_ERR_OUT_OF_RANGE;
304             HDF_LOGE(
305                 "%{public}s: More than %{public}d services are found, but up to %{public}d services can be returned",
306                 interfaceDesc, SERVICE_LIST_MAX, SERVICE_LIST_MAX);
307             break;
308         }
309         if (strcmp(record->interfaceDesc, interfaceDesc) == 0) {
310             serviceNames[serviceNum] = record->servName;
311             serviceNum = serviceNum + 1;
312         }
313     }
314     OsalMutexUnlock(&devSvcManager->mutex);
315     HDF_LOGD("find %{public}u services interfacedesc is %{public}s", serviceNum, interfaceDesc);
316     if (!HdfSbufWriteUint32(reply, serviceNum)) {
317         HDF_LOGE("failed to write serviceNum to buffer, interfacedesc is %{public}s, serviceNum is %{public}d",
318             interfaceDesc, serviceNum);
319         return HDF_FAILURE;
320     }
321     for (i = 0; i < serviceNum; i++) {
322         HdfSbufWriteString(reply, serviceNames[i]);
323     }
324     return status;
325 }
326 
DevSvcManagerRegsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)327 int DevSvcManagerRegsterServListener(struct IDevSvcManager *inst, struct ServStatListenerHolder *listenerHolder)
328 {
329     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
330     if (devSvcManager == NULL || listenerHolder == NULL) {
331         return HDF_ERR_INVALID_PARAM;
332     }
333 
334     OsalMutexLock(&devSvcManager->mutex);
335     DListInsertTail(&listenerHolder->node, &devSvcManager->svcstatListeners);
336     NotifyServiceStatusOnRegisterLocked(devSvcManager, listenerHolder);
337     OsalMutexUnlock(&devSvcManager->mutex);
338 
339     return HDF_SUCCESS;
340 }
341 
DevSvcManagerUnregsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)342 void DevSvcManagerUnregsterServListener(struct IDevSvcManager *inst, struct ServStatListenerHolder *listenerHolder)
343 {
344     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
345     if (devSvcManager == NULL || listenerHolder == NULL) {
346         return;
347     }
348 
349     OsalMutexLock(&devSvcManager->mutex);
350     DListRemove(&listenerHolder->node);
351     OsalMutexUnlock(&devSvcManager->mutex);
352 }
353 
DevSvcManagerConstruct(struct DevSvcManager * inst)354 bool DevSvcManagerConstruct(struct DevSvcManager *inst)
355 {
356     struct IDevSvcManager *devSvcMgrIf = NULL;
357     if (inst == NULL) {
358         HDF_LOGE("%{public}s: inst is null!", __func__);
359         return false;
360     }
361     devSvcMgrIf = &inst->super;
362     devSvcMgrIf->AddService = DevSvcManagerAddService;
363     devSvcMgrIf->UpdateService = DevSvcManagerUpdateService;
364     devSvcMgrIf->SubscribeService = DevSvcManagerSubscribeService;
365     devSvcMgrIf->UnsubscribeService = NULL;
366     devSvcMgrIf->RemoveService = DevSvcManagerRemoveService;
367     devSvcMgrIf->GetService = DevSvcManagerGetService;
368     devSvcMgrIf->ListAllService = DevSvcManagerListAllService;
369     devSvcMgrIf->GetObject = DevSvcManagerGetObject;
370     devSvcMgrIf->RegsterServListener = DevSvcManagerRegsterServListener;
371     devSvcMgrIf->UnregsterServListener = DevSvcManagerUnregsterServListener;
372     devSvcMgrIf->ListServiceByInterfaceDesc = DevSvcManagerListServiceByInterfaceDesc;
373     if (OsalMutexInit(&inst->mutex) != HDF_SUCCESS) {
374         HDF_LOGE("failed to create device service manager mutex");
375         return false;
376     }
377     DListHeadInit(&inst->services);
378     DListHeadInit(&inst->svcstatListeners);
379     return true;
380 }
381 
DevSvcManagerStartService(void)382 int DevSvcManagerStartService(void)
383 {
384     int ret;
385     struct IDevSvcManager *svcmgr = DevSvcManagerGetInstance();
386 
387     if (svcmgr == NULL) {
388         return HDF_ERR_INVALID_OBJECT;
389     }
390     if (svcmgr->StartService == NULL) {
391         return HDF_SUCCESS;
392     }
393 
394     ret = svcmgr->StartService(svcmgr);
395     if (ret != HDF_SUCCESS) {
396         HDF_LOGE("failed to start service manager");
397     }
398 
399     return ret;
400 }
401 
DevSvcManagerCreate(void)402 struct HdfObject *DevSvcManagerCreate(void)
403 {
404     static bool isDevSvcManagerInit = false;
405     static struct DevSvcManager devSvcManagerInstance;
406     if (!isDevSvcManagerInit) {
407         if (!DevSvcManagerConstruct(&devSvcManagerInstance)) {
408             return NULL;
409         }
410         isDevSvcManagerInit = true;
411     }
412     return (struct HdfObject *)&devSvcManagerInstance;
413 }
414 
DevSvcManagerRelease(struct IDevSvcManager * inst)415 void DevSvcManagerRelease(struct IDevSvcManager *inst)
416 {
417     struct DevSvcManager *devSvcManager = CONTAINER_OF(inst, struct DevSvcManager, super);
418     if (inst == NULL) {
419         return;
420     }
421     struct DevSvcRecord *record = NULL;
422     struct DevSvcRecord *tmp = NULL;
423     DLIST_FOR_EACH_ENTRY_SAFE(record, tmp, &devSvcManager->services, struct DevSvcRecord, entry) {
424         DevSvcRecordFreeInstance(record);
425     }
426     OsalMutexDestroy(&devSvcManager->mutex);
427 }
428 
DevSvcManagerGetInstance(void)429 struct IDevSvcManager *DevSvcManagerGetInstance(void)
430 {
431     static struct IDevSvcManager *instance = NULL;
432     if (instance == NULL) {
433         instance = (struct IDevSvcManager *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVSVC_MANAGER);
434     }
435     return instance;
436 }
437