]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blob - lib/proxy/master/linux/userspace/proxy_app.c
Use lib/ for source files for OpenAMP library
[processor-sdk/open-amp.git] / lib / proxy / master / linux / userspace / proxy_app.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <time.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <sys/ioctl.h>
8 #include <signal.h>
9 #include <unistd.h>
10 #include "proxy_app.h"
12 #define RPC_BUFF_SIZE 512
13 #define RPC_CHANNEL_READY_TO_CLOSE "rpc_channel_ready_to_close"
15 struct _proxy_data {
16         int active;
17         int rpmsg_proxy_fd;
18         struct _sys_rpc *rpc;
19         struct _sys_rpc *rpc_response;
20         char *firmware_path;
21 };
23 static struct _proxy_data *proxy;
24 char fw_dst_path[] = "/lib/firmware/r5_image_rpc_demo";
26 char *rproc_name = 0;
28 int handle_open(struct _sys_rpc *rpc)
29 {
30         int fd, bytes_written;
32         /* Open remote fd */
33         fd = open(rpc->sys_call_args.data, rpc->sys_call_args.int_field1,
34                   rpc->sys_call_args.int_field2);
36         /* Construct rpc response */
37         proxy->rpc_response->id = OPEN_SYSCALL_ID;
38         proxy->rpc_response->sys_call_args.int_field1 = fd;
39         proxy->rpc_response->sys_call_args.int_field2 = 0;      /*not used */
40         proxy->rpc_response->sys_call_args.data_len = 0;        /*not used */
42         /* Transmit rpc response */
43         bytes_written = write(proxy->rpmsg_proxy_fd, proxy->rpc_response,
44                               sizeof(struct _sys_rpc));
46         return (bytes_written != sizeof(struct _sys_rpc)) ? -1 : 0;
47 }
49 int handle_close(struct _sys_rpc *rpc)
50 {
51         int retval, bytes_written;
53         /* Close remote fd */
54         retval = close(rpc->sys_call_args.int_field1);
56         /* Construct rpc response */
57         proxy->rpc_response->id = CLOSE_SYSCALL_ID;
58         proxy->rpc_response->sys_call_args.int_field1 = retval;
59         proxy->rpc_response->sys_call_args.int_field2 = 0;      /*not used */
60         proxy->rpc_response->sys_call_args.data_len = 0;        /*not used */
62         /* Transmit rpc response */
63         bytes_written = write(proxy->rpmsg_proxy_fd, proxy->rpc_response,
64                               sizeof(struct _sys_rpc));
66         return (bytes_written != sizeof(struct _sys_rpc)) ? -1 : 0;
67 }
69 int handle_read(struct _sys_rpc *rpc)
70 {
71         int bytes_read, bytes_written, payload_size;
72         char *buff;
74         /* Allocate buffer for requested data size */
75         buff = malloc(rpc->sys_call_args.int_field2);
77         if (rpc->sys_call_args.int_field1 == 0)
78                 /* Perform read from fd for large size since this is a
79                    STD/I request */
80                 bytes_read = read(rpc->sys_call_args.int_field1, buff, 512);
81         else
82                 /* Perform read from fd */
83                 bytes_read = read(rpc->sys_call_args.int_field1, buff,
84                                   rpc->sys_call_args.int_field2);
86         /* Construct rpc response */
87         proxy->rpc_response->id = READ_SYSCALL_ID;
88         proxy->rpc_response->sys_call_args.int_field1 = bytes_read;
89         proxy->rpc_response->sys_call_args.int_field2 = 0;      /* not used */
90         proxy->rpc_response->sys_call_args.data_len = bytes_read;
91         if (bytes_read > 0)
92                 memcpy(proxy->rpc_response->sys_call_args.data, buff,
93                        bytes_read);
95         payload_size = sizeof(struct _sys_rpc) +
96             ((bytes_read > 0) ? bytes_read : 0);
98         /* Transmit rpc response */
99         bytes_written = write(proxy->rpmsg_proxy_fd, proxy->rpc_response,
100                               payload_size);
102         return (bytes_written != payload_size) ? -1 : 0;
105 int handle_write(struct _sys_rpc *rpc)
107         int bytes_written;
109         /* Write to remote fd */
110         bytes_written = write(rpc->sys_call_args.int_field1,
111                               rpc->sys_call_args.data,
112                               rpc->sys_call_args.int_field2);
114         /* Construct rpc response */
115         proxy->rpc_response->id = WRITE_SYSCALL_ID;
116         proxy->rpc_response->sys_call_args.int_field1 = bytes_written;
117         proxy->rpc_response->sys_call_args.int_field2 = 0;      /*not used */
118         proxy->rpc_response->sys_call_args.data_len = 0;        /*not used */
120         /* Transmit rpc response */
121         bytes_written = write(proxy->rpmsg_proxy_fd, proxy->rpc_response,
122                               sizeof(struct _sys_rpc));
124         return (bytes_written != sizeof(struct _sys_rpc)) ? -1 : 0;
127 int handle_rpc(struct _sys_rpc *rpc)
129         int retval;
130         char *data = (char *)rpc;
131         if (!strcmp(data, RPC_CHANNEL_READY_TO_CLOSE)) {
132                 proxy->active = 0;
133                 return 0;
134         }
136         /* Handle RPC */
137         switch ((int)(rpc->id)) {
138         case OPEN_SYSCALL_ID:
139                 {
140                         retval = handle_open(rpc);
141                         break;
142                 }
143         case CLOSE_SYSCALL_ID:
144                 {
145                         retval = handle_close(rpc);
146                         break;
147                 }
148         case READ_SYSCALL_ID:
149                 {
150                         retval = handle_read(rpc);
151                         break;
152                 }
153         case WRITE_SYSCALL_ID:
154                 {
155                         retval = handle_write(rpc);
156                         break;
157                 }
158         default:
159                 {
160                         printf
161                             ("\r\nMaster>Err:Invalid RPC sys call ID: %d:%d! \r\n",
162                              rpc->id, WRITE_SYSCALL_ID);
163                         retval = -1;
164                         break;
165                 }
166         }
168         return retval;
171 int terminate_rpc_app()
173         int bytes_written;
174         int msg = TERM_SYSCALL_ID;
175         printf("Master> sending shutdown signal.\n");
176         bytes_written = write(proxy->rpmsg_proxy_fd, &msg, sizeof(int));
177         return bytes_written;
180 void exit_action_handler(int signum)
182         proxy->active = 0;
185 void unload_drivers()
187         char sys_cmd[256];
189         system("modprobe -r rpmsg_proxy_dev_driver");
190         system("modprobe -r virtio_rpmsg_bus");
191         if (rproc_name) {
192                 sprintf(sys_cmd, "modprobe -r %s", rproc_name);
193                 system(sys_cmd);
194         }
195         system("modprobe -r remoteproc");
196         system("modprobe -r virtio_ring");
197         system("modprobe -r virtio");
200 void kill_action_handler(int signum)
202         printf("\r\nMaster>RPC service killed !!\r\n");
204         /* Send shutdown signal to remote application */
205         terminate_rpc_app();
207         /* wait for a while to let the remote finish cleanup */
208         sleep(1);
209         /* Close proxy rpmsg device */
210         close(proxy->rpmsg_proxy_fd);
212         /* Free up resources */
213         free(proxy->rpc);
214         free(proxy->rpc_response);
215         free(proxy);
217         /* Unload drivers */
218         unload_drivers();
221 void display_help_msg()
223         printf("\r\nLinux proxy application.\r\n");
224         printf("-r       Displays proxy application version.\n");
225         printf("-f       Accepts path of firmware to load on remote core.\n");
226         printf("-h       Displays this help message.\n");
229 int main(int argc, char *argv[])
231         struct sigaction exit_action;
232         struct sigaction kill_action;
233         unsigned int bytes_rcvd;
234         int i = 0;
235         int ret = 0;
236         char *firmware_path = 0;
237         char sys_cmd[512];
239         /* Initialize signalling infrastructure */
240         memset(&exit_action, 0, sizeof(struct sigaction));
241         memset(&kill_action, 0, sizeof(struct sigaction));
242         exit_action.sa_handler = exit_action_handler;
243         kill_action.sa_handler = kill_action_handler;
244         sigaction(SIGTERM, &exit_action, NULL);
245         sigaction(SIGINT, &exit_action, NULL);
246         sigaction(SIGKILL, &kill_action, NULL);
247         sigaction(SIGHUP, &kill_action, NULL);
249         /* Parse and process input args */
250         for (i = 1; i < argc; i++) {
251                 if (strcmp(argv[i], "-r") == 0) {
252                         printf("\r\nLinux proxy application version 1.0\r\n");
253                         return 0;
254                 } else if (strcmp(argv[i], "-h") == 0) {
255                         display_help_msg();
256                         return 0;
257                 } else if (strcmp(argv[i], "-f") == 0) {
258                         if (i + 1 < argc)
259                                 firmware_path = argv[i + 1];
260                 } else if (strcmp(argv[i], "--remoteproc") == 0) {
261                         if (i + 1 < argc)
262                                 rproc_name = argv[i + 1];
263                 }
264         }
265         if (!rproc_name)
266                 rproc_name = "zynqmp_r5_remoteproc";
268         /* Bring up remote firmware */
269         printf("\r\nMaster>Loading remote firmware\r\n");
271         if (firmware_path) {
272                 /* Copy the firmware to the preferred firmware location */
273                 sprintf(sys_cmd, "cp %s %s", firmware_path, fw_dst_path);
274                 system(sys_cmd);
275         }
276         sprintf(sys_cmd, "modprobe %s firmware=r5_image_rpc_demo", rproc_name);
277         system(sys_cmd);
279         /* Create rpmsg proxy device */
280         printf("\r\nMaster>Create rpmsg proxy device\r\n");
281         system("modprobe rpmsg_proxy_dev_driver");
283         /* Allocate memory for proxy data structure */
284         proxy = malloc(sizeof(struct _proxy_data));
285         if (proxy == 0) {
286                 printf("\r\nMaster>Failed to allocate memory.\r\n");
287                 return -1;
288         }
289         proxy->active = 1;
291         /* Open proxy rpmsg device */
292         printf("\r\nMaster>Opening rpmsg proxy device\r\n");
293         i = 0;
294         do {
295                 proxy->rpmsg_proxy_fd = open("/dev/rpmsg_proxy0", O_RDWR);
296                 sleep(1);
297         } while (proxy->rpmsg_proxy_fd < 0 && (i++ < 2));
299         if (proxy->rpmsg_proxy_fd < 0) {
300                 printf
301                     ("\r\nMaster>Failed to open rpmsg proxy driver device file.\r\n");
302                 ret = -1;
303                 goto error0;
304         }
306         /* Allocate memory for rpc payloads */
307         proxy->rpc = malloc(RPC_BUFF_SIZE);
308         proxy->rpc_response = malloc(RPC_BUFF_SIZE);
310         /* RPC service starts */
311         printf("\r\nMaster>RPC service started !!\r\n");
312         while (proxy->active) {
313                 /* Block on read for rpc requests from remote context */
314                 do {
315                         bytes_rcvd = read(proxy->rpmsg_proxy_fd, proxy->rpc,
316                                           RPC_BUFF_SIZE);
317                         if (!proxy->active)
318                                 break;
319                 } while (bytes_rcvd <= 0);
321                 /* User event, break! */
322                 if (!proxy->active)
323                         break;
325                 /* Handle rpc */
326                 if (handle_rpc(proxy->rpc)) {
327                         printf("\r\nMaster>Err:Handling remote procedure");
328                         printf(" call!\r\n");
329                         printf("\r\nrpc id %d\r\n", proxy->rpc->id);
330                         printf("\r\nrpc int field1 %d\r\n",
331                                proxy->rpc->sys_call_args.int_field1);
332                         printf("\r\nrpc int field2 %d\r\n",
333                                proxy->rpc->sys_call_args.int_field2);
334                         break;
335                 }
336         }
338         printf("\r\nMaster>RPC service exiting !!\r\n");
340         /* Send shutdown signal to remote application */
341         terminate_rpc_app();
343         /* Need to wait here for sometime to allow remote application to
344            complete its unintialization */
345         sleep(1);
347         /* Close proxy rpmsg device */
348         close(proxy->rpmsg_proxy_fd);
350         /* Free up resources */
351         free(proxy->rpc);
352         free(proxy->rpc_response);
354  error0:
355         free(proxy);
357         /* Unload drivers */
358         unload_drivers();
360         return ret;