blob: 001ee7c84a71021c38a8140842fc5b69a9eb6a8e [file] [log] [blame]
Julian Hallf7f84952020-11-23 17:55:51 +01001/*
2 * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "direct_caller.h"
8#include <rpc/common/endpoint/call_ep.h>
9#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,
17 int *opstatus, uint8_t **resp_buf, size_t *resp_len);
18static void call_end(void *context, rpc_call_handle handle);
19
20
21struct rpc_caller *direct_caller_init(struct direct_caller *s, struct call_ep *ep,
22 size_t req_buf_size, size_t resp_buf_size)
23{
24 struct rpc_caller *base = &s->rpc_caller;
25
26 base->context = s;
27 base->call_begin = call_begin;
28 base->call_invoke = call_invoke;
29 base->call_end = call_end;
30
31 s->call_ep = ep;
32 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
50struct rpc_caller *direct_caller_init_default(struct direct_caller *s, struct call_ep *ep)
51{
52 /* Initialise with default buffer sizes */
53 return direct_caller_init(s, ep,
54 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,
88 int *opstatus, uint8_t **resp_buf, size_t *resp_len)
89{
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
97 req.opcode = opcode;
98 req.caller_id = this_context->caller_id;
99 req.opstatus = 0;
100 req.req_buf = call_param_buf_init_full(this_context->req_buf,
101 this_context->req_buf_size, this_context->req_len);
102 req.resp_buf = call_param_buf_init_empty(this_context->resp_buf,
103 this_context->resp_buf_size);
104
105 status = call_ep_receive(this_context->call_ep, &req);
106
107 *resp_buf = this_context->resp_buf;
108 *resp_len = call_req_get_resp_buf(&req)->data_len;
109 *opstatus = call_req_get_opstatus(&req);
110 }
111
112 return status;
113}
114
115static void call_end(void *context, rpc_call_handle handle)
116{
117 struct direct_caller *this_context = (struct direct_caller*)context;
118
119 if ((handle == this_context) && this_context->is_call_transaction_in_progess) {
120
121 this_context->req_len = 0;
122 this_context->is_call_transaction_in_progess = false;
123 }
124}