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