From 796e6d94032c408fb9a87bc11ace55b7ed6229ce Mon Sep 17 00:00:00 2001 From: Serge Bazanski <q3k@q3k.org> Date: Sun, 30 Jul 2023 18:58:37 +0200 Subject: [PATCH] st3m: implement dumb VFS for / This allows us to os.listdir("/"). --- components/st3m/CMakeLists.txt | 1 + components/st3m/st3m_fs.c | 127 +++++++++++++++++++++++++++++++++ components/st3m/st3m_fs.h | 10 +++ main/fs.c | 21 +----- main/fs.h | 9 +-- main/main.c | 2 +- 6 files changed, 143 insertions(+), 27 deletions(-) create mode 100644 components/st3m/st3m_fs.c create mode 100644 components/st3m/st3m_fs.h diff --git a/components/st3m/CMakeLists.txt b/components/st3m/CMakeLists.txt index 2aac4cd768..d6cb7b5964 100644 --- a/components/st3m/CMakeLists.txt +++ b/components/st3m/CMakeLists.txt @@ -16,6 +16,7 @@ idf_component_register( st3m_captouch.c st3m_ringbuffer.c st3m_tar.c + st3m_fs.c INCLUDE_DIRS . REQUIRES diff --git a/components/st3m/st3m_fs.c b/components/st3m/st3m_fs.c new file mode 100644 index 0000000000..7738d1c93a --- /dev/null +++ b/components/st3m/st3m_fs.c @@ -0,0 +1,127 @@ +#include "st3m_fs.h" + +#include "st3m_mode.h" +#include "st3m_sys_data.h" +#include "st3m_tar.h" + +#include "esp_system.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" + +#include <errno.h> + +static const char *TAG = "st3m-fs"; + +// Entries for root filesystem. Ideally this wouldn't be static but would +// consult the ESP-IDF VFS registry. +static struct dirent _root_dirents[4] = { + { .d_ino = 1, .d_name = ".", .d_type = DT_DIR, }, + { .d_ino = 2, .d_name = "flash", .d_type = DT_DIR, }, + { .d_ino = 3, .d_name = "sd", .d_type = DT_DIR, }, + { .d_ino = 4, .d_name = "console", .d_type = DT_DIR, }, +}; + +// Handle of the wear levelling library instance +static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; + +static int _root_vfs_close(int fd) { + return 0; +} + +static int _root_vfs_fcntl(int fd, int cmd, int arg) { + return 0; +} + +static int _root_vfs_fstat(int fd, struct stat *st) { + st->st_mode = S_IFDIR; + return 0; +} + +static int _root_vfs_open(const char *path, int flags, int mode) { + if (strcmp(path, "/") == 0) { + if (flags == 0) { + return 0; + } + errno = EISDIR; + } else { + errno = ENOENT; + } + return -1; +} + +static ssize_t _root_vfs_read(int fd, void *data, size_t size) { + errno = EISDIR; + return -1; +} + +static ssize_t _root_vfs_write(int fd, const void *data, size_t size) { + errno = EISDIR; + return -1; +} + +typedef struct { + DIR _inner; + size_t ix; +} st3m_rootfs_dir_t; + +static DIR *_root_vfs_opendir(const char *name) { + if (strcmp(name, "/") != 0) { + errno = ENOENT; + return NULL; + } + + st3m_rootfs_dir_t *dir = calloc(1, sizeof(st3m_rootfs_dir_t)); + assert(dir != NULL); + return (DIR*)dir; +} + +static struct dirent *_root_vfs_readdir(DIR *pdir) { + st3m_rootfs_dir_t *dir = pdir; + if (dir->ix >= (sizeof(_root_dirents)/sizeof(struct dirent))) { + return NULL; + } + return &_root_dirents[dir->ix++]; +} + +static int _root_vfs_closedir(DIR *pdir) { + free(pdir); + return 0; +} + +// Root filesystem implementation, because otherwise os.listdir("/") fails... +static esp_vfs_t _root_vfs = { + .flags = ESP_VFS_FLAG_DEFAULT, + .close = &_root_vfs_close, + .fcntl = &_root_vfs_fcntl, + .fstat = &_root_vfs_fstat, + .open = &_root_vfs_open, + .read = &_root_vfs_read, + .write = &_root_vfs_write, + .opendir = &_root_vfs_opendir, + .readdir = &_root_vfs_readdir, + .closedir = &_root_vfs_closedir, +}; + +void st3m_fs_init(void) { + esp_err_t err; + + if ((err = esp_vfs_register("", &_root_vfs, NULL)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount root VFS: %s", esp_err_to_name(err)); + return; + } + + const esp_vfs_fat_mount_config_t mount_config = { + .max_files = 4, + .format_if_mount_failed = true, + .allocation_unit_size = CONFIG_WL_SECTOR_SIZE + }; + + err = esp_vfs_fat_spiflash_mount("/flash", "vfs", &mount_config, + &s_wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount FAT FS: %s", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "Mounted Flash VFS Partition at /flash"); +} diff --git a/components/st3m/st3m_fs.h b/components/st3m/st3m_fs.h new file mode 100644 index 0000000000..0164c17a8a --- /dev/null +++ b/components/st3m/st3m_fs.h @@ -0,0 +1,10 @@ +#pragma once + +// Mount filesystem. An error will be loged if the mount failed. +// +// Filesystem layout: +// /flash - FAT from flash ('vfat' partition, wear leveled) +// /sd - FAT from SD card, if available +// +// This function must not be called more than once. +void st3m_fs_init(void); \ No newline at end of file diff --git a/main/fs.c b/main/fs.c index 1fcab2a06e..19be43aa6b 100644 --- a/main/fs.c +++ b/main/fs.c @@ -3,6 +3,7 @@ #include "st3m_mode.h" #include "st3m_sys_data.h" #include "st3m_tar.h" +#include "st3m_fs.h" #include "esp_system.h" #include "esp_vfs.h" @@ -38,24 +39,8 @@ static void _extract_sys_data(void) { fclose(f); } -// Handle of the wear levelling library instance -static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; - -void st3m_fs_init(void) { - const esp_vfs_fat_mount_config_t mount_config = { - .max_files = 4, - .format_if_mount_failed = true, - .allocation_unit_size = CONFIG_WL_SECTOR_SIZE - }; - - esp_err_t err = esp_vfs_fat_spiflash_mount("/flash", "vfs", &mount_config, - &s_wl_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount FAT FS: %s", esp_err_to_name(err)); - return; - } - - ESP_LOGI(TAG, "Mounted Flash VFS Partition at /flash"); +void flow3r_fs_init(void) { + st3m_fs_init(); bool have_mpy = false; struct stat st; diff --git a/main/fs.h b/main/fs.h index 0164c17a8a..9e17f44a4f 100644 --- a/main/fs.h +++ b/main/fs.h @@ -1,10 +1,3 @@ #pragma once -// Mount filesystem. An error will be loged if the mount failed. -// -// Filesystem layout: -// /flash - FAT from flash ('vfat' partition, wear leveled) -// /sd - FAT from SD card, if available -// -// This function must not be called more than once. -void st3m_fs_init(void); \ No newline at end of file +void flow3r_fs_init(void); \ No newline at end of file diff --git a/main/main.c b/main/main.c index 42470a697d..d620b586d2 100644 --- a/main/main.c +++ b/main/main.c @@ -60,7 +60,7 @@ void flow3r_startup(void) { flow3r_bsp_i2c_init(); st3m_mode_set(st3m_mode_kind_starting, "fs"); st3m_mode_update_display(NULL); - st3m_fs_init(); + flow3r_fs_init(); st3m_mode_set(st3m_mode_kind_starting, "audio"); st3m_mode_update_display(NULL); st3m_scope_init(); -- GitLab