hosfs_rpmsg: merge hostfs_rpmsg to rpmsgfs

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2021-11-30 20:00:03 +08:00 committed by Xiang Xiao
parent 5ed85ef476
commit 985cc4fc6d
18 changed files with 3476 additions and 1896 deletions

View File

@ -134,3 +134,4 @@ source "fs/littlefs/Kconfig"
source "fs/unionfs/Kconfig"
source "fs/userfs/Kconfig"
source "fs/hostfs/Kconfig"
source "fs/rpmsgfs/Kconfig"

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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";

View File

@ -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
View 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
View 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

File diff suppressed because it is too large Load Diff

246
fs/rpmsgfs/rpmsgfs.h Normal file
View 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
View 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
View 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);
}

View File

@ -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;

View File

@ -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

View File

@ -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