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