/* * This is a sample demonstration application that showcases usage of rpmsg * This application is meant to run on the remote CPU running baremetal code. * This application allows to check the compatibility with linux OS running on * the master CPU. For this it echo MSG_LIMIT time message sent by the rpmsg * sample client available in linux kernel distribution. */ #include #include #include #include "platform_info.h" #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) #define RPMSG_SERV_NAME "rpmsg-client-sample" #define MSG_LIMIT 100 static struct rpmsg_endpoint lept; static int shutdown_req = 0; /*-----------------------------------------------------------------------------* * RPMSG endpoint callbacks *-----------------------------------------------------------------------------*/ static int rpmsg_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { (void)priv; (void)src; static uint32_t count = 0; char payload[RPMSG_BUFFER_SIZE]; /* Send data back MSG_LIMIT time to master */ memset(payload, 0, RPMSG_BUFFER_SIZE); memcpy(payload, data, len); if (++count <= MSG_LIMIT) { LPRINTF("echo message number %u: %s\n", (unsigned int)count, payload); if (rpmsg_send(ept, (char *)data, len) < 0) { LPERROR("rpmsg_send failed\n"); goto destroy_ept; } if (count == MSG_LIMIT) { goto destroy_ept; } } return RPMSG_SUCCESS; destroy_ept: shutdown_req = 1; return RPMSG_SUCCESS; } static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) { (void)ept; LPRINTF("unexpected Remote endpoint destroy\n"); shutdown_req = 1; } /*-----------------------------------------------------------------------------* * Application *-----------------------------------------------------------------------------*/ int app(struct rpmsg_device *rdev, void *priv) { int ret; /* Initialize RPMSG framework */ LPRINTF("Try to create rpmsg endpoint.\n"); ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERV_NAME, 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, rpmsg_service_unbind); if (ret) { LPERROR("Failed to create endpoint.\n"); return -1; } LPRINTF("Successfully created rpmsg endpoint.\n"); while (1) { platform_poll(priv); /* we got a shutdown request, exit */ if (shutdown_req) { break; } } rpmsg_destroy_ept(&lept); return 0; } /*-----------------------------------------------------------------------------* * Application entry point *-----------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { void *platform; struct rpmsg_device *rpdev; int ret; LPRINTF("Starting application...\n"); /* Initialize platform */ ret = platform_init(argc, argv, &platform); if (ret) { LPERROR("Failed to initialize platform.\n"); ret = -1; } else { rpdev = platform_create_rpmsg_vdev(platform, 0, VIRTIO_DEV_SLAVE, NULL, NULL); if (!rpdev) { LPERROR("Failed to create rpmsg virtio device.\n"); ret = -1; } else { app(rpdev, platform); platform_release_rpmsg_vdev(rpdev); ret = 0; } } LPRINTF("Stopping application...\n"); platform_cleanup(platform); return ret; }