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