• 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 "devsvc_manager.h"
10 #include "devmgr_service.h"
11 #include "hdf_base.h"
12 #include "hdf_cstring.h"
13 #include "hdf_log.h"
14 #include "hdf_object_manager.h"
15 #include "hdf_service_record.h"
16 #include "hdf_device_node.h"
17 #include "osal_mem.h"
18 
19 #define HDF_LOG_TAG devsvc_manager
20 
DevSvcManagerSearchService(struct IDevSvcManager * inst,uint32_t serviceKey)21 static struct DevSvcRecord *DevSvcManagerSearchService(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     OsalMutexLock(&devSvcManager->mutex);
32     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
33         if (record->key == serviceKey) {
34             searchResult = record;
35             break;
36         }
37     }
38     OsalMutexUnlock(&devSvcManager->mutex);
39     return searchResult;
40 }
41 
NotifyServiceStatusLocked(struct DevSvcManager * devSvcManager,struct DevSvcRecord * record,uint32_t status)42 static void NotifyServiceStatusLocked(struct DevSvcManager *devSvcManager,
43     struct DevSvcRecord *record, uint32_t status)
44 {
45     struct ServStatListenerHolder *holder = NULL;
46     struct ServStatListenerHolder *tmp = NULL;
47     struct ServiceStatus svcstat = {
48         .deviceClass = record->devClass,
49         .serviceName = record->servName,
50         .status = status,
51         .info = record->servInfo,
52     };
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(struct DevSvcManager * devSvcManager,struct ServStatListenerHolder * listenerHolder)65 static void NotifyServiceStatusOnRegisterLocked(struct DevSvcManager *devSvcManager,
66     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,const char * servName,uint16_t devClass,struct HdfDeviceObject * service,const char * servInfo)85 int DevSvcManagerAddService(struct IDevSvcManager *inst, const char *servName,
86     uint16_t devClass, struct HdfDeviceObject *service, const char *servInfo)
87 {
88     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
89     struct DevSvcRecord *record = NULL;
90     if (devSvcManager == NULL || service == NULL || servName == NULL) {
91         HDF_LOGE("failed to add service, input param is null");
92         return HDF_FAILURE;
93     }
94     record = DevSvcManagerSearchService(inst, HdfStringMakeHashKey(servName, 0));
95     if (record != NULL) {
96         HDF_LOGI("%s:add service %s exist, only update value", __func__, servName);
97         // on service died will release old service object
98         record->value = service;
99         return HDF_SUCCESS;
100     }
101     record = DevSvcRecordNewInstance();
102     if (record == NULL) {
103         HDF_LOGE("failed to add service , record is null");
104         return HDF_FAILURE;
105     }
106 
107     record->key = HdfStringMakeHashKey(servName, 0);
108     record->value = service;
109     record->devClass = devClass;
110     record->servName = HdfStringCopy(servName);
111     record->servInfo = HdfStringCopy(servInfo);
112     if (record->servName == NULL) {
113         DevSvcRecordFreeInstance(record);
114         return HDF_ERR_MALLOC_FAIL;
115     }
116     OsalMutexLock(&devSvcManager->mutex);
117     DListInsertTail(&record->entry, &devSvcManager->services);
118     NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_START);
119     OsalMutexUnlock(&devSvcManager->mutex);
120     return HDF_SUCCESS;
121 }
122 
DevSvcManagerUpdateService(struct IDevSvcManager * inst,const char * servName,uint16_t devClass,struct HdfDeviceObject * service,const char * servInfo)123 int DevSvcManagerUpdateService(struct IDevSvcManager *inst, const char *servName,
124     uint16_t devClass, struct HdfDeviceObject *service, const char *servInfo)
125 {
126     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
127     struct DevSvcRecord *record = NULL;
128     char *servInfoStr = NULL;
129     if (devSvcManager == NULL || service == NULL || servName == NULL) {
130         HDF_LOGE("failed to update service, invalid param");
131         return HDF_FAILURE;
132     }
133 
134     record = DevSvcManagerSearchService(inst, HdfStringMakeHashKey(servName, 0));
135     if (record == NULL) {
136         return HDF_DEV_ERR_NO_DEVICE;
137     }
138 
139     servInfoStr = HdfStringCopy(servInfo);
140     if (servInfoStr == NULL) {
141         return HDF_ERR_MALLOC_FAIL;
142     }
143     OsalMemFree((char *)record->servInfo);
144 
145     record->value = service;
146     record->devClass = devClass;
147     record->servInfo = servInfoStr;
148     OsalMutexLock(&devSvcManager->mutex);
149     NotifyServiceStatusLocked(devSvcManager, record, SERVIE_STATUS_CHANGE);
150     OsalMutexUnlock(&devSvcManager->mutex);
151     return HDF_SUCCESS;
152 }
153 
DevSvcManagerSubscribeService(struct IDevSvcManager * inst,const char * svcName,struct SubscriberCallback callBack)154 int DevSvcManagerSubscribeService(struct IDevSvcManager *inst, const char *svcName, struct SubscriberCallback callBack)
155 {
156     struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
157     struct HdfObject *deviceService = NULL;
158     if (inst == NULL || svcName == NULL || devMgrSvc == NULL) {
159         return HDF_FAILURE;
160     }
161 
162     deviceService = DevSvcManagerGetService(inst, svcName);
163     if (deviceService != NULL) {
164         if (callBack.OnServiceConnected != NULL) {
165             callBack.OnServiceConnected(callBack.deviceObject, deviceService);
166         }
167         return HDF_SUCCESS;
168     }
169 
170     return devMgrSvc->super.LoadDevice(&devMgrSvc->super, svcName);
171 }
172 
DevSvcManagerRemoveService(struct IDevSvcManager * inst,const char * svcName)173 void DevSvcManagerRemoveService(struct IDevSvcManager *inst, const char *svcName)
174 {
175     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
176     struct DevSvcRecord *serviceRecord = NULL;
177     uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
178 
179     if (svcName == NULL || devSvcManager == NULL) {
180         return;
181     }
182     serviceRecord = DevSvcManagerSearchService(inst, serviceKey);
183     if (serviceRecord == NULL) {
184         return;
185     }
186     OsalMutexLock(&devSvcManager->mutex);
187     NotifyServiceStatusLocked(devSvcManager, serviceRecord, SERVIE_STATUS_STOP);
188     DListRemove(&serviceRecord->entry);
189     OsalMutexUnlock(&devSvcManager->mutex);
190 
191     DevSvcRecordFreeInstance(serviceRecord);
192 }
193 
DevSvcManagerGetObject(struct IDevSvcManager * inst,const char * svcName)194 struct HdfDeviceObject *DevSvcManagerGetObject(struct IDevSvcManager *inst, const char *svcName)
195 {
196     uint32_t serviceKey = HdfStringMakeHashKey(svcName, 0);
197     struct DevSvcRecord *serviceRecord = NULL;
198     if (svcName == NULL) {
199         HDF_LOGE("Get service failed, svcName is null");
200         return NULL;
201     }
202     serviceRecord = DevSvcManagerSearchService(inst, serviceKey);
203     if (serviceRecord != NULL) {
204         return serviceRecord->value;
205     }
206     return NULL;
207 }
208 
209 // only use for kernel space
DevSvcManagerListService(struct HdfSBuf * serviecNameSet,DeviceClass deviceClass)210 void DevSvcManagerListService(struct HdfSBuf *serviecNameSet, DeviceClass deviceClass)
211 {
212     struct DevSvcRecord *record = NULL;
213     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)DevSvcManagerGetInstance();
214     if (devSvcManager == NULL) {
215         HDF_LOGE("failed to list service, devSvcManager is null");
216         return;
217     }
218 
219     OsalMutexLock(&devSvcManager->mutex);
220     DLIST_FOR_EACH_ENTRY(record, &devSvcManager->services, struct DevSvcRecord, entry) {
221         if (record->devClass == deviceClass) {
222             HdfSbufWriteString(serviecNameSet, record->servName);
223         }
224     }
225     OsalMutexUnlock(&devSvcManager->mutex);
226 }
227 
DevSvcManagerGetService(struct IDevSvcManager * inst,const char * svcName)228 struct HdfObject *DevSvcManagerGetService(struct IDevSvcManager *inst, const char *svcName)
229 {
230     struct HdfDeviceObject *deviceObject = DevSvcManagerGetObject(inst, svcName);
231     if (deviceObject == NULL) {
232         return NULL;
233     }
234     return (struct HdfObject *)deviceObject->service;
235 }
236 
DevSvcManagerRegsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)237 int DevSvcManagerRegsterServListener(struct IDevSvcManager *inst,
238     struct ServStatListenerHolder *listenerHolder)
239 {
240     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
241     if (devSvcManager == NULL || listenerHolder == NULL) {
242         return HDF_ERR_INVALID_PARAM;
243     }
244 
245     OsalMutexLock(&devSvcManager->mutex);
246     DListInsertTail(&listenerHolder->node, &devSvcManager->svcstatListeners);
247     NotifyServiceStatusOnRegisterLocked(devSvcManager, listenerHolder);
248     OsalMutexUnlock(&devSvcManager->mutex);
249 
250     return HDF_SUCCESS;
251 }
252 
DevSvcManagerUnregsterServListener(struct IDevSvcManager * inst,struct ServStatListenerHolder * listenerHolder)253 void DevSvcManagerUnregsterServListener(struct IDevSvcManager *inst,
254     struct ServStatListenerHolder *listenerHolder)
255 {
256     struct DevSvcManager *devSvcManager = (struct DevSvcManager *)inst;
257     if (devSvcManager == NULL || listenerHolder == NULL) {
258         return;
259     }
260 
261     OsalMutexLock(&devSvcManager->mutex);
262     DListRemove(&listenerHolder->node);
263     OsalMutexUnlock(&devSvcManager->mutex);
264 }
265 
DevSvcManagerConstruct(struct DevSvcManager * inst)266 bool DevSvcManagerConstruct(struct DevSvcManager *inst)
267 {
268     struct IDevSvcManager *devSvcMgrIf = NULL;
269     if (inst == NULL) {
270         HDF_LOGE("%s: inst is null!", __func__);
271         return false;
272     }
273     devSvcMgrIf = &inst->super;
274     devSvcMgrIf->AddService = DevSvcManagerAddService;
275     devSvcMgrIf->UpdateService = DevSvcManagerUpdateService;
276     devSvcMgrIf->SubscribeService = DevSvcManagerSubscribeService;
277     devSvcMgrIf->UnsubscribeService = NULL;
278     devSvcMgrIf->RemoveService = DevSvcManagerRemoveService;
279     devSvcMgrIf->GetService = DevSvcManagerGetService;
280     devSvcMgrIf->GetObject = DevSvcManagerGetObject;
281     devSvcMgrIf->RegsterServListener = DevSvcManagerRegsterServListener;
282     devSvcMgrIf->UnregsterServListener = DevSvcManagerUnregsterServListener;
283     if (OsalMutexInit(&inst->mutex) != HDF_SUCCESS) {
284         HDF_LOGE("failed to create device service manager mutex");
285         return false;
286     }
287     DListHeadInit(&inst->services);
288     DListHeadInit(&inst->svcstatListeners);
289     return true;
290 }
291 
DevSvcManagerStartService(void)292 int DevSvcManagerStartService(void)
293 {
294     int ret;
295     struct IDevSvcManager *svcmgr = DevSvcManagerGetInstance();
296 
297     if (svcmgr == NULL) {
298         return HDF_ERR_INVALID_OBJECT;
299     }
300     if (svcmgr->StartService == NULL) {
301         return HDF_SUCCESS;
302     }
303 
304     ret = svcmgr->StartService(svcmgr);
305     if (ret != HDF_SUCCESS) {
306         HDF_LOGE("failed to start service manager");
307     }
308 
309     return ret;
310 }
311 
DevSvcManagerCreate(void)312 struct HdfObject *DevSvcManagerCreate(void)
313 {
314     static bool isDevSvcManagerInit = false;
315     static struct DevSvcManager devSvcManagerInstance;
316     if (!isDevSvcManagerInit) {
317         if (!DevSvcManagerConstruct(&devSvcManagerInstance)) {
318             return NULL;
319         }
320         isDevSvcManagerInit = true;
321     }
322     return (struct HdfObject *)&devSvcManagerInstance;
323 }
324 
DevSvcManagerRelease(struct IDevSvcManager * inst)325 void DevSvcManagerRelease(struct IDevSvcManager *inst)
326 {
327     struct DevSvcManager *devSvcManager = CONTAINER_OF(inst, struct DevSvcManager, super);
328     if (inst == NULL) {
329         return;
330     }
331     struct DevSvcRecord *record = NULL;
332     struct DevSvcRecord *tmp = NULL;
333     DLIST_FOR_EACH_ENTRY_SAFE(record, tmp, &devSvcManager->services, struct DevSvcRecord, entry) {
334         DevSvcRecordFreeInstance(record);
335     }
336     OsalMutexDestroy(&devSvcManager->mutex);
337 }
338 
DevSvcManagerGetInstance()339 struct IDevSvcManager *DevSvcManagerGetInstance()
340 {
341     static struct IDevSvcManager *instance = NULL;
342     if (instance == NULL) {
343         instance = (struct IDevSvcManager *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVSVC_MANAGER);
344     }
345     return instance;
346 }
347