hosfs_rpmsg: merge hostfs_rpmsg to rpmsgfs
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
5ed85ef476
commit
985cc4fc6d
@ -134,3 +134,4 @@ source "fs/littlefs/Kconfig"
|
||||
source "fs/unionfs/Kconfig"
|
||||
source "fs/userfs/Kconfig"
|
||||
source "fs/hostfs/Kconfig"
|
||||
source "fs/rpmsgfs/Kconfig"
|
||||
|
@ -56,6 +56,7 @@ include unionfs/Make.defs
|
||||
include userfs/Make.defs
|
||||
include hostfs/Make.defs
|
||||
include littlefs/Make.defs
|
||||
include rpmsgfs/Make.defs
|
||||
|
||||
endif
|
||||
|
||||
|
@ -36,23 +36,3 @@ config FS_HOSTFS
|
||||
option to enable the handling of the trap.
|
||||
Theoretically, it can work for other environments as well.
|
||||
E.g. a real hardware + JTAG + OpenOCD.
|
||||
|
||||
config FS_HOSTFS_RPMSG
|
||||
bool "Host File System Rpmsg"
|
||||
default n
|
||||
depends on FS_HOSTFS
|
||||
depends on OPENAMP
|
||||
---help---
|
||||
Use Host file system to mount directories through rpmsg.
|
||||
This is the driver that sending the message.
|
||||
|
||||
This effectively replaces the ordinary hostfs backend.
|
||||
Right now, there is no way to enable both backends.
|
||||
|
||||
config FS_HOSTFS_RPMSG_SERVER
|
||||
bool "Host File System Rpmsg Server"
|
||||
default n
|
||||
depends on OPENAMP
|
||||
---help---
|
||||
Use Host file system to mount directories through rpmsg.
|
||||
This is the driver that receiving the message.
|
||||
|
@ -26,11 +26,3 @@ VPATH += :hostfs
|
||||
ifeq ($(CONFIG_FS_HOSTFS),y)
|
||||
CSRCS += hostfs.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FS_HOSTFS_RPMSG),y)
|
||||
CSRCS += hostfs_rpmsg.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FS_HOSTFS_RPMSG_SERVER),y)
|
||||
CSRCS += hostfs_rpmsg_server.c
|
||||
endif
|
||||
|
@ -1,775 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/hostfs/hostfs_rpmsg.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/hostfs.h>
|
||||
#include <nuttx/fs/hostfs_rpmsg.h>
|
||||
#include <nuttx/rptun/openamp.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
#include "hostfs_rpmsg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct hostfs_rpmsg_s
|
||||
{
|
||||
struct rpmsg_endpoint ept;
|
||||
FAR const char *cpuname;
|
||||
};
|
||||
|
||||
struct hostfs_rpmsg_cookie_s
|
||||
{
|
||||
sem_t sem;
|
||||
int result;
|
||||
FAR void *data;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static void hostfs_rpmsg_device_created(struct rpmsg_device *rdev,
|
||||
FAR void *priv_);
|
||||
static void hostfs_rpmsg_device_destroy(struct rpmsg_device *rdev,
|
||||
FAR void *priv_);
|
||||
static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv);
|
||||
static int hostfs_rpmsg_send_recv(uint32_t command, bool copy,
|
||||
FAR struct hostfs_rpmsg_header_s *msg,
|
||||
int len, FAR void *data);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct hostfs_rpmsg_s g_hostfs_rpmsg;
|
||||
|
||||
static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] =
|
||||
{
|
||||
[HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler,
|
||||
[HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_DUP] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_stat_handler,
|
||||
[HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler,
|
||||
[HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler,
|
||||
[HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler,
|
||||
[HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_default_handler,
|
||||
[HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_default_handler,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
FAR struct hostfs_rpmsg_cookie_s *cookie =
|
||||
(struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0 && cookie->data)
|
||||
{
|
||||
memcpy(cookie->data, data, len);
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
FAR struct hostfs_rpmsg_cookie_s *cookie =
|
||||
(struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct hostfs_rpmsg_read_s *rsp = data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result > 0)
|
||||
{
|
||||
memcpy(cookie->data, rsp->buf, B2C(cookie->result));
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
FAR struct hostfs_rpmsg_cookie_s *cookie =
|
||||
(struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct hostfs_rpmsg_readdir_s *rsp = data;
|
||||
FAR struct dirent *entry = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
nbstr2cstr(entry->d_name, rsp->name, NAME_MAX);
|
||||
entry->d_name[NAME_MAX] = '\0';
|
||||
entry->d_type = rsp->type;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
FAR struct hostfs_rpmsg_cookie_s *cookie =
|
||||
(struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct hostfs_rpmsg_statfs_s *rsp = data;
|
||||
FAR struct statfs *buf = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
buf->f_type = rsp->buf.f_type;
|
||||
buf->f_namelen = rsp->buf.f_namelen;
|
||||
buf->f_bsize = B2C(rsp->buf.f_bsize);
|
||||
buf->f_blocks = rsp->buf.f_blocks;
|
||||
buf->f_bfree = rsp->buf.f_bfree;
|
||||
buf->f_bavail = rsp->buf.f_bavail;
|
||||
buf->f_files = rsp->buf.f_files;
|
||||
buf->f_ffree = rsp->buf.f_ffree;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
FAR struct hostfs_rpmsg_cookie_s *cookie =
|
||||
(struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct hostfs_rpmsg_stat_s *rsp = data;
|
||||
FAR struct stat *buf = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
buf->st_dev = rsp->buf.st_dev;
|
||||
buf->st_ino = rsp->buf.st_ino;
|
||||
buf->st_mode = rsp->buf.st_mode;
|
||||
buf->st_nlink = rsp->buf.st_nlink;
|
||||
buf->st_uid = rsp->buf.st_uid;
|
||||
buf->st_gid = rsp->buf.st_gid;
|
||||
buf->st_rdev = rsp->buf.st_rdev;
|
||||
buf->st_size = B2C(rsp->buf.st_size);
|
||||
buf->st_atime = rsp->buf.st_atime;
|
||||
buf->st_mtime = rsp->buf.st_mtime;
|
||||
buf->st_ctime = rsp->buf.st_ctime;
|
||||
buf->st_blksize = B2C(rsp->buf.st_blksize);
|
||||
buf->st_blocks = rsp->buf.st_blocks;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hostfs_rpmsg_device_created(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = priv_;
|
||||
|
||||
if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
|
||||
{
|
||||
priv->ept.priv = priv;
|
||||
rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME,
|
||||
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
||||
hostfs_rpmsg_ept_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void hostfs_rpmsg_device_destroy(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = priv_;
|
||||
|
||||
if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
|
||||
{
|
||||
rpmsg_destroy_ept(&priv->ept);
|
||||
}
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_header_s *header = data;
|
||||
uint32_t command = header->command;
|
||||
|
||||
if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler))
|
||||
{
|
||||
return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_send_recv(uint32_t command, bool copy,
|
||||
FAR struct hostfs_rpmsg_header_s *msg,
|
||||
int len, FAR void *data)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
FAR struct hostfs_rpmsg_cookie_s cookie;
|
||||
int ret;
|
||||
|
||||
memset(&cookie, 0, sizeof(cookie));
|
||||
nxsem_init(&cookie.sem, 0, 0);
|
||||
nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
|
||||
|
||||
if (data)
|
||||
{
|
||||
cookie.data = data;
|
||||
}
|
||||
else if (copy)
|
||||
{
|
||||
cookie.data = msg;
|
||||
}
|
||||
|
||||
msg->command = command;
|
||||
msg->result = -ENXIO;
|
||||
msg->cookie = (uintptr_t)&cookie;
|
||||
|
||||
if (copy)
|
||||
{
|
||||
ret = rpmsg_send(&priv->ept, msg, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = rpmsg_send_nocopy(&priv->ept, msg, len);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&cookie.sem);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = cookie.result;
|
||||
}
|
||||
|
||||
fail:
|
||||
nxsem_destroy(&cookie.sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int host_open(FAR const char *pathname, int flags, int mode)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
FAR struct hostfs_rpmsg_open_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
msg->flags = flags;
|
||||
msg->mode = mode;
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPEN, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int host_close(int fd)
|
||||
{
|
||||
struct hostfs_rpmsg_close_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSE, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
ssize_t host_read(int fd, FAR void *buf, size_t count)
|
||||
{
|
||||
size_t read = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (read < count)
|
||||
{
|
||||
struct hostfs_rpmsg_read_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.count = C2B(count - read),
|
||||
};
|
||||
|
||||
ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READ, true,
|
||||
(FAR struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf);
|
||||
if (ret <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
read += B2C(ret);
|
||||
buf += B2C(ret);
|
||||
}
|
||||
|
||||
return read ? read : ret;
|
||||
}
|
||||
|
||||
ssize_t host_write(int fd, FAR const void *buf, size_t count)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
size_t written = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (written < count)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_write_s *msg;
|
||||
uint32_t space;
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
space -= sizeof(*msg);
|
||||
if (space > count - written)
|
||||
{
|
||||
space = count - written;
|
||||
}
|
||||
|
||||
msg->fd = fd;
|
||||
msg->count = C2B(space);
|
||||
memcpy(msg->buf, buf + written, space);
|
||||
|
||||
ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_WRITE, false,
|
||||
(FAR struct hostfs_rpmsg_header_s *)msg,
|
||||
sizeof(*msg) + space, NULL);
|
||||
if (ret <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
written += B2C(ret);
|
||||
}
|
||||
|
||||
return written ? written : ret;
|
||||
}
|
||||
|
||||
off_t host_lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
struct hostfs_rpmsg_lseek_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.offset = C2B(offset),
|
||||
.whence = whence,
|
||||
};
|
||||
|
||||
int ret;
|
||||
|
||||
ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_LSEEK, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
|
||||
return ret < 0 ? ret : B2C(ret);
|
||||
}
|
||||
|
||||
int host_ioctl(int fd, int request, unsigned long arg)
|
||||
{
|
||||
struct hostfs_rpmsg_ioctl_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.request = request,
|
||||
.arg = arg,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_IOCTL, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
void host_sync(int fd)
|
||||
{
|
||||
struct hostfs_rpmsg_sync_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
hostfs_rpmsg_send_recv(HOSTFS_RPMSG_SYNC, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int host_dup(int fd)
|
||||
{
|
||||
struct hostfs_rpmsg_dup_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_DUP, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int host_fstat(int fd, struct stat *buf)
|
||||
{
|
||||
struct hostfs_rpmsg_fstat_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FSTAT, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf);
|
||||
}
|
||||
|
||||
int host_ftruncate(int fd, off_t length)
|
||||
{
|
||||
struct hostfs_rpmsg_ftruncate_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.length = length,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FTRUNCATE, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
FAR void *host_opendir(FAR const char *name)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
FAR struct hostfs_rpmsg_opendir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(name) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, name);
|
||||
|
||||
ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPENDIR, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
|
||||
return ret < 0 ? NULL : (FAR void *)((uintptr_t)ret);
|
||||
}
|
||||
|
||||
int host_readdir(FAR void *dirp, FAR struct dirent *entry)
|
||||
{
|
||||
struct hostfs_rpmsg_readdir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READDIR, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), entry);
|
||||
}
|
||||
|
||||
void host_rewinddir(FAR void *dirp)
|
||||
{
|
||||
struct hostfs_rpmsg_rewinddir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
hostfs_rpmsg_send_recv(HOSTFS_RPMSG_REWINDDIR, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int host_closedir(FAR void *dirp)
|
||||
{
|
||||
struct hostfs_rpmsg_closedir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSEDIR, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int host_statfs(FAR const char *path, FAR struct statfs *buf)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
struct hostfs_rpmsg_statfs_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STATFS, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, buf);
|
||||
}
|
||||
|
||||
int host_unlink(FAR const char *pathname)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
struct hostfs_rpmsg_unlink_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_UNLINK, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int host_mkdir(FAR const char *pathname, mode_t mode)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
struct hostfs_rpmsg_mkdir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msg->mode = mode;
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_MKDIR, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int host_rmdir(FAR const char *pathname)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
struct hostfs_rpmsg_rmdir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RMDIR, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int host_rename(FAR const char *oldpath, FAR const char *newpath)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
struct hostfs_rpmsg_rename_s *msg;
|
||||
size_t len;
|
||||
size_t oldlen;
|
||||
uint32_t space;
|
||||
|
||||
len = sizeof(*msg);
|
||||
oldlen = B2C((strlen(oldpath) + 1 + 0x7) & ~0x7);
|
||||
len += oldlen + B2C(strlen(newpath) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, oldpath);
|
||||
cstr2bstr(msg->pathname + oldlen, newpath);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RENAME, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int host_stat(FAR const char *path, FAR struct stat *buf)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
FAR struct hostfs_rpmsg_stat_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STAT, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, buf);
|
||||
}
|
||||
|
||||
int host_fchstat(int fd, const struct stat *buf, int flags)
|
||||
{
|
||||
struct hostfs_rpmsg_fchstat_s msg =
|
||||
{
|
||||
.flags = flags,
|
||||
.buf = *buf,
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FCHSTAT, true,
|
||||
(struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int host_chstat(FAR const char *path, const FAR struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
FAR struct hostfs_rpmsg_chstat_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
msg->flags = flags;
|
||||
memcpy(&msg->buf, buf, sizeof(*buf));
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CHSTAT, false,
|
||||
(struct hostfs_rpmsg_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int hostfs_rpmsg_init(FAR const char *cpuname)
|
||||
{
|
||||
struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg;
|
||||
|
||||
priv->cpuname = cpuname;
|
||||
|
||||
return rpmsg_register_callback(priv,
|
||||
hostfs_rpmsg_device_created,
|
||||
hostfs_rpmsg_device_destroy,
|
||||
NULL);
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/hostfs/hostfs_rpmsg.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __FS_HOSTFS_HOSTFS_RPMSG_H
|
||||
#define __FS_HOSTFS_HOSTFS_RPMSG_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#define HOSTFS_RPMSG_EPT_NAME "rpmsg-hostfs"
|
||||
|
||||
#define HOSTFS_RPMSG_OPEN 1
|
||||
#define HOSTFS_RPMSG_CLOSE 2
|
||||
#define HOSTFS_RPMSG_READ 3
|
||||
#define HOSTFS_RPMSG_WRITE 4
|
||||
#define HOSTFS_RPMSG_LSEEK 5
|
||||
#define HOSTFS_RPMSG_IOCTL 6
|
||||
#define HOSTFS_RPMSG_SYNC 7
|
||||
#define HOSTFS_RPMSG_DUP 8
|
||||
#define HOSTFS_RPMSG_FSTAT 9
|
||||
#define HOSTFS_RPMSG_FTRUNCATE 10
|
||||
#define HOSTFS_RPMSG_OPENDIR 11
|
||||
#define HOSTFS_RPMSG_READDIR 12
|
||||
#define HOSTFS_RPMSG_REWINDDIR 13
|
||||
#define HOSTFS_RPMSG_CLOSEDIR 14
|
||||
#define HOSTFS_RPMSG_STATFS 15
|
||||
#define HOSTFS_RPMSG_UNLINK 16
|
||||
#define HOSTFS_RPMSG_MKDIR 17
|
||||
#define HOSTFS_RPMSG_RMDIR 18
|
||||
#define HOSTFS_RPMSG_RENAME 19
|
||||
#define HOSTFS_RPMSG_STAT 20
|
||||
#define HOSTFS_RPMSG_FCHSTAT 21
|
||||
#define HOSTFS_RPMSG_CHSTAT 22
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_header_s
|
||||
{
|
||||
uint32_t command;
|
||||
int32_t result;
|
||||
uint64_t cookie;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_open_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t flags;
|
||||
int32_t mode;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_close_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_read_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
uint32_t count;
|
||||
char buf[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_write_s hostfs_rpmsg_read_s
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_lseek_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
int32_t whence;
|
||||
int32_t offset;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_ioctl_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
int32_t request;
|
||||
int32_t arg;
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_sync_s hostfs_rpmsg_close_s
|
||||
#define hostfs_rpmsg_dup_s hostfs_rpmsg_close_s
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_fstat_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
union
|
||||
{
|
||||
struct stat buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int32_t fd;
|
||||
char pathname[0];
|
||||
};
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_ftruncate_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
int32_t length;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_opendir_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_readdir_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t fd;
|
||||
uint32_t type;
|
||||
char name[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_rewinddir_s hostfs_rpmsg_close_s
|
||||
#define hostfs_rpmsg_closedir_s hostfs_rpmsg_close_s
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_statfs_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
union
|
||||
{
|
||||
struct statfs buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_unlink_s hostfs_rpmsg_opendir_s
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_mkdir_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t mode;
|
||||
uint32_t reserved;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_rmdir_s hostfs_rpmsg_opendir_s
|
||||
#define hostfs_rpmsg_rename_s hostfs_rpmsg_opendir_s
|
||||
#define hostfs_rpmsg_stat_s hostfs_rpmsg_fstat_s
|
||||
|
||||
begin_packed_struct struct hostfs_rpmsg_fchstat_s
|
||||
{
|
||||
struct hostfs_rpmsg_header_s header;
|
||||
int32_t flags;
|
||||
union
|
||||
{
|
||||
struct stat buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int32_t fd;
|
||||
char pathname[0];
|
||||
};
|
||||
} end_packed_struct;
|
||||
|
||||
#define hostfs_rpmsg_chstat_s hostfs_rpmsg_fchstat_s
|
||||
|
||||
#endif /* __FS_HOSTFS_HOSTFS_RPMSG_H */
|
@ -1,883 +0,0 @@
|
||||
/****************************************************************************
|
||||
* fs/hostfs/hostfs_rpmsg_server.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/hostfs_rpmsg.h>
|
||||
#include <nuttx/rptun/openamp.h>
|
||||
|
||||
#include "hostfs_rpmsg.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct hostfs_rpmsg_server_s
|
||||
{
|
||||
struct rpmsg_endpoint ept;
|
||||
FAR struct file **files;
|
||||
FAR void **dirs;
|
||||
int file_rows;
|
||||
int dir_nums;
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
|
||||
static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_, FAR const char *name,
|
||||
uint32_t dest);
|
||||
static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept);
|
||||
static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] =
|
||||
{
|
||||
[HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_open_handler,
|
||||
[HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_close_handler,
|
||||
[HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler,
|
||||
[HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_write_handler,
|
||||
[HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_lseek_handler,
|
||||
[HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_ioctl_handler,
|
||||
[HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_sync_handler,
|
||||
[HOSTFS_RPMSG_DUP] = hostfs_rpmsg_dup_handler,
|
||||
[HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_fstat_handler,
|
||||
[HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_ftruncate_handler,
|
||||
[HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_opendir_handler,
|
||||
[HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler,
|
||||
[HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_rewinddir_handler,
|
||||
[HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_closedir_handler,
|
||||
[HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler,
|
||||
[HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_unlink_handler,
|
||||
[HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_mkdir_handler,
|
||||
[HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_rmdir_handler,
|
||||
[HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_rename_handler,
|
||||
[HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler,
|
||||
[HOSTFS_RPMSG_FCHSTAT] = hostfs_rpmsg_fchstat_handler,
|
||||
[HOSTFS_RPMSG_CHSTAT] = hostfs_rpmsg_chstat_handler,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int hostfs_rpmsg_attach_file(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
FAR struct file *filep)
|
||||
{
|
||||
FAR struct file **tmp;
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
if (priv->files[i][j].f_inode == NULL)
|
||||
{
|
||||
memcpy(&priv->files[i][j], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp[i] = kmm_zalloc(sizeof(struct file) *
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
|
||||
DEBUGASSERT(tmp[i]);
|
||||
if (tmp[i] == NULL)
|
||||
{
|
||||
kmm_free(tmp);
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->files = tmp;
|
||||
priv->file_rows++;
|
||||
|
||||
memcpy(&priv->files[i][0], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
out:
|
||||
nxsem_post(&priv->sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_detach_file(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd, FAR struct file *filep)
|
||||
{
|
||||
struct file *tfilep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
memcpy(filep, tfilep, sizeof(*filep));
|
||||
memset(tfilep, 0, sizeof(*tfilep));
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FAR struct file *hostfs_rpmsg_get_file(
|
||||
FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return filep;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_attach_dir(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
FAR void *dir)
|
||||
{
|
||||
FAR void **tmp;
|
||||
int i;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 1; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i] == NULL)
|
||||
{
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) *
|
||||
(priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
nxsem_post(&priv->sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dirs = tmp;
|
||||
priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void *hostfs_rpmsg_detach_dir(FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
priv->dirs[fd] = NULL;
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static FAR void *hostfs_rpmsg_get_dir(
|
||||
FAR struct hostfs_rpmsg_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_open_s *msg = data;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
ret = file_open(&file, msg->pathname, msg->flags, msg->mode);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = hostfs_rpmsg_attach_file(priv, &file);
|
||||
if (ret < 0)
|
||||
{
|
||||
file_close(&file);
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_close_s *msg = data;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
ret = hostfs_rpmsg_detach_file(priv, msg->fd, &file);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = file_close(&file);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_read_s *msg = data;
|
||||
FAR struct hostfs_rpmsg_read_s *rsp;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
uint32_t space;
|
||||
|
||||
rsp = rpmsg_get_tx_payload_buffer(ept, &space, true);
|
||||
if (!rsp)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*rsp = *msg;
|
||||
|
||||
space -= sizeof(*msg);
|
||||
if (space > msg->count)
|
||||
{
|
||||
space = msg->count;
|
||||
}
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_read(filep, rsp->buf, space);
|
||||
}
|
||||
|
||||
rsp->header.result = ret;
|
||||
return rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_write_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_write(filep, msg->buf, msg->count);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_lseek_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_seek(filep, msg->offset, msg->whence);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_ioctl_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_ioctl(filep, msg->request, msg->arg);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_sync_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fsync(filep);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_dup_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
struct file newfile;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_dup2(filep, &newfile);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = hostfs_rpmsg_attach_file(priv, &newfile);
|
||||
if (ret < 0)
|
||||
{
|
||||
file_close(&newfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_fstat_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
struct stat buf;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fstat(filep, &buf);
|
||||
if (ret >= 0)
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_ftruncate_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_truncate(filep, msg->length);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_opendir_s *msg = data;
|
||||
FAR void *dir;
|
||||
int ret = -ENOENT;
|
||||
|
||||
dir = opendir(msg->pathname);
|
||||
if (dir)
|
||||
{
|
||||
ret = hostfs_rpmsg_attach_dir(priv, dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_readdir_s *msg = data;
|
||||
FAR struct dirent *entry;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = hostfs_rpmsg_get_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
entry = readdir(dir);
|
||||
if (entry)
|
||||
{
|
||||
msg->type = entry->d_type;
|
||||
strcpy(msg->name, entry->d_name);
|
||||
len += strlen(entry->d_name) + 1;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, len);
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_rewinddir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = hostfs_rpmsg_get_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
rewinddir(dir);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_closedir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = hostfs_rpmsg_detach_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
ret = closedir(dir) ? -get_errno() : 0;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_statfs_s *msg = data;
|
||||
struct statfs buf;
|
||||
int ret;
|
||||
|
||||
ret = statfs(msg->pathname, &buf);
|
||||
if (ret)
|
||||
{
|
||||
ret = -get_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_unlink_s *msg = data;
|
||||
|
||||
msg->header.result = nx_unlink(msg->pathname);
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_mkdir_s *msg = data;
|
||||
int ret;
|
||||
|
||||
ret = mkdir(msg->pathname, msg->mode);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_rmdir_s *msg = data;
|
||||
int ret;
|
||||
|
||||
ret = rmdir(msg->pathname);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_rename_s *msg = data;
|
||||
FAR char *newpath;
|
||||
size_t oldlen;
|
||||
int ret;
|
||||
|
||||
oldlen = (strlen(msg->pathname) + 1 + 0x7) & ~0x7;
|
||||
newpath = msg->pathname + oldlen;
|
||||
|
||||
ret = rename(msg->pathname, newpath);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_stat_s *msg = data;
|
||||
struct stat buf;
|
||||
int ret;
|
||||
|
||||
ret = nx_stat(msg->pathname, &buf, 1);
|
||||
if (ret >= 0)
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_fchstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_fchstat_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
struct stat buf;
|
||||
|
||||
filep = hostfs_rpmsg_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
buf = msg->buf;
|
||||
ret = file_fchstat(filep, &buf, msg->flags);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_chstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_chstat_s *msg = data;
|
||||
struct timespec times[2];
|
||||
int ret = 0;
|
||||
|
||||
if (msg->flags & CH_STAT_MODE)
|
||||
{
|
||||
ret = chmod(msg->pathname, msg->buf.st_mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->flags & (CH_STAT_UID | CH_STAT_GID))
|
||||
{
|
||||
ret = chown(msg->pathname, msg->buf.st_uid, msg->buf.st_gid);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->flags & (CH_STAT_ATIME | CH_STAT_MTIME))
|
||||
{
|
||||
if (msg->flags & CH_STAT_ATIME)
|
||||
{
|
||||
times[0] = msg->buf.st_atim;
|
||||
}
|
||||
else
|
||||
{
|
||||
times[0].tv_nsec = UTIME_OMIT;
|
||||
}
|
||||
|
||||
if (msg->flags & CH_STAT_MTIME)
|
||||
{
|
||||
times[1] = msg->buf.st_mtim;
|
||||
}
|
||||
else
|
||||
{
|
||||
times[1].tv_nsec = UTIME_OMIT;
|
||||
}
|
||||
|
||||
ret = utimens(msg->pathname, times);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_, FAR const char *name,
|
||||
uint32_t dest)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv;
|
||||
int ret;
|
||||
|
||||
if (strcmp(name, HOSTFS_RPMSG_EPT_NAME))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
priv = kmm_zalloc(sizeof(*priv));
|
||||
if (!priv)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
priv->ept.priv = priv;
|
||||
nxsem_init(&priv->sem, 0, 1);
|
||||
|
||||
ret = rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME,
|
||||
RPMSG_ADDR_ANY, dest,
|
||||
hostfs_rpmsg_ept_cb, hostfs_rpmsg_ns_unbind);
|
||||
if (ret)
|
||||
{
|
||||
nxsem_destroy(&priv->sem);
|
||||
kmm_free(priv);
|
||||
}
|
||||
}
|
||||
|
||||
static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct hostfs_rpmsg_server_s *priv = ept->priv;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
if (priv->files[i][j].f_inode)
|
||||
{
|
||||
file_close(&priv->files[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
kmm_free(priv->files[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i])
|
||||
{
|
||||
closedir(priv->dirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rpmsg_destroy_ept(&priv->ept);
|
||||
nxsem_destroy(&priv->sem);
|
||||
|
||||
kmm_free(priv->files);
|
||||
kmm_free(priv->dirs);
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv)
|
||||
{
|
||||
struct hostfs_rpmsg_header_s *header = data;
|
||||
uint32_t command = header->command;
|
||||
|
||||
if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler))
|
||||
{
|
||||
return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int hostfs_rpmsg_server_init(void)
|
||||
{
|
||||
return rpmsg_register_callback(NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
hostfs_rpmsg_ns_bind);
|
||||
}
|
@ -135,6 +135,12 @@ FAR const char *fs_gettype(FAR struct statfs *statbuf)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
case RPMSGFS_MAGIC:
|
||||
fstype = "rpmsgfs";
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_USERFS
|
||||
case USERFS_MAGIC:
|
||||
fstype = "userfs";
|
||||
|
@ -178,6 +178,9 @@ extern const struct mountpt_operations cromfs_operations;
|
||||
#ifdef CONFIG_FS_UNIONFS
|
||||
extern const struct mountpt_operations unionfs_operations;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
extern const struct mountpt_operations rpmsgfs_operations;
|
||||
#endif
|
||||
|
||||
static const struct fsmap_t g_nonbdfsmap[] =
|
||||
{
|
||||
@ -207,6 +210,9 @@ static const struct fsmap_t g_nonbdfsmap[] =
|
||||
#endif
|
||||
#ifdef CONFIG_FS_UNIONFS
|
||||
{ "unionfs", &unionfs_operations },
|
||||
#endif
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
{ "rpmsgfs", &rpmsgfs_operations },
|
||||
#endif
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
12
fs/rpmsgfs/Kconfig
Normal file
12
fs/rpmsgfs/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config FS_RPMSGFS
|
||||
bool "RPMSG File System"
|
||||
default n
|
||||
depends on OPENAMP
|
||||
---help---
|
||||
Use rpmsg file system to mount remote directories to local.
|
||||
This the method for user to use remote file like own core.
|
28
fs/rpmsgfs/Make.defs
Normal file
28
fs/rpmsgfs/Make.defs
Normal file
@ -0,0 +1,28 @@
|
||||
############################################################################
|
||||
# fs/rpmsgfs/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Include RPSMGFS build support
|
||||
|
||||
DEPPATH += --dep-path rpmsgfs
|
||||
VPATH += :rpmsgfs
|
||||
|
||||
ifeq ($(CONFIG_FS_RPMSGFS),y)
|
||||
CSRCS += rpmsgfs.c rpmsgfs_client.c rpmsgfs_server.c
|
||||
endif
|
1456
fs/rpmsgfs/rpmsgfs.c
Normal file
1456
fs/rpmsgfs/rpmsgfs.c
Normal file
File diff suppressed because it is too large
Load Diff
246
fs/rpmsgfs/rpmsgfs.h
Normal file
246
fs/rpmsgfs/rpmsgfs.h
Normal file
@ -0,0 +1,246 @@
|
||||
/****************************************************************************
|
||||
* fs/rpmsgfs/rpmsgfs.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __FS_RPMSGFS_H
|
||||
#define __FS_RPMSGFS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#define RPMSGFS_NAME_PREFIX "rpmsgfs-"
|
||||
|
||||
#define RPMSGFS_OPEN 1
|
||||
#define RPMSGFS_CLOSE 2
|
||||
#define RPMSGFS_READ 3
|
||||
#define RPMSGFS_WRITE 4
|
||||
#define RPMSGFS_LSEEK 5
|
||||
#define RPMSGFS_IOCTL 6
|
||||
#define RPMSGFS_SYNC 7
|
||||
#define RPMSGFS_DUP 8
|
||||
#define RPMSGFS_FSTAT 9
|
||||
#define RPMSGFS_FTRUNCATE 10
|
||||
#define RPMSGFS_OPENDIR 11
|
||||
#define RPMSGFS_READDIR 12
|
||||
#define RPMSGFS_REWINDDIR 13
|
||||
#define RPMSGFS_CLOSEDIR 14
|
||||
#define RPMSGFS_STATFS 15
|
||||
#define RPMSGFS_UNLINK 16
|
||||
#define RPMSGFS_MKDIR 17
|
||||
#define RPMSGFS_RMDIR 18
|
||||
#define RPMSGFS_RENAME 19
|
||||
#define RPMSGFS_STAT 20
|
||||
#define RPMSGFS_FCHSTAT 21
|
||||
#define RPMSGFS_CHSTAT 22
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
begin_packed_struct struct rpmsgfs_header_s
|
||||
{
|
||||
uint32_t command;
|
||||
int32_t result;
|
||||
uint64_t cookie;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_open_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t flags;
|
||||
int32_t mode;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_close_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_read_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
uint32_t count;
|
||||
char buf[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_write_s rpmsgfs_read_s
|
||||
|
||||
begin_packed_struct struct rpmsgfs_lseek_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
int32_t whence;
|
||||
int32_t offset;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_ioctl_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
int32_t request;
|
||||
int32_t arg;
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_sync_s rpmsgfs_close_s
|
||||
#define rpmsgfs_dup_s rpmsgfs_close_s
|
||||
|
||||
begin_packed_struct struct rpmsgfs_fstat_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
union
|
||||
{
|
||||
struct stat buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int32_t fd;
|
||||
char pathname[0];
|
||||
};
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_ftruncate_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
int32_t length;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_opendir_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct rpmsgfs_readdir_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t fd;
|
||||
uint32_t type;
|
||||
char name[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_rewinddir_s rpmsgfs_close_s
|
||||
#define rpmsgfs_closedir_s rpmsgfs_close_s
|
||||
|
||||
begin_packed_struct struct rpmsgfs_statfs_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
union
|
||||
{
|
||||
struct statfs buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_unlink_s rpmsgfs_opendir_s
|
||||
|
||||
begin_packed_struct struct rpmsgfs_mkdir_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t mode;
|
||||
uint32_t reserved;
|
||||
char pathname[0];
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_rmdir_s rpmsgfs_opendir_s
|
||||
#define rpmsgfs_rename_s rpmsgfs_opendir_s
|
||||
#define rpmsgfs_stat_s rpmsgfs_fstat_s
|
||||
|
||||
begin_packed_struct struct rpmsgfs_fchstat_s
|
||||
{
|
||||
struct rpmsgfs_header_s header;
|
||||
int32_t flags;
|
||||
union
|
||||
{
|
||||
struct stat buf;
|
||||
uint32_t reserved[16];
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
int32_t fd;
|
||||
char pathname[0];
|
||||
};
|
||||
} end_packed_struct;
|
||||
|
||||
#define rpmsgfs_chstat_s rpmsgfs_fchstat_s
|
||||
|
||||
/****************************************************************************
|
||||
* Internal function prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsgfs_client_open(FAR void *handle,
|
||||
FAR const char *pathname, int flags, int mode);
|
||||
int rpmsgfs_client_close(FAR void *handle, int fd);
|
||||
ssize_t rpmsgfs_client_read(FAR void *handle, int fd,
|
||||
FAR void *buf, size_t count);
|
||||
ssize_t rpmsgfs_client_write(FAR void *handle, int fd,
|
||||
FAR const void *buf, size_t count);
|
||||
off_t rpmsgfs_client_lseek(FAR void *handle, int fd,
|
||||
off_t offset, int whence);
|
||||
int rpmsgfs_client_ioctl(FAR void *handle, int fd,
|
||||
int request, unsigned long arg);
|
||||
void rpmsgfs_client_sync(FAR void *handle, int fd);
|
||||
int rpmsgfs_client_dup(FAR void *handle, int fd);
|
||||
int rpmsgfs_client_fstat(FAR void *handle, int fd,
|
||||
FAR struct stat *buf);
|
||||
int rpmsgfs_client_fchstat(FAR void *handle, int fd,
|
||||
FAR const struct stat *buf, int flags);
|
||||
int rpmsgfs_client_ftruncate(FAR void *handle, int fd, off_t length);
|
||||
FAR void *rpmsgfs_client_opendir(FAR void *handle, FAR const char *name);
|
||||
int rpmsgfs_client_readdir(FAR void *handle, FAR void *dirp,
|
||||
FAR struct dirent *entry);
|
||||
void rpmsgfs_client_rewinddir(FAR void *handle, FAR void *dirp);
|
||||
int rpmsgfs_client_bind(FAR void **handle, FAR const char *cpuname);
|
||||
int rpmsgfs_client_unbind(FAR void *handle);
|
||||
int rpmsgfs_client_closedir(FAR void *handle, FAR void *dirp);
|
||||
int rpmsgfs_client_statfs(FAR void *handle, FAR const char *path,
|
||||
FAR struct statfs *buf);
|
||||
int rpmsgfs_client_unlink(FAR void *handle, FAR const char *pathname);
|
||||
int rpmsgfs_client_mkdir(FAR void *handle, FAR const char *pathname,
|
||||
mode_t mode);
|
||||
int rpmsgfs_client_rmdir(FAR void *handle, FAR const char *pathname);
|
||||
int rpmsgfs_client_rename(FAR void *handle, FAR const char *oldpath,
|
||||
FAR const char *newpath);
|
||||
int rpmsgfs_client_stat(FAR void *handle, FAR const char *path,
|
||||
FAR struct stat *buf);
|
||||
int rpmsgfs_client_chstat(FAR void *handle, FAR const char *path,
|
||||
FAR const struct stat *buf, int flags);
|
||||
|
||||
#endif /* __FS_RPMSGFS_H */
|
819
fs/rpmsgfs/rpmsgfs_client.c
Normal file
819
fs/rpmsgfs/rpmsgfs_client.c
Normal file
@ -0,0 +1,819 @@
|
||||
/****************************************************************************
|
||||
* fs/rpmsgfs/rpmsgfs_client.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/rpmsgfs.h>
|
||||
#include <nuttx/rptun/openamp.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
|
||||
#include "rpmsgfs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsgfs_s
|
||||
{
|
||||
struct rpmsg_endpoint ept;
|
||||
char cpuname[RPMSG_NAME_SIZE];
|
||||
};
|
||||
|
||||
struct rpmsgfs_cookie_s
|
||||
{
|
||||
sem_t sem;
|
||||
int result;
|
||||
FAR void *data;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsgfs_default_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
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_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static void rpmsgfs_device_created(struct rpmsg_device *rdev,
|
||||
FAR void *priv_);
|
||||
static void rpmsgfs_device_destroy(struct rpmsg_device *rdev,
|
||||
FAR void *priv_);
|
||||
static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv);
|
||||
static int rpmsgfs_send_recv(FAR struct rpmsgfs_s *priv,
|
||||
uint32_t command, bool copy,
|
||||
FAR struct rpmsgfs_header_s *msg,
|
||||
int len, FAR void *data);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const rpmsg_ept_cb g_rpmsgfs_handler[] =
|
||||
{
|
||||
[RPMSGFS_OPEN] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_CLOSE] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_READ] = rpmsgfs_read_handler,
|
||||
[RPMSGFS_WRITE] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_LSEEK] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_IOCTL] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_SYNC] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_DUP] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_FSTAT] = rpmsgfs_stat_handler,
|
||||
[RPMSGFS_FTRUNCATE] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_OPENDIR] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_READDIR] = rpmsgfs_readdir_handler,
|
||||
[RPMSGFS_REWINDDIR] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_CLOSEDIR] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_STATFS] = rpmsgfs_statfs_handler,
|
||||
[RPMSGFS_UNLINK] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_MKDIR] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_RMDIR] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_RENAME] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_STAT] = rpmsgfs_stat_handler,
|
||||
[RPMSGFS_FCHSTAT] = rpmsgfs_default_handler,
|
||||
[RPMSGFS_CHSTAT] = rpmsgfs_default_handler,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsgfs_default_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 =
|
||||
(struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0 && cookie->data)
|
||||
{
|
||||
memcpy(cookie->data, data, len);
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmsgfs_read_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 =
|
||||
(struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct rpmsgfs_read_s *rsp = data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result > 0)
|
||||
{
|
||||
memcpy(cookie->data, rsp->buf, B2C(cookie->result));
|
||||
}
|
||||
|
||||
nxsem_post(&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)
|
||||
{
|
||||
FAR struct rpmsgfs_header_s *header = data;
|
||||
FAR struct rpmsgfs_cookie_s *cookie =
|
||||
(struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct rpmsgfs_readdir_s *rsp = data;
|
||||
FAR struct dirent *entry = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
nbstr2cstr(entry->d_name, rsp->name, NAME_MAX);
|
||||
entry->d_name[NAME_MAX] = '\0';
|
||||
entry->d_type = rsp->type;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmsgfs_statfs_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 =
|
||||
(struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct rpmsgfs_statfs_s *rsp = data;
|
||||
FAR struct statfs *buf = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
buf->f_type = rsp->buf.f_type;
|
||||
buf->f_namelen = rsp->buf.f_namelen;
|
||||
buf->f_bsize = B2C(rsp->buf.f_bsize);
|
||||
buf->f_blocks = rsp->buf.f_blocks;
|
||||
buf->f_bfree = rsp->buf.f_bfree;
|
||||
buf->f_bavail = rsp->buf.f_bavail;
|
||||
buf->f_files = rsp->buf.f_files;
|
||||
buf->f_ffree = rsp->buf.f_ffree;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpmsgfs_stat_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 =
|
||||
(struct rpmsgfs_cookie_s *)(uintptr_t)header->cookie;
|
||||
FAR struct rpmsgfs_stat_s *rsp = data;
|
||||
FAR struct stat *buf = cookie->data;
|
||||
|
||||
cookie->result = header->result;
|
||||
if (cookie->result >= 0)
|
||||
{
|
||||
buf->st_dev = rsp->buf.st_dev;
|
||||
buf->st_ino = rsp->buf.st_ino;
|
||||
buf->st_mode = rsp->buf.st_mode;
|
||||
buf->st_nlink = rsp->buf.st_nlink;
|
||||
buf->st_uid = rsp->buf.st_uid;
|
||||
buf->st_gid = rsp->buf.st_gid;
|
||||
buf->st_rdev = rsp->buf.st_rdev;
|
||||
buf->st_size = B2C(rsp->buf.st_size);
|
||||
buf->st_atime = rsp->buf.st_atime;
|
||||
buf->st_mtime = rsp->buf.st_mtime;
|
||||
buf->st_ctime = rsp->buf.st_ctime;
|
||||
buf->st_blksize = B2C(rsp->buf.st_blksize);
|
||||
buf->st_blocks = rsp->buf.st_blocks;
|
||||
}
|
||||
|
||||
nxsem_post(&cookie->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rpmsgfs_device_created(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = priv_;
|
||||
char buf[RPMSG_NAME_SIZE];
|
||||
|
||||
if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
|
||||
{
|
||||
priv->ept.priv = priv;
|
||||
snprintf(buf, sizeof(buf), "%s%p", RPMSGFS_NAME_PREFIX, priv);
|
||||
rpmsg_create_ept(&priv->ept, rdev, buf,
|
||||
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
||||
rpmsgfs_ept_cb, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsgfs_device_destroy(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_)
|
||||
{
|
||||
struct rpmsgfs_s *priv = priv_;
|
||||
|
||||
if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0)
|
||||
{
|
||||
rpmsg_destroy_ept(&priv->ept);
|
||||
}
|
||||
}
|
||||
|
||||
static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_header_s *header = data;
|
||||
uint32_t command = header->command;
|
||||
|
||||
if (command < ARRAY_SIZE(g_rpmsgfs_handler))
|
||||
{
|
||||
return g_rpmsgfs_handler[command](ept, data, len, src, priv);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int rpmsgfs_send_recv(FAR struct rpmsgfs_s *priv,
|
||||
uint32_t command, bool copy,
|
||||
FAR struct rpmsgfs_header_s *msg,
|
||||
int len, FAR void *data)
|
||||
{
|
||||
FAR struct rpmsgfs_cookie_s cookie;
|
||||
int ret;
|
||||
|
||||
memset(&cookie, 0, sizeof(cookie));
|
||||
nxsem_init(&cookie.sem, 0, 0);
|
||||
nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
|
||||
|
||||
if (data)
|
||||
{
|
||||
cookie.data = data;
|
||||
}
|
||||
else if (copy)
|
||||
{
|
||||
cookie.data = msg;
|
||||
}
|
||||
|
||||
msg->command = command;
|
||||
msg->result = -ENXIO;
|
||||
msg->cookie = (uintptr_t)&cookie;
|
||||
|
||||
if (copy)
|
||||
{
|
||||
ret = rpmsg_send(&priv->ept, msg, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = rpmsg_send_nocopy(&priv->ept, msg, len);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = nxsem_wait_uninterruptible(&cookie.sem);
|
||||
if (ret == 0)
|
||||
{
|
||||
ret = cookie.result;
|
||||
}
|
||||
|
||||
fail:
|
||||
nxsem_destroy(&cookie.sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int rpmsgfs_client_open(FAR void *handle, FAR const char *pathname,
|
||||
int flags, int mode)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = handle;
|
||||
FAR struct rpmsgfs_open_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
msg->flags = flags;
|
||||
msg->mode = mode;
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_OPEN, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_close(FAR void *handle, int fd)
|
||||
{
|
||||
struct rpmsgfs_close_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_CLOSE, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
ssize_t rpmsgfs_client_read(FAR void *handle, int fd,
|
||||
FAR void *buf, size_t count)
|
||||
{
|
||||
size_t read = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (read < count)
|
||||
{
|
||||
struct rpmsgfs_read_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.count = C2B(count - read),
|
||||
};
|
||||
|
||||
ret = rpmsgfs_send_recv(handle, RPMSGFS_READ, true,
|
||||
(FAR struct rpmsgfs_header_s *)&msg, sizeof(msg), buf);
|
||||
if (ret <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
read += B2C(ret);
|
||||
buf += B2C(ret);
|
||||
}
|
||||
|
||||
return read ? read : ret;
|
||||
}
|
||||
|
||||
ssize_t rpmsgfs_client_write(FAR void *handle, int fd,
|
||||
FAR const void *buf, size_t count)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = handle;
|
||||
size_t written = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (written < count)
|
||||
{
|
||||
FAR struct rpmsgfs_write_s *msg;
|
||||
uint32_t space;
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
space -= sizeof(*msg);
|
||||
if (space > count - written)
|
||||
{
|
||||
space = count - written;
|
||||
}
|
||||
|
||||
msg->fd = fd;
|
||||
msg->count = C2B(space);
|
||||
memcpy(msg->buf, buf + written, space);
|
||||
|
||||
ret = rpmsgfs_send_recv(priv, RPMSGFS_WRITE, false,
|
||||
(FAR struct rpmsgfs_header_s *)msg,
|
||||
sizeof(*msg) + space, NULL);
|
||||
if (ret <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
written += B2C(ret);
|
||||
}
|
||||
|
||||
return written ? written : ret;
|
||||
}
|
||||
|
||||
off_t rpmsgfs_client_lseek(FAR void *handle, int fd,
|
||||
off_t offset, int whence)
|
||||
{
|
||||
struct rpmsgfs_lseek_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.offset = C2B(offset),
|
||||
.whence = whence,
|
||||
};
|
||||
|
||||
int ret;
|
||||
|
||||
ret = rpmsgfs_send_recv(handle, RPMSGFS_LSEEK, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
|
||||
return ret < 0 ? ret : B2C(ret);
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_IOCTL, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
void rpmsgfs_client_sync(FAR void *handle, int fd)
|
||||
{
|
||||
struct rpmsgfs_sync_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
rpmsgfs_send_recv(handle, RPMSGFS_SYNC, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_dup(FAR void *handle, int fd)
|
||||
{
|
||||
struct rpmsgfs_dup_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_DUP, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_fstat(FAR void *handle, int fd, struct stat *buf)
|
||||
{
|
||||
struct rpmsgfs_fstat_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_FSTAT, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), buf);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_ftruncate(FAR void *handle, int fd, off_t length)
|
||||
{
|
||||
struct rpmsgfs_ftruncate_s msg =
|
||||
{
|
||||
.fd = fd,
|
||||
.length = length,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_FTRUNCATE, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
FAR void *rpmsgfs_client_opendir(FAR void *handle, FAR const char *name)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = handle;
|
||||
FAR struct rpmsgfs_opendir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(name) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, name);
|
||||
|
||||
ret = rpmsgfs_send_recv(priv, RPMSGFS_OPENDIR, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
|
||||
return ret < 0 ? NULL : (FAR void *)((uintptr_t)ret);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_readdir(FAR void *handle, FAR void *dirp,
|
||||
FAR struct dirent *entry)
|
||||
{
|
||||
struct rpmsgfs_readdir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_READDIR, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), entry);
|
||||
}
|
||||
|
||||
void rpmsgfs_client_rewinddir(FAR void *handle, FAR void *dirp)
|
||||
{
|
||||
struct rpmsgfs_rewinddir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
rpmsgfs_send_recv(handle, RPMSGFS_REWINDDIR, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_bind(FAR void **handle, FAR const char *cpuname)
|
||||
{
|
||||
struct rpmsgfs_s *priv;
|
||||
int ret;
|
||||
|
||||
if (!cpuname)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = kmm_zalloc(sizeof(struct rpmsgfs_s));
|
||||
if (!priv)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strncpy(priv->cpuname, cpuname, RPMSG_NAME_SIZE);
|
||||
ret = rpmsg_register_callback(priv,
|
||||
rpmsgfs_device_created,
|
||||
rpmsgfs_device_destroy,
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*handle = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmsgfs_client_unbind(FAR void *handle)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
|
||||
rpmsg_unregister_callback(priv,
|
||||
rpmsgfs_device_created,
|
||||
rpmsgfs_device_destroy,
|
||||
NULL);
|
||||
|
||||
kmm_free(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmsgfs_client_closedir(FAR void *handle, FAR void *dirp)
|
||||
{
|
||||
struct rpmsgfs_closedir_s msg =
|
||||
{
|
||||
.fd = (uintptr_t)dirp,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_CLOSEDIR, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_statfs(FAR void *handle, FAR const char *path,
|
||||
FAR struct statfs *buf)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
struct rpmsgfs_statfs_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_STATFS, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, buf);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_unlink(FAR void *handle, FAR const char *pathname)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
struct rpmsgfs_unlink_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_UNLINK, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_mkdir(FAR void *handle, FAR const char *pathname,
|
||||
mode_t mode)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
struct rpmsgfs_mkdir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msg->mode = mode;
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_MKDIR, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_rmdir(FAR void *handle, FAR const char *pathname)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
struct rpmsgfs_rmdir_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(pathname) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, pathname);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_RMDIR, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_rename(FAR void *handle, FAR const char *oldpath,
|
||||
FAR const char *newpath)
|
||||
{
|
||||
struct rpmsgfs_s *priv = handle;
|
||||
struct rpmsgfs_rename_s *msg;
|
||||
size_t len;
|
||||
size_t oldlen;
|
||||
uint32_t space;
|
||||
|
||||
len = sizeof(*msg);
|
||||
oldlen = B2C((strlen(oldpath) + 1 + 0x7) & ~0x7);
|
||||
len += oldlen + B2C(strlen(newpath) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, oldpath);
|
||||
cstr2bstr(msg->pathname + oldlen, newpath);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_RENAME, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_stat(FAR void *handle, FAR const char *path,
|
||||
FAR struct stat *buf)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = handle;
|
||||
FAR struct rpmsgfs_stat_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_STAT, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, buf);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_fchstat(FAR void *handle, int fd,
|
||||
const struct stat *buf, int flags)
|
||||
{
|
||||
struct rpmsgfs_fchstat_s msg =
|
||||
{
|
||||
.flags = flags,
|
||||
.buf = *buf,
|
||||
.fd = fd,
|
||||
};
|
||||
|
||||
return rpmsgfs_send_recv(handle, RPMSGFS_FCHSTAT, true,
|
||||
(struct rpmsgfs_header_s *)&msg, sizeof(msg), NULL);
|
||||
}
|
||||
|
||||
int rpmsgfs_client_chstat(FAR void *handle, FAR const char *path,
|
||||
const FAR struct stat *buf, int flags)
|
||||
{
|
||||
FAR struct rpmsgfs_s *priv = handle;
|
||||
FAR struct rpmsgfs_chstat_s *msg;
|
||||
uint32_t space;
|
||||
size_t len;
|
||||
|
||||
len = sizeof(*msg);
|
||||
len += B2C(strlen(path) + 1);
|
||||
|
||||
msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true);
|
||||
if (!msg)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
DEBUGASSERT(len <= space);
|
||||
|
||||
msg->flags = flags;
|
||||
memcpy(&msg->buf, buf, sizeof(*buf));
|
||||
cstr2bstr(msg->pathname, path);
|
||||
|
||||
return rpmsgfs_send_recv(priv, RPMSGFS_CHSTAT, false,
|
||||
(struct rpmsgfs_header_s *)msg, len, NULL);
|
||||
}
|
883
fs/rpmsgfs/rpmsgfs_server.c
Normal file
883
fs/rpmsgfs/rpmsgfs_server.c
Normal file
@ -0,0 +1,883 @@
|
||||
/****************************************************************************
|
||||
* fs/rpmsgfs/rpmsgfs_server.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/fs/rpmsgfs.h>
|
||||
#include <nuttx/rptun/openamp.h>
|
||||
|
||||
#include "rpmsgfs.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rpmsgfs_server_s
|
||||
{
|
||||
struct rpmsg_endpoint ept;
|
||||
FAR struct file **files;
|
||||
FAR void **dirs;
|
||||
int file_rows;
|
||||
int dir_nums;
|
||||
sem_t sem;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsgfs_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
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_write_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_lseek_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_sync_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_dup_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_fstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_ftruncate_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_opendir_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);
|
||||
static int rpmsgfs_rewinddir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_closedir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_unlink_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_mkdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_rmdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_rename_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_fchstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
static int rpmsgfs_chstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
|
||||
static void rpmsgfs_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_, FAR const char *name,
|
||||
uint32_t dest);
|
||||
static void rpmsgfs_ns_unbind(FAR struct rpmsg_endpoint *ept);
|
||||
static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const rpmsg_ept_cb g_rpmsgfs_handler[] =
|
||||
{
|
||||
[RPMSGFS_OPEN] = rpmsgfs_open_handler,
|
||||
[RPMSGFS_CLOSE] = rpmsgfs_close_handler,
|
||||
[RPMSGFS_READ] = rpmsgfs_read_handler,
|
||||
[RPMSGFS_WRITE] = rpmsgfs_write_handler,
|
||||
[RPMSGFS_LSEEK] = rpmsgfs_lseek_handler,
|
||||
[RPMSGFS_IOCTL] = rpmsgfs_ioctl_handler,
|
||||
[RPMSGFS_SYNC] = rpmsgfs_sync_handler,
|
||||
[RPMSGFS_DUP] = rpmsgfs_dup_handler,
|
||||
[RPMSGFS_FSTAT] = rpmsgfs_fstat_handler,
|
||||
[RPMSGFS_FTRUNCATE] = rpmsgfs_ftruncate_handler,
|
||||
[RPMSGFS_OPENDIR] = rpmsgfs_opendir_handler,
|
||||
[RPMSGFS_READDIR] = rpmsgfs_readdir_handler,
|
||||
[RPMSGFS_REWINDDIR] = rpmsgfs_rewinddir_handler,
|
||||
[RPMSGFS_CLOSEDIR] = rpmsgfs_closedir_handler,
|
||||
[RPMSGFS_STATFS] = rpmsgfs_statfs_handler,
|
||||
[RPMSGFS_UNLINK] = rpmsgfs_unlink_handler,
|
||||
[RPMSGFS_MKDIR] = rpmsgfs_mkdir_handler,
|
||||
[RPMSGFS_RMDIR] = rpmsgfs_rmdir_handler,
|
||||
[RPMSGFS_RENAME] = rpmsgfs_rename_handler,
|
||||
[RPMSGFS_STAT] = rpmsgfs_stat_handler,
|
||||
[RPMSGFS_FCHSTAT] = rpmsgfs_fchstat_handler,
|
||||
[RPMSGFS_CHSTAT] = rpmsgfs_chstat_handler,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int rpmsgfs_attach_file(FAR struct rpmsgfs_server_s *priv,
|
||||
FAR struct file *filep)
|
||||
{
|
||||
FAR struct file **tmp;
|
||||
int ret;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
if (priv->files[i][j].f_inode == NULL)
|
||||
{
|
||||
memcpy(&priv->files[i][j], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp[i] = kmm_zalloc(sizeof(struct file) *
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
|
||||
DEBUGASSERT(tmp[i]);
|
||||
if (tmp[i] == NULL)
|
||||
{
|
||||
kmm_free(tmp);
|
||||
ret = -ENFILE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->files = tmp;
|
||||
priv->file_rows++;
|
||||
|
||||
memcpy(&priv->files[i][0], filep, sizeof(*filep));
|
||||
ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
out:
|
||||
nxsem_post(&priv->sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpmsgfs_detach_file(FAR struct rpmsgfs_server_s *priv,
|
||||
int fd, FAR struct file *filep)
|
||||
{
|
||||
struct file *tfilep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
memcpy(filep, tfilep, sizeof(*filep));
|
||||
memset(tfilep, 0, sizeof(*tfilep));
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FAR struct file *rpmsgfs_get_file(
|
||||
FAR struct rpmsgfs_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR struct file *filep;
|
||||
|
||||
if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]
|
||||
[fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK];
|
||||
nxsem_post(&priv->sem);
|
||||
|
||||
return filep;
|
||||
}
|
||||
|
||||
static int rpmsgfs_attach_dir(FAR struct rpmsgfs_server_s *priv,
|
||||
FAR void *dir)
|
||||
{
|
||||
FAR void **tmp;
|
||||
int i;
|
||||
|
||||
nxsem_wait(&priv->sem);
|
||||
for (i = 1; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i] == NULL)
|
||||
{
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) *
|
||||
(priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK));
|
||||
DEBUGASSERT(tmp);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
nxsem_post(&priv->sem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->dirs = tmp;
|
||||
priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
|
||||
|
||||
priv->dirs[i] = dir;
|
||||
nxsem_post(&priv->sem);
|
||||
return i;
|
||||
}
|
||||
|
||||
static void *rpmsgfs_detach_dir(FAR struct rpmsgfs_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
priv->dirs[fd] = NULL;
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static FAR void *rpmsgfs_get_dir(
|
||||
FAR struct rpmsgfs_server_s *priv,
|
||||
int fd)
|
||||
{
|
||||
FAR void *dir = NULL;
|
||||
|
||||
if (fd >= 1 && fd < priv->dir_nums)
|
||||
{
|
||||
nxsem_wait(&priv->sem);
|
||||
dir = priv->dirs[fd];
|
||||
nxsem_post(&priv->sem);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int rpmsgfs_open_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_open_s *msg = data;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
ret = file_open(&file, msg->pathname, msg->flags, msg->mode);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = rpmsgfs_attach_file(priv, &file);
|
||||
if (ret < 0)
|
||||
{
|
||||
file_close(&file);
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_close_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_close_s *msg = data;
|
||||
struct file file;
|
||||
int ret;
|
||||
|
||||
ret = rpmsgfs_detach_file(priv, msg->fd, &file);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = file_close(&file);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_read_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_read_s *msg = data;
|
||||
FAR struct rpmsgfs_read_s *rsp;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
uint32_t space;
|
||||
|
||||
rsp = rpmsg_get_tx_payload_buffer(ept, &space, true);
|
||||
if (!rsp)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*rsp = *msg;
|
||||
|
||||
space -= sizeof(*msg);
|
||||
if (space > msg->count)
|
||||
{
|
||||
space = msg->count;
|
||||
}
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_read(filep, rsp->buf, space);
|
||||
}
|
||||
|
||||
rsp->header.result = ret;
|
||||
return rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp));
|
||||
}
|
||||
|
||||
static int rpmsgfs_write_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_write_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_write(filep, msg->buf, msg->count);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_lseek_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_lseek_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_seek(filep, msg->offset, msg->whence);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
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_ioctl_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_ioctl(filep, msg->request, msg->arg);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_sync_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_sync_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fsync(filep);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_dup_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_dup_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
struct file newfile;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_dup2(filep, &newfile);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ret = rpmsgfs_attach_file(priv, &newfile);
|
||||
if (ret < 0)
|
||||
{
|
||||
file_close(&newfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_fstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_fstat_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
struct stat buf;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_fstat(filep, &buf);
|
||||
if (ret >= 0)
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_ftruncate_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_ftruncate_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
ret = file_truncate(filep, msg->length);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_opendir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_opendir_s *msg = data;
|
||||
FAR void *dir;
|
||||
int ret = -ENOENT;
|
||||
|
||||
dir = opendir(msg->pathname);
|
||||
if (dir)
|
||||
{
|
||||
ret = rpmsgfs_attach_dir(priv, dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_readdir_s *msg = data;
|
||||
FAR struct dirent *entry;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = rpmsgfs_get_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
entry = readdir(dir);
|
||||
if (entry)
|
||||
{
|
||||
msg->type = entry->d_type;
|
||||
strcpy(msg->name, entry->d_name);
|
||||
len += strlen(entry->d_name) + 1;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, len);
|
||||
}
|
||||
|
||||
static int rpmsgfs_rewinddir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_rewinddir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = rpmsgfs_get_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
rewinddir(dir);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_closedir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_closedir_s *msg = data;
|
||||
int ret = -ENOENT;
|
||||
FAR void *dir;
|
||||
|
||||
dir = rpmsgfs_detach_dir(priv, msg->fd);
|
||||
if (dir)
|
||||
{
|
||||
ret = closedir(dir) ? -get_errno() : 0;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_statfs_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_statfs_s *msg = data;
|
||||
struct statfs buf;
|
||||
int ret;
|
||||
|
||||
ret = statfs(msg->pathname, &buf);
|
||||
if (ret)
|
||||
{
|
||||
ret = -get_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_unlink_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_unlink_s *msg = data;
|
||||
|
||||
msg->header.result = nx_unlink(msg->pathname);
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_mkdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_mkdir_s *msg = data;
|
||||
int ret;
|
||||
|
||||
ret = mkdir(msg->pathname, msg->mode);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_rmdir_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_rmdir_s *msg = data;
|
||||
int ret;
|
||||
|
||||
ret = rmdir(msg->pathname);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_rename_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_rename_s *msg = data;
|
||||
FAR char *newpath;
|
||||
size_t oldlen;
|
||||
int ret;
|
||||
|
||||
oldlen = (strlen(msg->pathname) + 1 + 0x7) & ~0x7;
|
||||
newpath = msg->pathname + oldlen;
|
||||
|
||||
ret = rename(msg->pathname, newpath);
|
||||
msg->header.result = ret ? -get_errno() : 0;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_stat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_stat_s *msg = data;
|
||||
struct stat buf;
|
||||
int ret;
|
||||
|
||||
ret = nx_stat(msg->pathname, &buf, 1);
|
||||
if (ret >= 0)
|
||||
{
|
||||
msg->buf = buf;
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_fchstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_fchstat_s *msg = data;
|
||||
FAR struct file *filep;
|
||||
int ret = -ENOENT;
|
||||
struct stat buf;
|
||||
|
||||
filep = rpmsgfs_get_file(priv, msg->fd);
|
||||
if (filep != NULL)
|
||||
{
|
||||
buf = msg->buf;
|
||||
ret = file_fchstat(filep, &buf, msg->flags);
|
||||
}
|
||||
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static int rpmsgfs_chstat_handler(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv)
|
||||
{
|
||||
FAR struct rpmsgfs_chstat_s *msg = data;
|
||||
struct timespec times[2];
|
||||
int ret = 0;
|
||||
|
||||
if (msg->flags & CH_STAT_MODE)
|
||||
{
|
||||
ret = chmod(msg->pathname, msg->buf.st_mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->flags & (CH_STAT_UID | CH_STAT_GID))
|
||||
{
|
||||
ret = chown(msg->pathname, msg->buf.st_uid, msg->buf.st_gid);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->flags & (CH_STAT_ATIME | CH_STAT_MTIME))
|
||||
{
|
||||
if (msg->flags & CH_STAT_ATIME)
|
||||
{
|
||||
times[0] = msg->buf.st_atim;
|
||||
}
|
||||
else
|
||||
{
|
||||
times[0].tv_nsec = UTIME_OMIT;
|
||||
}
|
||||
|
||||
if (msg->flags & CH_STAT_MTIME)
|
||||
{
|
||||
times[1] = msg->buf.st_mtim;
|
||||
}
|
||||
else
|
||||
{
|
||||
times[1].tv_nsec = UTIME_OMIT;
|
||||
}
|
||||
|
||||
ret = utimens(msg->pathname, times);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -get_errno();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
msg->header.result = ret;
|
||||
return rpmsg_send(ept, msg, sizeof(*msg));
|
||||
}
|
||||
|
||||
static void rpmsgfs_ns_bind(FAR struct rpmsg_device *rdev,
|
||||
FAR void *priv_, FAR const char *name,
|
||||
uint32_t dest)
|
||||
{
|
||||
FAR struct rpmsgfs_server_s *priv;
|
||||
int ret;
|
||||
|
||||
if (strncmp(name, RPMSGFS_NAME_PREFIX, strlen(RPMSGFS_NAME_PREFIX)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
priv = kmm_zalloc(sizeof(*priv));
|
||||
if (!priv)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
priv->ept.priv = priv;
|
||||
nxsem_init(&priv->sem, 0, 1);
|
||||
|
||||
ret = rpmsg_create_ept(&priv->ept, rdev, name,
|
||||
RPMSG_ADDR_ANY, dest,
|
||||
rpmsgfs_ept_cb, rpmsgfs_ns_unbind);
|
||||
if (ret)
|
||||
{
|
||||
nxsem_destroy(&priv->sem);
|
||||
kmm_free(priv);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmsgfs_ns_unbind(FAR struct rpmsg_endpoint *ept)
|
||||
{
|
||||
FAR struct rpmsgfs_server_s *priv = ept->priv;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < priv->file_rows; i++)
|
||||
{
|
||||
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
|
||||
{
|
||||
if (priv->files[i][j].f_inode)
|
||||
{
|
||||
file_close(&priv->files[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
kmm_free(priv->files[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->dir_nums; i++)
|
||||
{
|
||||
if (priv->dirs[i])
|
||||
{
|
||||
closedir(priv->dirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
rpmsg_destroy_ept(&priv->ept);
|
||||
nxsem_destroy(&priv->sem);
|
||||
|
||||
kmm_free(priv->files);
|
||||
kmm_free(priv->dirs);
|
||||
kmm_free(priv);
|
||||
}
|
||||
|
||||
static int rpmsgfs_ept_cb(FAR struct rpmsg_endpoint *ept,
|
||||
FAR void *data, size_t len, uint32_t src,
|
||||
FAR void *priv)
|
||||
{
|
||||
struct rpmsgfs_header_s *header = data;
|
||||
uint32_t command = header->command;
|
||||
|
||||
if (command < ARRAY_SIZE(g_rpmsgfs_handler))
|
||||
{
|
||||
return g_rpmsgfs_handler[command](ept, data, len, src, priv);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int rpmsgfs_server_init(void)
|
||||
{
|
||||
return rpmsg_register_callback(NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
rpmsgfs_ns_bind);
|
||||
}
|
@ -207,6 +207,17 @@ struct fs_hostfsdir_s
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
/* RPMSGFS provides mapping to directories on the host machine in the
|
||||
* sim environment.
|
||||
*/
|
||||
|
||||
struct fs_rpmsgfsdir_s
|
||||
{
|
||||
FAR void *fs_dir; /* Opaque pointer to remote DIR */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOINT */
|
||||
|
||||
struct fs_dirent_s
|
||||
@ -288,6 +299,9 @@ struct fs_dirent_s
|
||||
#ifdef CONFIG_FS_HOSTFS
|
||||
struct fs_hostfsdir_s hostfs;
|
||||
#endif
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
struct fs_rpmsgfsdir_s rpmsgfs;
|
||||
#endif
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT */
|
||||
} u;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/fs/hostfs_rpmsg.h
|
||||
* include/nuttx/fs/rpmsgfs.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
@ -33,12 +33,8 @@ extern "C"
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_HOSTFS_RPMSG
|
||||
int hostfs_rpmsg_init(FAR const char *cpu_name);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FS_HOSTFS_RPMSG_SERVER
|
||||
int hostfs_rpmsg_server_init(void);
|
||||
#ifdef CONFIG_FS_RPMSGFS
|
||||
int rpmsgfs_server_init(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
@ -93,6 +93,7 @@
|
||||
#define HOSTFS_MAGIC 0x54534f48
|
||||
#define USERFS_MAGIC 0x52455355
|
||||
#define CROMFS_MAGIC 0x4d4f5243
|
||||
#define RPMSGFS_MAGIC 0x54534f47
|
||||
|
||||
#if defined(CONFIG_FS_LARGEFILE) && defined(CONFIG_HAVE_LONG_LONG)
|
||||
# define statfs64 statfs
|
||||
|
Loading…
Reference in New Issue
Block a user