mynewt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ccoll...@apache.org
Subject [05/19] incubator-mynewt-core git commit: Save multi-disk support WIP
Date Thu, 19 Jan 2017 17:36:16 GMT
Save multi-disk support WIP


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/1a029621
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/1a029621
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/1a029621

Branch: refs/heads/develop
Commit: 1a029621576f068a361d322d9dfb789a7f34d54d
Parents: 0845466
Author: Fabio Utzig <utzig@utzig.org>
Authored: Wed Dec 14 16:39:52 2016 -0200
Committer: Fabio Utzig <utzig@utzig.org>
Committed: Thu Jan 12 10:51:46 2017 -0200

----------------------------------------------------------------------
 fs/fatfs/src/mynewt_glue.c                |  24 +-
 fs/fatfs/src/mynewt_glue_2.c              | 410 +++++++++++++++++++++++++
 fs/fs/include/fs/fs_if.h                  |  21 +-
 fs/fs/src/fs_dirent.c                     |  15 +-
 fs/fs/src/fs_file.c                       |  62 +++-
 fs/fs/src/fs_mkdir.c                      |   6 +-
 fs/fs/src/fs_mount.c                      |  32 +-
 fs/fs/src/fs_priv.h                       |   3 +-
 hw/bsp/stm32f4discovery/include/bsp/bsp.h |   2 +-
 hw/drivers/mmc/include/mmc/mmc.h          |   3 +
 hw/drivers/mmc/src/mmc.c                  |  17 +
 hw/hal/include/hal/hal_flash.h            |   5 +-
 hw/hal/src/hal_flash.c                    |  14 +
 sys/diskio/include/diskio/diskio.h        |  51 +++
 sys/diskio/pkg.yml                        |  27 ++
 sys/diskio/src/diskio.c                   |  57 ++++
 16 files changed, 721 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fatfs/src/mynewt_glue.c
----------------------------------------------------------------------
diff --git a/fs/fatfs/src/mynewt_glue.c b/fs/fatfs/src/mynewt_glue.c
index 0f45cfb..f2382f8 100644
--- a/fs/fatfs/src/mynewt_glue.c
+++ b/fs/fatfs/src/mynewt_glue.c
@@ -1,6 +1,7 @@
 #include <assert.h>
 #include <sysinit/sysinit.h>
 #include <hal/hal_flash.h>
+#include <mmc/mmc.h>
 #include <flash_map/flash_map.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -348,17 +349,29 @@ disk_status(BYTE pdrv)
     return RES_OK;
 }
 
+static struct disk_ops *disk_ops_from_handle(BYTE pdrv)
+{
+    return &mmc_ops;
+}
+
 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;
-    rc = hal_flash_read(pdrv, address, (void *) buff, num_bytes);
+
+    dops = disk_ops_from_handle(pdrv);
+    if (dops == NULL) {
+        return STA_NOINIT;
+    }
+
+    rc = dops->read(pdrv, address, (void *) buff, num_bytes);
     if (rc < 0) {
         return STA_NOINIT;
     }
