From 84590ec0a4815e84cf32f790db5060f07ef98f7c Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 31 Jan 2017 17:23:25 +0200 Subject: [PATCH 1/4] FATFS enable support for multiple drives Current implementation has drive numbers and paths hardcoded to support only one FATFS drive. Arduino has it's own SPI driver to allow compatibility and flexibility. With the MR it is possible to have up to ```_VOLUMES``` drives connected (SPI, SDMMC and others) at the same time and accessed through VFS --- components/fatfs/src/diskio.c | 45 +++++++++-- components/fatfs/src/diskio.h | 7 ++ components/fatfs/src/esp_vfs_fat.h | 14 ++++ components/fatfs/src/vfs_fat.c | 113 +++++++++++++++++++++------ components/fatfs/src/vfs_fat_sdmmc.c | 23 ++++-- 5 files changed, 166 insertions(+), 36 deletions(-) diff --git a/components/fatfs/src/diskio.c b/components/fatfs/src/diskio.c index 004cfc5be..915bb8e2c 100644 --- a/components/fatfs/src/diskio.c +++ b/components/fatfs/src/diskio.c @@ -18,39 +18,70 @@ #include static const char* TAG = "ff_diskio"; -static ff_diskio_impl_t s_impls[_VOLUMES] = { { 0 } }; +static ff_diskio_impl_t * s_impls[_VOLUMES]; static sdmmc_card_t* s_cards[_VOLUMES] = { NULL }; +static bool s_impls_initialized = false; PARTITION VolToPart[] = { {0, 1}, /* Logical drive 0 ==> Physical drive 0, 1st partition */ {1, 0} /* Logical drive 1 ==> Physical drive 1, auto detection */ }; +BYTE ff_disk_getpdrv() +{ + BYTE i; + for(i=0; i<_VOLUMES; i++) { + if (!s_impls[i]) { + return i; + } + } + return 0xFF; +} + void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl) { assert(pdrv < _VOLUMES); - memcpy(&s_impls[pdrv], discio_impl, sizeof(ff_diskio_impl_t)); + + if (!s_impls_initialized) { + s_impls_initialized = true; + memset(s_impls, 0, _VOLUMES * sizeof(ff_diskio_impl_t*)); + } + + if (s_impls[pdrv]) { + ff_diskio_impl_t* im = s_impls[pdrv]; + s_impls[pdrv] = NULL; + free(im); + } + + if (!discio_impl) { + return; + } + + ff_diskio_impl_t * impl = (ff_diskio_impl_t *)malloc(sizeof(ff_diskio_impl_t)); + assert(impl != NULL); + memcpy(impl, discio_impl, sizeof(ff_diskio_impl_t)); + s_impls[pdrv] = impl; } DSTATUS ff_disk_initialize (BYTE pdrv) { - return s_impls[pdrv].init(pdrv); + return s_impls[pdrv]->init(pdrv); } DSTATUS ff_disk_status (BYTE pdrv) { - return s_impls[pdrv].status(pdrv); + return s_impls[pdrv]->status(pdrv); } DRESULT ff_disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { - return s_impls[pdrv].read(pdrv, buff, sector, count); + return s_impls[pdrv]->read(pdrv, buff, sector, count); } DRESULT ff_disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { - return s_impls[pdrv].write(pdrv, buff, sector, count); + return s_impls[pdrv]->write(pdrv, buff, sector, count); } DRESULT ff_disk_ioctl (BYTE pdrv, BYTE cmd, void* buff) { - return s_impls[pdrv].ioctl(pdrv, cmd, buff); + return s_impls[pdrv]->ioctl(pdrv, cmd, buff); } DWORD get_fattime(void) diff --git a/components/fatfs/src/diskio.h b/components/fatfs/src/diskio.h index 7c224809f..2fd27a864 100644 --- a/components/fatfs/src/diskio.h +++ b/components/fatfs/src/diskio.h @@ -76,6 +76,13 @@ void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl); */ void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card); +/** + * Get next available drive number + * + * @return 0xFF on fail, else the drive number + */ +BYTE ff_disk_getpdrv(); + /* Disk Status Bits (DSTATUS) */ #define STA_NOINIT 0x01 /* Drive not initialized */ diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index 087d6cf77..6dbef5cfb 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -57,6 +57,20 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, */ esp_err_t esp_vfs_fat_unregister(); +/** + * @brief Un-register FATFS from VFS + * + * @note FATFS structure returned by esp_vfs_fat_register is destroyed after + * this call. Make sure to call f_mount function to unmount it before + * calling esp_vfs_fat_unregister. + * @param base_path path prefix where FATFS is registered. This is the same + * used when esp_vfs_fat_register was called + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS + */ +esp_err_t esp_vfs_fat_unregister_ctx(const char* base_path); + /** * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount function */ diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 4ef387b43..6390fbcf7 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -28,6 +28,7 @@ typedef struct { char fat_drive[8]; + char base_path[ESP_VFS_PATH_MAX]; size_t max_files; FATFS fs; FIL files[0]; @@ -42,7 +43,6 @@ typedef struct { struct dirent cur_dirent; } vfs_fat_dir_t; - static const char* TAG = "vfs_fat"; static size_t vfs_fat_write(void* p, int fd, const void * data, size_t size); @@ -64,15 +64,42 @@ static int vfs_fat_closedir(void* ctx, DIR* pdir); static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode); static int vfs_fat_rmdir(void* ctx, const char* name); - -static char s_base_path[ESP_VFS_PATH_MAX]; +static vfs_fat_ctx_t* s_fat_ctxs[_VOLUMES] = { NULL, NULL }; +//compatibility static vfs_fat_ctx_t* s_fat_ctx = NULL; +static unsigned char esp_vfs_fat_get_ctx(const char* base_path) +{ + for(unsigned char i=0; i<_VOLUMES; i++) { + if (s_fat_ctxs[i] && !strcmp(s_fat_ctxs[i]->base_path, base_path)) { + return i; + } + } + return _VOLUMES; +} + +static unsigned char esp_vfs_fat_get_empty_ctx() +{ + for(unsigned char i=0; i<_VOLUMES; i++) { + if (!s_fat_ctxs[i]) { + return i; + } + } + return _VOLUMES; +} + esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, size_t max_files, FATFS** out_fs) { - if (s_fat_ctx) { + unsigned char ctx = esp_vfs_fat_get_ctx(base_path); + if (ctx < _VOLUMES) { return ESP_ERR_INVALID_STATE; } + + ctx = esp_vfs_fat_get_empty_ctx(); + if (ctx == _VOLUMES) { + return ESP_ERR_NO_MEM; + } + const esp_vfs_t vfs = { .flags = ESP_VFS_FLAG_CONTEXT_PTR, .write_p = &vfs_fat_write, @@ -95,22 +122,49 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz .rmdir_p = &vfs_fat_rmdir }; size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL); - s_fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size); - if (s_fat_ctx == NULL) { + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size); + if (fat_ctx == NULL) { return ESP_ERR_NO_MEM; } - s_fat_ctx->max_files = max_files; - strncpy(s_fat_ctx->fat_drive, fat_drive, sizeof(s_fat_ctx->fat_drive) - 1); - *out_fs = &s_fat_ctx->fs; - esp_err_t err = esp_vfs_register(base_path, &vfs, s_fat_ctx); + fat_ctx->max_files = max_files; + + strncpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); + fat_ctx->fat_drive[sizeof(fat_ctx->fat_drive) - 1] = 0; + + strncpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); + fat_ctx->base_path[sizeof(fat_ctx->base_path) - 1] = 0; + + esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx); if (err != ESP_OK) { - free(s_fat_ctx); - s_fat_ctx = NULL; + free(fat_ctx); return err; } - _lock_init(&s_fat_ctx->lock); - strncpy(s_base_path, base_path, sizeof(s_base_path) - 1); - s_base_path[sizeof(s_base_path) - 1] = 0; + + _lock_init(&fat_ctx->lock); + s_fat_ctxs[ctx] = fat_ctx; + + //compatibility + s_fat_ctx = fat_ctx; + + *out_fs = &fat_ctx->fs; + + return ESP_OK; +} + +esp_err_t esp_vfs_fat_unregister_ctx(const char* base_path) +{ + unsigned char ctx = esp_vfs_fat_get_ctx(base_path); + if (ctx == _VOLUMES) { + return ESP_ERR_INVALID_STATE; + } + vfs_fat_ctx_t* fat_ctx = s_fat_ctxs[ctx]; + esp_err_t err = esp_vfs_unregister(fat_ctx->base_path); + if (err != ESP_OK) { + return err; + } + _lock_close(&fat_ctx->lock); + free(fat_ctx); + s_fat_ctxs[ctx] = NULL; return ESP_OK; } @@ -119,12 +173,10 @@ esp_err_t esp_vfs_fat_unregister() if (s_fat_ctx == NULL) { return ESP_ERR_INVALID_STATE; } - esp_err_t err = esp_vfs_unregister(s_base_path); + esp_err_t err = esp_vfs_fat_unregister_ctx(s_fat_ctx->base_path); if (err != ESP_OK) { return err; } - _lock_close(&s_fat_ctx->lock); - free(s_fat_ctx); s_fat_ctx = NULL; return ESP_OK; } @@ -197,11 +249,19 @@ static void file_cleanup(vfs_fat_ctx_t* ctx, int fd) memset(&ctx->files[fd], 0, sizeof(FIL)); } +#define vfs_fat_fix_path(ctx, path) \ + if (((vfs_fat_ctx_t*)ctx)->fat_drive[0]) { \ + char buf_ ## path[strlen(path)+strlen(((vfs_fat_ctx_t*)ctx)->fat_drive)+1]; \ + sprintf(buf_ ## path,"%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path); \ + path = (const char *)buf_ ## path; \ + } + static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) { + vfs_fat_fix_path(ctx, path); ESP_LOGV(TAG, "%s: path=\"%s\", flags=%x, mode=%x", __func__, path, flags, mode); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; - _lock_acquire(&s_fat_ctx->lock); + _lock_acquire(&fat_ctx->lock); int fd = get_next_fd(fat_ctx); if (fd < 0) { ESP_LOGE(TAG, "open: no free file descriptors"); @@ -218,7 +278,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) goto out; } out: - _lock_release(&s_fat_ctx->lock); + _lock_release(&fat_ctx->lock); return fd; } @@ -257,7 +317,7 @@ static ssize_t vfs_fat_read(void* ctx, int fd, void * dst, size_t size) static int vfs_fat_close(void* ctx, int fd) { vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; - _lock_acquire(&s_fat_ctx->lock); + _lock_acquire(&fat_ctx->lock); FIL* file = &fat_ctx->files[fd]; FRESULT res = f_close(file); file_cleanup(fat_ctx, fd); @@ -267,7 +327,7 @@ static int vfs_fat_close(void* ctx, int fd) errno = fresult_to_errno(res); rc = -1; } - _lock_release(&s_fat_ctx->lock); + _lock_release(&fat_ctx->lock); return rc; } @@ -308,6 +368,7 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st) static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) { + vfs_fat_fix_path(ctx, path); FILINFO info; FRESULT res = f_stat(path, &info); if (res != FR_OK) { @@ -337,6 +398,7 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) static int vfs_fat_unlink(void* ctx, const char *path) { + vfs_fat_fix_path(ctx, path); FRESULT res = f_unlink(path); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -348,6 +410,8 @@ static int vfs_fat_unlink(void* ctx, const char *path) static int vfs_fat_link(void* ctx, const char* n1, const char* n2) { + vfs_fat_fix_path(ctx, n1); + vfs_fat_fix_path(ctx, n2); const size_t copy_buf_size = 4096; void* buf = malloc(copy_buf_size); if (buf == NULL) { @@ -402,6 +466,8 @@ fail1: static int vfs_fat_rename(void* ctx, const char *src, const char *dst) { + vfs_fat_fix_path(ctx, src); + vfs_fat_fix_path(ctx, dst); FRESULT res = f_rename(src, dst); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -413,6 +479,7 @@ static int vfs_fat_rename(void* ctx, const char *src, const char *dst) static DIR* vfs_fat_opendir(void* ctx, const char* name) { + vfs_fat_fix_path(ctx, name); vfs_fat_dir_t* fat_dir = calloc(1, sizeof(vfs_fat_dir_t)); if (!fat_dir) { errno = ENOMEM; @@ -517,6 +584,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset) static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) { (void) mode; + vfs_fat_fix_path(ctx, name); FRESULT res = f_mkdir(name); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -528,6 +596,7 @@ static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) static int vfs_fat_rmdir(void* ctx, const char* name) { + vfs_fat_fix_path(ctx, name); FRESULT res = f_unlink(name); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index e5956dd7b..f5e4c5099 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -22,6 +22,7 @@ static const char* TAG = "vfs_fat_sdmmc"; static sdmmc_card_t* s_card = NULL; +static uint8_t s_pdrv = 0; esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, const sdmmc_host_t* host_config, @@ -56,11 +57,18 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, } // connect SDMMC driver to FATFS - ff_diskio_register_sdmmc(0, s_card); + BYTE pdrv = ff_disk_getpdrv(); + if (pdrv == 0xFF) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + goto fail; + } + ff_diskio_register_sdmmc(pdrv, s_card); + s_pdrv = pdrv; + char drv[3] = {(char)('0' + pdrv), ':', 0}; // connect FATFS to VFS FATFS* fs; - err = esp_vfs_fat_register(base_path, "", mount_config->max_files, &fs); + err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); if (err == ESP_ERR_INVALID_STATE) { // it's okay, already registered with VFS } else if (err != ESP_OK) { @@ -69,7 +77,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, } // Try to mount partition - FRESULT res = f_mount(fs, "", 1); + FRESULT res = f_mount(fs, drv, 1); if (res != FR_OK) { err = ESP_FAIL; ESP_LOGW(TAG, "failed to mount card (%d)", res); @@ -79,7 +87,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, ESP_LOGW(TAG, "partitioning card"); DWORD plist[] = {100, 0, 0, 0}; workbuf = malloc(workbuf_size); - res = f_fdisk(0, plist, workbuf); + res = f_fdisk(s_pdrv, plist, workbuf); if (res != FR_OK) { err = ESP_FAIL; ESP_LOGD(TAG, "f_fdisk failed (%d)", res); @@ -94,7 +102,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, } free(workbuf); ESP_LOGW(TAG, "mounting again"); - res = f_mount(fs, "", 0); + res = f_mount(fs, drv, 0); if (res != FR_OK) { err = ESP_FAIL; ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res); @@ -105,7 +113,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, fail: free(workbuf); - esp_vfs_unregister(base_path); + esp_vfs_fat_unregister_ctx(base_path); free(s_card); s_card = NULL; return err; @@ -117,7 +125,8 @@ esp_err_t esp_vfs_fat_sdmmc_unmount() return ESP_ERR_INVALID_STATE; } // unmount - f_mount(0, "", 0); + char drv[3] = {(char)('0' + s_pdrv), ':', 0}; + f_mount(0, drv, 0); // release SD driver free(s_card); s_card = NULL; From a57b6326e3ffb9e664033eac28ab26078a62b4b5 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 31 Jan 2017 17:43:22 +0200 Subject: [PATCH 2/4] Fix ```if``` breaking the path --- components/fatfs/src/vfs_fat.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 6390fbcf7..e85666f1d 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -250,11 +250,9 @@ static void file_cleanup(vfs_fat_ctx_t* ctx, int fd) } #define vfs_fat_fix_path(ctx, path) \ - if (((vfs_fat_ctx_t*)ctx)->fat_drive[0]) { \ - char buf_ ## path[strlen(path)+strlen(((vfs_fat_ctx_t*)ctx)->fat_drive)+1]; \ - sprintf(buf_ ## path,"%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path); \ - path = (const char *)buf_ ## path; \ - } + char buf_ ## path[strlen(path)+strlen(((vfs_fat_ctx_t*)ctx)->fat_drive)+1]; \ + sprintf(buf_ ## path,"%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path); \ + path = (const char *)buf_ ## path; static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) { From 972c6f0caea1d9ec0bb23693859f8c75e18a5fc1 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 1 Feb 2017 17:55:25 +0200 Subject: [PATCH 3/4] implement review recomendations --- components/fatfs/src/diskio.c | 7 ++-- components/fatfs/src/diskio.h | 14 +++++-- components/fatfs/src/esp_vfs_fat.h | 10 ++++- components/fatfs/src/vfs_fat.c | 56 ++++++++++++++-------------- components/fatfs/src/vfs_fat_sdmmc.c | 29 ++++++++++---- 5 files changed, 72 insertions(+), 44 deletions(-) diff --git a/components/fatfs/src/diskio.c b/components/fatfs/src/diskio.c index 915bb8e2c..c61702f51 100644 --- a/components/fatfs/src/diskio.c +++ b/components/fatfs/src/diskio.c @@ -27,15 +27,16 @@ PARTITION VolToPart[] = { {1, 0} /* Logical drive 1 ==> Physical drive 1, auto detection */ }; -BYTE ff_disk_getpdrv() +esp_err_t ff_diskio_get_drive(BYTE* out_pdrv) { BYTE i; for(i=0; i<_VOLUMES; i++) { if (!s_impls[i]) { - return i; + *out_pdrv = i; + return ESP_OK; } } - return 0xFF; + return ESP_ERR_NOT_FOUND; } void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl) diff --git a/components/fatfs/src/diskio.h b/components/fatfs/src/diskio.h index 2fd27a864..64d5d5b8d 100644 --- a/components/fatfs/src/diskio.h +++ b/components/fatfs/src/diskio.h @@ -58,16 +58,19 @@ typedef struct { } ff_diskio_impl_t; /** - * Register diskio driver for given drive number. + * Register or unregister diskio driver for given drive number. * * When FATFS library calls one of disk_xxx functions for driver number pdrv, * corresponding function in discio_impl for given pdrv will be called. * * @param pdrv drive number - * @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions + * @param discio_impl pointer to ff_diskio_impl_t structure with diskio functions + * or NULL to unregister and free previously registered drive */ void ff_diskio_register(BYTE pdrv, const ff_diskio_impl_t* discio_impl); +#define ff_diskio_unregister(pdrv_) ff_diskio_register(pdrv_, NULL) + /** * Register SD/MMC diskio driver * @@ -79,9 +82,12 @@ void ff_diskio_register_sdmmc(BYTE pdrv, sdmmc_card_t* card); /** * Get next available drive number * - * @return 0xFF on fail, else the drive number + * @param out_pdrv pointer to the byte to set if successful + * + * @return ESP_OK on success + * ESP_ERR_NOT_FOUND if all drives are attached */ -BYTE ff_disk_getpdrv(); +esp_err_t ff_diskio_get_drive(BYTE* out_pdrv); /* Disk Status Bits (DSTATUS) */ diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index 6dbef5cfb..9c39198da 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -51,18 +51,24 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, * @note FATFS structure returned by esp_vfs_fat_register is destroyed after * this call. Make sure to call f_mount function to unmount it before * calling esp_vfs_fat_unregister. + * This function is left for compatibility and will be changed in + * future versions to accept base_path and replace the method below * @return * - ESP_OK on success * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS */ -esp_err_t esp_vfs_fat_unregister(); +esp_err_t esp_vfs_fat_unregister() __attribute__((deprecated)); /** * @brief Un-register FATFS from VFS * * @note FATFS structure returned by esp_vfs_fat_register is destroyed after * this call. Make sure to call f_mount function to unmount it before - * calling esp_vfs_fat_unregister. + * calling esp_vfs_fat_unregister_ctx. + * Difference between this function and the one above is that this one + * will release the correct drive, while the one above will release + * the last registered one + * * @param base_path path prefix where FATFS is registered. This is the same * used when esp_vfs_fat_register was called * @return diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index e85666f1d..10e207482 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -65,12 +65,12 @@ static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode); static int vfs_fat_rmdir(void* ctx, const char* name); static vfs_fat_ctx_t* s_fat_ctxs[_VOLUMES] = { NULL, NULL }; -//compatibility +//backwards-compatibility with esp_vfs_fat_unregister() static vfs_fat_ctx_t* s_fat_ctx = NULL; -static unsigned char esp_vfs_fat_get_ctx(const char* base_path) +static size_t find_context_index_by_path(const char* base_path) { - for(unsigned char i=0; i<_VOLUMES; i++) { + for(size_t i=0; i<_VOLUMES; i++) { if (s_fat_ctxs[i] && !strcmp(s_fat_ctxs[i]->base_path, base_path)) { return i; } @@ -78,9 +78,9 @@ static unsigned char esp_vfs_fat_get_ctx(const char* base_path) return _VOLUMES; } -static unsigned char esp_vfs_fat_get_empty_ctx() +static size_t find_unused_context_index() { - for(unsigned char i=0; i<_VOLUMES; i++) { + for(size_t i=0; i<_VOLUMES; i++) { if (!s_fat_ctxs[i]) { return i; } @@ -90,12 +90,12 @@ static unsigned char esp_vfs_fat_get_empty_ctx() esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, size_t max_files, FATFS** out_fs) { - unsigned char ctx = esp_vfs_fat_get_ctx(base_path); + size_t ctx = find_context_index_by_path(base_path); if (ctx < _VOLUMES) { return ESP_ERR_INVALID_STATE; } - ctx = esp_vfs_fat_get_empty_ctx(); + ctx = find_unused_context_index(); if (ctx == _VOLUMES) { return ESP_ERR_NO_MEM; } @@ -127,12 +127,8 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz return ESP_ERR_NO_MEM; } fat_ctx->max_files = max_files; - - strncpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); - fat_ctx->fat_drive[sizeof(fat_ctx->fat_drive) - 1] = 0; - - strncpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); - fat_ctx->base_path[sizeof(fat_ctx->base_path) - 1] = 0; + strlcpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); + strlcpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx); if (err != ESP_OK) { @@ -153,7 +149,7 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz esp_err_t esp_vfs_fat_unregister_ctx(const char* base_path) { - unsigned char ctx = esp_vfs_fat_get_ctx(base_path); + size_t ctx = find_context_index_by_path(base_path); if (ctx == _VOLUMES) { return ESP_ERR_INVALID_STATE; } @@ -249,14 +245,20 @@ static void file_cleanup(vfs_fat_ctx_t* ctx, int fd) memset(&ctx->files[fd], 0, sizeof(FIL)); } -#define vfs_fat_fix_path(ctx, path) \ - char buf_ ## path[strlen(path)+strlen(((vfs_fat_ctx_t*)ctx)->fat_drive)+1]; \ - sprintf(buf_ ## path,"%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path); \ - path = (const char *)buf_ ## path; +static void prepend_drive_to_path(void * ctx, const char * path, const char * path2){ + static char buf[FILENAME_MAX+3]; + static char buf2[FILENAME_MAX+3]; + sprintf(buf, "%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path); + path = (const char *)buf; + if(path2){ + sprintf(buf2, "%s%s", ((vfs_fat_ctx_t*)ctx)->fat_drive, path2); + path2 = (const char *)buf; + } +} static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) { - vfs_fat_fix_path(ctx, path); + prepend_drive_to_path(ctx, path, NULL); ESP_LOGV(TAG, "%s: path=\"%s\", flags=%x, mode=%x", __func__, path, flags, mode); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; _lock_acquire(&fat_ctx->lock); @@ -366,7 +368,7 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st) static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) { - vfs_fat_fix_path(ctx, path); + prepend_drive_to_path(ctx, path, NULL); FILINFO info; FRESULT res = f_stat(path, &info); if (res != FR_OK) { @@ -396,7 +398,7 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) static int vfs_fat_unlink(void* ctx, const char *path) { - vfs_fat_fix_path(ctx, path); + prepend_drive_to_path(ctx, path, NULL); FRESULT res = f_unlink(path); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -408,8 +410,7 @@ static int vfs_fat_unlink(void* ctx, const char *path) static int vfs_fat_link(void* ctx, const char* n1, const char* n2) { - vfs_fat_fix_path(ctx, n1); - vfs_fat_fix_path(ctx, n2); + prepend_drive_to_path(ctx, n1, n2); const size_t copy_buf_size = 4096; void* buf = malloc(copy_buf_size); if (buf == NULL) { @@ -464,8 +465,7 @@ fail1: static int vfs_fat_rename(void* ctx, const char *src, const char *dst) { - vfs_fat_fix_path(ctx, src); - vfs_fat_fix_path(ctx, dst); + prepend_drive_to_path(ctx, src, dst); FRESULT res = f_rename(src, dst); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -477,7 +477,7 @@ static int vfs_fat_rename(void* ctx, const char *src, const char *dst) static DIR* vfs_fat_opendir(void* ctx, const char* name) { - vfs_fat_fix_path(ctx, name); + prepend_drive_to_path(ctx, name, NULL); vfs_fat_dir_t* fat_dir = calloc(1, sizeof(vfs_fat_dir_t)); if (!fat_dir) { errno = ENOMEM; @@ -582,7 +582,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset) static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) { (void) mode; - vfs_fat_fix_path(ctx, name); + prepend_drive_to_path(ctx, name, NULL); FRESULT res = f_mkdir(name); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -594,7 +594,7 @@ static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) static int vfs_fat_rmdir(void* ctx, const char* name) { - vfs_fat_fix_path(ctx, name); + prepend_drive_to_path(ctx, name, NULL); FRESULT res = f_unlink(name); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index f5e4c5099..16effdce2 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -13,6 +13,7 @@ // limitations under the License. #include +#include #include "esp_log.h" #include "esp_vfs.h" #include "esp_vfs_fat.h" @@ -23,6 +24,7 @@ static const char* TAG = "vfs_fat_sdmmc"; static sdmmc_card_t* s_card = NULL; static uint8_t s_pdrv = 0; +static char * s_base_path = NULL; esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, const sdmmc_host_t* host_config, @@ -36,6 +38,20 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, if (s_card != NULL) { return ESP_ERR_INVALID_STATE; } + + // connect SDMMC driver to FATFS + BYTE pdrv = 0xFF; + if (ff_diskio_get_drive(&pdrv) != ESP_OK || pdrv == 0xFF) { + ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); + return ESP_ERR_NO_MEM; + } + + s_base_path = strdup(base_path); + if(!s_base_path){ + ESP_LOGD(TAG, "could not copy base_path"); + return ESP_ERR_NO_MEM; + } + // enable SDMMC sdmmc_host_init(); @@ -56,12 +72,6 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, *out_card = s_card; } - // connect SDMMC driver to FATFS - BYTE pdrv = ff_disk_getpdrv(); - if (pdrv == 0xFF) { - ESP_LOGD(TAG, "the maximum count of volumes is already mounted"); - goto fail; - } ff_diskio_register_sdmmc(pdrv, s_card); s_pdrv = pdrv; char drv[3] = {(char)('0' + pdrv), ':', 0}; @@ -114,6 +124,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, fail: free(workbuf); esp_vfs_fat_unregister_ctx(base_path); + ff_diskio_unregister(pdrv); free(s_card); s_card = NULL; return err; @@ -128,8 +139,12 @@ esp_err_t esp_vfs_fat_sdmmc_unmount() char drv[3] = {(char)('0' + s_pdrv), ':', 0}; f_mount(0, drv, 0); // release SD driver + ff_diskio_unregister(s_pdrv); free(s_card); s_card = NULL; sdmmc_host_deinit(); - return esp_vfs_fat_unregister(); + esp_err_t err = esp_vfs_fat_unregister_ctx(s_base_path); + free(s_base_path); + s_base_path = NULL; + return err; } From 0eeda99a8cac1634b4a279549bf6d3f7833eb315 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 2 Feb 2017 12:24:38 +0200 Subject: [PATCH 4/4] pick better name for unregister function and update docs --- components/fatfs/src/esp_vfs_fat.h | 2 +- components/fatfs/src/vfs_fat.c | 4 ++-- components/fatfs/src/vfs_fat_sdmmc.c | 4 ++-- docs/api/storage/fatfs.rst | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/fatfs/src/esp_vfs_fat.h b/components/fatfs/src/esp_vfs_fat.h index 9c39198da..4e27dce69 100644 --- a/components/fatfs/src/esp_vfs_fat.h +++ b/components/fatfs/src/esp_vfs_fat.h @@ -75,7 +75,7 @@ esp_err_t esp_vfs_fat_unregister() __attribute__((deprecated)); * - ESP_OK on success * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS */ -esp_err_t esp_vfs_fat_unregister_ctx(const char* base_path); +esp_err_t esp_vfs_fat_unregister_path(const char* base_path); /** * @brief Configuration arguments for esp_vfs_fat_sdmmc_mount function diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 10e207482..ecc3b1102 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -147,7 +147,7 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz return ESP_OK; } -esp_err_t esp_vfs_fat_unregister_ctx(const char* base_path) +esp_err_t esp_vfs_fat_unregister_path(const char* base_path) { size_t ctx = find_context_index_by_path(base_path); if (ctx == _VOLUMES) { @@ -169,7 +169,7 @@ esp_err_t esp_vfs_fat_unregister() if (s_fat_ctx == NULL) { return ESP_ERR_INVALID_STATE; } - esp_err_t err = esp_vfs_fat_unregister_ctx(s_fat_ctx->base_path); + esp_err_t err = esp_vfs_fat_unregister_path(s_fat_ctx->base_path); if (err != ESP_OK) { return err; } diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index 16effdce2..ea6093633 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -123,7 +123,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, fail: free(workbuf); - esp_vfs_fat_unregister_ctx(base_path); + esp_vfs_fat_unregister_path(base_path); ff_diskio_unregister(pdrv); free(s_card); s_card = NULL; @@ -143,7 +143,7 @@ esp_err_t esp_vfs_fat_sdmmc_unmount() free(s_card); s_card = NULL; sdmmc_host_deinit(); - esp_err_t err = esp_vfs_fat_unregister_ctx(s_base_path); + esp_err_t err = esp_vfs_fat_unregister_path(s_base_path); free(s_base_path); s_base_path = NULL; return err; diff --git a/docs/api/storage/fatfs.rst b/docs/api/storage/fatfs.rst index d2efc87ab..6dd04ae3e 100644 --- a/docs/api/storage/fatfs.rst +++ b/docs/api/storage/fatfs.rst @@ -8,7 +8,7 @@ Additionally, FatFs has been modified to support run-time pluggable disk IO laye Using FatFs with VFS -------------------- -``esp_vfs_fat.h`` header file defines functions to connect FatFs with VFS. ``esp_vfs_fat_register`` function allocates a ``FATFS`` structure, and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs. ``esp_vfs_fat_unregister`` function deletes the registration with VFS, and frees the ``FATFS`` structure. +``esp_vfs_fat.h`` header file defines functions to connect FatFs with VFS. ``esp_vfs_fat_register`` function allocates a ``FATFS`` structure, and registers a given path prefix in VFS. Subsequent operations on files starting with this prefix are forwarded to FatFs APIs. ``esp_vfs_fat_unregister_path`` function deletes the registration with VFS, and frees the ``FATFS`` structure. Most applications will use the following flow when working with ``esp_vfs_fat_`` functions: @@ -28,12 +28,12 @@ Most applications will use the following flow when working with ``esp_vfs_fat_`` 8. Call ``ff_diskio_register`` with NULL ``ff_diskio_impl_t*`` argument and the same drive number. -9. Call ``esp_vfs_fat_unregister`` to remove FatFs from VFS, and free the ``FATFS`` structure allocated on step 1. +9. Call ``esp_vfs_fat_unregister_path`` with the path where the file system is mounted to remove FatFs from VFS, and free the ``FATFS`` structure allocated on step 1. Convenience functions, ``esp_vfs_fat_sdmmc_mount`` and ``esp_vfs_fat_sdmmc_unmount``, which wrap these steps and also handle SD card initialization, are described in the next section. .. doxygenfunction:: esp_vfs_fat_register -.. doxygenfunction:: esp_vfs_fat_unregister +.. doxygenfunction:: esp_vfs_fat_unregister_path Using FatFs with VFS and SD cards