This is an automated email from the ASF dual-hosted git repository.

kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 9470a663cfc96f670fab8dd264b4aac87fd0f46e
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Sat Jun 21 22:30:17 2025 +0200

    fs/fatfs: Rework to use file system api
    
    This adds file disk listener that can mount fatfs
    disk (like sdcard) if it contains FAT data.
    
    Fixes problem with accessing disk grater then 2GB.
    Previous disk interface (that is now removed) used
    32 bit to address bytes of disk.
    Now disk access uses sectors as it the code for disk.
    
    Further more file name conversion from sd0: to 0: is
    now removed. FATFS driver wants to use 0: volumes
    and mynewt wanted to have sd0:
    Now disk will be mounted as 0: removing need for
    conversion and heap allocations.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 fs/fatfs/pkg.yml           |   8 +-
 fs/fatfs/src/mynewt_glue.c | 415 ++++++++++++++++++++-------------------------
 fs/fatfs/syscfg.yml        |   6 +
 3 files changed, 190 insertions(+), 239 deletions(-)

diff --git a/fs/fatfs/pkg.yml b/fs/fatfs/pkg.yml
index 01cef770d..6b389f60f 100644
--- a/fs/fatfs/pkg.yml
+++ b/fs/fatfs/pkg.yml
@@ -30,11 +30,11 @@ pkg.deps:
     - "@apache-mynewt-core/util/crc"
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
-    - "@apache-mynewt-core/test/testutil"
-    - "@apache-mynewt-core/sys/flash_map"
 pkg.req_apis:
     - log
     - stats
 
-pkg.init:
-    fatfs_pkg_init: 'MYNEWT_VAL(FATFS_SYSINIT_STAGE)'
+pkg.whole_archive: true
+
+pkg.cflags:
+    - -Wno-unused-variable
diff --git a/fs/fatfs/src/mynewt_glue.c b/fs/fatfs/src/mynewt_glue.c
index 0fbefeb47..ebaa4d697 100644
--- a/fs/fatfs/src/mynewt_glue.c
+++ b/fs/fatfs/src/mynewt_glue.c
@@ -22,11 +22,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "os/mynewt.h"
+#include <os/mynewt.h>
 #include <modlog/modlog.h>
-#include <hal/hal_flash.h>
 #include <disk/disk.h>
-#include <flash_map/flash_map.h>
 
 #include <fatfs/ff.h>
 #include <fatfs/diskio.h>
@@ -53,17 +51,12 @@ static int fatfs_closedir(struct fs_dir *dir);
 static int fatfs_dirent_name(const struct fs_dirent *fs_dirent, size_t max_len,
   char *out_name, uint8_t *out_name_len);
 static int fatfs_dirent_is_dir(const struct fs_dirent *fs_dirent);
