Config

Config subsystem is meant for persisting per-device configuration and runtime state for packages.

Configuration items are stored as key-value pairs, where both the key and the value are expected to be strings. Keys are divided into component elements, where packages register their subtree using the first element. E.g key id/serial consists of 2 components, id and serial. Package sys/id registered it’s subtree of configuration elements to be under id.

There are convenience routines for converting value back and forth from string.

Handlers

Config handlers for subtree implement a set of handler functions. These are registered using a call to conf_register().

  • ch_get

    This gets called when somebody asks for a config element value by it’s name using conf_get_value().

  • ch_set

    This is called when value is being set using conf_set_value(), and also when configuration is loaded from persisted storage with conf_load().

  • ch_commit

    This gets called after configuration has been loaded in full. Sometimes you don’t want individual configuration value to take effect right away, for example if there are multiple settings which are interdependent.

  • ch_export

    This gets called to dump all current configuration. This happens when conf_save() tries to save the settings, or when CLI is dumping current system configuration to console.

Persistence

Backend storage for the config can be either FCB, a file in filesystem, or both.

You can declare multiple sources for configuration; settings from all of these are restored when conf_load() is called.

There can be only one target for writing configuration; this is where data is stored when you call conf_save(), or conf_save_one().

FCB read target is registered using conf_fcb_src(), and write target using conf_fcb_dst(). conf_fcb_src() as side-effect initializes the FCB area, so it must be called when calling conf_fcb_dst(). File read target is registered using conf_file_src(), and write target conf_file_dst().

Convenience initialization of one config area can be enabled by setting either syscfg variable CONFIG_FCB or CONFIG_NFFS. These use other syscfg variables to figure which flash_map entry of BSP defines flash area, or which file to use. Check the syscfg.yml in sys/config package for more detailed description.

CLI

This can be enabled when shell package is enabled by setting syscfg variable CONFIG_CLI to 1.

Here you can set config variables, inspect their values and print both saved configuration as well as running configuration.

  • config dump

    Dump the current running configuration

  • config dump saved

    Dump the saved configuration. The values are printed in the ordered they’re restored.

  • config <key>

    Print the value of config variable identified by <key>

  • config <key> <value>

    Set the value of config variable <key> to be <value>

Example: Device Configuration

This is a simple example, config handler only implements ch_set and ch_export. ch_set is called when value is restored from storage (or when set initially), and ch_export is used to write the value to storage (or dump to console).

static int8 foo_val;

struct conf_handler my_conf = {
    .ch_name = "foo",
    .ch_set = foo_conf_set,
    .ch_export = foo_conf_export
}

static int
foo_conf_set(int argc, char **argv, char *val)
{
    if (argc == 1) {
        if (!strcmp(argv[0], "bar")) {
            return CONF_VALUE_SET(val, CONF_INT8, foo_val);
        }
    }
    return OS_ENOENT;
}

static int
foo_conf_export(void (*func)(char *name, char *val), enum conf_export_tgt tgt)
{
    char buf[4];

    conf_str_from_value(CONF_INT8, &foo_val, buf, sizeof(buf));
    func("foo/bar", buf)
    return 0;
}

Example: Persist Runtime State

This is a simple example showing how to persist runtime state. Here there is only ch_set defined, which is used when restoring value from persisted storage.

There’s a os_callout function which increments foo_val, and then persists the latest number. When system restarts, and calls conf_load(), foo_val will continue counting up from where it was before restart.

static int8 foo_val;

struct conf_handler my_conf = {
    .ch_name = "foo",
    .ch_set = foo_conf_set
}

static int
foo_conf_set(int argc, char **argv, char *val)
{
    if (argc == 1) {
        if (!strcmp(argv[0], "bar")) {
            return CONF_VALUE_SET(val, CONF_INT8, foo_val);
        }
    }
    return OS_ENOENT;
}

static void
foo_callout(struct os_event *ev)
{
    struct os_callout *c = (struct os_callout *)ev;
    char buf[4];

    foo_val++;
    conf_str_from_value(CONF_INT8, &foo_val, buf, sizeof(buf));
    conf_save_one("foo/bar", bar);

    callout_reset(c, OS_TICKS_PER_SEC * 120);
}

API

enum conf_type

Type of configuration value.

