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