diff --git a/comm/messages.c b/comm/messages.c index dc021b3..46e2ab7 100644 --- a/comm/messages.c +++ b/comm/messages.c @@ -66,7 +66,7 @@ static void settings_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer } IniWriter iw = iw_init((char *)buffer, bulk->offset, chunk); - settings_build_ini(&iw); + settings_build_units_ini(&iw); } /** @@ -80,7 +80,7 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg) assert_param(bulk); bulk->frame_id = msg->frame_id; - bulk->len = settings_get_ini_len(); + bulk->len = settings_get_units_ini_len(); bulk->read = settings_bulkread_cb; bulk->userdata = NULL; @@ -124,7 +124,7 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg) assert_param(bulk); bulk->frame_id = msg->frame_id; - bulk->len = settings_get_ini_len(); + bulk->len = settings_get_units_ini_len(); bulk->write = settings_bulkwrite_cb; settings_load_ini_begin(); diff --git a/framework/settings.c b/framework/settings.c index 97dffd2..45ec1f9 100644 --- a/framework/settings.c +++ b/framework/settings.c @@ -209,33 +209,63 @@ static void savebuf_flush(PayloadBuilder *pb, bool final) fls_printf("\r\n"); } -/** - * Write system settings to INI (without section) - */ -void settings_build_ini(IniWriter *iw) +// --------------------------------------------------------------- + +static void ini_preamble(IniWriter *iw, const char *filename) { // File header - iw_hdr_comment(iw, "CONFIG.INI"); + iw_hdr_comment(iw, filename); iw_hdr_comment(iw, "GEX v%s on %s", GEX_VERSION, GEX_PLATFORM); iw_hdr_comment(iw, "built %s at %s", __DATE__, __TIME__); iw_cmt_newline(iw); iw_comment(iw, "Overwrite this file to change settings."); iw_comment(iw, "Close the LOCK jumper to save them to Flash."); +} - systemsettings_build_ini(iw); +/** + * Write system settings to INI (without section) + */ +void settings_build_units_ini(IniWriter *iw) +{ + ini_preamble(iw, "UNITS.INI"); ureg_build_ini(iw); } +/** + * Write system settings to INI (without section) + */ +void settings_build_system_ini(IniWriter *iw) +{ + ini_preamble(iw, "SYSTEM.INI"); + + systemsettings_build_ini(iw); +} + +uint32_t settings_get_units_ini_len(void) +{ + // this writer is configured to skip everything, so each written byte will decrement the skip count + IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1); // count is never used, we use 1 because 0 means we're full + settings_build_units_ini(&iw); + // now we just check how many bytes were skipped + return 0xFFFFFFFF - iw.skip; +} + +uint32_t settings_get_system_ini_len(void) +{ + // same as above + IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1); + settings_build_system_ini(&iw); + return 0xFFFFFFFF - iw.skip; +} + +// --------------------------------------------------------------- void settings_load_ini_begin(void) { SystemSettings.modified = true; - - // load defaults - systemsettings_loadDefaults(); - ureg_remove_all_units(); + SystemSettings.pristine = true; } void settings_load_ini_key(const char *restrict section, const char *restrict key, const char *restrict value) @@ -244,25 +274,35 @@ void settings_load_ini_key(const char *restrict section, const char *restrict ke static char namebuf[INI_KEY_MAX]; if (streq(section, "SYSTEM")) { + + if (SystemSettings.pristine) { + SystemSettings.pristine = false; + systemsettings_loadDefaults(); + } + // system is always at the top systemsettings_load_ini(key, value); } else if (streq(section, "UNITS")) { + + if (SystemSettings.pristine) { + SystemSettings.pristine = false; + ureg_remove_all_units(); + } + // this will always come before individual units config // install or tear down units as described by the config ureg_instantiate_by_ini(key, value); - } else { + } + else { // not a standard section, may be some unit config - // all unit sections contain the colon character [TYPE:NAME] + // all unit sections contain the colon character [TYPE:NAME@CALLSIGN] const char *nameptr = strchr(section, ':'); const char *csptr = strchr(section, '@'); - dbg("cs = %s", csptr); if (nameptr && csptr) { strncpy(namebuf, nameptr+1, csptr - nameptr - 1); uint8_t cs = (uint8_t) avr_atoi(csptr + 1); - dbg("cs is %d", cs); - dbg("name is %s", namebuf); ureg_load_unit_ini_key(namebuf, key, value, cs); } else { dbg("! Bad config key: [%s] %s = %s", section, key, value); @@ -276,12 +316,3 @@ void settings_load_ini_end(void) dbg("Some units failed to init!!"); } } - -uint32_t settings_get_ini_len(void) -{ - // this writer is configured to skip everything, so each written byte will decrement the skip count - IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1); - settings_build_ini(&iw); - // now we just check how many bytes were skipped - return 0xFFFFFFFF - iw.skip; -} diff --git a/framework/settings.h b/framework/settings.h index 9e15365..c256d7b 100644 --- a/framework/settings.h +++ b/framework/settings.h @@ -51,16 +51,29 @@ void settings_load_ini_key(const char *restrict section, const char *restrict ke void settings_load_ini_end(void); /** - * Write all settings to a iniwriter + * Write UNITS.INI to a iniwriter * @param iw - writer handle */ -void settings_build_ini(IniWriter *iw); +void settings_build_units_ini(IniWriter *iw); /** - * Get total settings len (caution: this is expensive, works by dummy-printing everything) + * Get UNITS.INI len (expensive, uses dummy read) * * @return bytes */ -uint32_t settings_get_ini_len(void); +uint32_t settings_get_units_ini_len(void); + +/** + * Write SYSTEM.INI to iniwriter + * @param iw - writer handle + */ +void settings_build_system_ini(IniWriter *iw); + +/** + * Get SYSTEM.INI len (expensive, uses dummy read) + * + * @return bytes + */ +uint32_t settings_get_system_ini_len(void); #endif //GEX_SETTINGS_H diff --git a/framework/system_settings.h b/framework/system_settings.h index 776f618..b7f1e1b 100644 --- a/framework/system_settings.h +++ b/framework/system_settings.h @@ -17,6 +17,7 @@ struct system_settings { // Support flags put here for scoping, but not atcually part of the persistent settings volatile bool editable; //!< True if we booted with the LOCK jumper removed volatile bool modified; //!< True if user did any change to the settings (checked when the LOCK jumper is replaced) + volatile bool pristine; //!< Marks unknown state before we reach first section marker that determines what file it is }; extern struct system_settings SystemSettings; diff --git a/framework/unit_registry.c b/framework/unit_registry.c index 7ce2f47..358c41e 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -477,6 +477,8 @@ void ureg_build_ini(IniWriter *iw) count++; } li = li->next; + + if (iw->count == 0) return; // avoid printing discarded tail } re = re->next; iw_newline(iw); @@ -487,6 +489,8 @@ void ureg_build_ini(IniWriter *iw) while (li != NULL) { export_unit_do(li, iw); li = li->next; + + if (iw->count == 0) return; // avoid printing discarded tail } } diff --git a/platform/plat_compat.h b/platform/plat_compat.h index 5d08081..1a64d8a 100644 --- a/platform/plat_compat.h +++ b/platform/plat_compat.h @@ -5,6 +5,8 @@ #ifndef GEX_PLAT_COMPAT_H #define GEX_PLAT_COMPAT_H +#define VFS_DRIVE_NAME "GEX" + // -------- Static buffers --------- #define TSK_STACK_MAIN 220 // USB / VFS task stack size #define TSK_STACK_MSG 200 // TF message handler task stack size diff --git a/vfs/file_stream.c b/vfs/file_stream.c index cf369ed..d375934 100644 --- a/vfs/file_stream.c +++ b/vfs/file_stream.c @@ -193,8 +193,8 @@ static bool detect_conf(const uint8_t *data, uint32_t size) // and may not be known for a while - we cannot use that to detect anything, unless we buffer the entire file // (a bad idea) - // TODO detect config file - return data[0] == '#'; // here we just assume everything is INI + // Our INI files always start with two hashes + return size >= 2 && data[0] == '#' && data[1] == '#'; } static void iniparser_cb(const char *section, const char *key, const char *value, void *userData) diff --git a/vfs/vfs_user.c b/vfs/vfs_user.c index 93c8410..40e48bf 100644 --- a/vfs/vfs_user.c +++ b/vfs/vfs_user.c @@ -25,32 +25,34 @@ #include "vfs_manager.h" #include "str_utils.h" -const vfs_filename_t daplink_drive_name = "VIRTUALFS"; +const vfs_filename_t daplink_drive_name = VFS_DRIVE_NAME; // File callback to be used with vfs_add_file to return file contents -static uint32_t read_file_config_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) +static uint32_t read_file_units_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) { - vfs_printf("Read config.ini"); + vfs_printf("Read UNITS.INI"); const uint32_t avail = num_sectors*VFS_SECTOR_SIZE; const uint32_t skip = sector_offset*VFS_SECTOR_SIZE; IniWriter iw = iw_init((char *)data, skip, avail); - settings_build_ini(&iw); + settings_build_units_ini(&iw); return avail - iw.count; } +static uint32_t read_file_system_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors) +{ + vfs_printf("Read SYSTEM.INI"); + + const uint32_t avail = num_sectors*VFS_SECTOR_SIZE; + const uint32_t skip = sector_offset*VFS_SECTOR_SIZE; -//// -//static void write_file_config_ini(uint32_t sector_offset, const uint8_t *data, uint32_t num_sectors) -//{ -// vfs_printf("Write CONFIG.INI, so %d, ns %d", sector_offset, num_sectors); -// -// for(uint32_t i=0;i