This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 5d8cbfb279 rpmsgdev: add rpmsgdev poll() support. 5d8cbfb279 is described below commit 5d8cbfb279689466a00a073bb7fc356dd1d47891 Author: wangbowen6 <wangbow...@xiaomi.com> AuthorDate: Wed Sep 14 11:09:13 2022 +0800 rpmsgdev: add rpmsgdev poll() support. Signed-off-by: wangbowen6 <wangbow...@xiaomi.com> --- boards/sim/sim/sim/configs/rpserver/defconfig | 2 + boards/sim/sim/sim/src/sim_bringup.c | 1 + drivers/misc/Kconfig | 5 ++ drivers/misc/rpmsgdev.c | 112 +++++++++++++++++++++-- drivers/misc/rpmsgdev.h | 17 ++++ drivers/misc/rpmsgdev_server.c | 124 +++++++++++++++++++++++--- 6 files changed, 242 insertions(+), 19 deletions(-) diff --git a/boards/sim/sim/sim/configs/rpserver/defconfig b/boards/sim/sim/sim/configs/rpserver/defconfig index 9f633f020c..03170c742b 100644 --- a/boards/sim/sim/sim/configs/rpserver/defconfig +++ b/boards/sim/sim/sim/configs/rpserver/defconfig @@ -88,6 +88,8 @@ CONFIG_SIM_M32=y CONFIG_SIM_NETDEV=y CONFIG_SIM_NET_BRIDGE=y CONFIG_SIM_RPTUN_MASTER=y +CONFIG_SIM_UART0_NAME="/dev/ttyUSB0" +CONFIG_SIM_UART_NUMBER=1 CONFIG_SYSLOG_PREFIX=y CONFIG_SYSLOG_PREFIX_STRING="server: " CONFIG_SYSLOG_RPMSG_SERVER=y diff --git a/boards/sim/sim/sim/src/sim_bringup.c b/boards/sim/sim/sim/src/sim_bringup.c index bc37dc57cd..d0b4a099b3 100644 --- a/boards/sim/sim/sim/src/sim_bringup.c +++ b/boards/sim/sim/sim/src/sim_bringup.c @@ -440,6 +440,7 @@ int sim_bringup(void) #ifdef CONFIG_DEV_RPMSG rpmsgdev_register("server", "/dev/console", "/dev/server-console"); rpmsgdev_register("server", "/dev/null", "/dev/server-null"); + rpmsgdev_register("server", "/dev/ttyUSB0", "/dev/ttyUSB0"); #endif #ifdef CONFIG_RPMSGMTD diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 95be70c993..4a9671eb14 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -25,6 +25,11 @@ config DEV_RPMSG_SERVER default n depends on RPTUN +config DEV_RPMSG_NPOLLWAITERS + int "RPMSG Device Max Number of Poll Threads" + default 4 + depends on DEV_RPMSG_SERVER + config DRVR_MKRD bool "RAM disk wrapper (mkrd)" default n diff --git a/drivers/misc/rpmsgdev.c b/drivers/misc/rpmsgdev.c index 6d8628334b..75b0bc112d 100644 --- a/drivers/misc/rpmsgdev.c +++ b/drivers/misc/rpmsgdev.c @@ -29,7 +29,9 @@ #include <string.h> #include <assert.h> #include <fcntl.h> +#include <poll.h> #include <limits.h> +#include <debug.h> #include <nuttx/kmalloc.h> #include <nuttx/fs/fs.h> @@ -93,6 +95,8 @@ static off_t rpmsgdev_seek(FAR struct file *filep, off_t offset, static size_t rpmsgdev_ioctl_arglen(int cmd); static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); /* Functions for sending data to the remote cpu */ @@ -114,6 +118,9 @@ static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept, static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); +static int rpmsgdev_notify_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); /* Functions for creating communication with remote cpu */ @@ -134,12 +141,14 @@ static void rpmsgdev_ns_bound(struct rpmsg_endpoint *ept); static const rpmsg_ept_cb g_rpmsgdev_handler[] = { - [RPMSGDEV_OPEN] = rpmsgdev_default_handler, - [RPMSGDEV_CLOSE] = rpmsgdev_default_handler, - [RPMSGDEV_READ] = rpmsgdev_read_handler, - [RPMSGDEV_WRITE] = rpmsgdev_default_handler, - [RPMSGDEV_LSEEK] = rpmsgdev_default_handler, - [RPMSGDEV_IOCTL] = rpmsgdev_ioctl_handler, + [RPMSGDEV_OPEN] = rpmsgdev_default_handler, + [RPMSGDEV_CLOSE] = rpmsgdev_default_handler, + [RPMSGDEV_READ] = rpmsgdev_read_handler, + [RPMSGDEV_WRITE] = rpmsgdev_default_handler, + [RPMSGDEV_LSEEK] = rpmsgdev_default_handler, + [RPMSGDEV_IOCTL] = rpmsgdev_ioctl_handler, + [RPMSGDEV_POLL] = rpmsgdev_default_handler, + [RPMSGDEV_NOTIFY] = rpmsgdev_notify_handler, }; /* File operations */ @@ -152,7 +161,7 @@ const struct file_operations g_rpmsgdev_ops = rpmsgdev_write, /* write */ rpmsgdev_seek, /* seek */ rpmsgdev_ioctl, /* ioctl */ - NULL /* poll */ + rpmsgdev_poll /* poll */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS , NULL /* unlink */ #endif @@ -579,6 +588,7 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) msg = rpmsgdev_get_tx_payload_buffer(dev, &space); if (msg == NULL) { + nxmutex_unlock(&dev->excl); return -ENOMEM; } @@ -598,6 +608,63 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) return ret; } +/**************************************************************************** + * Name: rpmsgdev_poll + * + * Description: + * Rpmsg-device poll operation + * + * Parameters: + * filep - the file instance + * fds - The structure describing the events to be monitored. + * setup - true: Setup up the poll; false: Teardown the poll + * + * Returned Values: + * OK on success; A negated errno value is returned on any failure. + * + ****************************************************************************/ + +static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct rpmsgdev_s *dev; + struct rpmsgdev_poll_s msg; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(filep->f_inode != NULL); + + /* Recover our private data from the struct file instance */ + + dev = filep->f_inode->i_private; + DEBUGASSERT(dev != NULL); + + /* Take the semaphore */ + + ret = nxmutex_lock(&dev->excl); + if (ret < 0) + { + return ret; + } + + /* Setup or teardown the poll */ + + msg.events = fds->events; + msg.setup = setup; + msg.fds = (uint64_t)(uintptr_t)fds; + + ret = rpmsgdev_send_recv(dev, RPMSGDEV_POLL, true, &msg.header, + sizeof(msg), NULL); + if (ret < 0) + { + rpmsgdeverr("Send failed, ret=%d\n", ret); + } + + nxmutex_unlock(&dev->excl); + return ret; +} + /**************************************************************************** * Name: rpmsgdev_get_tx_payload_buffer * @@ -823,6 +890,37 @@ static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, return 0; } +/**************************************************************************** + * Name: rpmsgdev_notify_handler + * + * Description: + * Rpmsg-device poll notify handler. + * + * Parameters: + * ept - The rpmsg endpoint + * data - The return message + * len - The return message length + * src - unknow + * priv - unknow + * + * Returned Values: + * Always OK + * + ****************************************************************************/ + +static int rpmsgdev_notify_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgdev_notify_s *rsp = data; + FAR struct pollfd *fds; + + fds = (FAR struct pollfd *)(uintptr_t)rsp->fds; + poll_notify(&fds, 1, rsp->revents); + + return 0; +} + /**************************************************************************** * Name: rpmsgdev_ns_bound * diff --git a/drivers/misc/rpmsgdev.h b/drivers/misc/rpmsgdev.h index f51a7056f0..a92177f5ab 100644 --- a/drivers/misc/rpmsgdev.h +++ b/drivers/misc/rpmsgdev.h @@ -44,6 +44,8 @@ #define RPMSGDEV_WRITE 4 #define RPMSGDEV_LSEEK 5 #define RPMSGDEV_IOCTL 6 +#define RPMSGDEV_POLL 7 +#define RPMSGDEV_NOTIFY 8 /**************************************************************************** * Public Types @@ -92,6 +94,21 @@ begin_packed_struct struct rpmsgdev_ioctl_s char buf[1]; } end_packed_struct; +begin_packed_struct struct rpmsgdev_poll_s +{ + struct rpmsgdev_header_s header; + uint32_t events; + uint32_t setup; + uint64_t fds; +} end_packed_struct; + +begin_packed_struct struct rpmsgdev_notify_s +{ + struct rpmsgdev_header_s header; + uint64_t fds; + uint32_t revents; +} end_packed_struct; + /**************************************************************************** * Internal function prototypes ****************************************************************************/ diff --git a/drivers/misc/rpmsgdev_server.c b/drivers/misc/rpmsgdev_server.c index 6561f8d7f0..20dc0590f8 100644 --- a/drivers/misc/rpmsgdev_server.c +++ b/drivers/misc/rpmsgdev_server.c @@ -24,7 +24,9 @@ #include <string.h> #include <fcntl.h> +#include <poll.h> #include <errno.h> +#include <debug.h> #include <nuttx/kmalloc.h> #include <nuttx/fs/fs.h> @@ -45,6 +47,8 @@ struct rpmsgdev_server_s { struct rpmsg_endpoint ept; struct file file; + struct pollfd fds[CONFIG_DEV_RPMSG_NPOLLWAITERS]; + uint64_t cfds[CONFIG_DEV_RPMSG_NPOLLWAITERS]; }; /**************************************************************************** @@ -53,22 +57,26 @@ struct rpmsgdev_server_s /* Functions handle the messages from the client cpu */ -static int rpmsgdev_open_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int rpmsgdev_close_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept, - FAR void *data, size_t len, - uint32_t src, FAR void *priv); -static int rpmsgdev_write_handler(FAR struct rpmsg_endpoint *ept, +static int rpmsgdev_open_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); -static int rpmsgdev_lseek_handler(FAR struct rpmsg_endpoint *ept, +static int rpmsgdev_close_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); -static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, +static int rpmsgdev_write_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgdev_lseek_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static void rpmsgdev_poll_cb(FAR struct pollfd *fds); +static int rpmsgdev_poll_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); @@ -97,6 +105,7 @@ static const rpmsg_ept_cb g_rpmsgdev_handler[] = [RPMSGDEV_WRITE] = rpmsgdev_write_handler, [RPMSGDEV_LSEEK] = rpmsgdev_lseek_handler, [RPMSGDEV_IOCTL] = rpmsgdev_ioctl_handler, + [RPMSGDEV_POLL] = rpmsgdev_poll_handler, }; /**************************************************************************** @@ -251,6 +260,97 @@ static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept, return rpmsg_send(ept, msg, len); } +/**************************************************************************** + * Name: rpmsgdev_poll_cb + ****************************************************************************/ + +static void rpmsgdev_poll_cb(FAR struct pollfd *fds) +{ + FAR struct rpmsgdev_server_s *server = fds->arg; + FAR struct rpmsgdev_notify_s msg; + int tmp; + + DEBUGASSERT(fds != NULL && (uintptr_t)fds >= (uintptr_t)server->fds); + + tmp = fds - server->fds; + + msg.header.command = RPMSGDEV_NOTIFY; + msg.revents = fds->revents; + msg.fds = server->cfds[tmp]; + + fds->revents = 0; + + rpmsg_send(&server->ept, &msg, sizeof(msg)); +} + +/**************************************************************************** + * Name: rpmsgdev_poll_handler + ****************************************************************************/ + +static int rpmsgdev_poll_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgdev_server_s *server = ept->priv; + FAR struct rpmsgdev_poll_s *msg = data; + FAR struct pollfd *fds = NULL; + int i; + + DEBUGASSERT(msg->fds != 0); + + if (msg->setup) + { + for (i = 0; i < CONFIG_DEV_RPMSG_NPOLLWAITERS; i++) + { + if (server->cfds[i] == 0) + { + server->cfds[i] = msg->fds; + break; + } + } + + if (i >= CONFIG_DEV_RPMSG_NPOLLWAITERS) + { + msg->header.result = -EBUSY; + goto out; + } + + fds = &server->fds[i]; + fds->events = msg->events; + fds->revents = 0; + fds->cb = rpmsgdev_poll_cb; + fds->arg = server; + + msg->header.result = file_poll(&server->file, fds, true); + } + else + { + for (i = 0; i < CONFIG_DEV_RPMSG_NPOLLWAITERS; i++) + { + if (server->cfds[i] == msg->fds) + { + break; + } + } + + if (i >= CONFIG_DEV_RPMSG_NPOLLWAITERS) + { + msg->header.result = -EINVAL; + goto out; + } + + fds = &server->fds[i]; + msg->header.result = file_poll(&server->file, fds, false); + if (msg->header.result == OK) + { + server->cfds[i] = 0; + } + } + +out: + return rpmsg_send(ept, msg, len); +} + /**************************************************************************** * Name: rpmsgdev_ns_match ****************************************************************************/