blob: 61f25d78637ed622bc12f6586803747a43f719e1 [file] [log] [blame]
Julian Hallf7f84952020-11-23 17:55:51 +01001/*
julhal01c3f4e9a2020-12-15 13:39:01 +00002 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
Julian Hallf7f84952020-11-23 17:55:51 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "direct_caller.h"
julhal01c3f4e9a2020-12-15 13:39:01 +00008#include <rpc/common/endpoint/rpc_interface.h>
Julian Hallf7f84952020-11-23 17:55:51 +01009#include <protocols/rpc/common/packed-c/status.h>
10#include <stdlib.h>
11
12#define DIRECT_CALLER_DEFAULT_REQ_BUF_SIZE (4096)
13#define DIRECT_CALLER_DEFAULT_RESP_BUF_SIZE (4096)
14
15static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len);
16static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
Julian Halld1dfda52021-11-25 18:46:45 +010017 rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len);
Julian Hallf7f84952020-11-23 17:55:51 +010018static void call_end(void *context, rpc_call_handle handle);
19
20
julhal01c3f4e9a2020-12-15 13:39:01 +000021struct rpc_caller *direct_caller_init(struct direct_caller *s, struct rpc_interface *iface,
Julian Hallf7f84952020-11-23 17:55:51 +010022 size_t req_buf_size, size_t resp_buf_size)
23{
24 struct rpc_caller *base = &s->rpc_caller;
25
julhal01c3f4e9a2020-12-15 13:39:01 +000026 rpc_caller_init(base, s);
Julian Hallf7f84952020-11-23 17:55:51 +010027 base->call_begin = call_begin;
28 base->call_invoke = call_invoke;
29 base->call_end = call_end;
30
julhal01c3f4e9a2020-12-15 13:39:01 +000031 s->rpc_interface = iface;
Julian Hallf7f84952020-11-23 17:55:51 +010032 s->caller_id = 0;
33 s->is_call_transaction_in_progess = false;
34 s->req_len = 0;
35 s->req_buf_size = req_buf_size;
36 s->resp_buf_size = resp_buf_size;
37 s->req_buf = malloc(s->req_buf_size);
38 s->resp_buf = malloc(s->resp_buf_size);
39
40 if (!s->req_buf || !s->resp_buf) {
41
42 /* Buffer allocation failed */
43 base = NULL;
44 direct_caller_deinit(s);
45 }
46
47 return base;
48}
49
julhal01c3f4e9a2020-12-15 13:39:01 +000050struct rpc_caller *direct_caller_init_default(struct direct_caller *s, struct rpc_interface *iface)
Julian Hallf7f84952020-11-23 17:55:51 +010051{
52 /* Initialise with default buffer sizes */
julhal01c3f4e9a2020-12-15 13:39:01 +000053 return direct_caller_init(s, iface,
Julian Hallf7f84952020-11-23 17:55:51 +010054 DIRECT_CALLER_DEFAULT_REQ_BUF_SIZE,
55 DIRECT_CALLER_DEFAULT_RESP_BUF_SIZE);
56}
57
58void direct_caller_deinit(struct direct_caller *s)
59{
60 free(s->req_buf);
61 s->req_buf = NULL;
62 free(s->resp_buf);
63 s->resp_buf = NULL;
64}
65
66static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len)
67{
68 struct direct_caller *this_context = (struct direct_caller*)context;
69 rpc_call_handle handle = NULL;
70
71 if (!this_context->is_call_transaction_in_progess &&
72 (req_len <= this_context->req_buf_size)) {
73
74 this_context->is_call_transaction_in_progess = true;
75
76 if (req_buf){
77 *req_buf = this_context->req_buf;
78 this_context->req_len = req_len;
79 }
80
81 handle = this_context;
82 }
83
84 return handle;
85}
86
87static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
Julian Halld1dfda52021-11-25 18:46:45 +010088 rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len)
Julian Hallf7f84952020-11-23 17:55:51 +010089{
90 struct direct_caller *this_context = (struct direct_caller*)context;
91 rpc_status_t status = TS_RPC_ERROR_INVALID_TRANSACTION;
92
93 if ((handle == this_context) && this_context->is_call_transaction_in_progess) {
94
95 struct call_req req;
96
julhal01c3f4e9a2020-12-15 13:39:01 +000097 req.interface_id = 0;
Julian Hallf7f84952020-11-23 17:55:51 +010098 req.opcode = opcode;
julhal01c3f4e9a2020-12-15 13:39:01 +000099 req.encoding = this_context->rpc_caller.encoding;
Julian Hallf7f84952020-11-23 17:55:51 +0100100 req.caller_id = this_context->caller_id;
101 req.opstatus = 0;
102 req.req_buf = call_param_buf_init_full(this_context->req_buf,
103 this_context->req_buf_size, this_context->req_len);
104 req.resp_buf = call_param_buf_init_empty(this_context->resp_buf,
105 this_context->resp_buf_size);
106
julhal01c3f4e9a2020-12-15 13:39:01 +0000107 status = rpc_interface_receive(this_context->rpc_interface, &req);
Julian Hallf7f84952020-11-23 17:55:51 +0100108
109 *resp_buf = this_context->resp_buf;
110 *resp_len = call_req_get_resp_buf(&req)->data_len;
111 *opstatus = call_req_get_opstatus(&req);
112 }
113
114 return status;
115}
116
117static void call_end(void *context, rpc_call_handle handle)
118{
119 struct direct_caller *this_context = (struct direct_caller*)context;
120
121 if ((handle == this_context) && this_context->is_call_transaction_in_progess) {
122
123 this_context->req_len = 0;
124 this_context->is_call_transaction_in_progess = false;
125 }
126}