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 d0a74e3097ad30171b7d3a1454955db7d087b3aa
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Sat Jun 21 10:33:03 2025 +0200

    fs/disks: Rework disk interface
    
    Disk interface tightly coupled to file system
    and could not be used for exposing disk to something
    else then code in fs/fs.
    
    With this change new disk_listener interface allows
    code to be informed about disks being inserted
    and removed.
    
    Listeners in turn can mount file systems from disk
    or for example expose disk to USB host via MSC.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 fs/disk/include/disk/disk.h | 204 +++++++++++++++++++++++++++++++++++++++++---
 fs/disk/pkg.yml             |   5 +-
 fs/disk/src/disk.c          | 141 +++++-------------------------
 3 files changed, 219 insertions(+), 131 deletions(-)

diff --git a/fs/disk/include/disk/disk.h b/fs/disk/include/disk/disk.h
index cf2849629..514e6f330 100644
--- a/fs/disk/include/disk/disk.h
+++ b/fs/disk/include/disk/disk.h
@@ -22,7 +22,8 @@
 
 #include <stddef.h>
 #include <inttypes.h>
-#include "os/mynewt.h"
+#include <os/mynewt.h>
+#include <os/link_tables.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,19 +36,200 @@ extern "C" {
 #define DISK_EOS          4  /* OS error */
 #define DISK_EUNINIT      5  /* File system not initialized */
 
