1 /*
2 * Copyright (c) 2021, L&T Technology Services Ltd.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <errno.h>
9 #include <openamp/rpmsg_rpc_client_server.h>
10
11 #define LPERROR(format, ...) metal_log(METAL_LOG_ERROR, format, ##__VA_ARGS__)
12
13 static int rpmsg_endpoint_server_cb(struct rpmsg_endpoint *, void *,
14 size_t, uint32_t, void *);
15
rpmsg_rpc_server_init(struct rpmsg_rpc_svr * rpcs,struct rpmsg_device * rdev,const struct rpmsg_rpc_services * services,int len,rpmsg_ns_unbind_cb rpmsg_service_server_unbind)16 int rpmsg_rpc_server_init(struct rpmsg_rpc_svr *rpcs, struct rpmsg_device *rdev,
17 const struct rpmsg_rpc_services *services, int len,
18 rpmsg_ns_unbind_cb rpmsg_service_server_unbind)
19 {
20 int ret;
21
22 rpcs->services = services;
23 rpcs->n_services = len;
24
25 ret = rpmsg_create_ept(&rpcs->ept, rdev, RPMSG_RPC_SERVICE_NAME,
26 RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
27 rpmsg_endpoint_server_cb,
28 rpmsg_service_server_unbind);
29 if (ret)
30 return ret;
31
32 return ret;
33 }
34
find_service(struct rpmsg_rpc_svr * rpcs,unsigned int id)35 static const struct rpmsg_rpc_services *find_service(struct rpmsg_rpc_svr *rpcs,
36 unsigned int id)
37 {
38 const struct rpmsg_rpc_services *service;
39
40 for (unsigned int i = 0; i < rpcs->n_services; i++) {
41 service = &rpcs->services[i];
42
43 if (service->id == id) {
44 return service;
45 }
46 }
47 return NULL;
48 }
49
rpmsg_endpoint_server_cb(struct rpmsg_endpoint * ept,void * data,size_t len,uint32_t src,void * priv)50 static int rpmsg_endpoint_server_cb(struct rpmsg_endpoint *ept, void *data,
51 size_t len,
52 uint32_t src, void *priv)
53 {
54 unsigned char buf[MAX_BUF_LEN];
55 unsigned int id;
56 const struct rpmsg_rpc_services *service;
57 struct rpmsg_rpc_svr *rpcs;
58 (void)priv;
59 (void)src;
60
61 if (len > MAX_BUF_LEN)
62 return -EINVAL;
63
64 rpcs = metal_container_of(ept, struct rpmsg_rpc_svr, ept);
65
66 memcpy(buf, data, len);
67 id = *buf;
68 service = find_service(rpcs, id);
69
70 if (service) {
71 if (service->cb_function(buf, rpcs)) {
72 LPERROR("Service failed at rpc id: %ld\r\n", id);
73 }
74 } else {
75 LPERROR("Handling remote procedure call errors: rpc id %ld\r\n",
76 id);
77 rpmsg_rpc_server_send(rpcs, id, RPMSG_RPC_INVALID_ID, NULL, 0);
78 }
79 return RPMSG_SUCCESS;
80 }
81
rpmsg_rpc_server_send(struct rpmsg_rpc_svr * rpcs,uint32_t rpc_id,int status,void * request_param,size_t param_size)82 int rpmsg_rpc_server_send(struct rpmsg_rpc_svr *rpcs, uint32_t rpc_id,
83 int status, void *request_param, size_t param_size)
84 {
85 struct rpmsg_endpoint *ept = &rpcs->ept;
86 struct rpmsg_rpc_answer msg;
87
88 if (!ept)
89 return -EINVAL;
90 if (param_size > (MAX_BUF_LEN - sizeof(msg.status)))
91 return -EINVAL;
92
93 msg.id = rpc_id;
94 msg.status = status;
95 memcpy(msg.params, request_param, param_size);
96
97 return rpmsg_send(ept, &msg, MAX_FUNC_ID_LEN + param_size);
98 }
99