summaryrefslogtreecommitdiff
path: root/platform/rtthread
diff options
context:
space:
mode:
Diffstat (limited to 'platform/rtthread')
-rw-r--r--platform/rtthread/rt_usbd_adb_msh.c (renamed from platform/rtthread/rt_usbd_adb.c)87
-rw-r--r--platform/rtthread/rt_usbd_serial.c1
-rw-r--r--platform/rtthread/rt_usbh_msc.c11
-rw-r--r--platform/rtthread/rt_vfs_dfs.c310
4 files changed, 366 insertions, 43 deletions
diff --git a/platform/rtthread/rt_usbd_adb.c b/platform/rtthread/rt_usbd_adb_msh.c
index 4ab7f59a..d994894f 100644
--- a/platform/rtthread/rt_usbd_adb.c
+++ b/platform/rtthread/rt_usbd_adb_msh.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, sakumisu
+ * Copyright (c) 2024 ~ 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,33 +9,21 @@
#include "usbd_core.h"
#include "usbd_adb.h"
+#ifdef RT_USING_FINSH
+#include <shell.h>
+#include <finsh.h>
+#endif
+
#ifndef CONFIG_USBDEV_SHELL_RX_BUFSIZE
#define CONFIG_USBDEV_SHELL_RX_BUFSIZE (2048)
#endif
struct usbd_adb_shell {
struct rt_device parent;
- usb_osal_sem_t tx_done;
struct rt_ringbuffer rx_rb;
rt_uint8_t rx_rb_buffer[CONFIG_USBDEV_SHELL_RX_BUFSIZE];
} g_usbd_adb_shell;
-void usbd_adb_notify_shell_read(uint8_t *data, uint32_t len)
-{
- rt_ringbuffer_put(&g_usbd_adb_shell.rx_rb, data, len);
-
- if (g_usbd_adb_shell.parent.rx_indicate) {
- g_usbd_adb_shell.parent.rx_indicate(&g_usbd_adb_shell.parent, len);
- }
-}
-
-void usbd_adb_notify_write_done(void)
-{
- if (g_usbd_adb_shell.tx_done) {
- usb_osal_sem_give(g_usbd_adb_shell.tx_done);
- }
-}
-
static rt_err_t usbd_adb_shell_open(struct rt_device *dev, rt_uint16_t oflag)
{
while (!usb_device_is_configured(0)) {
@@ -46,10 +34,6 @@ static rt_err_t usbd_adb_shell_open(struct rt_device *dev, rt_uint16_t oflag)
static rt_err_t usbd_adb_shell_close(struct rt_device *dev)
{
- if (g_usbd_adb_shell.tx_done) {
- usb_osal_sem_give(g_usbd_adb_shell.tx_done);
- }
-
return RT_EOK;
}
@@ -70,15 +54,7 @@ static rt_ssize_t usbd_adb_shell_write(struct rt_device *dev,
RT_ASSERT(dev != RT_NULL);
- if (!usb_device_is_configured(0)) {
- return size;
- }
-
- if (usbd_adb_can_write() && size) {
- usb_osal_sem_reset(g_usbd_adb_shell.tx_done);
- usbd_abd_write(ADB_SHELL_LOALID, buffer, size);
- usb_osal_sem_take(g_usbd_adb_shell.tx_done, 0xffffffff);
- }
+ usbd_adb_write(ADB_LOCALID_SHELL, buffer, size);
return size;
}
@@ -94,7 +70,7 @@ const static struct rt_device_ops usbd_adb_shell_ops = {
};
#endif
-void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep)
+void rt_usbd_adb_shell_init(void)
{
rt_err_t ret;
struct rt_device *device;
@@ -125,31 +101,58 @@ void usbd_adb_shell_init(uint8_t in_ep, uint8_t out_ep)
device->fops = NULL;
#endif
- g_usbd_adb_shell.tx_done = usb_osal_sem_create(0);
rt_ringbuffer_init(&g_usbd_adb_shell.rx_rb, g_usbd_adb_shell.rx_rb_buffer, sizeof(g_usbd_adb_shell.rx_rb_buffer));
}
-static int adb_enter(int argc, char **argv)
+static void adb_shell_on_open(uint32_t remoteid)
{
- (void)argc;
- (void)argv;
-
+ USB_LOG_INFO("adb shell open, remoteid:%u\r\n", (unsigned)remoteid);
finsh_set_device("adb-sh");
rt_console_set_device("adb-sh");
+}
- return 0;
+static void adb_shell_on_close(uint32_t remoteid)
+{
+ USB_LOG_INFO("adb shell close, remoteid:%u\r\n", (unsigned)remoteid);
+}
+
+static void adb_shell_on_write(uint32_t remoteid, const uint8_t *data, uint32_t len)
+{
+ rt_size_t put;
+
+ put = rt_ringbuffer_put(&g_usbd_adb_shell.rx_rb, data, len);
+ if (g_usbd_adb_shell.parent.rx_indicate != RT_NULL) {
+ g_usbd_adb_shell.parent.rx_indicate(&g_usbd_adb_shell.parent, put);
+ }
+}
+
+static const struct adb_service adb_shell_service = {
+ .name = "shell:",
+ .localid = ADB_LOCALID_SHELL,
+ .on_open = adb_shell_on_open,
+ .on_close = adb_shell_on_close,
+ .on_write = adb_shell_on_write,
+};
+
+void usbd_adb_shell_init(void)
+{
+ if (usbd_adb_service_register(&adb_shell_service) != 0) {
+ USB_LOG_ERR("adb shell: register failed\r\n");
+ }
+ rt_usbd_adb_shell_init();
}
-MSH_CMD_EXPORT(adb_enter, adb_enter);
static int adb_exit(int argc, char **argv)
{
(void)argc;
(void)argv;
- usbd_adb_close(ADB_SHELL_LOALID);
+ usbd_adb_close(ADB_LOCALID_SHELL);
- finsh_set_device(RT_CONSOLE_DEVICE_NAME);
- rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+ if (rt_console_get_device() != rt_device_find(RT_CONSOLE_DEVICE_NAME)) {
+ rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+ finsh_set_device(RT_CONSOLE_DEVICE_NAME);
+ }
return 0;
}
diff --git a/platform/rtthread/rt_usbd_serial.c b/platform/rtthread/rt_usbd_serial.c
index 41fb01af..138f4cc8 100644
--- a/platform/rtthread/rt_usbd_serial.c
+++ b/platform/rtthread/rt_usbd_serial.c
@@ -258,6 +258,7 @@ void usbd_cdc_acm_serial_init(uint8_t busid, uint8_t in_ep, uint8_t out_ep)
serial->in_ep = in_ep;
serial->out_ep = out_ep;
serial->tx_done = usb_osal_sem_create(0);
+ USB_ASSERT(serial->tx_done != NULL);
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_ctrl));
usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &serial->intf_data));
diff --git a/platform/rtthread/rt_usbh_msc.c b/platform/rtthread/rt_usbh_msc.c
index 77846665..aa2e4a8d 100644
--- a/platform/rtthread/rt_usbh_msc.c
+++ b/platform/rtthread/rt_usbh_msc.c
@@ -29,9 +29,13 @@ static rt_err_t rt_udisk_init(rt_device_t dev)
return RT_EOK;
}
-
+#if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 0))
static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
rt_size_t size)
+#else
+static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
+ rt_size_t size)
+#endif
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
@@ -62,8 +66,13 @@ static rt_ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
return size;
}
+#if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 0))
static rt_ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
rt_size_t size)
+#else
+static rt_size_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
+ rt_size_t size)
+#endif
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
diff --git a/platform/rtthread/rt_vfs_dfs.c b/platform/rtthread/rt_vfs_dfs.c
new file mode 100644
index 00000000..6bd2f20f
--- /dev/null
+++ b/platform/rtthread/rt_vfs_dfs.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2026, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include <string.h>
+#include <errno.h>
+
+#include <dfs_fs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "usbd_core.h"
+#include "usb_vfs.h"
+
+#ifndef RT_USING_DFS
+#error "RT_USING_DFS must be enabled to use adb sync over the RT-Thread file system"
+#endif
+
+#ifndef CONFIG_USB_DFS_MOUNT_POINT
+#define CONFIG_USB_DFS_MOUNT_POINT "/"
+#endif
+
+/* -------------------------------------------------------------------------
+ * helpers
+ * ---------------------------------------------------------------------- */
+
+/**
+ * POSIX errno as a plain positive value.
+ *
+ * RT-Thread stores whatever code it was handed, and the DFS layer is not
+ * consistent about the sign, so it is normalised before being looked at.
+ */
+static int dfs_errno(void)
+{
+ int err = errno;
+
+ return (err < 0) ? -err : err;
+}
+
+/** errno -> VFS_ERR_*, so the host gets a readable reason. */
+static int dfs_errno_to_vfs(int err)
+{
+ switch (err) {
+ case ENOENT:
+ return VFS_ERR_NOENT;
+ case EEXIST:
+ return VFS_ERR_EXIST;
+ case EINVAL:
+ return VFS_ERR_INVAL;
+ case ENOTDIR:
+ return VFS_ERR_NOTDIR;
+ case EISDIR:
+ return VFS_ERR_ISDIR;
+ case ENOSPC:
+ return VFS_ERR_NOSPC;
+ case ENOMEM:
+ return VFS_ERR_NOMEM;
+ case EBUSY:
+ case EAGAIN:
+ return VFS_ERR_AGAIN;
+ case ENODEV:
+ return VFS_ERR_NODEV;
+ case EROFS:
+ case EACCES:
+ case EPERM:
+ return VFS_ERR_ROFS;
+ case EIO:
+ default:
+ return VFS_ERR_IO;
+ }
+}
+
+const char *vfs_get_fs_root_path(void)
+{
+ return CONFIG_USB_DFS_MOUNT_POINT;
+}
+
+const char *vfs_get_fs_description(void)
+{
+ return "CherryUSB VFS DFS";
+}
+
+int vfs_mkdir(const char *path)
+{
+ if (!path || !path[0]) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (mkdir(path, 0777) < 0) {
+ /* adb push of a directory tree re-sends SEND for directories it has
+ * already created, so "it is already there" has to count as success */
+ int err = dfs_errno();
+
+ if (err != EEXIST) {
+ return dfs_errno_to_vfs(err);
+ }
+ }
+
+ return 0;
+}
+
+int vfs_rmdir(const char *path)
+{
+ if (!path || !path[0]) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (rmdir(path) < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return 0;
+}
+
+VFS_DIR *vfs_opendir(const char *name)
+{
+ DIR *dir;
+
+ if (!name || !name[0]) {
+ return NULL;
+ }
+
+ dir = opendir(name);
+ if (!dir) {
+ return NULL;
+ }
+
+ return (VFS_DIR *)dir;
+}
+
+int vfs_closedir(VFS_DIR *dir)
+{
+ if (!dir) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (closedir((DIR *)dir) < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return 0;
+}
+
+struct vfs_dirent *vfs_readdir(VFS_DIR *dir)
+{
+ static struct vfs_dirent dirent;
+ struct dirent *entry;
+
+ if (!dir) {
+ return NULL;
+ }
+
+ entry = readdir((DIR *)dir);
+ if (!entry) {
+ return NULL; /* end of directory, or a hard error */
+ }
+
+ memset(&dirent, 0, sizeof(dirent));
+ strncpy(dirent.d_name, entry->d_name, sizeof(dirent.d_name) - 1);
+ dirent.d_name[sizeof(dirent.d_name) - 1] = '\0';
+ dirent.d_namlen = (uint8_t)strlen(dirent.d_name);
+ /* d_type is just the type field of a mode shifted down, see usb_vfs.h.
+ * RT-Thread hands back DT_*, so the two cases that matter are translated
+ * and anything else (including DT_UNKNOWN) falls back to a regular file. */
+ dirent.d_type = (entry->d_type == DT_DIR) ? (uint8_t)(VFS_S_IFDIR >> 12)
+ : (uint8_t)(VFS_S_IFREG >> 12);
+
+ return &dirent;
+}
+
+int vfs_stat(const char *path, struct vfs_stat *buf)
+{
+ struct stat st;
+
+ if (!path || !path[0] || !buf) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (stat(path, &st) < 0) {
+ /* Stay quiet on purpose: adb stats a path precisely to find out whether
+ * it exists, so "not found" is a normal answer and not an error. The
+ * service reports it to the host as "mode 0". */
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ memset(buf, 0, sizeof(*buf));
+ if (S_ISDIR(st.st_mode)) {
+ buf->st_mode = VFS_S_IFDIR | VFS_S_IRWXU | VFS_S_IRWXG | VFS_S_IRWXO;
+ } else {
+ buf->st_mode = VFS_S_IFREG | VFS_S_IRUSR | VFS_S_IRGRP | VFS_S_IROTH |
+ VFS_S_IWUSR | VFS_S_IWGRP | VFS_S_IWOTH;
+ }
+
+ buf->st_dev = 0;
+ buf->st_nlink = 1;
+ buf->st_size = st.st_size;
+ buf->st_mtime = st.st_mtime;
+ /* st_blksize/st_blocks are left at zero: RT-Thread's struct stat does not
+ * carry them consistently across DFS versions, and the adb STAT record
+ * only ever reports mode, size and mtime. */
+ return 0;
+}
+
+int vfs_statfs(const char *path, struct vfs_statfs *buf)
+{
+ struct statfs st;
+
+ if (!path || !path[0] || !buf) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (dfs_statfs(path, &st) < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ buf->f_bsize = st.f_bsize;
+ buf->f_blocks = st.f_blocks;
+ buf->f_bfree = st.f_bfree;
+ return 0;
+}
+
+int vfs_open(const char *path, uint8_t mode)
+{
+ int flags;
+ int fd;
+
+ if (!path || !path[0]) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (mode == VFS_O_RDONLY) {
+ flags = O_RDONLY; /* existing file only */
+ } else if (mode == VFS_O_WRONLY) {
+ flags = O_WRONLY | O_CREAT | O_TRUNC; /* create / truncate */
+ } else if (mode == VFS_O_RDWR) {
+ flags = O_RDWR | O_CREAT; /* create, no truncate */
+ } else {
+ return VFS_ERR_INVAL;
+ }
+
+ fd = open(path, flags, 0666);
+ if (fd < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return fd;
+}
+
+int vfs_close(int fd)
+{
+ if (fd < 0) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (close(fd) < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return 0;
+}
+
+int vfs_read(int fd, void *buf, size_t len)
+{
+ int ret;
+
+ if (fd < 0) {
+ return VFS_ERR_INVAL;
+ }
+
+ ret = (int)read(fd, buf, len);
+ if (ret < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return ret;
+}
+
+int vfs_write(int fd, const void *buf, size_t len)
+{
+ int ret;
+
+ if (fd < 0) {
+ return VFS_ERR_INVAL;
+ }
+
+ ret = (int)write(fd, buf, len);
+ if (ret < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return ret;
+}
+
+int vfs_unlink(const char *path)
+{
+ if (!path || !path[0]) {
+ return VFS_ERR_INVAL;
+ }
+
+ if (unlink(path) < 0) {
+ return dfs_errno_to_vfs(dfs_errno());
+ }
+
+ return 0;
+}