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

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

commit 3ea5f71fb72c37f7b51739f98b88dd792a59ed46
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Wed May 29 15:53:30 2024 +0200

    tinyusb/msc_fat_view: Add write support for config.txt
    
    Code allows to write back configuration.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 hw/usb/tinyusb/msc_fat_view/src/entry_config.c | 185 ++++++++++++++++++++++++-
 1 file changed, 181 insertions(+), 4 deletions(-)

diff --git a/hw/usb/tinyusb/msc_fat_view/src/entry_config.c 
b/hw/usb/tinyusb/msc_fat_view/src/entry_config.c
index be7f25a20..91f1be0ea 100644
--- a/hw/usb/tinyusb/msc_fat_view/src/entry_config.c
+++ b/hw/usb/tinyusb/msc_fat_view/src/entry_config.c
@@ -18,6 +18,7 @@
  */
 
 #include <stdint.h>
+#include <ctype.h>
 #include <stream/stream.h>
 #include <msc_fat_view/msc_fat_view.h>
 #include <modlog/modlog.h>
@@ -26,9 +27,13 @@
 
 struct config_export_stream {
     struct out_stream out_stream;
+    /* Buffer to write to (can be NULL) */
     uint8_t *buffer;
+    /* Stream start offset, writes to stream preceding this will be dropped */
     uint32_t buffer_start_offset;
+    /* Stream end offset, writes to stream after this will be dropped */
     uint16_t buffer_end_offset;
+    /* Current stream write offset */
     uint32_t write_offset;
 };
 
@@ -73,6 +78,7 @@ config_text_export(char *name, char *val)
 {
     int name_len = strlen(name);
     int val_len = 0;
+
     if (val) {
         val_len = strlen(val);
     }
@@ -84,6 +90,17 @@ config_text_export(char *name, char *val)
     ostream_write(&export_stream.out_stream, (const uint8_t *)"\n", 1, false);
 }
 
+static const char *const CONFIG_BEGIN = "#### Config begin ####\n";
+static const char *const CONFIG_END = "##### Config end #####\n";
+
+void
+config_txt_render_file(struct out_stream *stream)
+{
+    ostream_write_str(&export_stream.out_stream, CONFIG_BEGIN);
+    conf_export(config_text_export, CONF_EXPORT_SHOW);
+    ostream_write_str(&export_stream.out_stream, CONFIG_END);
+}
+
 static uint32_t
 config_txt_size(const file_entry_t *file_entry)
 {
@@ -92,7 +109,7 @@ config_txt_size(const file_entry_t *file_entry)
     export_stream.buffer_end_offset = 0;
     export_stream.write_offset = 0;
 
-    conf_export(config_text_export, CONF_EXPORT_SHOW);
+    config_txt_render_file(&export_stream.out_stream);
 
     return export_stream.write_offset;
 }
