lib: Add support for AM64x SoCs
[rpmsg/ti-rpmsg-char.git] / examples / rpmsg_char_simple.c
1 /*
2  * rpmsg_char_simple.c
3  *
4  * Simple Example application using rpmsg-char library
5  *
6  * Copyright (c) 2020 Texas Instruments Incorporated - https://www.ti.com
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * *  Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * *  Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * *  Neither the name of Texas Instruments Incorporated nor the names of
20  *    its contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  */
37 #include <sys/select.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <stdint.h>
42 #include <stddef.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <pthread.h>
50 #include <time.h>
51 #include <stdbool.h>
52 #include <semaphore.h>
54 #include <linux/rpmsg.h>
55 #include <ti_rpmsg_char.h>
57 #define NUM_ITERATIONS  100
58 #define REMOTE_ENDPT    14
60 int send_msg(int fd, char *msg, int len)
61 {
62         int ret = 0;
64         ret = write(fd, msg, len);
65         if (ret < 0) {
66                 perror("Can't write to rpmsg endpt device\n");
67                 return -1;
68         }
70         return ret;
71 }
73 int recv_msg(int fd, int len, char *reply_msg, int *reply_len)
74 {
75         int ret = 0;
77         /* Note: len should be max length of response expected */
78         ret = read(fd, reply_msg, len);
79         if (ret < 0) {
80                 perror("Can't read from rpmsg endpt device\n");
81                 return -1;
82         } else {
83                 *reply_len = ret;
84         }
86         return 0;
87 }
89 /* single thread communicating with a single endpoint */
90 int rpmsg_char_ping(int rproc_id, char *dev_name, int remote_endpt,
91                     int num_msgs)
92 {
93         int ret = 0;
94         int i = 0;
95         int packet_len;
96         char eptdev_name[32] = { 0 };
97         char packet_buf[512] = { 0 };
98         rpmsg_char_dev_t *rcdev;
99         int flags = 0;
101         /*
102          * Open the remote rpmsg device identified by dev_name and bind the
103          * device to a local end-point used for receiving messages from
104          * remote processor
105          */
106         sprintf(eptdev_name, "rpmsg-char-%d-%d", rproc_id, getpid());
107         rcdev = rpmsg_char_open(rproc_id, dev_name, remote_endpt,
108                                 eptdev_name, flags);
109         if (!rcdev) {
110                 perror("Can't create an endpoint device");
111                 return -EPERM;
112         }
113         printf("Created endpt device %s, fd = %d port = %d\n", eptdev_name,
114                 rcdev->fd, rcdev->endpt);
116         printf("Exchanging %d messages with rpmsg device ti.ipc4.ping-pong on rproc id %d ...\n\n",
117                 num_msgs, rproc_id);
119         for (i = 0; i < num_msgs; i++) {
120                 memset(packet_buf, 0, sizeof(packet_buf));
121                 sprintf(packet_buf, "hello there %d!", i);
122                 packet_len = strlen(packet_buf);
123                 printf("Sending message #%d: %s\n", i, packet_buf);
124                 ret = send_msg(rcdev->fd, (char *)packet_buf, packet_len);
125                 if (ret < 0) {
126                         printf("send_msg failed for iteration %d, ret = %d\n", i, ret);
127                         goto out;
128                 }
129                 if (ret != packet_len) {
130                         printf("bytes written does not match send request, ret = %d, packet_len = %d\n",
131                                 i, ret);
132                     goto out;
133                 }
135                 printf("Receiving message #%d: ", i);
136                 ret = recv_msg(rcdev->fd, 256, (char *)packet_buf, &packet_len);
137                 if (ret < 0) {
138                         printf("recv_msg failed for iteration %d, ret = %d\n", i, ret);
139                         goto out;
140                 }
141                 /* TODO: Verify data integrity */
143                 /* TODO: Reduce number of prints */
144                 printf("%s\n", packet_buf);
145         }
147         printf("\nCommunicated %d messages successfully on %s\n\n",
148                 num_msgs, eptdev_name);
150 out:
151         ret = rpmsg_char_close(rcdev);
152         if (ret < 0)
153                 perror("Can't delete the endpoint device\n");
155         return ret;
158 void usage()
160         printf("Usage: rpmsg_char_simple [-r <rproc_id>] [-n <num_msgs>] [-d <rpmsg_dev_name] [-p <remote_endpt]\n");
161         printf("\t\tDefaults: rproc_id: 0 num_msgs: %d rpmsg_dev_name: NULL remote_endpt: %d\n",
162                 NUM_ITERATIONS, REMOTE_ENDPT);
165 int main(int argc, char *argv[])
167         int ret, status, c;
168         int rproc_id = 0;
169         int num_msgs = NUM_ITERATIONS;
170         int remote_endpt = REMOTE_ENDPT;
171         char *dev_name = NULL;
173         while (1) {
174                 c = getopt(argc, argv, "r:n:p:d:");
175                 if (c == -1)
176                         break;
178                 switch (c) {
179                 case 'r':
180                         rproc_id = atoi(optarg);
181                         break;
182                 case 'n':
183                         num_msgs = atoi(optarg);
184                         break;
185                 case 'p':
186                         remote_endpt = atoi(optarg);
187                         break;
188                 case 'd':
189                         dev_name = optarg;
190                         break;
191                 default:
192                         usage();
193                         exit(0);
194                 }
195         }
197         if (rproc_id < 0 || rproc_id >= RPROC_ID_MAX) {
198                 printf("Invalid rproc id %d, should be less than %d\n",
199                         rproc_id, RPROC_ID_MAX);
200                 usage();
201                 return 1;
202         }
204         /* Use auto-detection for SoC */
205         ret = rpmsg_char_init(NULL);
206         if (ret) {
207                 printf("rpmsg_char_init failed, ret = %d\n", ret);
208                 return ret;
209         }
211         status = rpmsg_char_ping(rproc_id, dev_name, remote_endpt, num_msgs);
213         rpmsg_char_exit();
215         if (status < 0) {
216                 printf("TEST STATUS: FAILED\n");
217         } else {
218                 printf("TEST STATUS: PASSED\n");
219         }
221         return 0;