I've been trying to implement NFFS config-backed settings in a driver, but
going through the documentation and some of the examples in the core github
repo it isn't clear to me exactly when/where/how to correctly persist the
data to the NFFS partition.
I have the following two values to persist at the moment:
- mydriver/inits (int32)
- mydriver/ccm (base 64 encoded struct)
They show up fine in the active (in memory) config record set at startup
(visible via 'config dump'), but when I change the values and want to save
those changes to cfg/run, should the 'save' be implemented in the export
handler, or do I call `conf_save_one` when the value is changed and this
will handle the write in the background (meaning I leave `.ch_export` as
NULL)???
My current test code is below.
`*conf_save_one*` is called in both '*mydriver_conf_save_ccm*' and '
*mydriver_conf_export*', and I'm not sure which is 'right' to makes sure
the value is persisted to NFFS whenever a change is made.
I'm running this *in the simulator with -f support to use the same NFFS
partition*, and I've had very mixed results where sometimes the data shows
up with '*cat /cfg/run*' and other times it doesn't, and it hasn't been
obvious to me when or why.
------ START CODE ------
/** Callbacks and subtree name for the NFFS-based config data. */
struct conf_handler g_mydriver_conf = {
.ch_name = "mydriver",
.ch_get = mydriver_conf_get,
.ch_set = mydriver_conf_set,
.ch_commit = NULL,
.ch_export = mydriver_conf_export
};
/**
* Called when a value is requested by name via 'conf_register()'.
*/
static char *
mydriver_conf_get(int argc, char **argv, char *buf, int max_len)
{
if (argc == 1) {
if (!strcmp(argv[0], "inits")) {
return conf_str_from_value(CONF_INT32, &g_mydriver_conf_inits,
buf, max_len);
} else if (!strcmp(argv[0], "ccm")) {
return conf_str_from_bytes(&g_mydriver_xyz_cm,
sizeof(g_mydriver_xyz_cm), buf, max_len);
}
}
return NULL;
}
/**
* Called when a value is set via 'conf_set_value()' or when config data
* is loaded via 'conf_load()'.
*/
static int
mydriver_conf_set(int argc, char **argv, char *val)
{
int tmp;
/* Init counter */
if (argc == 1) {
if (!strcmp(argv[0], "inits")) {
return CONF_VALUE_SET(val, CONF_INT32, g_mydriver_conf_inits);
}
}
/* Custom correlation matrix values (encoded as BASE64). */
if (argc == 1) {
if (!strcmp(argv[0], "ccm")) {
tmp = sizeof(g_mydriver_xyz_cm);
return conf_bytes_from_str(val, &g_mydriver_xyz_cm, &tmp);
}
}
/* Unknown key! */
return OS_ENOENT;
}
/**
* Called to dump all current config data. This happens when 'conf_save()'
* tries to save the settings.
*/
static int
mydriver_conf_export(void (*func)(char *name, char *val),
enum conf_export_tgt tgt)
{
char buf[BASE64_ENCODE_SIZE(sizeof(g_mydriver_xyz_cm)+1)];
/* Persist init counter. */
memset(buf, 0, sizeof(buf));
conf_str_from_value(CONF_INT32, &g_mydriver_conf_inits, buf,
sizeof(buf));
func("mydriver/inits", buf);
conf_save_one("mydriver/inits", buf);
/* Persist correlation matrix to NFFS config memory. */
memset(buf, 0, sizeof(buf));
conf_str_from_bytes(&g_mydriver_xyz_cm, sizeof(g_mydriver_xyz_cm), buf,
sizeof(buf));
func("mydriver/ccm", buf);
conf_save_one("mydriver/ccm", buf);
return 0;
}
int
mydriver_conf_init(void)
{
int rc;
char buf[CONF_STR_FROM_BYTES_LEN(sizeof(g_mydriver_conf_inits))];
/* Register the mydriver subtree. */
rc = conf_register(&g_mydriver_conf);
if (rc != 0) {
goto err;
}
/* Make sure that config data has been loaded. */
conf_load();
/* Increment init counter and persist it again. */
g_mydriver_conf_inits++;
rc = conf_save_one("mydriver/inits",
conf_str_from_value(CONF_INT32, &g_mydriver_conf_inits,
buf, sizeof(buf)));
if (rc != 0) {
goto err;
}
return 0;
err:
return rc;
}
int
mydriver_conf_save_ccm(struct clr_mtx_3x3 *ccm)
{
int rc;
char buf[BASE64_ENCODE_SIZE(sizeof(ccm)+1)];
/*
* Note: doubles have up to 309 significant digits, so we use BASE64
* encoding to keep the config file size manageable. Base 64 is based on
* 6 bit values, so every 3 bytes of binary data (24 bits) will be
encoded
* as 4 bytes in BASE64 (24/6=4).
*/
/* Persist correlation matrix to NFFS config memory. */
conf_str_from_bytes(ccm, sizeof(ccm), buf, sizeof(buf));
rc = conf_save_one("mydriver/ccm", buf);
if (rc != 0) {
goto err;
}
return 0;
err:
return rc;
}
------- ENDCODE --------
Strangely, the '*ccm*' value only seem to be persisted AFTER I make a call
to '*config dump*' in the shell, as shown below:
*003332 compat> ls /cfg*
003583 17 /cfg/run
003583 1 files
*003584 compat> cat /cfg/run*
mydriver/inits=1
*004117 compat> config dump*
004373 mydriver/inits = 1
004373 mydriver/ccm =
cUuzkrkmwr/Iv8dHKMnUv2MIpdTKyeW/Ns5kB67F+D+m+zGUsEL5P2deceWqoeg/17kviMSU7r/SYMc9ZW7nv8ZHUYj8CuI/
004378 foo/bar = 0
004380 split/status = 0
004381 id/hwid = QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI=
004383 id/bsp = native
004384 id/app = blinky
004385 id/mfghash =
004385 id/serial =
004387 reboot/reboot_cnt =
004388 reboot/soft_reboot =
*004389 compat> ls /cfg/run*
004777 127 /cfg/run
004777 1 files
*004778 compat> cat /cfg/run*
mydriver/inits=1
mydriver/ccm=cUuzkrkmwr/Iv8dHKMnUv2MIpdTKyeW/Ns5kB67F+D+m+zGUsEL5P2deceWqoeg/17kviMSU7r/SYMc9ZW7nv8ZHUYj8CuI/
Kevin