rpmsgdev: forward all open/close to server to support complex driver
Before this commit, each rpmsgdev server only manages one file no matter how many times the client opened. It can't work fine with some complex drivers, such as input driver (keyboard, touchscreen and button), because input driver will alloc a new private open structure for every open operation to make sure all the applications don't miss data when input driver is used by multiple applications. This commit solves this problem by making the files in server and client be one-to-one. Signed-off-by: wangbowen6 <wangbowen6@xiaomi.com>
This commit is contained in:
parent
fc9b5e1980
commit
c860a6e5f1
@ -25,11 +25,6 @@ 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
|
||||
|
@ -54,6 +54,11 @@
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsgdev_priv_s
|
||||
{
|
||||
uint64_t filep; /* store server file pointer */
|
||||
};
|
||||
|
||||
struct rpmsgdev_s
|
||||
{
|
||||
struct rpmsg_endpoint ept; /* Rpmsg endpoint */
|
||||
@ -63,10 +68,6 @@ struct rpmsgdev_s
|
||||
* opreation until the connection
|
||||
* between two cpu established.
|
||||
*/
|
||||
mutex_t excl; /* Exclusive mutex, used to support thread
|
||||
* safe.
|
||||
*/
|
||||
int open_count; /* Device open count */
|
||||
};
|
||||
|
||||
/* Rpmsg device cookie used to handle the response from the remote cpu */
|
||||
@ -188,6 +189,7 @@ const struct file_operations g_rpmsgdev_ops =
|
||||
static int rpmsgdev_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
struct rpmsgdev_open_s msg;
|
||||
int ret;
|
||||
|
||||
@ -202,33 +204,30 @@ static int rpmsgdev_open(FAR struct file *filep)
|
||||
dev = filep->f_inode->i_private;
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
/* Take the semaphore */
|
||||
priv = (FAR struct rpmsgdev_priv_s *)kmm_zalloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = nxmutex_lock(&dev->excl);
|
||||
/* Try to open the device in the remote cpu */
|
||||
|
||||
msg.flags = filep->f_oflags;
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_OPEN, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgdeverr("semtake error, ret=%d\n", ret);
|
||||
rpmsgdeverr("open failed, ret=%d\n", ret);
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if this is the first time that the driver has been opened. */
|
||||
priv->filep = msg.filep;
|
||||
|
||||
if (dev->open_count++ == 0)
|
||||
{
|
||||
/* Try to open the file in the host file system */
|
||||
/* Attach the private date to the struct file instance */
|
||||
|
||||
msg.flags = filep->f_oflags;
|
||||
filep->f_priv = priv;
|
||||
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_OPEN, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgdeverr("open failed\n");
|
||||
dev->open_count--;
|
||||
}
|
||||
}
|
||||
|
||||
nxmutex_unlock(&dev->excl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -249,6 +248,7 @@ static int rpmsgdev_open(FAR struct file *filep)
|
||||
static int rpmsgdev_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
struct rpmsgdev_close_s msg;
|
||||
int ret;
|
||||
|
||||
@ -258,30 +258,24 @@ static int rpmsgdev_close(FAR struct file *filep)
|
||||
|
||||
/* Recover our private data from the struct file instance */
|
||||
|
||||
dev = filep->f_inode->i_private;
|
||||
DEBUGASSERT(dev != NULL);
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Take the semaphore */
|
||||
/* Try to close the device in the remote cpu */
|
||||
|
||||
ret = nxmutex_lock(&dev->excl);
|
||||
msg.filep = priv->filep;
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_CLOSE, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
rpmsgdeverr("close failed, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* There are no more references to the port */
|
||||
filep->f_priv = NULL;
|
||||
kmm_free(priv);
|
||||
|
||||
if (--dev->open_count == 0)
|
||||
{
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_CLOSE, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
dev->open_count++;
|
||||
}
|
||||
}
|
||||
|
||||
nxmutex_unlock(&dev->excl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -306,6 +300,7 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
struct rpmsgdev_read_s msg;
|
||||
struct iovec read;
|
||||
ssize_t ret;
|
||||
@ -321,29 +316,21 @@ static ssize_t rpmsgdev_read(FAR struct file *filep, FAR char *buffer,
|
||||
|
||||
/* 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;
|
||||
}
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Call the host to perform the read */
|
||||
|
||||
read.iov_base = buffer;
|
||||
read.iov_len = 0;
|
||||
|
||||
msg.filep = priv->filep;
|
||||
msg.count = buflen;
|
||||
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_READ, true, &msg.header,
|
||||
sizeof(msg) - 1, &read);
|
||||
|
||||
nxmutex_unlock(&dev->excl);
|
||||
|
||||
return read.iov_len ? read.iov_len : ret;
|
||||
}
|
||||
|
||||
@ -370,6 +357,7 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
FAR struct rpmsgdev_write_s *msg;
|
||||
struct rpmsgdev_cookie_s cookie;
|
||||
uint32_t space;
|
||||
@ -385,16 +373,9 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer,
|
||||
|
||||
/* 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;
|
||||
}
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Perform the rpmsg write */
|
||||
|
||||
@ -428,6 +409,7 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer,
|
||||
|
||||
msg->header.command = RPMSGDEV_WRITE;
|
||||
msg->header.result = -ENXIO;
|
||||
msg->filep = priv->filep;
|
||||
msg->count = space;
|
||||
memcpy(msg->buf, buffer + written, space);
|
||||
|
||||
@ -450,8 +432,6 @@ static ssize_t rpmsgdev_write(FAR struct file *filep, const char *buffer,
|
||||
|
||||
out:
|
||||
nxsem_destroy(&cookie.sem);
|
||||
nxmutex_unlock(&dev->excl);
|
||||
|
||||
return ret < 0 ? ret : buflen;
|
||||
}
|
||||
|
||||
@ -475,8 +455,8 @@ out:
|
||||
static off_t rpmsgdev_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
struct rpmsgdev_lseek_s msg;
|
||||
off_t ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
@ -484,27 +464,18 @@ static off_t rpmsgdev_seek(FAR struct file *filep, off_t offset, int whence)
|
||||
|
||||
/* 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;
|
||||
}
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Call our internal routine to perform the seek */
|
||||
|
||||
msg.filep = priv->filep;
|
||||
msg.offset = offset;
|
||||
msg.whence = whence;
|
||||
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_LSEEK, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
|
||||
nxmutex_unlock(&dev->excl);
|
||||
return ret;
|
||||
return rpmsgdev_send_recv(dev, RPMSGDEV_LSEEK, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -557,11 +528,11 @@ static size_t rpmsgdev_ioctl_arglen(int cmd)
|
||||
static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
FAR struct rpmsgdev_ioctl_s *msg;
|
||||
uint32_t space;
|
||||
size_t arglen;
|
||||
size_t msglen;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
@ -569,16 +540,9 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
|
||||
/* 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;
|
||||
}
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Call our internal routine to perform the ioctl */
|
||||
|
||||
@ -588,10 +552,10 @@ 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;
|
||||
}
|
||||
|
||||
msg->filep = priv->filep;
|
||||
msg->request = cmd;
|
||||
msg->arg = arg;
|
||||
msg->arglen = arglen;
|
||||
@ -601,11 +565,8 @@ static int rpmsgdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen);
|
||||
}
|
||||
|
||||
ret = rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header,
|
||||
msglen, arglen > 0 ? (FAR void *)arg : NULL);
|
||||
|
||||
nxmutex_unlock(&dev->excl);
|
||||
return ret;
|
||||
return rpmsgdev_send_recv(dev, RPMSGDEV_IOCTL, false, &msg->header,
|
||||
msglen, arglen > 0 ? (FAR void *)arg : NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -628,8 +589,8 @@ static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup)
|
||||
{
|
||||
FAR struct rpmsgdev_s *dev;
|
||||
FAR struct rpmsgdev_priv_s *priv;
|
||||
struct rpmsgdev_poll_s msg;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
@ -637,32 +598,19 @@ static int rpmsgdev_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
|
||||
/* 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;
|
||||
}
|
||||
dev = filep->f_inode->i_private;
|
||||
priv = filep->f_priv;
|
||||
DEBUGASSERT(dev != NULL && priv != NULL);
|
||||
|
||||
/* Setup or teardown the poll */
|
||||
|
||||
msg.events = fds->events;
|
||||
msg.setup = setup;
|
||||
msg.fds = (uint64_t)(uintptr_t)fds;
|
||||
msg.filep = priv->filep;
|
||||
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;
|
||||
return rpmsgdev_send_recv(dev, RPMSGDEV_POLL, true, &msg.header,
|
||||
sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1085,8 +1033,6 @@ int rpmsgdev_register(FAR const char *remotecpu, FAR const char *remotepath,
|
||||
dev->remotecpu = remotecpu;
|
||||
dev->remotepath = remotepath;
|
||||
|
||||
nxmutex_init(&dev->excl);
|
||||
|
||||
nxsem_init(&dev->wait, 0, 0);
|
||||
nxsem_set_protocol(&dev->wait, SEM_PRIO_NONE);
|
||||
|
||||
@ -1127,7 +1073,6 @@ fail_with_rpmsg:
|
||||
NULL);
|
||||
|
||||
fail:
|
||||
nxmutex_destroy(&dev->excl);
|
||||
nxsem_destroy(&dev->wait);
|
||||
kmm_free(dev);
|
||||
|
||||
|
@ -61,17 +61,20 @@ begin_packed_struct struct rpmsgdev_header_s
|
||||
begin_packed_struct struct rpmsgdev_open_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
uint64_t filep;
|
||||
int32_t flags;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgdev_close_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
uint64_t filep;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgdev_read_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
uint64_t filep;
|
||||
uint32_t count;
|
||||
char buf[1];
|
||||
} end_packed_struct;
|
||||
@ -81,6 +84,7 @@ begin_packed_struct struct rpmsgdev_read_s
|
||||
begin_packed_struct struct rpmsgdev_lseek_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
uint64_t filep;
|
||||
int32_t whence;
|
||||
int32_t offset;
|
||||
} end_packed_struct;
|
||||
@ -88,15 +92,17 @@ begin_packed_struct struct rpmsgdev_lseek_s
|
||||
begin_packed_struct struct rpmsgdev_ioctl_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
int32_t request;
|
||||
uint64_t filep;
|
||||
uint64_t arg;
|
||||
uint32_t arglen;
|
||||
int32_t request;
|
||||
char buf[1];
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgdev_poll_s
|
||||
{
|
||||
struct rpmsgdev_header_s header;
|
||||
uint64_t filep;
|
||||
uint32_t events;
|
||||
uint32_t setup;
|
||||
uint64_t fds;
|
||||
|
@ -28,7 +28,9 @@
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/list.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/drivers/rpmsgdev.h>
|
||||
#include <nuttx/rptun/openamp.h>
|
||||
@ -43,12 +45,23 @@
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsgdev_device_s
|
||||
{
|
||||
struct file file; /* The open file */
|
||||
struct pollfd fd; /* The poll fd */
|
||||
uint64_t cfd; /* The client poll fd pointer */
|
||||
struct list_node node; /* The double-linked list node */
|
||||
};
|
||||
|
||||
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];
|
||||
struct rpmsg_endpoint ept; /* Rpmsg end point */
|
||||
struct list_node head; /* The double-linked list head of opened
|
||||
* devices
|
||||
*/
|
||||
mutex_t lock; /* The mutex used to protect the list
|
||||
* operation
|
||||
*/
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -122,11 +135,31 @@ static int rpmsgdev_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
{
|
||||
FAR struct rpmsgdev_server_s *server = ept->priv;
|
||||
FAR struct rpmsgdev_open_s *msg = data;
|
||||
FAR struct rpmsgdev_device_s *dev;
|
||||
|
||||
msg->header.result = file_open(&server->file,
|
||||
dev = kmm_zalloc(sizeof(*dev));
|
||||
if (dev == NULL)
|
||||
{
|
||||
msg->header.result = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg->header.result = file_open(&dev->file,
|
||||
&ept->name[RPMSGDEV_NAME_PREFIX_LEN],
|
||||
msg->flags, 0);
|
||||
if (msg->header.result < 0)
|
||||
{
|
||||
kmm_free(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg->filep = (uint64_t)(uintptr_t)&dev->file;
|
||||
|
||||
nxmutex_lock(&server->lock);
|
||||
list_add_tail(&server->head, &dev->node);
|
||||
nxmutex_unlock(&server->lock);
|
||||
|
||||
out:
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
@ -140,8 +173,18 @@ static int rpmsgdev_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
{
|
||||
FAR struct rpmsgdev_server_s *server = ept->priv;
|
||||
FAR struct rpmsgdev_close_s *msg = data;
|
||||
FAR struct rpmsgdev_device_s *dev =
|
||||
(FAR struct rpmsgdev_device_s *)(uintptr_t)msg->filep;
|
||||
|
||||
msg->header.result = file_close(&server->file);
|
||||
msg->header.result = file_close(&dev->file);
|
||||
if (msg->header.result == 0)
|
||||
{
|
||||
nxmutex_lock(&server->lock);
|
||||
list_delete(&dev->node);
|
||||
nxmutex_unlock(&server->lock);
|
||||
|
||||
kmm_free(dev);
|
||||
}
|
||||
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
@ -154,9 +197,9 @@ static int rpmsgdev_read_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_read_s *msg = data;
|
||||
FAR struct rpmsgdev_read_s *rsp;
|
||||
FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep;
|
||||
int ret = -ENOENT;
|
||||
size_t read = 0;
|
||||
uint32_t space;
|
||||
@ -177,7 +220,7 @@ static int rpmsgdev_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
space = msg->count - read;
|
||||
}
|
||||
|
||||
ret = file_read(&server->file, rsp->buf, space);
|
||||
ret = file_read(filep, rsp->buf, space);
|
||||
|
||||
rsp->header.result = ret;
|
||||
rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp) - 1);
|
||||
@ -200,14 +243,14 @@ static int rpmsgdev_write_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_write_s *msg = data;
|
||||
FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep;
|
||||
size_t written = 0;
|
||||
int ret = -ENOENT;
|
||||
|
||||
while (written < msg->count)
|
||||
{
|
||||
ret = file_write(&server->file, msg->buf + written,
|
||||
ret = file_write(filep, msg->buf + written,
|
||||
msg->count - written);
|
||||
if (ret <= 0)
|
||||
{
|
||||
@ -234,10 +277,10 @@ static int rpmsgdev_lseek_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_lseek_s *msg = data;
|
||||
FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep;
|
||||
|
||||
msg->header.result = file_seek(&server->file, msg->offset, msg->whence);
|
||||
msg->header.result = file_seek(filep, msg->offset, msg->whence);
|
||||
|
||||
return rpmsg_send(ept, msg, len);
|
||||
}
|
||||
@ -250,10 +293,10 @@ static int rpmsgdev_ioctl_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_ioctl_s *msg = data;
|
||||
FAR struct file *filep = (FAR struct file *)(uintptr_t)msg->filep;
|
||||
|
||||
msg->header.result = file_ioctl(&server->file, msg->request,
|
||||
msg->header.result = file_ioctl(filep, msg->request,
|
||||
msg->arglen > 0 ? (unsigned long)msg->buf :
|
||||
msg->arg);
|
||||
|
||||
@ -267,16 +310,15 @@ static int rpmsgdev_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
static void rpmsgdev_poll_cb(FAR struct pollfd *fds)
|
||||
{
|
||||
FAR struct rpmsgdev_server_s *server = fds->arg;
|
||||
FAR struct rpmsgdev_device_s *dev =
|
||||
container_of(fds, FAR struct rpmsgdev_device_s, fd);
|
||||
FAR struct rpmsgdev_notify_s msg;
|
||||
int tmp;
|
||||
|
||||
DEBUGASSERT(fds != NULL && (uintptr_t)fds >= (uintptr_t)server->fds);
|
||||
|
||||
tmp = fds - server->fds;
|
||||
DEBUGASSERT(fds != NULL && dev->cfd != 0);
|
||||
|
||||
msg.header.command = RPMSGDEV_NOTIFY;
|
||||
msg.revents = fds->revents;
|
||||
msg.fds = server->cfds[tmp];
|
||||
msg.fds = dev->cfd;
|
||||
|
||||
fds->revents = 0;
|
||||
|
||||
@ -293,61 +335,34 @@ static int rpmsgdev_poll_handler(FAR struct rpmsg_endpoint *ept,
|
||||
{
|
||||
FAR struct rpmsgdev_server_s *server = ept->priv;
|
||||
FAR struct rpmsgdev_poll_s *msg = data;
|
||||
FAR struct pollfd *fds = NULL;
|
||||
int i;
|
||||
FAR struct rpmsgdev_device_s *dev =
|
||||
(FAR struct rpmsgdev_device_s *)(uintptr_t)msg->filep;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Do not allow double setup */
|
||||
|
||||
if (i >= CONFIG_DEV_RPMSG_NPOLLWAITERS)
|
||||
{
|
||||
msg->header.result = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
DEBUGASSERT(dev->cfd == 0);
|
||||
|
||||
fds = &server->fds[i];
|
||||
fds->events = msg->events;
|
||||
fds->revents = 0;
|
||||
fds->cb = rpmsgdev_poll_cb;
|
||||
fds->arg = server;
|
||||
dev->cfd = msg->fds;
|
||||
dev->fd.events = msg->events;
|
||||
dev->fd.revents = 0;
|
||||
dev->fd.cb = rpmsgdev_poll_cb;
|
||||
dev->fd.arg = server;
|
||||
|
||||
msg->header.result = file_poll(&server->file, fds, true);
|
||||
msg->header.result = file_poll(&dev->file, &dev->fd, 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);
|
||||
msg->header.result = file_poll(&dev->file, &dev->fd, false);
|
||||
if (msg->header.result == OK)
|
||||
{
|
||||
server->cfds[i] = 0;
|
||||
dev->cfd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return rpmsg_send(ept, msg, len);
|
||||
}
|
||||
|
||||
@ -379,6 +394,8 @@ static void rpmsgdev_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
return;
|
||||
}
|
||||
|
||||
list_initialize(&server->head);
|
||||
nxmutex_init(&server->lock);
|
||||
server->ept.priv = server;
|
||||
|
||||
ret = rpmsg_create_ept(&server->ept, rdev, name,
|
||||
@ -397,10 +414,31 @@ static void rpmsgdev_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
static void rpmsgdev_ns_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct rpmsgdev_server_s *server = ept->priv;
|
||||
FAR struct rpmsgdev_device_s *dev;
|
||||
FAR struct rpmsgdev_device_s *tmpdev;
|
||||
|
||||
nxmutex_lock(&server->lock);
|
||||
|
||||
list_for_every_entry_safe(&server->head, dev, tmpdev,
|
||||
struct rpmsgdev_device_s, node)
|
||||
{
|
||||
if (dev->cfd != 0)
|
||||
{
|
||||
file_poll(&dev->file, &dev->fd, false);
|
||||
}
|
||||
|
||||
if (dev->file.f_inode != NULL)
|
||||
{
|
||||
file_close(&dev->file);
|
||||
}
|
||||
|
||||
list_delete(&dev->node);
|
||||
kmm_free(dev);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&server->lock);
|
||||
|
||||
file_close(&server->file);
|
||||
rpmsg_destroy_ept(&server->ept);
|
||||
|
||||
kmm_free(server);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user