1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <devsvc_manager_proxy.h>
17 #include <devsvc_manager_stub.h>
18 #include <hdf_base.h>
19 #include <hdf_log.h>
20 #include <osal_mem.h>
21 #include "hdf_cstring.h"
22 #include "hdf_service_status.h"
23 #include "servmgr_hdi.h"
24
25 #define SERVICE_LIST_MAX 16
26
27 struct HDIServiceManagerClient {
28 struct HDIServiceManager iservmgr;
29 struct HdfRemoteService *remote;
30 };
31 int ServiceStatusListenerMarshalling(struct ServiceStatusListener *listener, struct HdfSBuf *buf);
32
ServiceManagerHdiCall(struct HDIServiceManagerClient * servMgrClient,int32_t id,struct HdfSBuf * data,struct HdfSBuf * reply)33 static int32_t ServiceManagerHdiCall(struct HDIServiceManagerClient *servMgrClient, int32_t id,
34 struct HdfSBuf *data, struct HdfSBuf *reply)
35 {
36 if (servMgrClient->remote == NULL || servMgrClient->remote->dispatcher == NULL ||
37 servMgrClient->remote->dispatcher->Dispatch == NULL) {
38 return HDF_ERR_INVALID_OBJECT;
39 }
40
41 return servMgrClient->remote->dispatcher->Dispatch(servMgrClient->remote, id, data, reply);
42 }
43
HdiServiceSetGetInstance(const uint32_t serviceNum)44 static struct HdiServiceSet *HdiServiceSetGetInstance(const uint32_t serviceNum)
45 {
46 struct HdiServiceSet *serviceSet = OsalMemAlloc(sizeof(struct HdiServiceSet));
47 if (serviceSet == NULL) {
48 HDF_LOGE("%{public}s: OOM", __func__);
49 return NULL;
50 }
51 serviceSet->serviceNames = OsalMemCalloc(sizeof(char *) * serviceNum);
52 if (serviceSet->serviceNames == NULL) {
53 HDF_LOGE("%{public}s: OOM", __func__);
54 HdiServiceSetRelease(serviceSet);
55 return NULL;
56 }
57 serviceSet->count = serviceNum;
58 return serviceSet;
59 }
60
HdiServiceSetUnMarshalling(struct HdfSBuf * buf,struct HdiServiceSet * serviceSet)61 static int32_t HdiServiceSetUnMarshalling(struct HdfSBuf *buf, struct HdiServiceSet *serviceSet)
62 {
63 for (uint32_t i = 0; i < serviceSet->count; i++) {
64 const char *serviceName = HdfSbufReadString(buf);
65 if (serviceName == NULL) {
66 break;
67 }
68 serviceSet->serviceNames[i] = HdfStringCopy(serviceName);
69 }
70
71 return HDF_SUCCESS;
72 }
73
HDIServMgrListServiceByInterfaceDesc(struct HDIServiceManager * iServMgr,const char * interfaceDesc)74 struct HdiServiceSet *HDIServMgrListServiceByInterfaceDesc(
75 struct HDIServiceManager *iServMgr, const char *interfaceDesc)
76 {
77 if (iServMgr == NULL || interfaceDesc == NULL || strlen(interfaceDesc) == 0) {
78 return NULL;
79 }
80 struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(iServMgr, struct HDIServiceManagerClient, iservmgr);
81 struct HdiServiceSet *serviceSet = NULL;
82 struct HdfSBuf *data = NULL;
83 struct HdfSBuf *reply = NULL;
84 uint32_t serviceNum = 0;
85
86 do {
87 data = HdfSbufTypedObtain(SBUF_IPC);
88 reply = HdfSbufTypedObtain(SBUF_IPC);
89 if (data == NULL || reply == NULL) {
90 break;
91 }
92 if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
93 !HdfSbufWriteString(data, interfaceDesc)) {
94 break;
95 }
96 int32_t status =
97 ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_LIST_SERVICE_BY_INTERFACEDESC, data, reply);
98 if (status != HDF_SUCCESS) {
99 HDF_LOGE("%{public}s: failed to get %{public}s service collection, the status is %{public}d", __func__,
100 interfaceDesc, status);
101 break;
102 }
103 if (!HdfSbufReadUint32(reply, &serviceNum)) {
104 break;
105 }
106 if (serviceNum == 0 || serviceNum > SERVICE_LIST_MAX) {
107 break;
108 }
109 serviceSet = HdiServiceSetGetInstance(serviceNum);
110 if (serviceSet == NULL) {
111 break;
112 }
113 HdiServiceSetUnMarshalling(reply, serviceSet);
114 } while (0);
115
116 HdfSbufRecycle(reply);
117 HdfSbufRecycle(data);
118
119 return serviceSet;
120 }
121
HDIServMgrGetService(struct HDIServiceManager * iServMgr,const char * serviceName)122 struct HdfRemoteService *HDIServMgrGetService(struct HDIServiceManager *iServMgr, const char* serviceName)
123 {
124 if (iServMgr == NULL || serviceName == NULL) {
125 return NULL;
126 }
127 struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(iServMgr, struct HDIServiceManagerClient, iservmgr);
128 struct HdfSBuf *data = NULL;
129 struct HdfSBuf *reply = NULL;
130 struct HdfRemoteService *service = NULL;
131
132 do {
133 data = HdfSbufTypedObtain(SBUF_IPC);
134 reply = HdfSbufTypedObtain(SBUF_IPC);
135 if (data == NULL || reply == NULL) {
136 break;
137 }
138
139 if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
140 !HdfSbufWriteString(data, serviceName)) {
141 break;
142 }
143 int status = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_GET_SERVICE, data, reply);
144 if (status == HDF_SUCCESS) {
145 service = HdfSbufReadRemoteService(reply);
146 } else {
147 HDF_LOGI("%{public}s: %{public}s not found", __func__, serviceName);
148 }
149 } while (0);
150
151 HdfSbufRecycle(reply);
152 HdfSbufRecycle(data);
153
154 return service;
155 }
156
HDIServMgrRegisterServiceStatusListener(struct HDIServiceManager * self,struct ServiceStatusListener * listener,uint16_t deviceClass)157 int32_t HDIServMgrRegisterServiceStatusListener(struct HDIServiceManager *self,
158 struct ServiceStatusListener *listener, uint16_t deviceClass)
159 {
160 if (self == NULL || listener == NULL) {
161 return HDF_ERR_INVALID_PARAM;
162 }
163 struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(self, struct HDIServiceManagerClient, iservmgr);
164
165 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
166 if (data == NULL) {
167 return HDF_ERR_MALLOC_FAIL;
168 }
169
170 if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
171 !HdfSbufWriteUint16(data, deviceClass) ||
172 ServiceStatusListenerMarshalling(listener, data) != HDF_SUCCESS) {
173 HdfSbufRecycle(data);
174 return HDF_FAILURE;
175 }
176
177 int32_t ret = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_REGISTER_SVCLISTENER, data, NULL);
178 if (ret != HDF_SUCCESS) {
179 HDF_LOGE("failed to register hdi service listener");
180 }
181 HdfSbufRecycle(data);
182 return ret;
183 }
184
HDIServMgrUnregisterServiceStatusListener(struct HDIServiceManager * self,struct ServiceStatusListener * listener)185 int32_t HDIServMgrUnregisterServiceStatusListener(struct HDIServiceManager *self,
186 struct ServiceStatusListener *listener)
187 {
188 if (self == NULL || listener == NULL) {
189 return HDF_ERR_INVALID_PARAM;
190 }
191 struct HDIServiceManagerClient *servMgrClient = CONTAINER_OF(self, struct HDIServiceManagerClient, iservmgr);
192 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
193 if (data == NULL) {
194 return HDF_ERR_MALLOC_FAIL;
195 }
196
197 if (!HdfRemoteServiceWriteInterfaceToken(servMgrClient->remote, data) ||
198 ServiceStatusListenerMarshalling(listener, data) != HDF_SUCCESS) {
199 HdfSbufRecycle(data);
200 return HDF_FAILURE;
201 }
202
203 int32_t ret = ServiceManagerHdiCall(servMgrClient, DEVSVC_MANAGER_UNREGISTER_SVCLISTENER, data, NULL);
204 if (ret != HDF_SUCCESS) {
205 HDF_LOGE("failed to unregister hdi service listener");
206 }
207 HdfSbufRecycle(data);
208 return ret;
209 }
210
HDIServiceManagerConstruct(struct HDIServiceManager * inst)211 void HDIServiceManagerConstruct(struct HDIServiceManager *inst)
212 {
213 inst->GetService = HDIServMgrGetService;
214 inst->RegisterServiceStatusListener = HDIServMgrRegisterServiceStatusListener;
215 inst->UnregisterServiceStatusListener = HDIServMgrUnregisterServiceStatusListener;
216 inst->ListServiceByInterfaceDesc = HDIServMgrListServiceByInterfaceDesc;
217 }
218
HDIServiceManagerGet(void)219 struct HDIServiceManager *HDIServiceManagerGet(void)
220 {
221 struct HdfRemoteService *remote = HdfRemoteServiceGet(DEVICE_SERVICE_MANAGER_SA_ID);
222 if (remote == NULL) {
223 HDF_LOGE("%{public}s: hdi service %{public}s not found", __func__, DEVICE_SERVICE_MANAGER);
224 return NULL;
225 }
226
227 struct HDIServiceManagerClient *iServMgrClient = OsalMemAlloc(sizeof(struct HDIServiceManagerClient));
228 if (iServMgrClient == NULL) {
229 HDF_LOGE("%{public}s: OOM", __func__);
230 HdfRemoteServiceRecycle(remote);
231 return NULL;
232 }
233 if (!HdfRemoteServiceSetInterfaceDesc(remote, "HDI.IServiceManager.V1_0")) {
234 HDF_LOGE("%{public}s: failed to init interface desc", __func__);
235 HdfRemoteServiceRecycle(remote);
236 OsalMemFree(iServMgrClient);
237 return NULL;
238 }
239 iServMgrClient->remote = remote;
240
241 HDIServiceManagerConstruct(&iServMgrClient->iservmgr);
242 return &iServMgrClient->iservmgr;
243 }
244
HDIServiceManagerRelease(struct HDIServiceManager * servmgr)245 void HDIServiceManagerRelease(struct HDIServiceManager *servmgr)
246 {
247 if (servmgr == NULL) {
248 return;
249 }
250 struct HDIServiceManagerClient *iServMgrClient = CONTAINER_OF(servmgr, struct HDIServiceManagerClient, iservmgr);
251 HdfRemoteServiceRecycle(iServMgrClient->remote);
252 OsalMemFree(iServMgrClient);
253 }
254
HdiServiceSetRelease(struct HdiServiceSet * serviceSet)255 int32_t HdiServiceSetRelease(struct HdiServiceSet *serviceSet)
256 {
257 if (serviceSet == NULL) {
258 return HDF_SUCCESS;
259 }
260 if (serviceSet->count > SERVICE_LIST_MAX) {
261 HDF_LOGE("%{public}s: failed to release serviceSet, serviceSet->count is tainted", __func__);
262 return HDF_FAILURE;
263 }
264 if (serviceSet->serviceNames != NULL) {
265 for (uint32_t i = 0; i < serviceSet->count; i++) {
266 if (serviceSet->serviceNames[i] != NULL) {
267 OsalMemFree((void *)serviceSet->serviceNames[i]);
268 serviceSet->serviceNames[i] = NULL;
269 }
270 }
271 OsalMemFree(serviceSet->serviceNames);
272 serviceSet->serviceNames = NULL;
273 }
274 OsalMemFree(serviceSet);
275 return HDF_SUCCESS;
276 }
277