-struct disk_ops {
-    int (*read)(uint8_t, uint32_t, void *, uint32_t);
-    int (*write)(uint8_t, uint32_t, const void *, uint32_t);
-    int (*ioctl)(uint8_t, uint32_t, void *);
+typedef struct disk disk_t;
+typedef struct disk_info disk_info_t;
+typedef struct disk_listener disk_listener_t;
 
-    SLIST_ENTRY(disk_ops) sc_next;
+/**
+ * Disk information
+ */
+struct disk_info {
+    /* Disk name (information only) */
+    const char *name;
+    /* Disk block (sector) count */
+    uint32_t block_count;
+    /* Block size (usually 512) */
+    uint16_t block_size;
+    /* Set to 1 if disk is present */
+    uint16_t present : 1;
+};
+
+typedef struct disk_ops {
+    /** Get basic information about disk
+     *
+     * @param disk - disk to query
+     * @param info - disk information to fill
+     * @return 0 on success, SYS_EINVAL if arguments are incorrect
+     */
+    int (*get_info)(const struct disk *disk, struct disk_info *info);
+
+    /**
+     * Inform driver that disk was just removed
+     * @param disk - disk that was ejected
+     * @return 0 on success, SYS_EINVAL if arguments are incorrect
+     */
+    int (*eject)(struct disk *disk);
+    /**
+     * Read disk block
+     * @param disk - dist to read from
+     * @param lba - block to read
+     * @param buf - buffer for data
+     * @param block_count - number for blocks to read
+     * @return 0 on success
+     */
+    int (*read)(struct disk *disk, uint32_t lba, void *buf, uint32_t 
block_count);
+    /**
+     * Write disk block
+     * @param disk - dist to write to
+     * @param lba - block to write to
+     * @param buf - data buffer
+     * @param block_count - number of blocks to write
+     * @return 0 on success
+     */
+    int (*write)(struct disk *disk, uint32_t lba, const void *buf, uint32_t 
block_count);
+} disk_ops_t;
+
+/* Disk listener operations */
+typedef struct disk_listener_ops {
+    /* New disk was inserted to driver and could be mounter */
+    int (*disk_added)(struct disk_listener *listener, struct disk *disk);
+    /* Disk was ejected and should be unmounted */
+    int (*disk_removed)(struct disk_listener *listener, struct disk *disk);
+} disk_listener_ops_t;
+
+/* Disk listener */
+struct disk_listener {
+    const disk_listener_ops_t *ops;
 };
 
-int disk_register(const char *disk_name, const char *fs_name, struct disk_ops 
*dops);
-struct disk_ops *disk_ops_for(const char *disk_name);
-char *disk_fs_for(const char *disk_name);
-char *disk_name_from_path(const char *path);
-char *disk_filepath_from_path(const char *path);
+/* Base for disks */
+struct disk {
+    const disk_ops_t *ops;
+};
+
+/**
+ * Function called when disk was inserted into a driver
+ * and system could mount it or otherwise be aware that new
+ * disk could be used
+ *
+ * @param disk - disk that was inserted
+ *
+ * @return 0 - for success
+ */
+int mn_disk_inserted(disk_t *disk);
+
+/**
+ * Function called when disk was removed, if disk was
+ * mounted it file system can be unmounted. If disk
+ * was present to MSC it can no longer be advertised
+ * as present.
+ *
+ * @param disk - disk that was remove from driver
+ *
+ * @return 0 -for success
+ */
+int mn_disk_ejected(disk_t *disk);
+
+/**
+ * Function return 1 if disk is present
+ *
+ * @param disk - disk to check for presence
+ * @return 1 - disk is present, 0 - disk is not present
+ */
+static inline int
+disk_present(disk_t *disk)
+{
+    disk_info_t di;
+    disk->ops->get_info(disk, &di);
+
+    return di.present;
+}
+
+/**
+ * Get disk information
+ * Disk information consist of size information
+ *
+ * @param disk - disk to get information from
+ * @param di - pointer to data to received disk information
+ *
+ * @return 0 - for success
+ */
+static inline int
+mn_disk_info_get(disk_t *disk, disk_info_t *di)
+{
+    return disk->ops->get_info(disk, di);
+}
+
+/**
+ * Read sector(s) from disk
+ *
+ * @param disk - disk to read data from
+ * @param lba - sector number
+ * @param buf - buffer to be filled with data from disk
+ * @param block_count - number of sectors to read
+ * @return 0 - for success
+ */
+static inline int
+mn_disk_read(disk_t *disk, uint32_t lba, void *buf, uint32_t block_count)
+{
+    return disk->ops->read(disk, lba, buf, block_count);
+}
+
+/**
+ * Write sector(s) to disk
+ *
+ * @param disk - disk to write to
+ * @param lba - first sector to write to
+ * @param buf - buffer with data
+ * @param block_count - number of sectors to write
+ * @return 0 - for success
+ */
+static inline int
+mn_disk_write(disk_t *disk, uint32_t lba, const void *buf, uint32_t 
block_count)
+{
+    return disk->ops->write(disk, lba, buf, block_count);
+}
+
+/**
+ * Eject disk
+ *
+ * Calling this function will result in calling disk listeners about
+ * disk being removed via disk_removed(). This may result in file
+ * system being unmounted.
+ *
+ * @param disk - disk to eject
+ * @return 0 - for success
+ */
+static inline int
+mn_disk_eject(disk_t *disk)
+{
+    return disk->ops->eject(disk);
+}
+
+/**
+ * Link time table to hold all available disk listeners
+ * that will be informed when disk is available and
+ * can be mounted or used in other ways.
+ */
+LINK_TABLE(disk_listener_t *, disk_listeners)
+
+/**
+ * @brief Macros to put disk_listener in link table
+ *
+ * i.e.
+ * // Define disk_listener_t structure
+ * disk_listener_t mounter = {
+ *    .opt = &mounter_ops,
+ * };
+ *
+ * DISK_LISTENER(mounter_entry, mounter)
+ *
+ * @param listener_entry - new pointer variable name that will be put in
+ *                         disk_listeners table
+ * @param listener - object of type disk_listener_t
+ */
+#define DISK_LISTENER(listener_entry, listener)                               \
+    LINK_TABLE_ELEMENT(disk_listeners, listener_entry) = &listener;
 
 #ifdef __cplusplus
 }
diff --git a/fs/disk/pkg.yml b/fs/disk/pkg.yml
index 52a0f7f11..1157f15e9 100644
--- a/fs/disk/pkg.yml
+++ b/fs/disk/pkg.yml
@@ -18,10 +18,13 @@
 #
 
 pkg.name: fs/disk
-pkg.description: Disk management layer to glue filesystems to disk devices.
+pkg.description: Disk management layer to disk devices.
 pkg.author: "Apache Mynewt <[email protected]>"
 pkg.homepage: "http://mynewt.apache.org/";
 pkg.keywords:
 
 pkg.deps:
     - "@apache-mynewt-core/kernel/os"
+
+pkg.link_tables:
+    - disk_listeners
diff --git a/fs/disk/src/disk.c b/fs/disk/src/disk.c
index 93a2741fd..d84ca22b4 100644
--- a/fs/disk/src/disk.c
+++ b/fs/disk/src/disk.c
@@ -17,135 +17,38 @@
  * under the License.
  */
 
