diff options
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.c | 1 | ||||
| -rw-r--r-- | platform/rtthread/rt_usbh_msc.c | 11 | ||||
| -rw-r--r-- | platform/rtthread/rt_vfs_dfs.c | 310 |
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; +} |