-
-#define DRIVE_LEN 4
+static int fatfs_mount(const file_system_t *fs);
+static int fatfs_umount(const file_system_t *fs);
 
 struct fatfs_file {
     struct fs_ops *fops;
-    FIL *file;
-};
-
-struct fatfs_dir {
-    struct fs_ops *fops;
-    FATFS_DIR *dir;
+    FIL fil;
 };
 
 struct fatfs_dirent {
@@ -71,11 +64,10 @@ struct fatfs_dirent {
     FILINFO filinfo;
 };
 
-/* NOTE: to ease memory management of dirent structs, this single static
- * variable holds the latest entry found by readdir. This limits FAT to
- * working on a single thread, single opendir -> closedir cycle.
- */
-static struct fatfs_dirent dirent;
+struct fatfs_dir {
+    struct fatfs_dirent dirent;
+    FATFS_DIR dir;
+};
 
 static struct fs_ops fatfs_ops = {
     .f_open = fatfs_open,
@@ -99,9 +91,19 @@ static struct fs_ops fatfs_ops = {
     .f_dirent_name = fatfs_dirent_name,
     .f_dirent_is_dir = fatfs_dirent_is_dir,
 
-    .f_name = "fatfs"
+    .f_mount = fatfs_mount,
+    .f_umount = fatfs_umount,
 };
 
+typedef struct fat_disk {
+    file_system_t fs;
+    char vol[4];
+    FATFS fatfs;
+    disk_t *disk;
+} fat_disk_t;
+
+static fat_disk_t *fat_vol[_VOLUMES];
+
 int fatfs_to_vfs_error(FRESULT res)
 {
     int rc = FS_EOS;
@@ -171,112 +173,22 @@ int fatfs_to_vfs_error(FRESULT res)
     return rc;
 }
 
-struct mounted_disk {
-    char *disk_name;
-    int disk_number;
-    struct disk_ops *dops;
-
-    SLIST_ENTRY(mounted_disk) sc_next;
-};
-
-static SLIST_HEAD(, mounted_disk) mounted_disks = SLIST_HEAD_INITIALIZER();
-
-static int
-drivenumber_from_disk(char *disk_name)
-{
-    struct mounted_disk *sc;
-    struct mounted_disk *new_disk;
-    int disk_number;
-    FATFS *fs;
-    char path[6];
-
-    disk_number = 0;
-    if (disk_name) {
-        SLIST_FOREACH(sc, &mounted_disks, sc_next) {
-            if (strcmp(sc->disk_name, disk_name) == 0) {
-                return sc->disk_number;
-            }
-            disk_number++;
-        }
-    }
-
-    /* XXX: check for errors? */
-    fs = malloc(sizeof(FATFS));
-    sprintf(path, "%d:", (uint8_t)disk_number);
-    f_mount(fs, path, 1);
-
-    /* FIXME */
-    new_disk = malloc(sizeof(struct mounted_disk));
-    new_disk->disk_name = strdup(disk_name);
-    new_disk->disk_number = disk_number;
-    new_disk->dops = disk_ops_for(disk_name);
-    SLIST_INSERT_HEAD(&mounted_disks, new_disk, sc_next);
-
-    return disk_number;
-}
-
-/**
- * Converts fs path to fatfs path
- *
- * Function changes mmc0:/dir/file.ext to 0:/dir/file.ext
- *
- * @param fs_path
- * @return pointer to allocated memory with fatfs path
- */
-static char *
-fatfs_path_from_fs_path(const char *fs_path)
-{
-    char *disk;
-    int drive_number;
-    char *file_path = NULL;
-    char *fatfs_path = NULL;
-
-    disk = disk_name_from_path(fs_path);
-    if (disk == NULL) {
-        goto err;
-    }
-    drive_number = drivenumber_from_disk(disk);
-    free(disk);
-    file_path = disk_filepath_from_path(fs_path);
-
-    if (file_path == NULL) {
-        goto err;
-    }
-
-    fatfs_path = malloc(strlen(file_path) + 3);
-    if (fatfs_path == NULL) {
-        goto err;
-    }
-    sprintf(fatfs_path, "%d:%s", drive_number, file_path);
-err:
-    free(file_path);
-    return fatfs_path;
-}
-
 static int
 fatfs_open(const char *path, uint8_t access_flags, struct fs_file 
**out_fs_file)
 {
     FRESULT res;
-    FIL *out_file = NULL;
     BYTE mode;
     struct fatfs_file *file = NULL;
-    char *fatfs_path = NULL;
     int rc;
 
     FATFS_LOG_DEBUG("Open file %s", path);
 
-    file = malloc(sizeof(struct fatfs_file));
+    file = os_malloc(sizeof(struct fatfs_file));
     if (!file) {
         rc = FS_ENOMEM;
         goto out;
     }
 
-    out_file = malloc(sizeof(FIL));
-    if (!out_file) {
-        rc = FS_ENOMEM;
-        goto out;
-    }
-
     mode = FA_OPEN_EXISTING;
     if (access_flags & FS_ACCESS_READ) {
         mode |= FA_READ;
@@ -292,29 +204,21 @@ fatfs_open(const char *path, uint8_t access_flags, struct 
fs_file **out_fs_file)
         mode |= FA_CREATE_ALWAYS;
     }
 
-    fatfs_path = fatfs_path_from_fs_path(path);
-    if (fatfs_path == NULL) {
-        rc = FS_ENOMEM;
-        goto out;
-    }
-    res = f_open(out_file, fatfs_path, mode);
+    res = f_open(&file->fil, path, mode);
     if (res != FR_OK) {
         rc = fatfs_to_vfs_error(res);
         goto out;
     }
 
-    file->file = out_file;
     file->fops = &fatfs_ops;
     *out_fs_file = (struct fs_file *) file;
     rc = FS_EOK;
 
 out:
-    free(fatfs_path);
     if (rc != FS_EOK) {
         FATFS_LOG_ERROR("File %s open failed %d", path, rc);
 
         if (file) free(file);
-        if (out_file) free(out_file);
     } else {
         FATFS_LOG_DEBUG("File %s opened %p", path, *out_fs_file);
     }
@@ -324,15 +228,12 @@ out:
 static int
 fatfs_close(struct fs_file *fs_file)
 {
-    FRESULT res = FR_OK;
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    struct fatfs_file *fat_file = (struct fatfs_file *)fs_file;
+    FRESULT res;
 
-    FATFS_LOG_DEBUG("Open file %p", fs_file);
+    FATFS_LOG_DEBUG("Close file %p", fs_file);
 
-    if (file != NULL) {
-        res = f_close(file);
-        free(file);
-    }
+    res = f_close(&fat_file->fil);
 
     free(fs_file);
     return fatfs_to_vfs_error(res);
@@ -342,7 +243,7 @@ static int
 fatfs_seek(struct fs_file *fs_file, uint32_t offset)
 {
     FRESULT res;
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
 
     FATFS_LOG_DEBUG("File %p seek %u", fs_file, offset);
 
@@ -354,7 +255,7 @@ static uint32_t
 fatfs_getpos(const struct fs_file *fs_file)
 {
     uint32_t offset;
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
 
     offset = (uint32_t) f_tell(file);
     return offset;
@@ -363,7 +264,7 @@ fatfs_getpos(const struct fs_file *fs_file)
 static int
 fatfs_file_len(const struct fs_file *fs_file, uint32_t *out_len)
 {
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
 
     *out_len = (uint32_t) f_size(file);
 
@@ -377,7 +278,7 @@ fatfs_read(struct fs_file *fs_file, uint32_t len, void 
*out_data,
            uint32_t *out_len)
 {
     FRESULT res;
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
     UINT uint_len;
 
     FATFS_LOG_DEBUG("File %p read %u", fs_file, len);
@@ -392,7 +293,7 @@ fatfs_write(struct fs_file *fs_file, const void *data, int 
len)
 {
     FRESULT res;
     UINT out_len;
-    FIL *file = ((struct fatfs_file *) fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
 
     FATFS_LOG_DEBUG("File %p write %u", fs_file, len);
 
@@ -407,7 +308,7 @@ static int
 fatfs_flush(struct fs_file *fs_file)
 {
     FRESULT res;
-    FIL *file = ((struct fatfs_file *)fs_file)->file;
+    FIL *file = &((struct fatfs_file *)fs_file)->fil;
 
     FATFS_LOG_DEBUG("Flush %p", fs_file);
 
@@ -420,17 +321,10 @@ static int
 fatfs_unlink(const char *path)
 {
     FRESULT res;
-    char *fatfs_path;
 
     FATFS_LOG_INFO("Unlink %s", path);
 
-    fatfs_path = fatfs_path_from_fs_path(path);
-
-    if (fatfs_path == NULL) {
-        return FS_ENOMEM;
-    }
-    res = f_unlink(fatfs_path);
-    free(fatfs_path);
+    res = f_unlink(path);
 
     return fatfs_to_vfs_error(res);
 }
@@ -439,23 +333,10 @@ static int
 fatfs_rename(const char *from, const char *to)
 {
     FRESULT res;
-    char *fatfs_src_path;
-    char *fatfs_dst_path;
 
     FATFS_LOG_INFO("Rename %s to %s", from, to);
 
-    fatfs_src_path = fatfs_path_from_fs_path(from);
-    fatfs_dst_path = fatfs_path_from_fs_path(to);
-
-    if (fatfs_src_path == NULL || fatfs_dst_path == NULL) {
-        free(fatfs_src_path);
-        free(fatfs_dst_path);
-        return FS_ENOMEM;
-    }
-
-    res = f_rename(fatfs_src_path, fatfs_dst_path);
-    free(fatfs_src_path);
-    free(fatfs_dst_path);
+    res = f_rename(from, to);
 
     return fatfs_to_vfs_error(res);
 }
@@ -464,17 +345,10 @@ static int
 fatfs_mkdir(const char *path)
 {
     FRESULT res;
-    char *fatfs_path;
 
     FATFS_LOG_INFO("Mkdir %s", path);
 
-    fatfs_path = fatfs_path_from_fs_path(path);
-
-    if (fatfs_path == NULL) {
-        return FS_ENOMEM;
-    }
-
-    res = f_mkdir(fatfs_path);
+    res = f_mkdir(path);
     return fatfs_to_vfs_error(res);
 }
 
@@ -482,45 +356,34 @@ static int
 fatfs_opendir(const char *path, struct fs_dir **out_fs_dir)
 {
     FRESULT res;
-    FATFS_DIR *out_dir = NULL;
     struct fatfs_dir *dir = NULL;
-    char *fatfs_path = NULL;
     int rc;
 
-    dir = malloc(sizeof(struct fatfs_dir));
+    dir = os_malloc(sizeof(struct fatfs_dir));
     if (!dir) {
         rc = FS_ENOMEM;
         goto out;
     }
+    dir->dirent.fops = &fatfs_ops;
 
-    out_dir = malloc(sizeof(FATFS_DIR));
-    if (!out_dir) {
-        rc = FS_ENOMEM;
-        goto out;
-    }
-
-    fatfs_path = fatfs_path_from_fs_path(path);
-
-    res = f_opendir(out_dir, fatfs_path);
+    res = f_opendir(&dir->dir, path);
     if (res != FR_OK) {
         rc = fatfs_to_vfs_error(res);
         goto out;
     }
 
-    dir->dir = out_dir;
-    dir->fops = &fatfs_ops;
     *out_fs_dir = (struct fs_dir *)dir;
     rc = FS_EOK;
 
     FATFS_LOG_INFO("Open dir %s -> %p", path, *out_fs_dir);
 
 out:
-    free(fatfs_path);
     if (rc != FS_EOK) {
         FATFS_LOG_ERROR("Open dir %s failed %d", path, rc);
 
-        if (dir) free(dir);
-        if (out_dir) free(out_dir);
+        if (dir) {
+            os_free(dir);
+        }
     }
     return rc;
 }
@@ -529,18 +392,18 @@ static int
 fatfs_readdir(struct fs_dir *fs_dir, struct fs_dirent **out_fs_dirent)
 {
     FRESULT res;
-    FATFS_DIR *dir = ((struct fatfs_dir *) fs_dir)->dir;
+    struct fatfs_dir *fat_dir = ((struct fatfs_dir *)fs_dir);
+    FATFS_DIR *dir = &fat_dir->dir;
 
     FATFS_LOG_DEBUG("Read dir %p", fs_dir);
 
-    dirent.fops = &fatfs_ops;
-    res = f_readdir(dir, &dirent.filinfo);
+    res = f_readdir(dir, &fat_dir->dirent.filinfo);
     if (res != FR_OK) {
         return fatfs_to_vfs_error(res);
     }
 
-    *out_fs_dirent = (struct fs_dirent *) &dirent;
-    if (!dirent.filinfo.fname[0]) {
+    *out_fs_dirent = (struct fs_dirent *)&fat_dir->dirent;
+    if (!fat_dir->dirent.filinfo.fname[0]) {
         return FS_ENOENT;
     }
     return FS_EOK;
@@ -550,13 +413,13 @@ static int
 fatfs_closedir(struct fs_dir *fs_dir)
 {
     FRESULT res;
-    FATFS_DIR *dir = ((struct fatfs_dir *) fs_dir)->dir;
+    FATFS_DIR *dir = &((struct fatfs_dir *)fs_dir)->dir;
 
     FATFS_LOG_INFO("Close dir %p", fs_dir);
 
     res = f_closedir(dir);
-    free(dir);
-    free(fs_dir);
+
+    os_free(fs_dir);
     return fatfs_to_vfs_error(res);
 }
 
@@ -585,6 +448,30 @@ fatfs_dirent_is_dir(const struct fs_dirent *fs_dirent)
     return filinfo->fattrib & AM_DIR;
 }
 
+static int
+fatfs_mount(const file_system_t *fs)
+{
+    int rc;
+    fat_disk_t *fat_disk = (fat_disk_t *)fs;
+
+    /* Pass to FAT driver */
+    rc = f_mount(&fat_disk->fatfs, fat_disk->vol, 0);
+
+    return rc;
+}
+
+static int
+fatfs_umount(const file_system_t *fs)
+{
+    int rc;
+    fat_disk_t *fat_disk = (fat_disk_t *)fs;
+
+    /* Pass to FAT driver */
+    rc = f_mount(NULL, fat_disk->vol, 0);
+
+    return rc;
+}
+
 DSTATUS
 disk_initialize(BYTE pdrv)
 {
@@ -599,67 +486,40 @@ disk_status(BYTE pdrv)
     return RES_OK;
 }
 
-static struct disk_ops *dops_from_handle(BYTE pdrv)
-{
-    struct mounted_disk *sc;
-
-    SLIST_FOREACH(sc, &mounted_disks, sc_next) {
-        if (sc->disk_number == pdrv) {
-            return sc->dops;
-        }
-    }
-
-    return NULL;
-}
-
 DRESULT
 disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count)
 {
     int rc;
-    uint32_t address;
-    uint32_t num_bytes;
-    struct disk_ops *dops;
-
-    /* NOTE: safe to assume sector size as 512 for now, see ffconf.h */
-    address = (uint32_t) sector * 512;
-    num_bytes = (uint32_t) count * 512;
-
-    dops = dops_from_handle(pdrv);
-    if (dops == NULL) {
-        return STA_NOINIT;
-    }
+    struct fat_disk *fat_disk = fat_vol[pdrv];
 
-    rc = dops->read(pdrv, address, (void *) buff, num_bytes);
-    if (rc < 0) {
-        return STA_NOINIT;
+    if (fat_disk != NULL) {
+        rc = mn_disk_read(fat_disk->disk, sector, buff, count);
+        if (rc != 0) {
+            rc = FR_NOT_READY;
+        }
+    } else {
+        rc = FR_NOT_READY;
     }
 
-    return RES_OK;
+    return rc;
 }
 
 DRESULT
 disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)
 {
     int rc;
-    uint32_t address;
-    uint32_t num_bytes;
-    struct disk_ops *dops;
-
-    /* NOTE: safe to assume sector size as 512 for now, see ffconf.h */
-    address = (uint32_t) sector * 512;
-    num_bytes = (uint32_t) count * 512;
-
-    dops = dops_from_handle(pdrv);
-    if (dops == NULL) {
-        return STA_NOINIT;
-    }
+    struct fat_disk *fat_disk = fat_vol[pdrv];
 
-    rc = dops->write(pdrv, address, (const void *) buff, num_bytes);
-    if (rc < 0) {
-        return STA_NOINIT;
+    if (fat_disk != NULL) {
+        rc = mn_disk_write(fat_disk->disk, sector, buff, count);
+        if (rc != 0) {
+            rc = FR_NOT_READY;
+        }
+    } else {
+        rc = FR_NOT_READY;
     }
 
-    return RES_OK;
+    return rc;
 }
 
 DRESULT
@@ -742,11 +602,96 @@ ff_wtoupper(WCHAR chr)
     return toupper(chr);
 }
 
-void
-fatfs_pkg_init(void)
+#if MYNEWT_VAL_FATFS_AUTO_MOUNT_DISKS
+int
+fatfs_disk_added(struct disk_listener *listener, struct disk *disk)
 {
-    /* Ensure this function only gets called by sysinit. */
-    SYSINIT_ASSERT_ACTIVE();
+    fat_disk_t *fat_disk;
+    int i;
+    int rc;
+
+    for (i = 0; i < _VOLUMES; ++i) {
+        if (fat_vol[i] == NULL) {
+            break;
+        }
+    }
+    if (i >= _VOLUMES) {
+        fat_disk = NULL;
+        FATFS_LOG_ERROR("Can mount additional volumes");
+        goto end;
+    }
+    fat_disk = os_malloc(sizeof(*fat_disk));
+
+    if (fat_disk == NULL) {
+        FATFS_LOG_ERROR("No enough heap for FAT file system");
+        goto end;
+    }
+
+    if (mn_disk_read(disk, 0, fat_disk->fatfs.win, 1) == 0) {
+        disk_info_t di;
+        uint8_t fs_type = fat_disk->fatfs.win[450];
+        mn_disk_info_get(disk, &di);
+
+        /* Check if first partition is FAT */
+        if (fs_type == 0x0C || fs_type == 0x0B || (_FS_EXFAT && fs_type == 
0x07)) {
+            fat_disk->disk = disk;
+            fat_disk->fs.ops = &fatfs_ops;
+            fat_disk->fs.name = "fatfs";
+            fat_disk->vol[0] = '0' + i;
+            fat_disk->vol[1] = ':';
+            fat_disk->vol[2] = '\0';
+
+            /* Associate in mynewt */
+            rc = fs_mount(&fat_disk->fs, fat_disk->vol);
+            if (rc != 0) {
+                FATFS_LOG_ERROR("Can't mount FAT file system");
+            } else {
+                fat_vol[i] = fat_disk;
+                /* Disk successfully mounted, prevent from being freed */
+                FATFS_LOG_INFO("Mounted FAT partition from %s at %s", di.name,
+                               fat_disk->vol);
+                fat_disk = NULL;
+            }
+        } else {
+            FATFS_LOG_INFO("Disk %s not with FAT file system", di.name);
+        }
+    }
+end:
+    if (fat_disk) {
+        os_free(fat_disk);
+    }
+    return 0;
+}
 
-    fs_register(&fatfs_ops);
+int
+fatfs_disk_removed(struct disk_listener *listener, struct disk *disk)
+{
+    int i;
+    int rc = FS_EINVAL;
+    struct fat_disk *fat_disk;
+
+    for (i = 0; i < _VOLUMES; ++i) {
+        fat_disk = fat_vol[i];
+        if (fat_disk->disk == disk) {
+            fs_unmount_file_system(&fat_disk->fs);
+            fat_vol[i] = NULL;
+            os_free(fat_disk);
+            rc = 0;
+            break;
+        }
+    }
+    return rc;
 }
+
+const disk_listener_ops_t fatfs_disk_listener_ops = {
+    .disk_added = fatfs_disk_added,
+    .disk_removed = fatfs_disk_removed,
+};
+
+disk_listener_t fatfs_disk_listener = {
+    .ops = &fatfs_disk_listener_ops,
+};
+
+DISK_LISTENER(fatfs_disk_listener_ptr, fatfs_disk_listener)
+
+#endif
diff --git a/fs/fatfs/syscfg.yml b/fs/fatfs/syscfg.yml
index 66035279b..93c85f947 100644
--- a/fs/fatfs/syscfg.yml
+++ b/fs/fatfs/syscfg.yml
@@ -48,6 +48,12 @@ syscfg.defs:
             Timout for locking file system object.
         value: 1000
 
+    FATFS_AUTO_MOUNT_DISKS:
+        description: >
+            If 1 package tries to read every disks that is inserted
+            and if it's FAT disk, mounts it automatically.
+        value: 1
+
     FATFS_LOG_MODULE:
         description: 'Numeric module ID to use for FATFS log messages.'
         value: 253

Reply via email to