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

Reply via email to