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