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 static int rpmsg_endpoint_client_cb(struct rpmsg_endpoint *, void *, size_t,
12 uint32_t, void *);
13
rpmsg_service_client_unbind(struct rpmsg_endpoint * ept)14 static void rpmsg_service_client_unbind(struct rpmsg_endpoint *ept)
15 {
16 struct rpmsg_rpc_clt *rpc;
17 (void)ept;
18
19 rpc = metal_container_of(ept, struct rpmsg_rpc_clt, ept);
20 rpmsg_destroy_ept(&rpc->ept);
21 if (rpc->shutdown_cb)
22 rpc->shutdown_cb(rpc);
23 }
24
rpmsg_rpc_client_init(struct rpmsg_rpc_clt * rpc,struct rpmsg_device * rdev,rpmsg_rpc_shutdown_cb shutdown_cb,const struct rpmsg_rpc_client_services * services,int len)25 int rpmsg_rpc_client_init(struct rpmsg_rpc_clt *rpc,
26 struct rpmsg_device *rdev,
27 rpmsg_rpc_shutdown_cb shutdown_cb,
28 const struct rpmsg_rpc_client_services *services,
29 int len)
30 {
31 int ret;
32
33 if (!rpc || !rdev)
34 return -EINVAL;
35
36 rpc->services = services;
37 rpc->n_services = len;
38
39 rpc->shutdown_cb = shutdown_cb;
40
41 ret = rpmsg_create_ept(&rpc->ept, rdev,
42 RPMSG_RPC_SERVICE_NAME, RPMSG_ADDR_ANY,
43 RPMSG_ADDR_ANY,
44 rpmsg_endpoint_client_cb,
45 rpmsg_service_client_unbind);
46
47 return ret;
48 }
49
rpmsg_rpc_client_send(struct rpmsg_rpc_clt * rpc,uint32_t rpc_id,void * request_param,size_t req_param_size)50 int rpmsg_rpc_client_send(struct rpmsg_rpc_clt *rpc,
51 uint32_t rpc_id, void *request_param,
52 size_t req_param_size)
53 {
54 unsigned char tmpbuf[MAX_BUF_LEN];
55
56 if (!rpc)
57 return -EINVAL;
58
59 /* to optimize with the zero copy API */
60 memcpy(tmpbuf, &rpc_id, MAX_FUNC_ID_LEN);
61 memcpy(&tmpbuf[MAX_FUNC_ID_LEN], request_param, req_param_size);
62 return rpmsg_send(&rpc->ept, tmpbuf, MAX_FUNC_ID_LEN + req_param_size);
63 }
64
find_service(struct rpmsg_rpc_clt * rpc,uint32_t id)65 static const struct rpmsg_rpc_client_services *find_service(struct
66 rpmsg_rpc_clt * rpc,
67 uint32_t id)
68 {
69 const struct rpmsg_rpc_client_services *service;
70
71 for (unsigned int i = 0; i < rpc->n_services; i++) {
72 service = &rpc->services[i];
73
74 if (service->id == id) {
75 return service;
76 }
77 }
78 return NULL;
79 }
80
rpmsg_rpc_client_release(struct rpmsg_rpc_clt * rpc)81 void rpmsg_rpc_client_release(struct rpmsg_rpc_clt *rpc)
82 {
83 if (!rpc)
84 return;
85 rpmsg_destroy_ept(&rpc->ept);
86
87 }
88
rpmsg_endpoint_client_cb(struct rpmsg_endpoint * ept,void * data,size_t len,uint32_t src,void * priv)89 static int rpmsg_endpoint_client_cb(struct rpmsg_endpoint *ept,
90 void *data, size_t len,
91 uint32_t src, void *priv)
92 {
93 struct rpmsg_rpc_clt *rpc;
94 const struct rpmsg_rpc_client_services *service;
95 struct rpmsg_rpc_answer *msg;
96 (void)priv;
97 (void)src;
98
99 if (!data || !ept)
100 return -EINVAL;
101
102 msg = (struct rpmsg_rpc_answer *)data;
103
104 rpc = metal_container_of(ept,
105 struct rpmsg_rpc_clt,
106 ept);
107 service = find_service(rpc, msg->id);
108 if (!service)
109 return -EINVAL;
110
111 /* Invoke the callback function of the rpc */
112 service->cb(rpc, msg->status, msg->params, len);
113
114 return RPMSG_SUCCESS;
115 }
116