/* * Copyright (c) 2021, L&T Technology Services Ltd. * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include static int rpmsg_endpoint_client_cb(struct rpmsg_endpoint *, void *, size_t, uint32_t, void *); static void rpmsg_service_client_unbind(struct rpmsg_endpoint *ept) { struct rpmsg_rpc_clt *rpc; (void)ept; rpc = metal_container_of(ept, struct rpmsg_rpc_clt, ept); rpmsg_destroy_ept(&rpc->ept); if (rpc->shutdown_cb) rpc->shutdown_cb(rpc); } int 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) { int ret; if (!rpc || !rdev) return -EINVAL; rpc->services = services; rpc->n_services = len; rpc->shutdown_cb = shutdown_cb; ret = rpmsg_create_ept(&rpc->ept, rdev, RPMSG_RPC_SERVICE_NAME, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, rpmsg_endpoint_client_cb, rpmsg_service_client_unbind); return ret; } int rpmsg_rpc_client_send(struct rpmsg_rpc_clt *rpc, uint32_t rpc_id, void *request_param, size_t req_param_size) { unsigned char tmpbuf[MAX_BUF_LEN]; if (!rpc) return -EINVAL; /* to optimize with the zero copy API */ memcpy(tmpbuf, &rpc_id, MAX_FUNC_ID_LEN); memcpy(&tmpbuf[MAX_FUNC_ID_LEN], request_param, req_param_size); return rpmsg_send(&rpc->ept, tmpbuf, MAX_FUNC_ID_LEN + req_param_size); } static const struct rpmsg_rpc_client_services *find_service(struct rpmsg_rpc_clt * rpc, uint32_t id) { const struct rpmsg_rpc_client_services *service; for (unsigned int i = 0; i < rpc->n_services; i++) { service = &rpc->services[i]; if (service->id == id) { return service; } } return NULL; } void rpmsg_rpc_client_release(struct rpmsg_rpc_clt *rpc) { if (!rpc) return; rpmsg_destroy_ept(&rpc->ept); } static int rpmsg_endpoint_client_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { struct rpmsg_rpc_clt *rpc; const struct rpmsg_rpc_client_services *service; struct rpmsg_rpc_answer *msg; (void)priv; (void)src; if (!data || !ept) return -EINVAL; msg = (struct rpmsg_rpc_answer *)data; rpc = metal_container_of(ept, struct rpmsg_rpc_clt, ept); service = find_service(rpc, msg->id); if (!service) return -EINVAL; /* Invoke the callback function of the rpc */ service->cb(rpc, msg->status, msg->params, len); return RPMSG_SUCCESS; }