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