diff --git a/fs/rpmsgfs/rpmsgfs.h b/fs/rpmsgfs/rpmsgfs.h index 59cc3ab15e..fe102c9d9d 100644 --- a/fs/rpmsgfs/rpmsgfs.h +++ b/fs/rpmsgfs/rpmsgfs.h @@ -110,7 +110,9 @@ begin_packed_struct struct rpmsgfs_ioctl_s struct rpmsgfs_header_s header; int32_t fd; int32_t request; - int32_t arg; + uint64_t arg; + uint32_t arglen; + char buf[0]; } end_packed_struct; #define rpmsgfs_sync_s rpmsgfs_close_s diff --git a/fs/rpmsgfs/rpmsgfs_client.c b/fs/rpmsgfs/rpmsgfs_client.c index f92e8c6163..1feb2b11a0 100644 --- a/fs/rpmsgfs/rpmsgfs_client.c +++ b/fs/rpmsgfs/rpmsgfs_client.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -62,6 +63,9 @@ static int rpmsgfs_default_handler(FAR struct rpmsg_endpoint *ept, static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); +static int rpmsgfs_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); @@ -94,7 +98,7 @@ static const rpmsg_ept_cb g_rpmsgfs_handler[] = [RPMSGFS_READ] = rpmsgfs_read_handler, [RPMSGFS_WRITE] = rpmsgfs_default_handler, [RPMSGFS_LSEEK] = rpmsgfs_default_handler, - [RPMSGFS_IOCTL] = rpmsgfs_default_handler, + [RPMSGFS_IOCTL] = rpmsgfs_ioctl_handler, [RPMSGFS_SYNC] = rpmsgfs_default_handler, [RPMSGFS_DUP] = rpmsgfs_default_handler, [RPMSGFS_FSTAT] = rpmsgfs_stat_handler, @@ -156,6 +160,25 @@ static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept, return 0; } +static int rpmsgfs_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct rpmsgfs_header_s *header = data; + FAR struct rpmsgfs_cookie_s *cookie = + (FAR struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie; + FAR struct rpmsgfs_ioctl_s *rsp = data; + + if (cookie->result >= 0 && rsp->arglen > 0) + { + memcpy(cookie->data, (FAR void *)(uintptr_t)rsp->arg, rsp->arglen); + } + + rpmsg_post(ept, &cookie->sem); + + return 0; +} + static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv) @@ -353,6 +376,19 @@ fail: return ret; } +static size_t rpmsgfs_ioctl_arglen(int cmd) +{ + switch (cmd) + { + case FIONBIO: + case FIONWRITE: + case FIONREAD: + return sizeof(int); + default: + return 0; + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -483,15 +519,34 @@ off_t rpmsgfs_client_lseek(FAR void *handle, int fd, int rpmsgfs_client_ioctl(FAR void *handle, int fd, int request, unsigned long arg) { - struct rpmsgfs_ioctl_s msg = - { - .fd = fd, - .request = request, - .arg = arg, - }; + size_t arglen = rpmsgfs_ioctl_arglen(request); + FAR struct rpmsgfs_s *priv = handle; + FAR struct rpmsgfs_ioctl_s *msg; + uint32_t space; + size_t len; - return rpmsgfs_send_recv(handle, RPMSGFS_IOCTL, true, - (struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL); + len = sizeof(*msg) + arglen; + msg = rpmsgfs_get_tx_payload_buffer(priv, &space); + if (msg == NULL) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + msg->fd = fd; + msg->request = request; + msg->arg = arg; + msg->arglen = arglen; + + if (arglen > 0) + { + memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen); + } + + return rpmsgfs_send_recv(handle, RPMSGFS_IOCTL, false, + (FAR struct rpmsgfs_header_s *)msg, len, + arglen > 0 ? (FAR void *)arg : NULL); } void rpmsgfs_client_sync(FAR void *handle, int fd) diff --git a/fs/rpmsgfs/rpmsgfs_server.c b/fs/rpmsgfs/rpmsgfs_server.c index 9a7b27b5a8..41b7984a0c 100644 --- a/fs/rpmsgfs/rpmsgfs_server.c +++ b/fs/rpmsgfs/rpmsgfs_server.c @@ -443,7 +443,8 @@ static int rpmsgfs_ioctl_handler(FAR struct rpmsg_endpoint *ept, filep = rpmsgfs_get_file(priv, msg->fd); if (filep != NULL) { - ret = file_ioctl(filep, msg->request, msg->arg); + ret = file_ioctl(filep, msg->request, msg->arglen > 0 ? + (unsigned long)msg->buf : msg->arg); } msg->header.result = ret;