-#include <stdlib.h>
-#include <string.h>
-#include "os/mynewt.h"
+#include <inttypes.h>
+#include <os/mynewt.h>
+#include <os/link_tables.h>
 #include <disk/disk.h>
 
-struct disk_info {
-    const char *disk_name;
-    const char *fs_name;
-    struct disk_ops *dops;
+#define DISK_EOK     0 /* Success */
+#define DISK_EHW     1 /* Error accessing storage medium */
+#define DISK_ENOMEM  2 /* Insufficient memory */
+#define DISK_ENOENT  3 /* No such file or directory */
+#define DISK_EOS     4 /* OS error */
+#define DISK_EUNINIT 5 /* File system not initialized */
 
-    SLIST_ENTRY(disk_info) sc_next;
-};
-
-static SLIST_HEAD(, disk_info) disks = SLIST_HEAD_INITIALIZER();
-
-/**
- *
- */
-int disk_register(const char *disk_name, const char *fs_name, struct disk_ops 
*dops)
+int
+mn_disk_inserted(disk_t *disk)
 {
-    struct disk_info *info = NULL;
-    struct disk_info *sc;
-
-    SLIST_FOREACH(sc, &disks, sc_next) {
-        if (strcmp(sc->disk_name, disk_name) == 0) {
-            return DISK_ENOENT;
-        }
-    }
+    int count = LINK_TABLE_SIZE(disk_listeners);
 
-    info = malloc(sizeof(struct disk_info));
-    if (!info) {
-        return DISK_ENOMEM;
+    for (int i = 0; i < count; ++i) {
+        disk_listener_t *listener = disk_listeners[i];
+        listener->ops->disk_added(listener, disk);
     }
-
-    info->disk_name = disk_name;
-    info->fs_name = fs_name;
-    info->dops = dops;
-
-    SLIST_INSERT_HEAD(&disks, info, sc_next);
-
     return 0;
 }
 
-struct disk_ops *
-disk_ops_for(const char *disk_name)
+int
+mn_disk_ejected(disk_t *disk)
 {
-    struct disk_info *sc;
+    int count = LINK_TABLE_SIZE(disk_listeners);
 
-    if (disk_name) {
-        SLIST_FOREACH(sc, &disks, sc_next) {
-            if (strcmp(sc->disk_name, disk_name) == 0) {
-                return sc->dops;
-            }
-        }
+    for (int i = 0; i < count; ++i) {
+        disk_listener_t *listener = disk_listeners[i];
+        listener->ops->disk_removed(listener, disk);
     }
-
-    return NULL;
-}
-
-char *
-disk_fs_for(const char *disk_name)
-{
-    struct disk_info *sc;
-
-    if (disk_name) {
-        SLIST_FOREACH(sc, &disks, sc_next) {
-            if (strcmp(sc->disk_name, disk_name) == 0) {
-                return ((char *) sc->fs_name);
-            }
-        }
-    }
-
-    return NULL;
-}
-
-char *
-disk_name_from_path(const char *path)
-{
-    char *colon;
-    uint8_t len;
-    char *disk;
-
-    colon = (char *) path;
-    while (*colon && *colon != ':') {
-        colon++;
-    }
-
-    if (*colon != ':') {
-        return NULL;
-    }
-
-    len = colon - path;
-    disk = malloc(len + 1);
-    if (!disk) {
-        return NULL;
-    }
-    memcpy(disk, path, len);
-    disk[len] = '\0';
-
-    return disk;
-}
-
-/**
- * @brief Returns the path with the disk prefix removed (if found)
- *
- * Paths should be given in the form disk<number>:/path. This routine
- * will parse and return only the path, removing the disk information.
- */
-char *
-disk_filepath_from_path(const char *path)
-{
-    char *colon;
-    char *filepath;
-    size_t len;
-
-    colon = (char *) path;
-    while (*colon && *colon != ':') {
-        colon++;
-    }
-
-    if (*colon != ':') {
-        filepath = strdup(path);
-    } else {
-        colon++;
-        len = strlen(colon);
-        filepath = malloc(len + 1);
-        memcpy(filepath, colon, len);
-        filepath[len] = '\0';
-    }
-
-    return filepath;
+    return 0;
 }

Reply via email to