diff options
Diffstat (limited to 'platform')
| -rw-r--r-- | platform/blackmagic/bmp_port_cdc_acm.c | 18 | ||||
| -rw-r--r-- | platform/daplink/dap_main.c | 41 | ||||
| -rw-r--r-- | platform/fatfs/usbd_fatfs_mtp.c | 351 | ||||
| -rw-r--r-- | platform/fatfs/usbh_fatfs.c | 11 | ||||
| -rw-r--r-- | platform/fatfs/vfs_fatfs_port.c | 504 | ||||
| -rw-r--r-- | platform/idf/usbh_fatfs.c | 5 | ||||
| -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 | ||||
| -rw-r--r-- | platform/zephyr/usbh_msc_disk.c | 126 |
11 files changed, 1007 insertions, 458 deletions
diff --git a/platform/blackmagic/bmp_port_cdc_acm.c b/platform/blackmagic/bmp_port_cdc_acm.c index ae4e5457..e1353d66 100644 --- a/platform/blackmagic/bmp_port_cdc_acm.c +++ b/platform/blackmagic/bmp_port_cdc_acm.c @@ -9,24 +9,16 @@ #include "usbd_cdc_acm.h" #include "general.h" #include "gdb_if.h" -#include "hpm_l1c_drv.h" + +#define USBD_VID 0xffff +#define USBD_PID 0xffff +#define USBD_MAX_POWER 100 +#define USBD_LANGID_STRING 1033 #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x01 #define CDC_INT_EP 0x83 -#define CDC_MAX_PACKET_SIZE 512 - -#ifdef CONFIG_USB_HS -#if CDC_MAX_PACKET_SIZE != 512 -#error "CDC_MAX_PACKET_SIZE must be 512 in hs" -#endif -#else -#if CDC_MAX_PACKET_SIZE != 64 -#error "CDC_MAX_PACKET_SIZE must be 64 in fs" -#endif -#endif - /*!< config descriptor size */ #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) diff --git a/platform/daplink/dap_main.c b/platform/daplink/dap_main.c index 27e0355b..b145c223 100644 --- a/platform/daplink/dap_main.c +++ b/platform/daplink/dap_main.c @@ -335,17 +335,16 @@ static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Request[DAP_PACKET_COU static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t USB_Response[DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Response Buffer static uint16_t USB_RespSize[DAP_PACKET_COUNT]; // Response Size -volatile struct cdc_line_coding g_cdc_lincoding; -volatile uint8_t config_uart = 0; -volatile uint8_t config_uart_transfer = 0; - USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t uartrx_ringbuffer[CONFIG_UARTRX_RINGBUF_SIZE]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usbrx_ringbuffer[CONFIG_USBRX_RINGBUF_SIZE]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_tmpbuffer[DAP_PACKET_SIZE]; +static volatile struct cdc_line_coding g_cdc_lincoding; +static volatile uint8_t config_uart = 0; +static volatile uint8_t config_uart_transfer = 0; static volatile uint8_t usbrx_idle_flag = 0; -static volatile uint8_t usbtx_idle_flag = 0; -static volatile uint8_t uarttx_idle_flag = 0; +static volatile uint8_t usbtx_idle_flag = 1; +static volatile uint8_t uarttx_idle_flag = 1; USB_NOCACHE_RAM_SECTION chry_ringbuffer_t g_uartrx; USB_NOCACHE_RAM_SECTION chry_ringbuffer_t g_usbrx; @@ -356,9 +355,6 @@ void usbd_event_handler(uint8_t busid, uint8_t event) switch (event) { case USBD_EVENT_RESET: usbrx_idle_flag = 0; - usbtx_idle_flag = 0; - uarttx_idle_flag = 0; - config_uart_transfer = 0; break; case USBD_EVENT_CONNECTED: break; @@ -437,20 +433,13 @@ void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) { (void)busid; - uint32_t size; - uint8_t *buffer; chry_ringbuffer_linear_read_done(&g_uartrx, nbytes); if ((nbytes % DAP_PACKET_SIZE) == 0 && nbytes) { /* send zlp */ usbd_ep_start_write(0, CDC_IN_EP, NULL, 0); } else { - if (chry_ringbuffer_get_used(&g_uartrx)) { - buffer = chry_ringbuffer_linear_read_setup(&g_uartrx, &size); - usbd_ep_start_write(0, CDC_IN_EP, buffer, size); - } else { - usbtx_idle_flag = 1; - } + usbtx_idle_flag = 1; } } @@ -624,7 +613,8 @@ void chry_dap_handle(void) void usbd_cdc_acm_set_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding) { (void)busid; - if (memcmp(line_coding, (uint8_t *)&g_cdc_lincoding, sizeof(struct cdc_line_coding)) != 0) { + + if (memcmp((uint8_t *)&g_cdc_lincoding, line_coding, sizeof(struct cdc_line_coding)) != 0 && line_coding->dwDTERate != 0) { memcpy((uint8_t *)&g_cdc_lincoding, line_coding, sizeof(struct cdc_line_coding)); config_uart = 1; config_uart_transfer = 0; @@ -642,6 +632,10 @@ void chry_dap_usb2uart_handle(void) uint32_t size; uint8_t *buffer; + if (usb_device_is_configured(0) == 0) { + return; + } + if (config_uart) { /* disable irq here */ config_uart = 0; @@ -700,16 +694,9 @@ __WEAK void chry_dap_usb2uart_uart_config_callback(struct cdc_line_coding *line_ /* called by user */ void chry_dap_usb2uart_uart_send_complete(uint32_t size) { - uint8_t *buffer; - chry_ringbuffer_linear_read_done(&g_usbrx, size); - if (chry_ringbuffer_get_used(&g_usbrx)) { - buffer = chry_ringbuffer_linear_read_setup(&g_usbrx, &size); - chry_dap_usb2uart_uart_send_bydma(buffer, size); - } else { - uarttx_idle_flag = 1; - } + uarttx_idle_flag = 1; } /* implment by user */ @@ -746,4 +733,4 @@ int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length) memcpy(mass_block[sector].BlockSpace, buffer, length); return 0; } -#endif +#endif
\ No newline at end of file diff --git a/platform/fatfs/usbd_fatfs_mtp.c b/platform/fatfs/usbd_fatfs_mtp.c deleted file mode 100644 index 8126e3d5..00000000 --- a/platform/fatfs/usbd_fatfs_mtp.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2025, sakumisu - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "ff.h" -#include "diskio.h" -#include "usbd_core.h" -#include "usb_osal.h" -#include "usbd_mtp.h" - -FATFS s_sd_disk; -FIL s_file; -BYTE work[FF_MAX_SS]; - -const TCHAR driver_num_buf[3] = { '0', ':', '\0' }; - -const char *show_error_string(FRESULT fresult); - -static FRESULT sd_mount_fs(void) -{ - FRESULT fresult = f_mount(&s_sd_disk, driver_num_buf, 1); - if (fresult == FR_OK) { - printf("SD card has been mounted successfully\n"); - } else { - printf("Failed to mount SD card, cause: %s\n", show_error_string(fresult)); - } - - return fresult; -} - -#if 0 -static FRESULT sd_mkfs(void) -{ - printf("Formatting the SD card, depending on the SD card capacity, the formatting process may take a long time\n"); - FRESULT fresult = f_mkfs(driver_num_buf, NULL, work, sizeof(work)); - if (fresult != FR_OK) { - printf("Making File system failed, cause: %s\n", show_error_string(fresult)); - } else { - printf("Making file system is successful\n"); - } - - return fresult; -} -#endif - -static FRESULT sd_write_file(void) -{ - FRESULT fresult = f_open(&s_file, "0:/readme.txt", FA_WRITE | FA_CREATE_ALWAYS); - if (fresult != FR_OK) { - printf("Create new file failed, cause: %d\n", show_error_string(fresult)); - } else { - printf("Create new file successfully, status=%d\n", fresult); - } - char hello_str[] = "Hello, this is SD card FATFS demo\n"; - UINT byte_written; - fresult = f_write(&s_file, hello_str, sizeof(hello_str), &byte_written); - if (fresult != FR_OK) { - printf("Write file failed, cause: %s\n", show_error_string(fresult)); - } else { - printf("Write file operation is successfully\n"); - } - - f_close(&s_file); - - return fresult; -} - -const char *show_error_string(FRESULT fresult) -{ - const char *result_str; - - switch (fresult) { - case FR_OK: - result_str = "succeeded"; - break; - case FR_DISK_ERR: - result_str = "A hard error occurred in the low level disk I/O level"; - break; - case FR_INT_ERR: - result_str = "Assertion failed"; - break; - case FR_NOT_READY: - result_str = "The physical drive cannot work"; - break; - case FR_NO_FILE: - result_str = "Could not find the file"; - break; - case FR_NO_PATH: - result_str = "Could not find the path"; - break; - case FR_INVALID_NAME: - result_str = "Tha path name format is invalid"; - break; - case FR_DENIED: - result_str = "Access denied due to prohibited access or directory full"; - break; - case FR_EXIST: - result_str = "Access denied due to prohibited access"; - break; - case FR_INVALID_OBJECT: - result_str = "The file/directory object is invalid"; - break; - case FR_WRITE_PROTECTED: - result_str = "The physical drive is write protected"; - break; - case FR_INVALID_DRIVE: - result_str = "The logical driver number is invalid"; - break; - case FR_NOT_ENABLED: - result_str = "The volume has no work area"; - break; - case FR_NO_FILESYSTEM: - result_str = "There is no valid FAT volume"; - break; - case FR_MKFS_ABORTED: - result_str = "THe f_mkfs() aborted due to any problem"; - break; - case FR_TIMEOUT: - result_str = "Could not get a grant to access the volume within defined period"; - break; - case FR_LOCKED: - result_str = "The operation is rejected according to the file sharing policy"; - break; - case FR_NOT_ENOUGH_CORE: - result_str = "LFN working buffer could not be allocated"; - break; - case FR_TOO_MANY_OPEN_FILES: - result_str = "Number of open files > FF_FS_LOCK"; - break; - case FR_INVALID_PARAMETER: - result_str = "Given parameter is invalid"; - break; - default: - result_str = "Unknown error"; - break; - } - return result_str; -} - -const char *usbd_mtp_fs_root_path(void) -{ - return driver_num_buf; -} - -const char *usbd_mtp_fs_description(void) -{ - return "CherryUSB MTP"; -} - -int usbd_mtp_mkdir(const char *path) -{ - FRESULT result = f_mkdir(path); - if (result != FR_OK) { - printf("f_mkdir failed, cause: %s\n", show_error_string(result)); - return -1; - } - return 0; // Directory created successfully -} - -int usbd_mtp_rmdir(const char *path) -{ - FRESULT result = f_rmdir(path); - if (result != FR_OK) { - printf("f_mkdir failed, cause: %s\n", show_error_string(result)); - return -1; - } - return 0; // Directory created successfully -} - -MTP_DIR *usbd_mtp_opendir(const char *name) -{ - FRESULT result; - DIR *dir; - - dir = usb_osal_malloc(sizeof(DIR)); - result = f_opendir(dir, name); - if (result != FR_OK) { - printf("f_opendir failed, cause: %s\n", show_error_string(result)); - usb_osal_free(dir); - return NULL; // Failed to open directory - } - return (MTP_DIR *)dir; -} - -int usbd_mtp_closedir(MTP_DIR *dir) -{ - FRESULT result; - result = f_closedir((DIR *)dir); - if (result != FR_OK) { - printf("f_closedir failed, cause: %s\n", show_error_string(result)); - return -1; // Failed to close directory - } - usb_osal_free(dir); // Free the directory structure - return result; -} - -struct mtp_dirent *usbd_mtp_readdir(MTP_DIR *dir) -{ - FILINFO fno; - FRESULT result; - - result = f_readdir((DIR *)dir, &fno); - if (result != FR_OK || fno.fname[0] == 0) - return NULL; - - static struct mtp_dirent dirent; - memset(&dirent, 0, sizeof(struct mtp_dirent)); - strncpy(dirent.d_name, fno.fname, sizeof(dirent.d_name) - 1); - dirent.d_name[sizeof(dirent.d_name) - 1] = '\0'; - dirent.d_namlen = strlen(dirent.d_name); - - return &dirent; -} - -#undef SS -#if FF_MAX_SS == FF_MIN_SS -#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ -#else -#define SS(fs) ((fs)->ssize) /* Variable sector size */ -#endif - -int usbd_mtp_stat(const char *path, struct mtp_stat *buf) -{ - FILINFO file_info; - FRESULT result; - FATFS *f; - f = &s_sd_disk; - - result = f_stat(path, &file_info); - if (result != FR_OK) { - printf("f_stat failed, cause: %s\n", show_error_string(result)); - return -1; - } - buf->st_mode = MTP_S_IFREG | MTP_S_IRUSR | MTP_S_IRGRP | MTP_S_IROTH | - MTP_S_IWUSR | MTP_S_IWGRP | MTP_S_IWOTH; - if (file_info.fattrib & AM_DIR) { - buf->st_mode &= ~MTP_S_IFREG; - buf->st_mode |= MTP_S_IFDIR | MTP_S_IXUSR | MTP_S_IXGRP | MTP_S_IXOTH; - } - if (file_info.fattrib & AM_RDO) - buf->st_mode &= ~(MTP_S_IWUSR | MTP_S_IWGRP | MTP_S_IWOTH); - - buf->st_size = file_info.fsize; - buf->st_blksize = f->csize * SS(f); - if (file_info.fattrib & AM_ARC) { - buf->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / f->csize + 1) : 0; - buf->st_blocks *= (buf->st_blksize / 512); // man say st_blocks is number of 512B blocks allocated - } else { - buf->st_blocks = f->csize; - } - return 0; -} - -int usbd_mtp_statfs(const char *path, struct mtp_statfs *buf) -{ - FATFS *f; - FRESULT res; - DWORD fre_clust, fre_sect, tot_sect; - - f = &s_sd_disk; - - res = f_getfree(path, &fre_clust, &f); - if (res != FR_OK) { - printf("f_getfree failed, cause: %s\n", show_error_string(res)); - return -1; - } - tot_sect = (f->n_fatent - 2) * f->csize; - fre_sect = fre_clust * f->csize; - - buf->f_blocks = tot_sect; - buf->f_bfree = fre_sect; -#if FF_MAX_SS != FF_MIN_SS - buf->f_bsize = f->ssize; -#else - buf->f_bsize = FF_MIN_SS; -#endif - return 0; -} - -int usbd_mtp_open(const char *path, uint8_t mode) -{ - BYTE flags; - - if (mode == MTP_O_RDONLY) { - flags = FA_READ | FA_OPEN_EXISTING; - } else if (mode == MTP_O_WRONLY) { - flags = FA_WRITE | FA_OPEN_ALWAYS; - } else if (mode == MTP_O_RDWR) { - flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; - } else { - return -1; // Invalid mode - } - - FRESULT result = f_open(&s_file, path, flags); - if (result != FR_OK) { - printf("f_open failed, cause: %s\n", show_error_string(result)); - return -1; - } - return 0; -} - -int usbd_mtp_close(int fd) -{ - FRESULT result = f_close(&s_file); - if (result != FR_OK) { - printf("f_close failed, cause: %s\n", show_error_string(result)); - return -1; - } - return 0; -} - -int usbd_mtp_read(int fd, void *buf, size_t len) -{ - UINT bytes_read; - FRESULT result = f_read(&s_file, buf, len, &bytes_read); - if (result != FR_OK) { - printf("f_read failed, cause: %s\n", show_error_string(result)); - return -1; - } - return bytes_read; // Return number of bytes read -} - -int usbd_mtp_write(int fd, const void *buf, size_t len) -{ - UINT bytes_written; - FRESULT result = f_write(&s_file, buf, len, &bytes_written); - if (result != FR_OK) { - printf("f_write failed, cause: %s\n", show_error_string(result)); - return -1; - } - return bytes_written; // Return number of bytes written -} - -int usbd_mtp_unlink(const char *path) -{ - FRESULT result = f_unlink(path); - if (result != FR_OK) { - printf("f_unlink failed, cause: %s\n", show_error_string(result)); - return -1; - } - return 0; // File deleted successfully -} - -void usbd_mtp_mount() -{ - sd_mount_fs(); - - // write a file to test the SD card - sd_write_file(); -} diff --git a/platform/fatfs/usbh_fatfs.c b/platform/fatfs/usbh_fatfs.c index abb7181b..9c799d62 100644 --- a/platform/fatfs/usbh_fatfs.c +++ b/platform/fatfs/usbh_fatfs.c @@ -14,12 +14,17 @@ int USB_disk_initialize(void) { active_msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda"); if (active_msc_class == NULL) { - printf("do not find /dev/sda\r\n"); + USB_LOG_ERR("do not find /dev/sda\r\n"); return RES_NOTRDY; } if (usbh_msc_scsi_init(active_msc_class) < 0) { return RES_NOTRDY; } + + if ((active_msc_class->blocksize < FF_MIN_SS) || (active_msc_class->blocksize > FF_MAX_SS)) { + USB_LOG_ERR("unsupported block size %u\r\n", (unsigned int)active_msc_class->blocksize); + return RES_NOTRDY; + } return RES_OK; } @@ -38,7 +43,7 @@ int USB_disk_read(BYTE *buff, LBA_t sector, UINT count) if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) { align_buf = (uint8_t *)aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize); if (!align_buf) { - printf("msc get align buf failed\r\n"); + USB_LOG_ERR("msc get align buf failed\r\n"); return -USB_ERR_NOMEM; } } @@ -68,7 +73,7 @@ int USB_disk_write(const BYTE *buff, LBA_t sector, UINT count) if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) { align_buf = (uint8_t *)aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize); if (!align_buf) { - printf("msc get align buf failed\r\n"); + USB_LOG_ERR("msc get align buf failed\r\n"); return -USB_ERR_NOMEM; } usb_memcpy(align_buf, buff, count * active_msc_class->blocksize); diff --git a/platform/fatfs/vfs_fatfs_port.c b/platform/fatfs/vfs_fatfs_port.c new file mode 100644 index 00000000..efb14d33 --- /dev/null +++ b/platform/fatfs/vfs_fatfs_port.c @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2024 ~ 2026, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "ff.h" +#include "diskio.h" +#include "usbd_core.h" +#include "usb_vfs.h" + +FATFS s_sd_disk; +FIL s_file; +BYTE work[FF_MAX_SS]; + +const TCHAR driver_num_buf[4] = { DEV_SD + '0', ':', '/', '\0' }; + +static const char *show_error_string(FRESULT fresult); + +static FRESULT sd_mount_fs(void) +{ + FRESULT fresult = f_mount(&s_sd_disk, driver_num_buf, 1); + if (fresult == FR_OK) { + printf("SD card has been mounted successfully\n"); + } else { + printf("Failed to mount SD card, cause: %s\n", show_error_string(fresult)); + } + + fresult = f_chdrive(driver_num_buf); + return fresult; +} + +#if 0 +static FRESULT sd_mkfs(void) +{ + printf("Formatting the SD card, depending on the SD card capacity, the formatting process may take a long time\n"); + FRESULT fresult = f_mkfs(driver_num_buf, NULL, work, sizeof(work)); + if (fresult != FR_OK) { + printf("Making File system failed, cause: %s\n", show_error_string(fresult)); + } else { + printf("Making file system is successful\n"); + } + + return fresult; +} +#endif + +static FRESULT sd_write_file(void) +{ + FRESULT fresult = f_open(&s_file, "readme.txt", FA_WRITE | FA_CREATE_ALWAYS); + if (fresult != FR_OK) { + printf("Create new file failed, cause: %s\n", show_error_string(fresult)); + } else { + printf("Create new file successfully, status=%d\n", fresult); + } + char hello_str[] = "Hello, this is SD card FATFS demo\n"; + UINT byte_written; + fresult = f_write(&s_file, hello_str, sizeof(hello_str), &byte_written); + if (fresult != FR_OK) { + printf("Write file failed, cause: %s\n", show_error_string(fresult)); + } else { + printf("Write file operation is successfully\n"); + } + + f_close(&s_file); + + return fresult; +} + +static const char *show_error_string(FRESULT fresult) +{ + const char *result_str; + + switch (fresult) { + case FR_OK: + result_str = "succeeded"; + break; + case FR_DISK_ERR: + result_str = "A hard error occurred in the low level disk I/O level"; + break; + case FR_INT_ERR: + result_str = "Assertion failed"; + break; + case FR_NOT_READY: + result_str = "The physical drive cannot work"; + break; + case FR_NO_FILE: + result_str = "Could not find the file"; + break; + case FR_NO_PATH: + result_str = "Could not find the path"; + break; + case FR_INVALID_NAME: + result_str = "Tha path name format is invalid"; + break; + case FR_DENIED: + result_str = "Access denied due to prohibited access or directory full"; + break; + case FR_EXIST: + result_str = "Access denied due to prohibited access"; + break; + case FR_INVALID_OBJECT: + result_str = "The file/directory object is invalid"; + break; + case FR_WRITE_PROTECTED: + result_str = "The physical drive is write protected"; + break; + case FR_INVALID_DRIVE: + result_str = "The logical driver number is invalid"; + break; + case FR_NOT_ENABLED: + result_str = "The volume has no work area"; + break; + case FR_NO_FILESYSTEM: + result_str = "There is no valid FAT volume"; + break; + case FR_MKFS_ABORTED: + result_str = "THe f_mkfs() aborted due to any problem"; + break; + case FR_TIMEOUT: + result_str = "Could not get a grant to access the volume within defined period"; + break; + case FR_LOCKED: + result_str = "The operation is rejected according to the file sharing policy"; + break; + case FR_NOT_ENOUGH_CORE: + result_str = "LFN working buffer could not be allocated"; + break; + case FR_TOO_MANY_OPEN_FILES: + result_str = "Number of open files > FF_FS_LOCK"; + break; + case FR_INVALID_PARAMETER: + result_str = "Given parameter is invalid"; + break; + default: + result_str = "Unknown error"; + break; + } + return result_str; +} + +const char *vfs_get_fs_root_path(void) +{ + return "/"; +} + +const char *vfs_get_fs_description(void) +{ + return "CherryUSB VFS FATFS"; +} + +/* ------------------------------------------------------------------------- + * helpers + * ---------------------------------------------------------------------- */ + +/** FatFs result -> VFS_ERR_*, so the host gets a readable reason. */ +static int adb_err(FRESULT fr) +{ + switch (fr) { + case FR_OK: + return 0; + case FR_NO_FILE: + case FR_NO_PATH: + return VFS_ERR_NOENT; + case FR_EXIST: + return VFS_ERR_EXIST; + case FR_INVALID_NAME: + return VFS_ERR_INVAL; + case FR_INVALID_PARAMETER: + return VFS_ERR_INVAL; + case FR_INVALID_OBJECT: + return VFS_ERR_INVAL; + case FR_WRITE_PROTECTED: + return VFS_ERR_ROFS; + case FR_DENIED: + /* "access denied", which FatFs also uses for a full directory */ + return VFS_ERR_ROFS; + case FR_INVALID_DRIVE: + case FR_NOT_ENABLED: + case FR_NO_FILESYSTEM: + case FR_NOT_READY: + return VFS_ERR_NODEV; + case FR_TIMEOUT: + case FR_LOCKED: + return VFS_ERR_AGAIN; + case FR_NOT_ENOUGH_CORE: + case FR_TOO_MANY_OPEN_FILES: + return VFS_ERR_NOMEM; + case FR_DISK_ERR: + case FR_INT_ERR: + default: + return VFS_ERR_IO; + } +} + +/** + * days since 1970-01-01, proleptic gregorian (Howard Hinnant's algorithm). + * Kept here rather than pulling in <time.h>, which an RTOS may not have. + */ +static int days_from_civil(int y, unsigned m, unsigned d) +{ + int era; + unsigned yoe, doy, doe; + + y -= (m <= 2u) ? 1 : 0; + era = (y >= 0 ? y : y - 399) / 400; + yoe = (unsigned)(y - era * 400); + doy = (153u * (m + (m > 2u ? (unsigned)-3 : 9u)) + 2u) / 5u + d - 1u; + doe = yoe * 365u + yoe / 4u - yoe / 100u + doy; + + return era * 146097 + (int)doe - 719468; +} + +/** + * FatFs date/time -> unix seconds. + * + * adb sync carries the file time in STAT and DENT records, but FatFs keeps a + * packed DOS timestamp, so it has to be converted somewhere. Doing it here + * keeps the protocol layer free of file system specifics. + */ +static uint32_t fat_time_to_unix(uint16_t fdate, uint16_t ftime) +{ + unsigned year = 1980u + ((fdate >> 9) & 0x7Fu); + unsigned month = (fdate >> 5) & 0x0Fu; + unsigned day = fdate & 0x1Fu; + unsigned hour = ((unsigned)ftime >> 11) & 0x1Fu; + unsigned minute = ((unsigned)ftime >> 5) & 0x3Fu; + unsigned second = ((unsigned)ftime & 0x1Fu) * 2u; + + if ((fdate == 0) || (month == 0) || (day == 0)) { + return 0; /* FatFs stores 0 when there is no valid timestamp */ + } + + return (uint32_t)(days_from_civil((int)year, month, day) * 86400 + + (int)(hour * 3600u + minute * 60u + second)); +} + +int vfs_mkdir(const char *path) +{ + FRESULT result; + + if (!path || !path[0]) { + return VFS_ERR_INVAL; + } + + result = f_mkdir(path); + /* 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 */ + if ((result != FR_OK) && (result != FR_EXIST)) { + return adb_err(result); + } + + return 0; +} + +int vfs_rmdir(const char *path) +{ + FRESULT result = f_rmdir(path); + + if (result != FR_OK) { + return adb_err(result); + } + + return 0; +} + +VFS_DIR *vfs_opendir(const char *name) +{ + FRESULT result; + DIR *dir; + + if (!name || !name[0]) { + return NULL; + } + + dir = usb_osal_malloc(sizeof(DIR)); + if (!dir) { + return NULL; + } + + result = f_opendir(dir, name); + if (result != FR_OK) { + usb_osal_free(dir); + return NULL; + } + + return (VFS_DIR *)dir; +} + +int vfs_closedir(VFS_DIR *dir) +{ + FRESULT result; + + if (!dir) { + return VFS_ERR_INVAL; + } + + result = f_closedir((DIR *)dir); + usb_osal_free(dir); /* release it either way */ + + if (result != FR_OK) { + return adb_err(result); + } + + return 0; +} + +struct vfs_dirent *vfs_readdir(VFS_DIR *dir) +{ + static struct vfs_dirent dirent; + FILINFO fno; + FRESULT result; + + if (!dir) { + return NULL; + } + + result = f_readdir((DIR *)dir, &fno); + if ((result != FR_OK) || (fno.fname[0] == 0)) { + return NULL; /* end of directory, or a hard error */ + } + + memset(&dirent, 0, sizeof(dirent)); + strncpy(dirent.d_name, fno.fname, 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 vfs_posix.h */ + dirent.d_type = (uint8_t)(((fno.fattrib & AM_DIR) ? VFS_S_IFDIR + : VFS_S_IFREG) >> + 12); + + return &dirent; +} + +#undef SS +#if FF_MAX_SS == FF_MIN_SS +#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + +int vfs_stat(const char *path, struct vfs_stat *buf) +{ + FILINFO file_info; + FRESULT result; + FATFS *f; + + if (!path || !path[0] || !buf) { + return VFS_ERR_INVAL; + } + + f = &s_sd_disk; + + result = f_stat(path, &file_info); + if (result != FR_OK) { + /* 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 adb_err(result); + } + + memset(buf, 0, sizeof(*buf)); + buf->st_mode = VFS_S_IFREG | VFS_S_IRUSR | VFS_S_IRGRP | VFS_S_IROTH | + VFS_S_IWUSR | VFS_S_IWGRP | VFS_S_IWOTH; + if (file_info.fattrib & AM_DIR) { + buf->st_mode &= ~VFS_S_IFREG; + buf->st_mode |= VFS_S_IFDIR | VFS_S_IXUSR | VFS_S_IXGRP | VFS_S_IXOTH; + } + if (file_info.fattrib & AM_RDO) { + buf->st_mode &= ~(VFS_S_IWUSR | VFS_S_IWGRP | VFS_S_IWOTH); + } + + buf->st_dev = 0; + buf->st_nlink = 1; + buf->st_size = file_info.fsize; + buf->st_blksize = f->csize * SS(f); + if (file_info.fattrib & AM_ARC) { + buf->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / f->csize + 1) : 0; + buf->st_blocks *= (buf->st_blksize / 512); /* st_blocks is in 512B units */ + } else { + buf->st_blocks = f->csize; + } + buf->st_mtime = fat_time_to_unix(file_info.fdate, file_info.ftime); + return 0; +} + +int vfs_statfs(const char *path, struct vfs_statfs *buf) +{ + FATFS *f; + FRESULT res; + DWORD fre_clust, fre_sect, tot_sect; + + if (!path || !path[0] || !buf) { + return VFS_ERR_INVAL; + } + + f = &s_sd_disk; + + res = f_getfree(path, &fre_clust, &f); + if (res != FR_OK) { + return adb_err(res); + } + tot_sect = (f->n_fatent - 2) * f->csize; + fre_sect = fre_clust * f->csize; + + buf->f_blocks = tot_sect; + buf->f_bfree = fre_sect; +#if FF_MAX_SS != FF_MIN_SS + buf->f_bsize = f->ssize; +#else + buf->f_bsize = FF_MIN_SS; +#endif + return 0; +} + +int vfs_open(const char *path, uint8_t mode) +{ + FRESULT result; + BYTE flags; + + if (!path || !path[0]) { + return VFS_ERR_INVAL; + } + + if (mode == VFS_O_RDONLY) { + flags = FA_READ | FA_OPEN_EXISTING; + } else if (mode == VFS_O_WRONLY) { + flags = FA_WRITE | FA_CREATE_ALWAYS; + } else if (mode == VFS_O_RDWR) { + flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; + } else { + return VFS_ERR_INVAL; + } + + result = f_open(&s_file, path, flags); + if (result != FR_OK) { + return adb_err(result); + } + + return 0; +} + +int vfs_close(int fd) +{ + FRESULT result; + + (void)fd; + + result = f_close(&s_file); + if (result != FR_OK) { + return adb_err(result); + } + + return 0; +} + +int vfs_read(int fd, void *buf, size_t len) +{ + UINT bytes_read; + FRESULT result; + + (void)fd; + + result = f_read(&s_file, buf, len, &bytes_read); + if (result != FR_OK) { + return adb_err(result); + } + + return (int)bytes_read; +} + +int vfs_write(int fd, const void *buf, size_t len) +{ + UINT bytes_written; + FRESULT result; + + (void)fd; + + result = f_write(&s_file, buf, len, &bytes_written); + if (result != FR_OK) { + return adb_err(result); + } + + return (int)bytes_written; +} + +int vfs_unlink(const char *path) +{ + FRESULT result = f_unlink(path); + + if (result != FR_OK) { + return adb_err(result); + } + + return 0; +} + +void vfs_mount(void) +{ + //sd_mkfs(); + + sd_mount_fs(); + + sd_write_file(); +}
\ No newline at end of file diff --git a/platform/idf/usbh_fatfs.c b/platform/idf/usbh_fatfs.c index fef0798f..ca2713ae 100644 --- a/platform/idf/usbh_fatfs.c +++ b/platform/idf/usbh_fatfs.c @@ -9,6 +9,7 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_idf_version.h" #include "esp_log.h" #include "esp_check.h" #include "diskio_impl.h" @@ -215,12 +216,16 @@ esp_err_t msc_host_vfs_register(struct usbh_msc *msc_class, strcpy(vfs->base_path, base_path); vfs->pdrv = pdrv; +#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(6, 0, 0) esp_vfs_fat_conf_t conf = { .base_path = base_path, .fat_drive = drive, .max_files = mount_config->max_files, }; ret = esp_vfs_fat_register(&conf, &fs); +#else + ret = esp_vfs_fat_register(base_path, drive, mount_config->max_files, &fs); +#endif ESP_GOTO_ON_ERROR(ret, fail, TAG, "Failed to register filesystem, error=%s", esp_err_to_name(ret)); vfs->fs = fs; 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; +} diff --git a/platform/zephyr/usbh_msc_disk.c b/platform/zephyr/usbh_msc_disk.c index 6890f985..129cbfe4 100644 --- a/platform/zephyr/usbh_msc_disk.c +++ b/platform/zephyr/usbh_msc_disk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, sakumisu + * Copyright (c) 2025-2026 sakumisu * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,16 +13,37 @@ #endif #endif -struct usbh_msc *active_msc_class; +struct usbh_msc_disk_context { + struct usbh_msc *msc_class; + struct disk_info disk; + char name[CONFIG_USBHOST_DEV_NAMELEN]; + char devname[CONFIG_USBHOST_DEV_NAMELEN]; +}; + +static struct usbh_msc_disk_context + msc_disk_context[CONFIG_USBHOST_MAX_MSC_CLASS]; + +static struct usbh_msc_disk_context *disk_msc_context(struct disk_info *disk) +{ + return CONTAINER_OF(disk, struct usbh_msc_disk_context, disk); +} + +static bool disk_msc_connected(const struct usbh_msc *msc_class) +{ + return msc_class != NULL && msc_class->hport != NULL && + msc_class->hport->connected; +} static int disk_msc_access_init(struct disk_info *disk) { - active_msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda"); - if (active_msc_class == NULL) { - printf("do not find /dev/sda\r\n"); + struct usbh_msc_disk_context *ctx = disk_msc_context(disk); + + ctx->msc_class = (struct usbh_msc *)usbh_find_class_instance(ctx->devname); + if (ctx->msc_class == NULL) { + printf("do not find %s\r\n", ctx->devname); return -ENODEV; } - if (usbh_msc_scsi_init(active_msc_class) < 0) { + if (usbh_msc_scsi_init(ctx->msc_class) < 0) { return -EIO; } return 0; @@ -30,6 +51,12 @@ static int disk_msc_access_init(struct disk_info *disk) static int disk_msc_access_status(struct disk_info *disk) { + struct usbh_msc_disk_context *ctx = disk_msc_context(disk); + + if (!disk_msc_connected(ctx->msc_class)) { + return DISK_STATUS_NOMEDIA; + } + return DISK_STATUS_OK; } @@ -38,25 +65,30 @@ static int disk_msc_access_read(struct disk_info *disk, uint8_t *buff, { int ret; uint8_t *align_buf; + struct usbh_msc_disk_context *ctx = disk_msc_context(disk); + + if (!disk_msc_connected(ctx->msc_class)) { + return -ENODEV; + } align_buf = (uint8_t *)buff; #ifdef CONFIG_DCACHE if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) { - align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize); + align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * ctx->msc_class->blocksize); if (!align_buf) { printf("msc get align buf failed\r\n"); return -ENOMEM; } } #endif - if (usbh_msc_scsi_read10(active_msc_class, sector, align_buf, count) < 0) { + if (usbh_msc_scsi_read10(ctx->msc_class, sector, align_buf, count) < 0) { ret = -EIO; } else { ret = 0; } #ifdef CONFIG_DCACHE if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) { - usb_memcpy(buff, align_buf, count * active_msc_class->blocksize); + usb_memcpy(buff, align_buf, count * ctx->msc_class->blocksize); k_free(align_buf); } #endif @@ -68,19 +100,24 @@ static int disk_msc_access_write(struct disk_info *disk, const uint8_t *buff, { int ret; uint8_t *align_buf; + struct usbh_msc_disk_context *ctx = disk_msc_context(disk); + + if (!disk_msc_connected(ctx->msc_class)) { + return -ENODEV; + } align_buf = (uint8_t *)buff; #ifdef CONFIG_DCACHE if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) { - align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize); + align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * ctx->msc_class->blocksize); if (!align_buf) { printf("msc get align buf failed\r\n"); return -ENOMEM; } - usb_memcpy(align_buf, buff, count * active_msc_class->blocksize); + usb_memcpy(align_buf, buff, count * ctx->msc_class->blocksize); } #endif - if (usbh_msc_scsi_write10(active_msc_class, sector, align_buf, count) < 0) { + if (usbh_msc_scsi_write10(ctx->msc_class, sector, align_buf, count) < 0) { ret = -EIO; } else { ret = 0; @@ -95,14 +132,22 @@ static int disk_msc_access_write(struct disk_info *disk, const uint8_t *buff, static int disk_msc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { + struct usbh_msc_disk_context *ctx = disk_msc_context(disk); + switch (cmd) { case DISK_IOCTL_CTRL_SYNC: break; case DISK_IOCTL_GET_SECTOR_COUNT: - *(uint32_t *)buff = active_msc_class->blocknum; + if (!disk_msc_connected(ctx->msc_class)) { + return -ENODEV; + } + *(uint32_t *)buff = ctx->msc_class->blocknum; break; case DISK_IOCTL_GET_SECTOR_SIZE: - *(uint32_t *)buff = active_msc_class->blocksize; + if (!disk_msc_connected(ctx->msc_class)) { + return -ENODEV; + } + *(uint32_t *)buff = ctx->msc_class->blocksize; break; case DISK_IOCTL_GET_ERASE_BLOCK_SZ: *(uint32_t *)buff = 1U; @@ -126,17 +171,56 @@ static const struct disk_operations msc_disk_ops = { .ioctl = disk_msc_access_ioctl, }; -static struct disk_info usbh_msc_disk = { - .name = "USB", - .ops = &msc_disk_ops, -}; +__WEAK void usbh_msc_app_run(struct usbh_msc *msc_class) +{ + (void)msc_class; +} + +__WEAK void usbh_msc_app_stop(struct usbh_msc *msc_class) +{ + (void)msc_class; +} void usbh_msc_run(struct usbh_msc *msc_class) { - disk_access_register(&usbh_msc_disk); + uint8_t index; + struct usbh_msc_disk_context *ctx; + + if (msc_class == NULL || msc_class->sdchar < 'a' || + msc_class->sdchar >= 'a' + CONFIG_USBHOST_MAX_MSC_CLASS) { + return; + } + + index = msc_class->sdchar - 'a'; + ctx = &msc_disk_context[index]; + memset(ctx, 0, sizeof(*ctx)); + snprintf(ctx->name, sizeof(ctx->name), "USB%u", index); + snprintf(ctx->devname, sizeof(ctx->devname), "/dev/sd%c", msc_class->sdchar); + ctx->msc_class = msc_class; + ctx->disk.name = ctx->name; + ctx->disk.ops = &msc_disk_ops; + + if (disk_access_register(&ctx->disk) < 0) { + return; + } + + usbh_msc_app_run(msc_class); } void usbh_msc_stop(struct usbh_msc *msc_class) { - disk_access_unregister(&usbh_msc_disk); -}
\ No newline at end of file + uint8_t index; + struct usbh_msc_disk_context *ctx; + + usbh_msc_app_stop(msc_class); + + if (msc_class == NULL || msc_class->sdchar < 'a' || + msc_class->sdchar >= 'a' + CONFIG_USBHOST_MAX_MSC_CLASS) { + return; + } + + index = msc_class->sdchar - 'a'; + ctx = &msc_disk_context[index]; + disk_access_unregister(&ctx->disk); + ctx->msc_class = NULL; +} |
