1 /*
2 * Copyright (c) 2020-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 "sidecar.h"
10 #include "hdf_base.h"
11 #include "hdf_log.h"
12 #include "message_router.h"
13 #include "message_router_inner.h"
14 #include "securec.h"
15
16 #ifdef USERSPACE_CLIENT_SUPPORT
17 #define HDF_LOG_TAG UMsgEngine
18 #else
19 #define HDF_LOG_TAG KMsgEngine
20 #endif
21
22 // Service has only one private data.The service ID of current service
23 typedef struct {
24 DispatcherId dispatcherId;
25 ServiceId serviceId;
26 } SideCarPrivateData;
27
MessageInputCheck(const Service * sideCar,ServiceId receiver,struct HdfSBuf * sendData)28 static ErrorCode MessageInputCheck(const Service *sideCar, ServiceId receiver, struct HdfSBuf *sendData)
29 {
30 SideCarPrivateData *privateData = NULL;
31 if (sideCar == NULL || sideCar->privateData == NULL) {
32 HDF_LOGE("%s:sideCar or sideCar.privateData is NULL", __func__);
33 return ME_ERROR_NULL_PTR;
34 }
35
36 privateData = (SideCarPrivateData *)sideCar->privateData;
37 if (receiver >= MESSAGE_ENGINE_MAX_SERVICE || privateData->serviceId >= MESSAGE_ENGINE_MAX_SERVICE) {
38 return ME_ERROR_NO_SUCH_SERVICE;
39 }
40 return ME_SUCCESS;
41 }
42
CreateMessageContext(ServiceId sender,ServiceId receiver,uint32_t commandId,struct HdfSBuf * sendData)43 static MessageContext *CreateMessageContext(ServiceId sender, ServiceId receiver, uint32_t commandId,
44 struct HdfSBuf *sendData)
45 {
46 MessageContext *context = (MessageContext *)OsalMemCalloc(sizeof(MessageContext));
47 if (context == NULL) {
48 return NULL;
49 }
50
51 context->commandId = commandId;
52 context->senderId = sender;
53 context->receiverId = receiver;
54 context->reqData = sendData;
55 context->crossNode = false;
56
57 return context;
58 }
59
60 #define MESSAGE_CMD_BITS 16
61 #define MESSAGE_CMD_MASK 0xffff
62
GetServiceID(uint32_t id)63 inline static uint32_t GetServiceID(uint32_t id)
64 {
65 return (id & ~((uint32_t)(MESSAGE_CMD_MASK))) >> MESSAGE_CMD_BITS;
66 }
67
GetCmd(uint32_t id)68 inline static uint32_t GetCmd(uint32_t id)
69 {
70 return id & MESSAGE_CMD_MASK;
71 }
72
DispatchToMessage(struct HdfDeviceIoClient * client,int id,struct HdfSBuf * reqData,struct HdfSBuf * rspData)73 int32_t DispatchToMessage(struct HdfDeviceIoClient *client, int id, struct HdfSBuf *reqData, struct HdfSBuf *rspData)
74 {
75 ErrorCode errCode;
76 ServiceId serviceId = GetServiceID(id);
77 uint32_t cmd = GetCmd(id);
78 MessageContext *context = NULL;
79 RemoteService *targetService = NULL;
80
81 if (client == NULL) {
82 return HDF_ERR_INVALID_PARAM;
83 }
84 if (serviceId >= MESSAGE_ENGINE_MAX_SERVICE) {
85 return ME_ERROR_NO_SUCH_SERVICE;
86 }
87 context = CreateMessageContext(RESERVED_SERVICE_ID, serviceId, cmd, reqData);
88 if (context == NULL) {
89 return ME_ERROR_NULL_PTR;
90 }
91 context->rspData = rspData;
92 context->requestType = MESSAGE_TYPE_SYNC_REQ;
93 context->client = client;
94 do {
95 targetService = RefRemoteService(serviceId);
96 if (targetService == NULL || targetService->SendMessage == NULL) {
97 HDF_LOGE("%s:Target service is NULL or has no SendMessage!", __func__);
98 errCode = ME_ERROR_NO_SUCH_SERVICE;
99 break;
100 }
101
102 errCode = targetService->SendMessage(targetService, context);
103 } while (false);
104 if (targetService != NULL && targetService->Disref != NULL) {
105 targetService->Disref(targetService);
106 }
107 OsalMemFree(context);
108 return errCode;
109 }
110
SideCarSendSyncMessage(const Service * sideCar,ServiceId receiver,uint32_t commandId,struct HdfSBuf * sendData,struct HdfSBuf * recvData)111 static ErrorCode SideCarSendSyncMessage(const Service *sideCar, ServiceId receiver, uint32_t commandId,
112 struct HdfSBuf *sendData, struct HdfSBuf *recvData)
113 {
114 SideCarPrivateData *privateData = NULL;
115 MessageContext *context = NULL;
116 RemoteService *targetService = NULL;
117 ErrorCode errCode = MessageInputCheck(sideCar, receiver, sendData);
118 if (errCode != ME_SUCCESS) {
119 return errCode;
120 }
121 privateData = (SideCarPrivateData *)sideCar->privateData;
122 context = CreateMessageContext(privateData->serviceId, receiver, commandId, sendData);
123 if (context == NULL) {
124 return ME_ERROR_NULL_PTR;
125 }
126 context->rspData = recvData;
127 context->requestType = MESSAGE_TYPE_SYNC_REQ;
128 do {
129 targetService = RefRemoteService(receiver);
130 if (targetService == NULL || targetService->SendMessage == NULL) {
131 HDF_LOGE("Target service is NULL or has no SendMessage!");
132 errCode = ME_ERROR_NO_SUCH_SERVICE;
133 break;
134 }
135
136 errCode = targetService->SendMessage(targetService, context);
137 } while (false);
138 if (targetService != NULL && targetService->Disref != NULL) {
139 targetService->Disref(targetService);
140 }
141 OsalMemFree(context);
142 return errCode;
143 }
144
SideCarSendAsyncMessageInner(const Service * sideCar,ServiceId receiver,uint32_t commandId,struct HdfSBuf * reqData,MessageCallBack callback)145 static ErrorCode SideCarSendAsyncMessageInner(const Service *sideCar, ServiceId receiver, uint32_t commandId,
146 struct HdfSBuf *reqData, MessageCallBack callback)
147 {
148 SideCarPrivateData *privateData = NULL;
149 MessageContext *context = NULL;
150 struct HdfSBuf *rspData = NULL;
151 RemoteService *targetService = NULL;
152 ErrorCode errCode = MessageInputCheck(sideCar, receiver, reqData);
153 if (errCode != ME_SUCCESS) {
154 return errCode;
155 }
156
157 privateData = (SideCarPrivateData *)sideCar->privateData;
158 context = CreateMessageContext(privateData->serviceId, receiver, commandId, reqData);
159 if (context == NULL) {
160 return ME_ERROR_NULL_PTR;
161 }
162 rspData = HdfSbufObtainDefaultSize();
163 if (rspData == NULL) {
164 OsalMemFree(context);
165 return HDF_FAILURE;
166 }
167 context->requestType = MESSAGE_TYPE_ASYNC_REQ;
168 context->callback = callback;
169 context->rspData = rspData;
170 do {
171 targetService = RefRemoteService(receiver);
172 if (targetService == NULL || targetService->SendMessage == NULL) {
173 HDF_LOGE("Target service is NULL or has no SendMessage!");
174 errCode = ME_ERROR_NO_SUCH_SERVICE;
175 break;
176 }
177
178 errCode = targetService->SendMessage(targetService, context);
179 } while (false);
180 if (targetService != NULL && targetService->Disref != NULL) {
181 targetService->Disref(targetService);
182 }
183 if (errCode != ME_SUCCESS) {
184 HdfSbufRecycle(rspData);
185 OsalMemFree(context);
186 }
187 return errCode;
188 }
189
SideCarSendAsyncMessage(const Service * sideCar,ServiceId receiver,uint32_t commandId,struct HdfSBuf * reqData,MessageCallBack callback)190 static ErrorCode SideCarSendAsyncMessage(const Service *sideCar, ServiceId receiver, uint32_t commandId,
191 struct HdfSBuf *reqData, MessageCallBack callback)
192 {
193 if (callback == NULL) {
194 HDF_LOGE("%s:Callback function can not be NULL.Did you mean SendOnewayMessage?", __func__);
195 return ME_ERROR_PARA_WRONG;
196 }
197 return SideCarSendAsyncMessageInner(sideCar, receiver, commandId, reqData, callback);
198 }
199
SideCarSendOneWayMessage(const struct SideCar_ * sideCar,ServiceId receiver,uint32_t commandId,struct HdfSBuf * reqData)200 static ErrorCode SideCarSendOneWayMessage(const struct SideCar_ *sideCar, ServiceId receiver, uint32_t commandId,
201 struct HdfSBuf *reqData)
202 {
203 return SideCarSendAsyncMessageInner(sideCar, receiver, commandId, reqData, NULL);
204 }
205
DestroyService(Service * service)206 static ErrorCode DestroyService(Service *service)
207 {
208 SideCarPrivateData *data = NULL;
209 ErrorCode errCode;
210 if (service == NULL) {
211 return ME_ERROR_NULL_PTR;
212 }
213
214 if (service->privateData == NULL) {
215 HDF_LOGE("%s:privateData is NULL!", __func__);
216 return ME_ERROR_PARA_WRONG;
217 }
218 data = (SideCarPrivateData *)service->privateData;
219 HDF_LOGE("Destroy service! id=%d", data->serviceId);
220 errCode = UnregistLocalService(data->dispatcherId, data->serviceId);
221 if (errCode != ME_SUCCESS) {
222 HDF_LOGE("Unregist service failed!ret=%d", errCode);
223 return errCode;
224 }
225
226 OsalMemFree(data);
227 service->privateData = NULL;
228 OsalMemFree(service);
229 return ME_SUCCESS;
230 }
231
InitService(struct ServiceDef * def,const ServiceCfg * cfg)232 Service *InitService(struct ServiceDef *def, const ServiceCfg *cfg)
233 {
234 Service *service = NULL;
235 SideCarPrivateData *privateData = NULL;
236 ErrorCode errCode;
237 if (cfg == NULL || def == NULL) {
238 return NULL;
239 }
240
241 if (def->serviceId == RESERVED_SERVICE_ID) {
242 HDF_LOGE("%s:Init service with ID 0 is not allowed!", __func__);
243 return NULL;
244 }
245
246 service = (Service *)OsalMemCalloc(sizeof(Service));
247 if (service == NULL) {
248 HDF_LOGE("%s:OsalMemAlloc return NULL!", __func__);
249 return NULL;
250 }
251 service->SendAsyncMessage = SideCarSendAsyncMessage;
252 service->SendSyncMessage = SideCarSendSyncMessage;
253 service->SendOneWayMessage = SideCarSendOneWayMessage;
254 service->Destroy = DestroyService;
255
256 privateData = (SideCarPrivateData *)OsalMemCalloc(sizeof(SideCarPrivateData));
257 if (privateData == NULL) {
258 OsalMemFree(service);
259 HDF_LOGE("%s:OsalMemAlloc return NULL!", __func__);
260 return NULL;
261 }
262 privateData->serviceId = def->serviceId;
263 privateData->dispatcherId = cfg->dispatcherId;
264 service->privateData = (void *)privateData;
265 privateData = NULL;
266
267 errCode = RegistLocalService(cfg->dispatcherId, def);
268 if (errCode != ME_SUCCESS) {
269 OsalMemFree(service->privateData);
270 service->privateData = NULL;
271 OsalMemFree(service);
272 service = NULL;
273 HDF_LOGE("Register service failed!serviceId=%d,ret=%d", def->serviceId, errCode);
274 return NULL;
275 }
276 return service;
277 }
278