@@ -105,8 +122,168 @@ config_txt_read(const struct file_entry *entry, uint32_t 
file_sector, uint8_t bu
     export_stream.buffer_end_offset = export_stream.buffer_start_offset + 512;
     export_stream.write_offset = 0;
 
-    MSC_FAT_VIEW_LOG_DEBUG("Config.txt read %d\n", file_sector);
-    conf_export(config_text_export, CONF_EXPORT_SHOW);
+    MSC_FAT_VIEW_LOG_DEBUG("Config.txt read sector %d\n", file_sector);
+    config_txt_render_file(&export_stream.out_stream);
+}
+
+static uint8_t *line;
+static size_t line_len;
+
+enum config_write_state {
+    WRITE_STATE_IDLE,
+    WRITE_STATE_DROP,
+    WRITE_STATE_CONFIG_LINES,
+    WRITE_STATE_CONFIG_WRITTEN,
+
+} config_write_state;
+
+static struct os_callout reboot_callout;
+
+static void
+reboot_fun(struct os_event *ev)
+{
+    os_reboot(0);
+}
+
+static void
+handle_line(uint8_t *bl, uint8_t *el)
+{
+    size_t len = el - bl;
+    uint8_t *p;
+    uint8_t *nb;
+    uint8_t *ne;
+    uint8_t *vb;
+
+    if (config_write_state == WRITE_STATE_IDLE) {
+        if (memcmp(CONFIG_BEGIN, bl, len) == 0) {
+            config_write_state = WRITE_STATE_CONFIG_LINES;
+            return;
+        }
+    } else if (config_write_state == WRITE_STATE_CONFIG_LINES) {
+        if (memcmp(CONFIG_END, bl, len) == 0) {
+            conf_commit(NULL);
+            conf_save();
+            config_write_state = WRITE_STATE_CONFIG_WRITTEN;
+            os_callout_init(&reboot_callout, os_eventq_dflt_get(), reboot_fun, 
NULL);
+            os_callout_reset(&reboot_callout, os_time_ms_to_ticks32(2000));
+            return;
+        }
+
+        /* Trim line to first # */
+        for (p = bl; p < el && *p != '#'; ++p) {
+        }
+        el = p;
+        /* Trim trailing spaces */
+        for (p = el - 1; p >= bl && isspace(*p); --p) {
+        }
+        el = p + 1;
+
+        /* Trim leading spaces */
+        for (p = bl; p < el && isspace(*p); ++p) {
+        }
+        if (p >= el) {
+            return;
+        }
+        /* Variable name start found */
+        nb = p;
+        /* Find variable name end */
+        for (; p < el && !isspace(*p) && *p != '='; ++p) {
+        }
+        ne = p;
+        /* Skip spaces if any */
+        for (; p < el && isspace(*p); ++p) {
+        }
+        /* If next character is not = nothing to set */
+        if (p >= el || *p != '=') {
+            return;
+        }
+        /* Trim spaces after = */
+        for (++p; p < el && isspace(*p); ++p) {
+        }
+        if (p >= el) {
+            return;
+        }
+        vb = p;
+        /* Add string terminators */
+        *ne = '\0';
+        *el = '\0';
+        conf_set_value((char *)nb, (char *)vb);
+    }
+}
+
+static int
+config_write_sector(uint32_t sector, uint8_t *buffer)
+{
+    uint8_t *p;
+    uint8_t *e = buffer + 512;
+    uint8_t *line_begin = buffer;
+    uint8_t *bl;
+    uint8_t *el;
+    int c;
+
+    for (p = buffer; p < e; ++p) {
+        if (config_write_state == WRITE_STATE_CONFIG_WRITTEN) {
+            config_write_state = WRITE_STATE_IDLE;
+            return 512;
+        } else if (config_write_state == WRITE_STATE_DROP) {
+            return 0;
+        } else {
+            c = *p;
+            if (c == '\r' || c == '\n') {
+                if (line) {
+                    line_len += (p - line_begin);
+                    line = os_realloc(line, line_len + (p - line_begin));
+                    bl = line;
+                    el = bl + line_len;
+                } else {
+                    bl = line_begin;
+                    el = p;
+                    line_len = p - bl;
+                }
+                if (line_len) {
+                    handle_line(bl, el);
+                }
+                os_free(line);
+                line = NULL;
+                line_begin = p + 1;
+            } else if (iscntrl(c)) {
+                if (config_write_state != WRITE_STATE_IDLE) {
+                    config_write_state = WRITE_STATE_IDLE;
+                    return 512;
+                }
+            }
+        }
+    }
+    return config_write_state == WRITE_STATE_IDLE ? 0 : 512;
+}
+
+
+static void
+config_txt_write(const struct file_entry *entry, uint32_t file_sector, uint8_t 
buffer[512])
+{
+    MSC_FAT_VIEW_LOG_DEBUG("Config.txt write sector %d\n", file_sector);
+
+    config_write_sector(file_sector, buffer);
+}
+
+static int
+config_write_sector_handler(struct msc_fat_view_write_handler *handler, 
uint32_t sector,
+                            uint8_t *buffer)
+{
+    MSC_FAT_VIEW_LOG_DEBUG("config_write_sector_handler %d\n", (int)sector);
+
+    return config_write_sector(sector, buffer);
+}
+
+static int
+config_file_written(struct msc_fat_view_write_handler *handler, uint32_t size, 
uint32_t sector,
+                    bool first_sector)
+{
+    MSC_FAT_VIEW_LOG_DEBUG("config_file_written %d %d\n", (unsigned)size, 
(unsigned )sector);
+
+    return 0;
 }
 
-ROOT_DIR_ENTRY(config_txt, "CONFIG.TXT", FAT_FILE_ENTRY_ATTRIBUTE_READ_ONLY, 
config_txt_size, config_txt_read, NULL, NULL);
+ROOT_DIR_ENTRY(config_txt, "CONFIG.TXT", FAT_FILE_ENTRY_ATTRIBUTE_FILE, 
config_txt_size,
+               config_txt_read, config_txt_write, NULL, NULL);
+MSC_FAT_VIEW_WRITE_HANDLER(config_handler, config_write_sector_handler, 
config_file_written);

Reply via email to