@@ -372,11 +385,18 @@ 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;
-    rc = hal_flash_write(pdrv, address, (const void *) buff, num_bytes);
+
+    dops = disk_ops_from_handle(pdrv);
+    if (dops == NULL) {
+        return STA_NOINIT;
+    }
+
+    rc = dops->write(pdrv, address, (const void *) buff, num_bytes);
     if (rc < 0) {
         return STA_NOINIT;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fatfs/src/mynewt_glue_2.c
----------------------------------------------------------------------
diff --git a/fs/fatfs/src/mynewt_glue_2.c b/fs/fatfs/src/mynewt_glue_2.c
new file mode 100644
index 0000000..8be7265
--- /dev/null
+++ b/fs/fatfs/src/mynewt_glue_2.c
@@ -0,0 +1,410 @@
+#include <assert.h>
+#include <sysinit/sysinit.h>
+#include <hal/hal_flash.h>
+#include <flash_map/flash_map.h>
+#include <mmc/mmc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fatfs/ff.h>
+#include <fatfs/diskio.h>
+
+#include <fs/fs.h>
+#include <fs/fs_if.h>
+
+static int fatfs_open(const char *path, uint8_t access_flags,
+  struct fs_file **out_file);
+static int fatfs_close(struct fs_file *fs_file);
+static int fatfs_read(struct fs_file *fs_file, uint32_t len, void *out_data,
+  uint32_t *out_len);
+static int fatfs_write(struct fs_file *fs_file, const void *data, int len);
+static int fatfs_seek(struct fs_file *fs_file, uint32_t offset);
+static uint32_t fatfs_getpos(const struct fs_file *fs_file);
+static int fatfs_file_len(const struct fs_file *fs_file, uint32_t *out_len);
+static int fatfs_unlink(const char *path);
+static int fatfs_rename(const char *from, const char *to);
+static int fatfs_mkdir(const char *path);
+static int fatfs_opendir(const char *path, struct fs_dir **out_fs_dir);
+static int fatfs_readdir(struct fs_dir *dir, struct fs_dirent **out_dirent);
+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);
+
+/* 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 FILINFO filinfo;
+
+static const struct fs_ops fatfs_ops = {
+    .f_open = fatfs_open,
+    .f_close = fatfs_close,
+    .f_read = fatfs_read,
+    .f_write = fatfs_write,
+
+    .f_seek = fatfs_seek,
+    .f_getpos = fatfs_getpos,
+    .f_filelen = fatfs_file_len,
+
+    .f_unlink = fatfs_unlink,
+    .f_rename = fatfs_rename,
+    .f_mkdir = fatfs_mkdir,
+
+    .f_opendir = fatfs_opendir,
+    .f_readdir = fatfs_readdir,
+    .f_closedir = fatfs_closedir,
+
+    .f_dirent_name = fatfs_dirent_name,
+    .f_dirent_is_dir = fatfs_dirent_is_dir,
+
+    .f_name = "fatfs"
+};
+
+int fatfs_to_vfs_error(FRESULT res)
+{
+    int rc = FS_EOS;
+
+    switch (res) {
+    case FR_OK:
+        rc = FS_EOK;
+        break;
+    case FR_DISK_ERR:              /* (1) A hard error occurred in the low level disk I/O
layer */
+        rc = FS_EHW;
+        break;
+    case FR_INT_ERR:               /* (2) Assertion failed */
+        rc = FS_EOS;
+        break;
+    case FR_NOT_READY:             /* (3) The physical drive cannot work */
+        rc = FS_ECORRUPT;
+        break;
+    case FR_NO_FILE:               /* (4) Could not find the file */
+        /* passthrough */
+    case FR_NO_PATH:               /* (5) Could not find the path */
+        rc = FS_ENOENT;
+        break;
+    case FR_INVALID_NAME:          /* (6) The path name format is invalid */
+        rc = FS_EINVAL;
+        break;
+    case FR_DENIED:                /* (7) Access denied due to prohibited access or directory
full */
+        rc = FS_EACCESS;
+        break;
+    case FR_EXIST:                 /* (8) Access denied due to prohibited access */
+        rc = FS_EEXIST;
+        break;
+    case FR_INVALID_OBJECT:        /* (9) The file/directory object is invalid */
+        rc = FS_EINVAL;
+        break;
+    case FR_WRITE_PROTECTED:       /* (10) The physical drive is write protected */
+        /* TODO: assign correct error */
+        break;
+    case FR_INVALID_DRIVE:         /* (11) The logical drive number is invalid */
+        rc = FS_EHW;
+        break;
+    case FR_NOT_ENABLED:           /* (12) The volume has no work area */
+        rc = FS_EUNEXP;
+        break;
+    case FR_NO_FILESYSTEM:         /* (13) There is no valid FAT volume */
+        rc = FS_EUNINIT;
+        break;
+    case FR_MKFS_ABORTED:          /* (14) The f_mkfs() aborted due to any problem */
+        /* TODO: assign correct error */
+        break;
+    case FR_TIMEOUT:               /* (15) Could not get a grant to access the volume within
defined period */
+        /* TODO: assign correct error */
+        break;
+    case FR_LOCKED:                /* (16) The operation is rejected according to the file
sharing policy */
+        /* TODO: assign correct error */
+        break;
+    case FR_NOT_ENOUGH_CORE:       /* (17) LFN working buffer could not be allocated */
+        rc = FS_ENOMEM;
+        break;
+    case FR_TOO_MANY_OPEN_FILES:   /* (18) Number of open files > _FS_LOCK */
+        /* TODO: assign correct error */
+        break;
+    case FR_INVALID_PARAMETER:     /* (19) Given parameter is invalid */
+        rc = FS_EINVAL;
+        break;
+    }
+
+    return rc;
+}
+
+static int
+fatfs_open(const char *path, uint8_t access_flags, struct fs_file **out_fs_file)
+{
+    FRESULT res;
+    FIL *out_file;
+    BYTE mode;
+
+    out_file = malloc(sizeof(FIL));
+    if (!out_file) {
+        return FS_ENOMEM;
+    }
+
+    mode = FA_OPEN_EXISTING;
+    if (access_flags & FS_ACCESS_READ) {
+        mode |= FA_READ;
+    }
+    if (access_flags & FS_ACCESS_WRITE) {
+        mode |= FA_WRITE;
+    }
+    if (access_flags & FS_ACCESS_APPEND) {
+        mode |= FA_OPEN_APPEND;
+    }
+    if (access_flags & FS_ACCESS_TRUNCATE) {
+        mode &= ~FA_OPEN_EXISTING;
+        mode |= FA_CREATE_ALWAYS;
+    }
+
+    res = f_open(out_file, path, mode);
+    if (res != FR_OK) {
+        free(out_file);
+        return fatfs_to_vfs_error(res);
+    }
+    *out_fs_file = (struct fs_file *)out_file;
+    return FS_EOK;
+}
+
+static int
+fatfs_close(struct fs_file *fs_file)
+{
+    FRESULT res;
+    FIL *file = (FIL *)fs_file;
+
+    if (file == NULL) {
+        return FS_EOK;
+    }
+
+    res = f_close(file);
+    free(file);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_seek(struct fs_file *fs_file, uint32_t offset)
+{
+    FRESULT res;
+    FIL *file = (FIL *)fs_file;
+
+    res = f_lseek(file, offset);
+    return fatfs_to_vfs_error(res);
+}
+
+static uint32_t
+fatfs_getpos(const struct fs_file *fs_file)
+{
+    uint32_t offset;
+    FIL *file = (FIL *)fs_file;
+
+    offset = (uint32_t) f_tell(file);
+    return offset;
+}
+
+static int
+fatfs_file_len(const struct fs_file *fs_file, uint32_t *out_len)
+{
+    uint32_t offset;
+    FIL *file = (FIL *)fs_file;
+
+    offset = (uint32_t) f_size(file);
+    return offset;
+}
+
+static int
+fatfs_read(struct fs_file *fs_file, uint32_t len, void *out_data,
+           uint32_t *out_len)
+{
+    FRESULT res;
+    FIL *file = (FIL *)fs_file;
+
+    res = f_read(file, out_data, len, (UINT *)out_len);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_write(struct fs_file *fs_file, const void *data, int len)
+{
+    FRESULT res;
+    UINT out_len;
+    FIL *file = (FIL *)fs_file;
+
+    res = f_write(file, data, len, &out_len);
+    if (len != out_len) {
+        return FS_EFULL;
+    }
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_unlink(const char *path)
+{
+    FRESULT res;
+
+    res = f_unlink(path);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_rename(const char *from, const char *to)
+{
+    FRESULT res;
+
+    res = f_rename(from, to);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_mkdir(const char *path)
+{
+    FRESULT res;
+
+    res = f_mkdir(path);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_opendir(const char *path, struct fs_dir **out_fs_dir)
+{
+    FRESULT res;
+    FATFS_DIR *out_dir;
+
+    out_dir = malloc(sizeof(FATFS_DIR));
+    if (!out_dir) {
+        return FS_ENOMEM;
+    }
+
+    res = f_opendir(out_dir, path);
+    if (res != FR_OK) {
+        return fatfs_to_vfs_error(res);
+    }
+    *out_fs_dir = (struct fs_dir *)out_dir;
+    return FS_EOK;
+}
+
+static int
+fatfs_readdir(struct fs_dir *fs_dir, struct fs_dirent **out_fs_dirent)
+{
+    FRESULT res;
+    FATFS_DIR *dir = (FATFS_DIR *)fs_dir;
+
+    res = f_readdir(dir, &filinfo);
+    if (res != FR_OK) {
+        return fatfs_to_vfs_error(res);
+    }
+
+    *out_fs_dirent = (struct fs_dirent *)&filinfo;
+    if (!filinfo.fname[0]) {
+        return FS_ENOENT;
+    }
+    return FS_EOK;
+}
+
+static int
+fatfs_closedir(struct fs_dir *fs_dir)
+{
+    FRESULT res;
+    FATFS_DIR *dir = (FATFS_DIR *)fs_dir;
+
+    res = f_closedir(dir);
+    free(dir);
+    return fatfs_to_vfs_error(res);
+}
+
+static int
+fatfs_dirent_name(const struct fs_dirent *fs_dirent, size_t max_len,
+                  char *out_name, uint8_t *out_name_len)
+{
+    const FILINFO *dirent = (const FILINFO *)fs_dirent;
+    size_t out_len;
+
+    assert(dirent != NULL);
+    out_len = max_len < sizeof(dirent->fname) ? max_len : sizeof(dirent->fname);
+    memcpy(out_name, dirent->fname, out_len);
+    *out_name_len = out_len;
+    return FS_EOK;
+}
+
+static int
+fatfs_dirent_is_dir(const struct fs_dirent *fs_dirent)
+{
+    const FILINFO *dirent = (const FILINFO *)fs_dirent;
+
+    assert(dirent != NULL);
+    return dirent->fattrib & AM_DIR;
+}
+
+DSTATUS
+disk_initialize(BYTE pdrv)
+{
+    /* Don't need to do anything while using hal_flash */
+    return RES_OK;
+}
+
+DSTATUS
+disk_status(BYTE pdrv)
+{
+    /* Always OK on native emulated flash */
+    return RES_OK;
+}
+
+DRESULT
+disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count)
+{
+    int rc;
+    uint32_t address;
+    uint32_t num_bytes;
+
+    /* NOTE: safe to assume sector size as 512 for now, see ffconf.h */
+    address = (uint32_t) sector * 512;
+    num_bytes = (uint32_t) count * 512;
+    //rc = hal_flash_read(pdrv, address, (void *) buff, num_bytes);
+    rc = mmc_read(pdrv, address, (void *) buff, num_bytes);
+    if (rc < 0) {
+        return STA_NOINIT;
+    }
+
+    return RES_OK;
+}
+
+DRESULT
+disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count)
+{
+    int rc;
+    uint32_t address;
+    uint32_t num_bytes;
+
+    /* NOTE: safe to assume sector size as 512 for now, see ffconf.h */
+    address = (uint32_t) sector * 512;
+    num_bytes = (uint32_t) count * 512;
+    //rc = hal_flash_write(pdrv, address, (const void *) buff, num_bytes);
+    rc = mmc_write(pdrv, address, (const void *) buff, num_bytes);
+    if (rc < 0) {
+        return STA_NOINIT;
+    }
+
+    return RES_OK;
+}
+
+DRESULT
+disk_ioctl(BYTE pdrv, BYTE cmd, void* buff)
+{
+    return RES_OK;
+}
+
+/* FIXME: _FS_NORTC=1 because there is not hal_rtc interface */
+DWORD
+get_fattime(void)
+{
+    return 0;
+}
+
+void
+fatfs_pkg_init(void)
+{
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    fs_register(&fatfs_ops);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/include/fs/fs_if.h
----------------------------------------------------------------------
diff --git a/fs/fs/include/fs/fs_if.h b/fs/fs/include/fs/fs_if.h
index 5d71f1b..842f070 100644
--- a/fs/fs/include/fs/fs_if.h
+++ b/fs/fs/include/fs/fs_if.h
@@ -52,12 +52,27 @@ struct fs_ops {
     int (*f_dirent_is_dir)(const struct fs_dirent *dirent);
 
     const char *f_name;
+
+    SLIST_ENTRY(fs_ops) sc_next;
 };
 
-/*
- * Currently allow only one type of FS, starts at root.
+/**
+ * Registers a new filesystem interface
+ *
+ * @param fops filesystem operations table
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int fs_register(const struct fs_ops *fops);
+
+/**
+ * Retrieve a filesystem's operations table
+ *
+ * @param name Name of the filesystem to retrieve fs_ops for
+ *
+ * @return valid pointer on success, NULL on failure
  */
-int fs_register(const struct fs_ops *);
+struct fs_ops *fs_ops_for(const char *name);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/src/fs_dirent.c
----------------------------------------------------------------------
diff --git a/fs/fs/src/fs_dirent.c b/fs/fs/src/fs_dirent.c
index bc526f2..b5fd6c5 100644
--- a/fs/fs/src/fs_dirent.c
+++ b/fs/fs/src/fs_dirent.c
@@ -23,30 +23,35 @@
 int
 fs_opendir(const char *path, struct fs_dir **out_dir)
 {
-    return fs_root_ops->f_opendir(path, out_dir);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_opendir(path, out_dir);
 }
 
 int
 fs_readdir(struct fs_dir *dir, struct fs_dirent **out_dirent)
 {
-    return fs_root_ops->f_readdir(dir, out_dirent);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_readdir(dir, out_dirent);
 }
 
 int
 fs_closedir(struct fs_dir *dir)
 {
-    return fs_root_ops->f_closedir(dir);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_closedir(dir);
 }
 
 int
 fs_dirent_name(const struct fs_dirent *dirent, size_t max_len,
   char *out_name, uint8_t *out_name_len)
 {
-    return fs_root_ops->f_dirent_name(dirent, max_len, out_name, out_name_len);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_dirent_name(dirent, max_len, out_name, out_name_len);
 }
 
 int
 fs_dirent_is_dir(const struct fs_dirent *dirent)
 {
-    return fs_root_ops->f_dirent_is_dir(dirent);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_dirent_is_dir(dirent);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/src/fs_file.c
----------------------------------------------------------------------
diff --git a/fs/fs/src/fs_file.c b/fs/fs/src/fs_file.c
index fcc2e2c..fdcecda 100644
--- a/fs/fs/src/fs_file.c
+++ b/fs/fs/src/fs_file.c
@@ -21,50 +21,96 @@
 
 #include "fs_priv.h"
 
+static int
+not_initialized(const void *v, ...)
+{
+    return FS_EUNINIT;
+}
+
+static struct fs_ops not_initialized_ops = {
+    .f_open          = not_initialized,
+    .f_close         = not_initialized,
+    .f_read          = not_initialized,
+    .f_write         = not_initialized,
+    .f_seek          = not_initialized,
+    .f_getpos        = not_initialized,
+    .f_filelen       = not_initialized,
+    .f_unlink        = not_initialized,
+    .f_rename        = not_initialized,
+    .f_mkdir         = not_initialized,
+    .f_opendir       = not_initialized,
+    .f_readdir       = not_initialized,
+    .f_closedir      = not_initialized,
+    .f_dirent_name   = not_initialized,
+    .f_dirent_is_dir = not_initialized,
+    .f_name          = "fakefs",
+};
+
+struct fs_ops *
+safe_fs_ops_for(const char *fs_name)
+{
+    struct fs_ops *fops;
+
+    fops = fs_ops_for("fatfs");
+    if (fops == NULL) {
+        fops = &not_initialized_ops;
+    }
+
+    return fops;
+}
+
 int
 fs_open(const char *filename, uint8_t access_flags, struct fs_file **out_file)
 {
-    return fs_root_ops->f_open(filename, access_flags, out_file);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_open(filename, access_flags, out_file);
 }
 
 int
 fs_close(struct fs_file *file)
 {
-    return fs_root_ops->f_close(file);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_close(file);
 }
 
 int
 fs_read(struct fs_file *file, uint32_t len, void *out_data, uint32_t *out_len)
 {
-    return fs_root_ops->f_read(file, len, out_data, out_len);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_read(file, len, out_data, out_len);
 }
 
 int
 fs_write(struct fs_file *file, const void *data, int len)
 {
-    return fs_root_ops->f_write(file, data, len);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_write(file, data, len);
 }
 
 int
 fs_seek(struct fs_file *file, uint32_t offset)
 {
-    return fs_root_ops->f_seek(file, offset);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_seek(file, offset);
 }
 
 uint32_t
 fs_getpos(const struct fs_file *file)
 {
-    return fs_root_ops->f_getpos(file);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_getpos(file);
 }
 
 int
 fs_filelen(const struct fs_file *file, uint32_t *out_len)
 {
-    return fs_root_ops->f_filelen(file, out_len);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_filelen(file, out_len);
 }
 
 int
 fs_unlink(const char *filename)
 {
-    return fs_root_ops->f_unlink(filename);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_unlink(filename);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/src/fs_mkdir.c
----------------------------------------------------------------------
diff --git a/fs/fs/src/fs_mkdir.c b/fs/fs/src/fs_mkdir.c
index 2072229..546736f 100644
--- a/fs/fs/src/fs_mkdir.c
+++ b/fs/fs/src/fs_mkdir.c
@@ -24,11 +24,13 @@
 int
 fs_rename(const char *from, const char *to)
 {
-    return fs_root_ops->f_rename(from, to);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_rename(from, to);
 }
 
 int
 fs_mkdir(const char *path)
 {
-    return fs_root_ops->f_mkdir(path);
+    struct fs_ops *fops = safe_fs_ops_for("fatfs");
+    return fops->f_mkdir(path);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/src/fs_mount.c
----------------------------------------------------------------------
diff --git a/fs/fs/src/fs_mount.c b/fs/fs/src/fs_mount.c
index 9645d1a..174fac8 100644
--- a/fs/fs/src/fs_mount.c
+++ b/fs/fs/src/fs_mount.c
@@ -22,19 +22,41 @@
 #include "fs/fs_if.h"
 #include "fs_priv.h"
 
-const struct fs_ops *fs_root_ops = NULL;
+static SLIST_HEAD(, fs_ops) root_fops = SLIST_HEAD_INITIALIZER();
+static bool g_cli_initialized = false;
 
 int
 fs_register(const struct fs_ops *fops)
 {
-    if (fs_root_ops) {
-        return FS_EEXIST;
+    SLIST_FOREACH(sc, &root_fops, sc_next) {
+        if (strcmp(sc->f_name, fops->f_name) == 0) {
+            return FS_EEXIST;
+        }
     }
-    fs_root_ops = fops;
+
+    SLIST_INSERT_HEAD(&root_fops, fops, sc_next);
 
 #if MYNEWT_VAL(FS_CLI)
-    fs_cli_init();
+    if (!g_cli_initialized) {
+        fs_cli_init();
+        g_cli_initialized = true;
+    }
 #endif
 
     return FS_EOK;
 }
+
+struct fs_ops *
+fs_ops_for(const char *fs_name)
+{
+    struct fs_ops *fops = NULL;
+
+    SLIST_FOREACH(sc, &root_fops, sc_next) {
+        if (strcmp(sc->f_name, fs_name) == 0) {
+            fops = sc;
+            break;
+        }
+    }
+
+    return fops;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/fs/fs/src/fs_priv.h
----------------------------------------------------------------------
diff --git a/fs/fs/src/fs_priv.h b/fs/fs/src/fs_priv.h
index 5733733..d9cbd2d 100644
--- a/fs/fs/src/fs_priv.h
+++ b/fs/fs/src/fs_priv.h
@@ -26,7 +26,8 @@ extern "C" {
 #endif
 
 struct fs_ops;
-extern const struct fs_ops *fs_root_ops;
+struct fs_ops *fs_ops_for(const char *fs_name);
+struct fs_ops *safe_fs_ops_for(const char *fs_name);
 
 #if MYNEWT_VAL(FS_CLI)
 void fs_cli_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/hw/bsp/stm32f4discovery/include/bsp/bsp.h
----------------------------------------------------------------------
diff --git a/hw/bsp/stm32f4discovery/include/bsp/bsp.h b/hw/bsp/stm32f4discovery/include/bsp/bsp.h
index dd038e9..ca8a92c 100644
--- a/hw/bsp/stm32f4discovery/include/bsp/bsp.h
+++ b/hw/bsp/stm32f4discovery/include/bsp/bsp.h
@@ -41,7 +41,7 @@ extern uint8_t _ccram_start;
 #define CCRAM_SIZE      (64 * 1024)
 
 /* LED pins */
-#define LED_BLINK_PIN   MCU_GPIO_PORTD(12)
+#define LED_BLINK_PIN   MCU_GPIO_PORTD(13)
 
 /* UART */
 #define UART_CNT 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/hw/drivers/mmc/include/mmc/mmc.h
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/include/mmc/mmc.h b/hw/drivers/mmc/include/mmc/mmc.h
index d65363d..a13b682 100644
--- a/hw/drivers/mmc/include/mmc/mmc.h
+++ b/hw/drivers/mmc/include/mmc/mmc.h
@@ -21,6 +21,7 @@
 #define __MMC_H__
 
 #include <os/os_dev.h>
+#include <diskio/diskio.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -43,6 +44,8 @@ extern "C" {
 #define MMC_ERASE_ERROR       (-11)
 #define MMC_ADDR_ERROR        (-12)
 
+extern struct disk_ops mmc_ops;
+
 /**
  * Initialize the MMC driver
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/hw/drivers/mmc/src/mmc.c
----------------------------------------------------------------------
diff --git a/hw/drivers/mmc/src/mmc.c b/hw/drivers/mmc/src/mmc.c
index ca89434..0b2aa98 100644
--- a/hw/drivers/mmc/src/mmc.c
+++ b/hw/drivers/mmc/src/mmc.c
@@ -583,3 +583,20 @@ out:
     hal_gpio_write(mmc->ss_pin, 1);
     return (rc);
 }
+
+/*
+ *
+ */
+int mmc_ioctl(int cmd, void *arg)
+{
+    return 0;
+}
+
+/*
+ *
+ */
+struct disk_ops mmc_ops = {
+    .read  = mmc_read,
+    .write = mmc_write,
+    .ioctl = mmc_ioctl,
+};

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/hw/hal/include/hal/hal_flash.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_flash.h b/hw/hal/include/hal/hal_flash.h
index 2895479..1fdc91e 100644
--- a/hw/hal/include/hal/hal_flash.h
+++ b/hw/hal/include/hal/hal_flash.h
@@ -25,7 +25,11 @@ extern "C" {
 #endif
 
 #include <inttypes.h>
+#include <diskio/diskio.h>
 
+extern struct disk_ops hal_flash_ops;
+
+int hal_flash_ioctl(uint8_t flash_id, uint32_t cmd, void *args);
 int hal_flash_read(uint8_t flash_id, uint32_t address, void *dst,
   uint32_t num_bytes);
 int hal_flash_write(uint8_t flash_id, uint32_t address, const void *src,
@@ -35,7 +39,6 @@ int hal_flash_erase(uint8_t flash_id, uint32_t address, uint32_t num_bytes);
 uint8_t hal_flash_align(uint8_t flash_id);
 int hal_flash_init(void);
 
-
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/hw/hal/src/hal_flash.c
----------------------------------------------------------------------
diff --git a/hw/hal/src/hal_flash.c b/hw/hal/src/hal_flash.c
index ba51f8a..a95b57b 100644
--- a/hw/hal/src/hal_flash.c
+++ b/hw/hal/src/hal_flash.c
@@ -24,6 +24,8 @@
 #include "hal/hal_flash.h"
 #include "hal/hal_flash_int.h"
 
+#include <diskio/diskio.h>
+
 int
 hal_flash_init(void)
 {
@@ -167,3 +169,15 @@ hal_flash_erase(uint8_t id, uint32_t address, uint32_t num_bytes)
     }
     return 0;
 }
+
+int
+hal_flash_ioctl(uint8_t id, uint32_t cmd, void *args)
+{
+    return 0;
+}
+
+static struct disk_ops hal_flash_ops = {
+    .read  = hal_flash_read,
+    .write = hal_flash_write,
+    .ioctl = hal_flash_ioctl,
+};

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/sys/diskio/include/diskio/diskio.h
----------------------------------------------------------------------
diff --git a/sys/diskio/include/diskio/diskio.h b/sys/diskio/include/diskio/diskio.h
new file mode 100644
index 0000000..a0a68f6
--- /dev/null
+++ b/sys/diskio/include/diskio/diskio.h
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __DISKIO_H__
+#define __DISKIO_H__
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DISKIO_EOK          0  /* Success */
+#define DISKIO_EHW          1  /* Error accessing storage medium */
+#define DISKIO_ENOMEM       2  /* Insufficient memory */
+#define DISKIO_ENOENT       3  /* No such file or directory */
+#define DISKIO_EOS          4  /* OS error */
+#define DISKIO_EUNINIT      5  /* File system not initialized */
+
+struct disk_ops {
+    int (*read)(int, uint32_t, void *, uint32_t);
+    int (*write)(int, uint32_t, const void *, uint32_t);
+    int (*ioctl)(int, uint32_t, const void *);
+
+    SLIST_ENTRY(disk_ops) sc_next;
+};
+
+int diskio_register(const char *disk_name, const char *fs_name, struct disk_ops *dops);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/sys/diskio/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/diskio/pkg.yml b/sys/diskio/pkg.yml
new file mode 100644
index 0000000..8981937
--- /dev/null
+++ b/sys/diskio/pkg.yml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: sys/diskio
+pkg.description: Disk IO layer to glue filesystems to disk devices.
+pkg.author: "Apache Mynewt <dev@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - kernel/os

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1a029621/sys/diskio/src/diskio.c
----------------------------------------------------------------------
diff --git a/sys/diskio/src/diskio.c b/sys/diskio/src/diskio.c
new file mode 100644
index 0000000..e74eae3
--- /dev/null
+++ b/sys/diskio/src/diskio.c
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "syscfg/syscfg.h"
+#include "fs/fs.h"
+#include <diskio/diskio.h>
+
+static struct disk_info {
+    char *disk_name;
+    char *fs_name;
+    struct disk_ops *dops;
+};
+
+static SLIST_HEAD(, disk_info) disks = SLIST_HEAD_INITIALIZER();
+
+/**
+ *
+ */
+int diskio_register(const char *disk_name, const char *fs_name, struct disk_ops *dops)
+{
+    struct disk_info *info = NULL;
+
+    SLIST_FOREACH(sc, &disks, sc_next) {
+        if (strcmp(sc->disk_name, disk_name) == 0) {
+            return DISKIO_EEXIST;
+        }
+    }
+
+    info = malloc(sizeof(struct disk_info));
+    if (!info) {
+        return DISKIO_ENOMEM;
+    }
+
+    info.disk_name = disk_name;
+    info.fs_name = fs_name;
+    info.dops = dops;
+
+    SLIST_INSERT_HEAD(&disks, info, sc_next);
+
+    return 0;
+}


Mime
View raw message