Values:

enum conf_export_tgt

Parameter to commit handler describing where data is going to.

Values:

enumerator CONF_EXPORT_PERSIST

Value is to be persisted.

enumerator CONF_EXPORT_SHOW

Value is to be display.

typedef enum conf_export_tgt conf_export_tgt_t
typedef char *(*conf_get_handler_t)(int argc, char **argv, char *val, int val_len_max)

Handler for getting configuration items, this handler is called per-configuration section.

Configuration sections are delimited by ‘/’, for example:

  • section/name/value

Would be passed as:

  • argc = 3

  • argv[0] = section

  • argv[1] = name

  • argv[2] = value

The handler returns the value into val, null terminated, up to val_len_max.

Return

A pointer to val or NULL if error.

Parameters
  • argc: The number of sections in the configuration variable

  • argv: The array of configuration sections

  • val: A pointer to the buffer to return the configuration value into.

  • val_len_max: The maximum length of the val buffer to copy into.

typedef char *(*conf_get_handler_ext_t)(int argc, char **argv, char *val, int val_len_max, void *arg)
typedef int (*conf_set_handler_t)(int argc, char **argv, char *val)

Set the configuration variable pointed to by argc and argv.

See description of ch_get_handler_t for format of these variables. This sets the configuration variable to the shadow value, but does not apply the configuration change. In order to apply the change, call the ch_commit() handler.

Return

0 on success, non-zero error code on failure.

Parameters
  • argc: The number of sections in the configuration variable.

  • argv: The array of configuration sections

  • val: The value to configure that variable to

typedef int (*conf_set_handler_ext_t)(int argc, char **argv, char *val, void *arg)
typedef int (*conf_commit_handler_t)(void)

Commit shadow configuration state to the active configuration.

Return

0 on success, non-zero error code on failure.

typedef int (*conf_commit_handler_ext_t)(void *arg)
typedef void (*conf_export_func_t)(char *name, char *val)

Called per-configuration variable being exported.

Parameters
  • name: The name of the variable to export

  • val: The value of the variable to export

typedef int (*conf_export_handler_t)(conf_export_func_t export_func, conf_export_tgt_t tgt)

Export all of the configuration variables, calling the export_func per variable being exported.

Return

0 on success, non-zero error code on failure.

Parameters
  • export_func: The export function to call.

  • tgt: The target of the export, either for persistence or display.

typedef int (*conf_export_handler_ext_t)(conf_export_func_t export_func, conf_export_tgt_t tgt, void *arg)
typedef void (*conf_store_load_cb)(char *name, char *val, void *cb_arg)
void conf_init(void)
void conf_store_init(void)
int conf_register(struct conf_handler *cf)

Register a handler for configurations items.

Return

0 on success, non-zero on failure.

Parameters
  • cf: Structure containing registration info.

int conf_load(void)

Load configuration from registered persistence sources.

Handlers for configuration subtrees registered earlier will be called for encountered values.

Return

0 on success, non-zero on failure.

int conf_load_one(char *name)

Load configuration from a specific registered persistence source.

Handlers will be called for configuration subtree for encountered values.

Return

0 on success, non-zero on failure.

Parameters
  • name: of the configuration subtree.

int conf_ensure_loaded(void)

Loads the configuration if it hasn’t been loaded since reboot.

Return

0 on success, non-zero on failure.

void conf_export(conf_export_func_t export_func, enum conf_export_tgt tgt)

Export configuration via user defined function.

Parameters
  • export_func: function to receive configuration entry

  • tgt: - export target declaration

int conf_set_from_storage(void)

Config setting comes as a result of conf_load().

Return

1 if yes, 0 if not.

int conf_save(void)

Save currently running configuration.

All configuration which is different from currently persisted values will be saved.

Return

0 on success, non-zero on failure.

int conf_save_tree(char *name)

Save currently running configuration for configuration subtree.

Return

0 on success, non-zero on failure.

Parameters
  • name: Name of the configuration subtree.

int conf_save_one(const char *name, char *var)

Write a single configuration value to persisted storage (if it has changed value).

Return

0 on success, non-zero on failure.

Parameters
  • name: Name/key of the configuration item.

  • var: Value of the configuration item.

int conf_set_value(char *name, char *val_str)

