1 /*
2 * Copyright (c) 2021-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 "svcmgr_ioservice.h"
10 #include "hdf_base.h"
11 #include "hdf_dlist.h"
12 #include "hdf_io_service_if.h"
13 #include "hdf_log.h"
14 #include "hdf_sbuf.h"
15 #include "ioservstat_listener.h"
16 #include "osal_mem.h"
17
18 struct SvcMgrIoservice {
19 struct ISvcMgrIoservice svcmgr;
20 struct HdfIoService *iosvc;
21 struct DListHead listeners;
22 };
23
ProcessListenClass(struct SvcMgrIoservice * svcmgrInst,uint16_t devClass,int cmdId)24 static int32_t ProcessListenClass(struct SvcMgrIoservice *svcmgrInst, uint16_t devClass, int cmdId)
25 {
26 struct HdfSBuf *data = HdfSbufObtainDefaultSize();
27 if (data == NULL) {
28 return HDF_ERR_MALLOC_FAIL;
29 }
30
31 (void)HdfSbufWriteUint16(data, devClass);
32 if (svcmgrInst->iosvc == NULL || svcmgrInst->iosvc->dispatcher == NULL ||
33 svcmgrInst->iosvc->dispatcher->Dispatch == NULL) {
34 HdfSbufRecycle(data);
35 return HDF_ERR_INVALID_OBJECT;
36 }
37 int32_t ret = svcmgrInst->iosvc->dispatcher->Dispatch(
38 (struct HdfObject *)svcmgrInst->iosvc, cmdId, data, NULL);
39 HdfSbufRecycle(data);
40 return ret;
41 }
42
SetListenClass(struct SvcMgrIoservice * svcmgrInst,uint16_t devClass)43 static int32_t SetListenClass(struct SvcMgrIoservice *svcmgrInst, uint16_t devClass)
44 {
45 return ProcessListenClass(svcmgrInst, devClass, SVCMGR_REGISTER_LISTENER);
46 }
47
UnSetListenClass(struct SvcMgrIoservice * svcmgrInst,uint16_t devClass)48 static int32_t UnSetListenClass(struct SvcMgrIoservice *svcmgrInst, uint16_t devClass)
49 {
50 return ProcessListenClass(svcmgrInst, devClass, SVCMGR_UNREGISTER_LISTENER);
51 }
52
SvcMgrIoserviceRegSvcStatListener(struct ISvcMgrIoservice * self,struct ServiceStatusListener * listener,uint16_t deviceClass)53 int32_t SvcMgrIoserviceRegSvcStatListener(
54 struct ISvcMgrIoservice *self, struct ServiceStatusListener *listener, uint16_t deviceClass)
55 {
56 if (self == NULL || listener == NULL || deviceClass >= DEVICE_CLASS_MAX) {
57 return HDF_ERR_INVALID_PARAM;
58 }
59
60 struct SvcMgrIoservice *svcmgrInst = CONTAINER_OF(self, struct SvcMgrIoservice, svcmgr);
61 struct IoServiceStatusListener *listenerInst
62 = CONTAINER_OF(listener, struct IoServiceStatusListener, svcstatListener);
63
64 listenerInst->deviceClass = deviceClass;
65 int ret = SetListenClass(svcmgrInst, deviceClass);
66 if (ret != HDF_SUCCESS) {
67 HDF_LOGE("failed to set listen class");
68 return ret;
69 }
70
71 return HdfDeviceRegisterEventListener(svcmgrInst->iosvc, &listenerInst->ioservListener);
72 }
73
SvcMgrIoserviceUnRegSvcStatListener(struct ISvcMgrIoservice * self,struct ServiceStatusListener * listener)74 int32_t SvcMgrIoserviceUnRegSvcStatListener(struct ISvcMgrIoservice *self, struct ServiceStatusListener *listener)
75 {
76 if (self == NULL || listener == NULL) {
77 return HDF_ERR_INVALID_PARAM;
78 }
79
80 struct SvcMgrIoservice *svcmgrInst = CONTAINER_OF(self, struct SvcMgrIoservice, svcmgr);
81 struct IoServiceStatusListener *listenerInst
82 = CONTAINER_OF(listener, struct IoServiceStatusListener, svcstatListener);
83
84 int ret = HdfDeviceUnregisterEventListener(svcmgrInst->iosvc, &listenerInst->ioservListener);
85 if (ret != HDF_SUCCESS) {
86 return ret;
87 }
88
89 if (HdfIoserviceGetListenerCount(svcmgrInst->iosvc) == 0) {
90 ret = UnSetListenClass(svcmgrInst, listenerInst->deviceClass);
91 }
92
93 return ret;
94 }
95
SvcMgrIoserviceConstruct(struct ISvcMgrIoservice * svcmgrInst)96 static void SvcMgrIoserviceConstruct(struct ISvcMgrIoservice *svcmgrInst)
97 {
98 svcmgrInst->RegisterServiceStatusListener = SvcMgrIoserviceRegSvcStatListener;
99 svcmgrInst->UnregisterServiceStatusListener = SvcMgrIoserviceUnRegSvcStatListener;
100 }
101
SvcMgrIoserviceGet(void)102 struct ISvcMgrIoservice *SvcMgrIoserviceGet(void)
103 {
104 struct SvcMgrIoservice *svcmgrInst = OsalMemCalloc(sizeof(struct SvcMgrIoservice));
105 if (svcmgrInst == NULL) {
106 return NULL;
107 }
108
109 svcmgrInst->iosvc = HdfIoServiceBind(DEV_SVCMGR_NODE);
110 if (svcmgrInst->iosvc == NULL) {
111 HDF_LOGE("ioserivce %s not exist", DEV_SVCMGR_NODE);
112 OsalMemFree(svcmgrInst);
113 return NULL;
114 }
115 SvcMgrIoserviceConstruct(&svcmgrInst->svcmgr);
116 return &svcmgrInst->svcmgr;
117 }
118
SvcMgrIoserviceRelease(struct ISvcMgrIoservice * svcmgr)119 void SvcMgrIoserviceRelease(struct ISvcMgrIoservice *svcmgr)
120 {
121 if (svcmgr == NULL) {
122 return;
123 }
124 struct SvcMgrIoservice *svcmgrInst = CONTAINER_OF(svcmgr, struct SvcMgrIoservice, svcmgr);
125 HdfIoServiceRecycle(svcmgrInst->iosvc);
126 OsalMemFree(svcmgrInst);
127 }