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