Set configuration item identified by name to be value val_str.

This finds the configuration handler for this subtree and calls it’s set handler.

Return

0 on success, non-zero on failure.

Parameters
  • name: Name/key of the configuration item.

  • val_str: Value of the configuration item.

char *conf_get_value(char *name, char *buf, int buf_len)

Get value of configuration item identified by name.

This calls the configuration handler ch_get for the subtree.

Configuration handler can copy the string to buf, the maximum number of bytes it will copy is limited by buf_len.

Return value will be pointer to beginning of the value. Note that this might, or might not be the same as buf.

Return

pointer to value on success, NULL on failure.

Parameters
  • name: Name/key of the configuration item.

  • val_str: Value of the configuration item.

int conf_get_stored_value(char *name, char *buf, int buf_len)

Get stored value of configuration item identified by name.

This traverses the configuration area(s), and copies the value of the latest value.

Value is copied to buf, the maximum number of bytes it will copy is limited by buf_len.

Return

0 on success, non-zero on failure.

Parameters
  • name: Name/key of the configuration item.

  • val_str: Value of the configuration item.

int conf_commit(char *name)

Call commit for all configuration handler.

This should apply all configuration which has been set, but not applied yet.

Return

0 on success, non-zero on failure.

Parameters
  • name: Name of the configuration subtree, or NULL to commit everything.

int conf_value_from_str(char *val_str, enum conf_type type, void *vp, int maxlen)

Convenience routine for converting value passed as a string to native data type.

Return

0 on success, non-zero on failure.

Parameters
  • val_str: Value of the configuration item as string.

  • type: Type of the value to convert to.

  • vp: Pointer to variable to fill with the decoded value.

  • vp: Size of that variable.

int conf_bytes_from_str(char *val_str, void *vp, int *len)

Convenience routine for converting byte array passed as a base64 encoded string.

Return

0 on success, non-zero on failure.

Parameters
  • val_str: Value of the configuration item as string.

  • vp: Pointer to variable to fill with the decoded value.

  • len: Size of that variable. On return the number of bytes in the array.

char *conf_str_from_value(enum conf_type type, void *vp, char *buf, int buf_len)

Convenience routine for converting native data type to a string.

Return

0 on success, non-zero on failure.

Parameters
  • type: Type of the value to convert from.

  • vp: Pointer to variable to convert.

  • buf: Buffer where string value will be stored.

  • buf_len: Size of the buffer.

char *conf_str_from_bytes(void *vp, int vp_len, char *buf, int buf_len)

Convenience routine for converting byte array into a base64 encoded string.

Return

0 on success, non-zero on failure.

Parameters
  • vp: Pointer to variable to convert.

  • vp_len: Number of bytes to convert.

  • buf: Buffer where string value will be stored.

  • buf_len: Size of the buffer.

void conf_lock(void)

Locks the config package.

If another task tries to read or write a setting while the config package is locked, the operation will block until the package is unlocked. The locking task is permitted to read and write settings as usual. A call to conf_lock() should always be followed by conf_unlock().

Typical usage of the config API does not require manual locking. This function is only needed for unusual use cases such as temporarily changing the destination medium for an isolated series of writes.

void conf_unlock(void)

Unlocks the config package.

This function reverts the effects of the conf_lock() function. Typical usage of the config API does not require manual locking.

void conf_src_register(struct conf_store *cs)
void conf_dst_register(struct conf_store *cs)
CONF_STR_FROM_BYTES_LEN(len)

Return the length of a configuration string from buffer length.

CONF_VALUE_SET(str, type, val)

Convert a string into a value of type.

struct conf_handler
#include <config.h>

Configuration handler, used to register a config item/subtree.

Public Members

char *ch_name

The name of the conifguration item/subtree.

bool ch_ext

Whether to use the extended callbacks.

false: standard true: extended

union conf_handler.[anonymous] [anonymous]

Get configuration value.

union conf_handler.[anonymous] [anonymous]

Set configuration value.

union conf_handler.[anonymous] [anonymous]

Commit configuration value.

union conf_handler.[anonymous] [anonymous]

Export configuration value.

void *ch_arg

Custom argument that gets passed to the extended callbacks.

struct conf_store_itf
#include <config_store.h>
struct conf_store
#include <config_store.h>