subsys/settings: Allow to register custom backends in settings subsystem
Major changes are: - Expose settings backend API to enable custom backend support. - Add a new CONFIG_SETTINGS_CUSTOM backend to allow registering a custom backend. - Change api of the handlers h_set() routines to allow for backend-specific read callbacks. - Provide a customizable settings_backend_init() routine for custom backends. - Move runtime settings support to be its own backend. Signed-off-by: François Delawarde <fnde@oticon.com>
This commit is contained in:
parent
686830bbda
commit
94451b22fc
31 changed files with 739 additions and 544 deletions
|
@ -21,13 +21,13 @@ Settings handlers for subtree implement a set of handler functions.
|
|||
These are registered using a call to ``settings_register()``.
|
||||
|
||||
**h_get**
|
||||
This gets called when asking for a settings element value
|
||||
by its name using ``settings_get_value()``.
|
||||
This gets called when asking for a settings element value by its name using
|
||||
``settings_runtime_get()`` from the runtime backend.
|
||||
|
||||
**h_set**
|
||||
This gets called when the value is being set using ``settings_set_value()``,
|
||||
and also when setting is loaded from persisted storage with
|
||||
``settings_load()``.
|
||||
This gets called when the value is loaded from persisted storage with
|
||||
``settings_load()``, or when using ``settings_runtime_set()`` from the
|
||||
runtime backend.
|
||||
|
||||
**h_commit**
|
||||
This gets called after the settings have been loaded in full.
|
||||
|
@ -40,11 +40,38 @@ These are registered using a call to ``settings_register()``.
|
|||
when ``settings_save()`` tries to save the settings or transfer to any
|
||||
user-implemented back-end.
|
||||
|
||||
Persistence
|
||||
***********
|
||||
Backends
|
||||
********
|
||||
|
||||
Backend storage for the settings can be a Flash Circular Buffer (FCB)
|
||||
or a file in the filesystem.
|
||||
Backends are meant to load and save data to/from setting handlers, and
|
||||
implement a set of handler functions. These are registered using a call to
|
||||
``settings_src_register()`` for backends that can load data, and/or
|
||||
``settings_dst_register()`` for backends that can save data. The current
|
||||
implementation allows for multiple source backends but only a single destination
|
||||
backend.
|
||||
|
||||
**csi_load**
|
||||
This gets called when loading values from persistent storage using
|
||||
``settings_load()``.
|
||||
|
||||
**csi_save**
|
||||
This gets called when a saving a single setting to persistent storage using
|
||||
``settings_save_one()``.
|
||||
|
||||
**csi_save_start**
|
||||
This gets called when starting a save of all current settings using
|
||||
``settings_save()``.
|
||||
|
||||
**csi_save_end**
|
||||
This gets called after having saved of all current settings using
|
||||
``settings_save()``.
|
||||
|
||||
Zephyr Storage Backends
|
||||
***********************
|
||||
|
||||
Zephyr has two existing backend storages which can be a Flash Circular Buffer
|
||||
(:option:`CONFIG_SETTINGS_FCB`) or a file in the filesystem
|
||||
(:option:`CONFIG_SETTINGS_FS`).
|
||||
|
||||
You can declare multiple sources for settings; settings from
|
||||
all of these are restored when ``settings_load()`` is called.
|
||||
|
@ -89,12 +116,12 @@ export functionality, for example, writing to the shell console).
|
|||
.h_export = foo_settings_export
|
||||
};
|
||||
|
||||
static int foo_settings_set(int argc, char **argv, void *value_ctx)
|
||||
static int foo_settings_set(int argc, char **argv, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
if (argc == 1) {
|
||||
if (!strcmp(argv[0], "bar")) {
|
||||
return settings_val_read_cb(value_ctx, &foo_val,
|
||||
sizeof(foo_val));
|
||||
return read_cb(cb_arg, &foo_val, sizeof(foo_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,12 +156,12 @@ up from where it was before restart.
|
|||
.h_set = foo_settings_set
|
||||
};
|
||||
|
||||
static int foo_settings_set(int argc, char **argv, void *value_ctx)
|
||||
static int foo_settings_set(int argc, char **argv, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
if (argc == 1) {
|
||||
if (!strcmp(argv[0], "bar")) {
|
||||
return settings_val_read_cb(value_ctx, &foo_val,
|
||||
sizeof(foo_val));
|
||||
return read_cb(cb_arg, &foo_val, sizeof(foo_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +179,37 @@ up from where it was before restart.
|
|||
sys_reboot(SYS_REBOOT_COLD);
|
||||
}
|
||||
|
||||
Example: Custom Backend Implementation
|
||||
**************************************
|
||||
|
||||
This is a simple example showing how to register a simple custom backend
|
||||
handler (:option:`CONFIG_SETTINGS_CUSTOM`).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static int settings_custom_load(struct settings_store *cs)
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
static int settings_custom_save(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len)
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
static struct settings_store_itf settings_custom_itf = {
|
||||
.csi_load = settings_custom_load,
|
||||
.csi_save = settings_custom_save,
|
||||
};
|
||||
|
||||
int settings_backend_init(void)
|
||||
{
|
||||
settings_dst_register(&settings_custom_itf);
|
||||
settings_src_register(&settings_custom_itf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ extern "C" {
|
|||
*/
|
||||
#define SETTINGS_EXTRA_LEN ((SETTINGS_MAX_DIR_DEPTH - 1) + 2)
|
||||
|
||||
#define SETTINGS_NMGR_OP 0
|
||||
typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len);
|
||||
|
||||
/**
|
||||
* @struct settings_handler
|
||||
|
@ -57,14 +57,16 @@ struct settings_handler {
|
|||
* - val_len_max - size of that buffer.
|
||||
*/
|
||||
|
||||
int (*h_set)(int argc, char **argv, void *value_ctx);
|
||||
int (*h_set)(int argc, char **argv, size_t len,
|
||||
settings_read_cb read_cb, void *cb_arg);
|
||||
/**< Set value handler of settings items identified by keyword names.
|
||||
*
|
||||
* Parameters:
|
||||
* - argc - count of item in argv, argv - array of pointers to keyword
|
||||
* names.
|
||||
* - value_ctx - pointer to the value context which is used parameter
|
||||
* for data extracting routine (@ref settings_val_read_cb).
|
||||
* - argc - count of item in argv.
|
||||
* - argv - array of pointers to keyword names.
|
||||
* - len - the size of the data found in the backend.
|
||||
* - read_cb - function provided to read the data from the backend.
|
||||
* - cb_arg - arguments for the read function provided by the backend.
|
||||
*/
|
||||
|
||||
int (*h_commit)(void);
|
||||
|
@ -151,88 +153,151 @@ int settings_save_one(const char *name, void *value, size_t val_len);
|
|||
*/
|
||||
int settings_delete(const char *name);
|
||||
|
||||
/**
|
||||
* Set settings item identified by @p name to be value @p value.
|
||||
* This finds the settings handler for this subtree and calls it's
|
||||
* set handler.
|
||||
*
|
||||
* @param name Name/key of the settings item.
|
||||
* @param value Pointer to the value of the settings item. This value will
|
||||
* be transferred to the @ref settings_handler::h_set handler implementation.
|
||||
* @param len Length of value string.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int settings_set_value(char *name, void *value, size_t len);
|
||||
|
||||
/**
|
||||
* Get value of settings item identified by @p name.
|
||||
* This calls the settings handler h_get for the subtree.
|
||||
*
|
||||
* Configuration handler should copy the string to @p buf, the maximum
|
||||
* number of bytes it will copy is limited by @p buf_len.
|
||||
*
|
||||
* @param name Name/key of the settings item.
|
||||
*
|
||||
* @param buf buffer for value of the settings item.
|
||||
* If value is not string, the value will be filled in *buf.
|
||||
*
|
||||
* @param buf_len size of buf.
|
||||
*
|
||||
* @return Positive: Length of copied dat. Negative: -ERCODE
|
||||
*/
|
||||
int settings_get_value(char *name, char *buf, int buf_len);
|
||||
|
||||
/**
|
||||
* Call commit for all settings handler. This should apply all
|
||||
* settings which has been set, but not applied yet.
|
||||
*
|
||||
* @param name Name of the settings subtree, or NULL to commit everything.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int settings_commit(char *name);
|
||||
|
||||
/**
|
||||
* Persistent data extracting routine.
|
||||
*
|
||||
* This function read and decode data from non-volatile storage to user buffer
|
||||
* This function should be used inside set handler in order to read the settings
|
||||
* data from backend storage.
|
||||
*
|
||||
* @param[in] value_ctx Data context provided by the h_set handler.
|
||||
* @param[out] buf Buffer for data read.
|
||||
* @param[in] len Length of @p buf.
|
||||
*
|
||||
* @retval Negative value on failure. 0 and positive: Length of data loaded to
|
||||
* the @p buf.
|
||||
*/
|
||||
int settings_val_read_cb(void *value_ctx, void *buf, size_t len);
|
||||
|
||||
/**
|
||||
* This function fetch length of decode data.
|
||||
* This function should be used inside set handler in order to detect the
|
||||
* settings data length.
|
||||
*
|
||||
* @param[in] value_ctx Data context provided by the h_set handler.
|
||||
*
|
||||
* @retval length of data.
|
||||
*/
|
||||
size_t settings_val_get_len_cb(void *value_ctx);
|
||||
int settings_commit(void);
|
||||
|
||||
/**
|
||||
* @} settings
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Config storage
|
||||
* API for config storage
|
||||
*/
|
||||
|
||||
struct settings_store_itf;
|
||||
|
||||
/**
|
||||
* @struct settings_store
|
||||
* Backend handler node for storage handling.
|
||||
*/
|
||||
struct settings_store {
|
||||
sys_snode_t cs_next;
|
||||
/**< Linked list node info for internal usage. */
|
||||
|
||||
const struct settings_store_itf *cs_itf;
|
||||
/**< Backend handler structure. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct settings_store_itf
|
||||
* Backend handler functions.
|
||||
* Sources are registered using a call to @ref settings_src_register.
|
||||
* Destinations are registered using a call to @ref settings_dst_register.
|
||||
*/
|
||||
struct settings_store_itf {
|
||||
int (*csi_load)(struct settings_store *cs);
|
||||
/**< Loads all values from storage.
|
||||
*
|
||||
* Parameters:
|
||||
* - cs - Corresponding backend handler node
|
||||
*/
|
||||
|
||||
int (*csi_save_start)(struct settings_store *cs);
|
||||
/**< Handler called before an export operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - cs - Corresponding backend handler node
|
||||
*/
|
||||
|
||||
int (*csi_save)(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len);
|
||||
/**< Save a single key-value pair to storage.
|
||||
*
|
||||
* Parameters:
|
||||
* - cs - Corresponding backend handler node
|
||||
* - name - Key in string format
|
||||
* - value - Binary value
|
||||
* - val_len - Length of value in bytes.
|
||||
*/
|
||||
|
||||
int (*csi_save_end)(struct settings_store *cs);
|
||||
/**< Handler called after an export operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - cs - Corresponding backend handler node
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a backend handler acting as source.
|
||||
*
|
||||
* @param cs Backend handler node containing handler information.
|
||||
*
|
||||
*/
|
||||
void settings_src_register(struct settings_store *cs);
|
||||
|
||||
/**
|
||||
* Register a backend handler acting as destination.
|
||||
*
|
||||
* @param cs Backend handler node containing handler information.
|
||||
*
|
||||
*/
|
||||
void settings_dst_register(struct settings_store *cs);
|
||||
|
||||
|
||||
/*
|
||||
* API for handler lookup
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parses a key to an array of elements and locate corresponding module handler.
|
||||
*
|
||||
* @param name Key in string format
|
||||
* @param name_argc Parsed number of elements.
|
||||
* @param name_argv Parsed array of elements.
|
||||
*
|
||||
* @return settings_handler node on success, NULL on failure.
|
||||
*/
|
||||
struct settings_handler *settings_parse_and_lookup(char *name, int *name_argc,
|
||||
char *name_argv[]);
|
||||
|
||||
|
||||
/*
|
||||
* API for runtime settings
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SETTINGS_RUNTIME
|
||||
|
||||
/**
|
||||
* Set a value with a specific key to a module handler.
|
||||
*
|
||||
* @param name Key in string format.
|
||||
* @param data Binary value.
|
||||
* @param len Value length in bytes.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int settings_runtime_set(const char *name, void *data, size_t len);
|
||||
|
||||
/**
|
||||
* Get a value corresponding to a key from a module handler.
|
||||
*
|
||||
* @param name Key in string format.
|
||||
* @param data Returned binary value.
|
||||
* @param len Returned value length in bytes.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int settings_runtime_get(const char *name, void *data, size_t len);
|
||||
|
||||
/**
|
||||
* Apply settings in a module handler.
|
||||
*
|
||||
* @param name Key in string format.
|
||||
*
|
||||
* @return 0 on success, non-zero on failure.
|
||||
*/
|
||||
int settings_runtime_commit(const char *name);
|
||||
|
||||
#endif /* CONFIG_SETTINGS_RUNTIME */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -114,54 +114,49 @@ void save_on_flash(u8_t id)
|
|||
k_work_submit(&storage_work);
|
||||
}
|
||||
|
||||
static int ps_set(int argc, char **argv, void *val_ctx)
|
||||
static int ps_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
|
||||
if (argc == 1) {
|
||||
if (!strcmp(argv[0], "rc")) {
|
||||
len = settings_val_read_cb(val_ctx, &reset_counter,
|
||||
len = read_cb(cb_arg, &reset_counter,
|
||||
sizeof(reset_counter));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "gdtt")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&gen_def_trans_time_srv_user_data.tt,
|
||||
sizeof(gen_def_trans_time_srv_user_data.tt));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "gpo")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&gen_power_onoff_srv_user_data.onpowerup,
|
||||
sizeof(gen_power_onoff_srv_user_data.onpowerup));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "ltd")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&light_ctl_srv_user_data.lightness_temp_def,
|
||||
sizeof(light_ctl_srv_user_data.lightness_temp_def));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "ltl")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&light_ctl_srv_user_data.lightness_temp_last,
|
||||
sizeof(light_ctl_srv_user_data.lightness_temp_last));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "lr")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&light_lightness_srv_user_data.lightness_range,
|
||||
sizeof(light_lightness_srv_user_data.lightness_range));
|
||||
}
|
||||
|
||||
if (!strcmp(argv[0], "tr")) {
|
||||
len = settings_val_read_cb(
|
||||
val_ctx,
|
||||
len = read_cb(cb_arg,
|
||||
&light_ctl_srv_user_data.temperature_range,
|
||||
sizeof(light_ctl_srv_user_data.temperature_range));
|
||||
}
|
||||
|
|
|
@ -3332,7 +3332,8 @@ next:
|
|||
return load->count ? BT_GATT_ITER_CONTINUE : BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
static int ccc_set(int argc, char **argv, void *val_ctx)
|
||||
static int ccc_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct ccc_store ccc_store[CCC_STORE_MAX];
|
||||
struct ccc_load load;
|
||||
|
@ -3356,9 +3357,8 @@ static int ccc_set(int argc, char **argv, void *val_ctx)
|
|||
|
||||
load.addr_with_id.addr = &addr;
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx)) {
|
||||
len = settings_val_read_cb(val_ctx, ccc_store,
|
||||
sizeof(ccc_store));
|
||||
if (len_rd) {
|
||||
len = read_cb(cb_arg, ccc_store, sizeof(ccc_store));
|
||||
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to decode value (err %d)", len);
|
||||
|
@ -3388,7 +3388,8 @@ static int ccc_set(int argc, char **argv, void *val_ctx)
|
|||
BT_SETTINGS_DEFINE(ccc, ccc_set, NULL, NULL);
|
||||
|
||||
#if defined(CONFIG_BT_GATT_CACHING)
|
||||
static int cf_set(int argc, char **argv, void *val_ctx)
|
||||
static int cf_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct gatt_cf_cfg *cfg;
|
||||
bt_addr_le_t addr;
|
||||
|
@ -3414,9 +3415,8 @@ static int cf_set(int argc, char **argv, void *val_ctx)
|
|||
}
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx)) {
|
||||
len = settings_val_read_cb(val_ctx, cfg->data,
|
||||
sizeof(cfg->data));
|
||||
if (len_rd) {
|
||||
len = read_cb(cb_arg, cfg->data, sizeof(cfg->data));
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to decode value (err %d)", len);
|
||||
return len;
|
||||
|
@ -3436,11 +3436,12 @@ BT_SETTINGS_DEFINE(cf, cf_set, NULL, NULL);
|
|||
|
||||
static u8_t stored_hash[16];
|
||||
|
||||
static int db_hash_set(int argc, char **argv, void *val_ctx)
|
||||
static int db_hash_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = settings_val_read_cb(val_ctx, stored_hash, sizeof(stored_hash));
|
||||
len = read_cb(cb_arg, stored_hash, sizeof(stored_hash));
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to decode value (err %d)", len);
|
||||
return len;
|
||||
|
|
|
@ -271,12 +271,14 @@ int bt_keys_store(struct bt_keys *keys)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int keys_set(int argc, char **argv, void *value_ctx)
|
||||
static int keys_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_keys *keys;
|
||||
bt_addr_le_t addr;
|
||||
u8_t id;
|
||||
int len, err;
|
||||
size_t len;
|
||||
int err;
|
||||
char val[BT_KEYS_STORAGE_LEN];
|
||||
|
||||
if (argc < 1) {
|
||||
|
@ -284,9 +286,9 @@ static int keys_set(int argc, char **argv, void *value_ctx)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = settings_val_read_cb(value_ctx, val, sizeof(val));
|
||||
len = read_cb(cb_arg, val, sizeof(val));
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read value (err %d)", len);
|
||||
BT_ERR("Failed to read value (err %zu)", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -323,8 +325,8 @@ static int keys_set(int argc, char **argv, void *value_ctx)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(value_ctx) != BT_KEYS_STORAGE_LEN) {
|
||||
BT_ERR("Invalid key length %d != %zu", len,
|
||||
if (len_rd != BT_KEYS_STORAGE_LEN) {
|
||||
BT_ERR("Invalid key length %zu != %zu", len,
|
||||
BT_KEYS_STORAGE_LEN);
|
||||
bt_keys_clear(keys);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -125,33 +125,35 @@ static struct {
|
|||
struct cfg_val cfg;
|
||||
} stored_cfg;
|
||||
|
||||
static inline int mesh_x_set(void *val_ctx, void *out, size_t read_len)
|
||||
static inline int mesh_x_set(settings_read_cb read_cb, void *cb_arg, void *out,
|
||||
size_t read_len)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
len = settings_val_read_cb(val_ctx, out, read_len);
|
||||
len = read_cb(cb_arg, out, read_len);
|
||||
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read value (err %d)", len);
|
||||
BT_ERR("Failed to read value (err %zu)", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
BT_HEXDUMP_DBG(out, len, "val");
|
||||
|
||||
if (len != read_len) {
|
||||
BT_ERR("Unexpected value length (%d != %zu)", len, read_len);
|
||||
BT_ERR("Unexpected value length (%zu != %zu)", len, read_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_set(int argc, char **argv, void *val_ctx)
|
||||
static int net_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct net_val net;
|
||||
int err;
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("val (null)");
|
||||
|
||||
bt_mesh_comp_unprovision();
|
||||
|
@ -159,7 +161,7 @@ static int net_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &net, sizeof(net));
|
||||
err = mesh_x_set(read_cb, cb_arg, &net, sizeof(net));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'net\'");
|
||||
return err;
|
||||
|
@ -174,12 +176,13 @@ static int net_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iv_set(int argc, char **argv, void *val_ctx)
|
||||
static int iv_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct iv_val iv;
|
||||
int err;
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("IV deleted");
|
||||
|
||||
bt_mesh.iv_index = 0U;
|
||||
|
@ -187,7 +190,7 @@ static int iv_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &iv, sizeof(iv));
|
||||
err = mesh_x_set(read_cb, cb_arg, &iv, sizeof(iv));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'iv\'");
|
||||
return err;
|
||||
|
@ -203,19 +206,20 @@ static int iv_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int seq_set(int argc, char **argv, void *val_ctx)
|
||||
static int seq_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct seq_val seq;
|
||||
int err;
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("val (null)");
|
||||
|
||||
bt_mesh.seq = 0U;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &seq, sizeof(seq));
|
||||
err = mesh_x_set(read_cb, cb_arg, &seq, sizeof(seq));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'seq\'");
|
||||
return err;
|
||||
|
@ -266,7 +270,8 @@ static struct bt_mesh_rpl *rpl_alloc(u16_t src)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int rpl_set(int argc, char **argv, void *val_ctx)
|
||||
static int rpl_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_rpl *entry;
|
||||
struct rpl_val rpl;
|
||||
|
@ -281,7 +286,7 @@ static int rpl_set(int argc, char **argv, void *val_ctx)
|
|||
src = strtol(argv[0], NULL, 16);
|
||||
entry = rpl_find(src);
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("val (null)");
|
||||
if (entry) {
|
||||
(void)memset(entry, 0, sizeof(*entry));
|
||||
|
@ -300,7 +305,7 @@ static int rpl_set(int argc, char **argv, void *val_ctx)
|
|||
}
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &rpl, sizeof(rpl));
|
||||
err = mesh_x_set(read_cb, cb_arg, &rpl, sizeof(rpl));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set `net`");
|
||||
return err;
|
||||
|
@ -315,7 +320,8 @@ static int rpl_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int net_key_set(int argc, char **argv, void *val_ctx)
|
||||
static int net_key_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_subnet *sub;
|
||||
struct net_key_val key;
|
||||
|
@ -325,7 +331,7 @@ static int net_key_set(int argc, char **argv, void *val_ctx)
|
|||
net_idx = strtol(argv[0], NULL, 16);
|
||||
sub = bt_mesh_subnet_get(net_idx);
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("val (null)");
|
||||
if (!sub) {
|
||||
BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
|
||||
|
@ -337,7 +343,7 @@ static int net_key_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &key, sizeof(key));
|
||||
err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'net-key\'");
|
||||
return err;
|
||||
|
@ -377,7 +383,8 @@ static int net_key_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int app_key_set(int argc, char **argv, void *val_ctx)
|
||||
static int app_key_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_app_key *app;
|
||||
struct app_key_val key;
|
||||
|
@ -386,7 +393,7 @@ static int app_key_set(int argc, char **argv, void *val_ctx)
|
|||
|
||||
app_idx = strtol(argv[0], NULL, 16);
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("val (null)");
|
||||
BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
|
||||
|
||||
|
@ -398,7 +405,7 @@ static int app_key_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &key, sizeof(key));
|
||||
err = mesh_x_set(read_cb, cb_arg, &key, sizeof(key));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'app-key\'");
|
||||
return err;
|
||||
|
@ -428,7 +435,8 @@ static int app_key_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hb_pub_set(int argc, char **argv, void *val_ctx)
|
||||
static int hb_pub_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
|
||||
struct hb_pub_val hb_val;
|
||||
|
@ -438,7 +446,7 @@ static int hb_pub_set(int argc, char **argv, void *val_ctx)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
pub->dst = BT_MESH_ADDR_UNASSIGNED;
|
||||
pub->count = 0U;
|
||||
pub->ttl = 0U;
|
||||
|
@ -449,7 +457,7 @@ static int hb_pub_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &hb_val, sizeof(hb_val));
|
||||
err = mesh_x_set(read_cb, cb_arg, &hb_val, sizeof(hb_val));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'hb_val\'");
|
||||
return err;
|
||||
|
@ -472,7 +480,8 @@ static int hb_pub_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cfg_set(int argc, char **argv, void *val_ctx)
|
||||
static int cfg_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
|
||||
int err;
|
||||
|
@ -481,14 +490,15 @@ static int cfg_set(int argc, char **argv, void *val_ctx)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
stored_cfg.valid = false;
|
||||
BT_DBG("Cleared configuration state");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
err = mesh_x_set(val_ctx, &stored_cfg.cfg, sizeof(stored_cfg.cfg));
|
||||
err = mesh_x_set(read_cb, cb_arg, &stored_cfg.cfg,
|
||||
sizeof(stored_cfg.cfg));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'cfg\'");
|
||||
return err;
|
||||
|
@ -500,23 +510,25 @@ static int cfg_set(int argc, char **argv, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set_bind(struct bt_mesh_model *mod, void *val_ctx)
|
||||
static int mod_set_bind(struct bt_mesh_model *mod, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int len, i;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
/* Start with empty array regardless of cleared or set value */
|
||||
for (i = 0; i < ARRAY_SIZE(mod->keys); i++) {
|
||||
mod->keys[i] = BT_MESH_KEY_UNUSED;
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("Cleared bindings for model");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = settings_val_read_cb(val_ctx, mod->keys, sizeof(mod->keys));
|
||||
len = read_cb(cb_arg, mod->keys, sizeof(mod->keys));
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read value (err %d)", len);
|
||||
BT_ERR("Failed to read value (err %zu)", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -525,21 +537,22 @@ static int mod_set_bind(struct bt_mesh_model *mod, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set_sub(struct bt_mesh_model *mod, void *val_ctx)
|
||||
static int mod_set_sub(struct bt_mesh_model *mod, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
/* Start with empty array regardless of cleared or set value */
|
||||
(void)memset(mod->groups, 0, sizeof(mod->groups));
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
BT_DBG("Cleared subscriptions for model");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = settings_val_read_cb(val_ctx, mod->groups, sizeof(mod->groups));
|
||||
len = read_cb(cb_arg, mod->groups, sizeof(mod->groups));
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read value (err %d)", len);
|
||||
BT_ERR("Failed to read value (err %zu)", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -548,7 +561,8 @@ static int mod_set_sub(struct bt_mesh_model *mod, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set_pub(struct bt_mesh_model *mod, void *val_ctx)
|
||||
static int mod_set_pub(struct bt_mesh_model *mod, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct mod_pub_val pub;
|
||||
int err;
|
||||
|
@ -558,7 +572,7 @@ static int mod_set_pub(struct bt_mesh_model *mod, void *val_ctx)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (settings_val_get_len_cb(val_ctx) == 0) {
|
||||
if (len_rd == 0) {
|
||||
mod->pub->addr = BT_MESH_ADDR_UNASSIGNED;
|
||||
mod->pub->key = 0U;
|
||||
mod->pub->cred = 0U;
|
||||
|
@ -571,7 +585,7 @@ static int mod_set_pub(struct bt_mesh_model *mod, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mesh_x_set(val_ctx, &pub, sizeof(pub));
|
||||
err = mesh_x_set(read_cb, cb_arg, &pub, sizeof(pub));
|
||||
if (err) {
|
||||
BT_ERR("Failed to set \'model-pub\'");
|
||||
return err;
|
||||
|
@ -591,7 +605,8 @@ static int mod_set_pub(struct bt_mesh_model *mod, void *val_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mod_set(bool vnd, int argc, char **argv, void *val_ctx)
|
||||
static int mod_set(bool vnd, int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
struct bt_mesh_model *mod;
|
||||
u8_t elem_idx, mod_idx;
|
||||
|
@ -617,34 +632,37 @@ static int mod_set(bool vnd, int argc, char **argv, void *val_ctx)
|
|||
}
|
||||
|
||||
if (!strcmp(argv[1], "bind")) {
|
||||
return mod_set_bind(mod, val_ctx);
|
||||
return mod_set_bind(mod, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "sub")) {
|
||||
return mod_set_sub(mod, val_ctx);
|
||||
return mod_set_sub(mod, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "pub")) {
|
||||
return mod_set_pub(mod, val_ctx);
|
||||
return mod_set_pub(mod, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
BT_WARN("Unknown module key %s", argv[1]);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int sig_mod_set(int argc, char **argv, void *val_ctx)
|
||||
static int sig_mod_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
return mod_set(false, argc, argv, val_ctx);
|
||||
return mod_set(false, argc, argv, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
static int vnd_mod_set(int argc, char **argv, void *val_ctx)
|
||||
static int vnd_mod_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
return mod_set(true, argc, argv, val_ctx);
|
||||
return mod_set(true, argc, argv, len_rd, read_cb, cb_arg);
|
||||
}
|
||||
|
||||
const struct mesh_setting {
|
||||
const char *name;
|
||||
int (*func)(int argc, char **argv, void *val_ctx);
|
||||
int (*func)(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg);
|
||||
} settings[] = {
|
||||
{ "Net", net_set },
|
||||
{ "IV", iv_set },
|
||||
|
@ -658,7 +676,8 @@ const struct mesh_setting {
|
|||
{ "v", vnd_mod_set },
|
||||
};
|
||||
|
||||
static int mesh_set(int argc, char **argv, void *val_ctx)
|
||||
static int mesh_set(int argc, char **argv, size_t len_rd,
|
||||
settings_read_cb read_cb, void *cb_arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -672,7 +691,8 @@ static int mesh_set(int argc, char **argv, void *val_ctx)
|
|||
argc--;
|
||||
argv++;
|
||||
|
||||
return settings[i].func(argc, argv, val_ctx);
|
||||
return settings[i].func(argc, argv, len_rd, read_cb,
|
||||
cb_arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,11 @@ int bt_settings_decode_key(char *key, bt_addr_le_t *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set(int argc, char **argv, void *value_ctx)
|
||||
static int set(int argc, char **argv, size_t len_rd, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
const struct bt_settings_handler *h;
|
||||
|
||||
for (h = _bt_settings_start; h < _bt_settings_end; h++) {
|
||||
|
@ -96,7 +98,8 @@ static int set(int argc, char **argv, void *value_ctx)
|
|||
argc--;
|
||||
argv++;
|
||||
|
||||
return h->set(argc, argv, value_ctx);
|
||||
return h->set(argc, argv, len_rd, read_cb,
|
||||
cb_arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,13 +110,12 @@ static int set(int argc, char **argv, void *value_ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
len = settings_val_read_cb(value_ctx, &bt_dev.id_addr,
|
||||
sizeof(bt_dev.id_addr));
|
||||
len = read_cb(cb_arg, &bt_dev.id_addr, sizeof(bt_dev.id_addr));
|
||||
|
||||
if (len < sizeof(bt_dev.id_addr[0])) {
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read ID address from storage"
|
||||
" (err %d)", len);
|
||||
" (err %zu)", len);
|
||||
} else {
|
||||
BT_ERR("Invalid length ID address in storage");
|
||||
BT_HEXDUMP_DBG(&bt_dev.id_addr, len,
|
||||
|
@ -137,11 +139,10 @@ static int set(int argc, char **argv, void *value_ctx)
|
|||
|
||||
#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
|
||||
if (!strcmp(argv[0], "name")) {
|
||||
len = settings_val_read_cb(value_ctx, &bt_dev.name,
|
||||
sizeof(bt_dev.name) - 1);
|
||||
len = read_cb(cb_arg, &bt_dev.name, sizeof(bt_dev.name) - 1);
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read device name from storage"
|
||||
" (err %d)", len);
|
||||
" (err %zu)", len);
|
||||
} else {
|
||||
bt_dev.name[len] = '\0';
|
||||
|
||||
|
@ -153,12 +154,11 @@ static int set(int argc, char **argv, void *value_ctx)
|
|||
|
||||
#if defined(CONFIG_BT_PRIVACY)
|
||||
if (!strcmp(argv[0], "irk")) {
|
||||
len = settings_val_read_cb(value_ctx, bt_dev.irk,
|
||||
sizeof(bt_dev.irk));
|
||||
len = read_cb(cb_arg, bt_dev.irk, sizeof(bt_dev.irk));
|
||||
if (len < sizeof(bt_dev.irk[0])) {
|
||||
if (len < 0) {
|
||||
BT_ERR("Failed to read IRK from storage"
|
||||
" (err %d)", len);
|
||||
" (err %zu)", len);
|
||||
} else {
|
||||
BT_ERR("Invalid length IRK in storage");
|
||||
(void)memset(bt_dev.irk, 0, sizeof(bt_dev.irk));
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
struct bt_settings_handler {
|
||||
const char *name;
|
||||
int (*set)(int argc, char **argv, void *value_ctx);
|
||||
int (*set)(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg);
|
||||
int (*commit)(void);
|
||||
int (*export)(int (*func)(const char *name, void *val,
|
||||
size_t val_len));
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
|
||||
menuconfig SETTINGS
|
||||
bool "Enable settings subsystem with non-volatile storage"
|
||||
# Only NFFS is currently supported as FS.
|
||||
# The reason in that FatFs doesn't implement the fs_rename() API
|
||||
depends on (FILE_SYSTEM && FILE_SYSTEM_NFFS) || (FCB && FLASH_PAGE_LAYOUT)
|
||||
help
|
||||
The settings subsystem allows its users to serialize and
|
||||
deserialize state in memory into and from non-volatile memory.
|
||||
|
@ -21,6 +18,12 @@ module-str = settings
|
|||
source "subsys/logging/Kconfig.template.log_config"
|
||||
endif
|
||||
|
||||
config SETTINGS_RUNTIME
|
||||
bool "runtime storage back-end"
|
||||
depends on SETTINGS
|
||||
help
|
||||
Enables runtime storage back-end.
|
||||
|
||||
# Hidden option to enable encoding length into settings entry
|
||||
config SETTINGS_ENCODE_LEN
|
||||
depends on SETTINGS
|
||||
|
@ -35,7 +38,9 @@ config SETTINGS_USE_BASE64
|
|||
|
||||
choice
|
||||
prompt "Storage back-end"
|
||||
optional
|
||||
default SETTINGS_FCB if FCB
|
||||
default SETTINGS_NONE
|
||||
depends on SETTINGS
|
||||
help
|
||||
Storage back-end to be used by the settings subsystem.
|
||||
|
@ -52,6 +57,16 @@ config SETTINGS_FS
|
|||
select SETTINGS_ENCODE_LEN
|
||||
help
|
||||
Use a file system as a settings storage back-end.
|
||||
|
||||
config SETTINGS_CUSTOM
|
||||
bool "CUSTOM"
|
||||
help
|
||||
Use a custom settings storage back-end.
|
||||
|
||||
config SETTINGS_NONE
|
||||
bool "NONE"
|
||||
help
|
||||
No storage back-end.
|
||||
endchoice
|
||||
|
||||
config SETTINGS_FCB_NUM_AREAS
|
||||
|
|
|
@ -7,5 +7,6 @@ zephyr_sources(
|
|||
settings_line.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_SETTINGS_RUNTIME settings_runtime.c)
|
||||
zephyr_sources_ifdef(CONFIG_SETTINGS_FS settings_file.c)
|
||||
zephyr_sources_ifdef(CONFIG_SETTINGS_FCB settings_fcb.c)
|
||||
|
|
|
@ -89,7 +89,7 @@ int settings_parse_name(char *name, int *name_argc, char *name_argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct settings_handler *settings_parse_and_lookup(char *name,
|
||||
struct settings_handler *settings_parse_and_lookup(char *name,
|
||||
int *name_argc,
|
||||
char *name_argv[])
|
||||
{
|
||||
|
@ -102,120 +102,12 @@ static struct settings_handler *settings_parse_and_lookup(char *name,
|
|||
return settings_handler_lookup(name_argv[0]);
|
||||
}
|
||||
|
||||
int settings_set_value_priv(char *name, void *val_read_cb_ctx, off_t off,
|
||||
u8_t is_runtime)
|
||||
int settings_commit(void)
|
||||
{
|
||||
int name_argc;
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
struct settings_handler *ch;
|
||||
struct read_value_cb_ctx value_ctx;
|
||||
|
||||
ch = settings_parse_and_lookup(name, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value_ctx.read_cb_ctx = val_read_cb_ctx;
|
||||
value_ctx.off = off;
|
||||
value_ctx.runtime = is_runtime;
|
||||
|
||||
return ch->h_set(name_argc - 1, &name_argv[1], (void *)&value_ctx);
|
||||
}
|
||||
|
||||
/* API */
|
||||
int settings_set_value(char *name, void *val_str, size_t len)
|
||||
{
|
||||
struct runtime_value_ctx rt_ctx;
|
||||
|
||||
rt_ctx.p_value = val_str;
|
||||
rt_ctx.size = len;
|
||||
|
||||
return settings_set_value_priv(name, &rt_ctx, 0, 1);
|
||||
}
|
||||
|
||||
/* API */
|
||||
int settings_val_read_cb(void *value_ctx, void *buf, size_t len)
|
||||
{
|
||||
struct read_value_cb_ctx *value_context = value_ctx;
|
||||
size_t len_read;
|
||||
int rc;
|
||||
struct runtime_value_ctx *rt_ctx;
|
||||
|
||||
if (value_context->runtime) {
|
||||
rt_ctx = value_context->read_cb_ctx;
|
||||
len_read = MIN(len, rt_ctx->size);
|
||||
memcpy(buf, rt_ctx->p_value, len_read);
|
||||
return len_read;
|
||||
} else {
|
||||
rc = settings_line_val_read(value_context->off, 0, buf, len,
|
||||
&len_read,
|
||||
value_context->read_cb_ctx);
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
return len_read;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* API */
|
||||
size_t settings_val_get_len_cb(void *value_ctx)
|
||||
{
|
||||
struct read_value_cb_ctx *value_context = value_ctx;
|
||||
struct runtime_value_ctx *rt_ctx;
|
||||
|
||||
if (value_context->runtime) {
|
||||
rt_ctx = value_context->read_cb_ctx;
|
||||
return rt_ctx->size;
|
||||
} else {
|
||||
return settings_line_val_get_len(value_context->off,
|
||||
value_context->read_cb_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get value in printable string form. If value is not string, the value
|
||||
* will be filled in *buf.
|
||||
* Return value will be pointer to beginning of that buffer,
|
||||
* except for string it will pointer to beginning of string.
|
||||
*/
|
||||
int settings_get_value(char *name, char *buf, int buf_len)
|
||||
{
|
||||
int name_argc;
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
struct settings_handler *ch;
|
||||
|
||||
ch = settings_parse_and_lookup(name, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ch->h_get) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return ch->h_get(name_argc - 1, &name_argv[1], buf, buf_len);
|
||||
}
|
||||
|
||||
int settings_commit(char *name)
|
||||
{
|
||||
int name_argc;
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
struct settings_handler *ch;
|
||||
int rc;
|
||||
int rc2;
|
||||
|
||||
if (name) {
|
||||
ch = settings_parse_and_lookup(name, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ch->h_commit) {
|
||||
return ch->h_commit();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
rc = 0;
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
|
||||
if (ch->h_commit) {
|
||||
|
@ -226,5 +118,4 @@ int settings_commit(char *name)
|
|||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,11 @@ LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL);
|
|||
#define SETTINGS_FCB_VERS 1
|
||||
|
||||
struct settings_fcb_load_cb_arg {
|
||||
load_cb cb;
|
||||
line_load_cb cb;
|
||||
void *cb_arg;
|
||||
};
|
||||
|
||||
static int settings_fcb_load(struct settings_store *cs, load_cb cb,
|
||||
void *cb_arg);
|
||||
static int settings_fcb_load(struct settings_store *cs);
|
||||
static int settings_fcb_save(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len);
|
||||
|
||||
|
@ -102,7 +101,7 @@ static int settings_fcb_load_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int settings_fcb_load(struct settings_store *cs, load_cb cb,
|
||||
static int settings_fcb_load_priv(struct settings_store *cs, line_load_cb cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct settings_fcb *cf = (struct settings_fcb *)cs;
|
||||
|
@ -118,6 +117,12 @@ static int settings_fcb_load(struct settings_store *cs, load_cb cb,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int settings_fcb_load(struct settings_store *cs)
|
||||
{
|
||||
return settings_fcb_load_priv(cs, settings_line_load_cb, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int read_handler(void *ctx, off_t off, char *buf, size_t *len)
|
||||
{
|
||||
struct fcb_entry_ctx *entry_ctx = ctx;
|
||||
|
@ -208,7 +213,7 @@ static void settings_fcb_compress(struct settings_fcb *cf)
|
|||
continue;
|
||||
}
|
||||
|
||||
rc = settings_entry_copy(&loc2, 0, &loc1, 0,
|
||||
rc = settings_line_entry_copy(&loc2, 0, &loc1, 0,
|
||||
loc1.loc.fe_data_len);
|
||||
if (rc) {
|
||||
continue;
|
||||
|
@ -243,7 +248,7 @@ static int write_handler(void *ctx, off_t off, char const *buf, size_t len)
|
|||
}
|
||||
|
||||
/* ::csi_save implementation */
|
||||
static int settings_fcb_save(struct settings_store *cs, const char *name,
|
||||
static int settings_fcb_save_priv(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len)
|
||||
{
|
||||
struct settings_fcb *cf = (struct settings_fcb *)cs;
|
||||
|
@ -284,6 +289,29 @@ static int settings_fcb_save(struct settings_store *cs, const char *name,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int settings_fcb_save(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len)
|
||||
{
|
||||
struct settings_line_dup_check_arg cdca;
|
||||
|
||||
if (val_len > 0 && value == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we're writing the same value again.
|
||||
*/
|
||||
cdca.name = name;
|
||||
cdca.val = (char *)value;
|
||||
cdca.is_dup = 0;
|
||||
cdca.val_len = val_len;
|
||||
settings_fcb_load_priv(cs, settings_line_dup_check_cb, &cdca);
|
||||
if (cdca.is_dup == 1) {
|
||||
return 0;
|
||||
}
|
||||
return settings_fcb_save_priv(cs, name, (char *)value, val_len);
|
||||
}
|
||||
|
||||
void settings_mount_fcb_backend(struct settings_fcb *cf)
|
||||
{
|
||||
u8_t rbs;
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
#include "settings/settings_file.h"
|
||||
#include "settings_priv.h"
|
||||
|
||||
static int settings_file_load(struct settings_store *cs, load_cb cb,
|
||||
void *cb_arg);
|
||||
static int settings_file_load(struct settings_store *cs);
|
||||
static int settings_file_save(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len);
|
||||
|
||||
|
@ -49,11 +48,8 @@ int settings_file_dst(struct settings_file *cf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to load configuration items. cb must be called for every configuration
|
||||
* item found.
|
||||
*/
|
||||
static int settings_file_load(struct settings_store *cs, load_cb cb,
|
||||
|
||||
static int settings_file_load_priv(struct settings_store *cs, line_load_cb cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct settings_file *cf = (struct settings_file *)cs;
|
||||
|
@ -110,6 +106,14 @@ static int settings_file_load(struct settings_store *cs, load_cb cb,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to load configuration items.
|
||||
*/
|
||||
static int settings_file_load(struct settings_store *cs)
|
||||
{
|
||||
return settings_file_load_priv(cs, settings_line_load_cb, NULL);
|
||||
}
|
||||
|
||||
static void settings_tmpfile(char *dst, const char *src, char *pfx)
|
||||
{
|
||||
int len;
|
||||
|
@ -247,7 +251,7 @@ int settings_file_save_and_compress(struct settings_file *cf, const char *name,
|
|||
loc2 = loc1;
|
||||
loc2.len += 2;
|
||||
loc2.seek -= 2;
|
||||
rc = settings_entry_copy(&loc3, 0, &loc2, 0, loc2.len);
|
||||
rc = settings_line_entry_copy(&loc3, 0, &loc2, 0, loc2.len);
|
||||
if (rc) {
|
||||
/* compressed file might be corrupted */
|
||||
goto end_rolback;
|
||||
|
@ -287,10 +291,7 @@ end_rolback:
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to save configuration.
|
||||
*/
|
||||
static int settings_file_save(struct settings_store *cs, const char *name,
|
||||
static int settings_file_save_priv(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len)
|
||||
{
|
||||
struct settings_file *cf = (struct settings_file *)cs;
|
||||
|
@ -336,6 +337,33 @@ static int settings_file_save(struct settings_store *cs, const char *name,
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to save configuration.
|
||||
*/
|
||||
static int settings_file_save(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len)
|
||||
{
|
||||
struct settings_line_dup_check_arg cdca;
|
||||
|
||||
if (val_len > 0 && value == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we're writing the same value again.
|
||||
*/
|
||||
cdca.name = name;
|
||||
cdca.val = (char *)value;
|
||||
cdca.is_dup = 0;
|
||||
cdca.val_len = val_len;
|
||||
settings_file_load_priv(cs, settings_line_dup_check_cb, &cdca);
|
||||
if (cdca.is_dup == 1) {
|
||||
return 0;
|
||||
}
|
||||
return settings_file_save_priv(cs, name, (char *)value, val_len);
|
||||
}
|
||||
|
||||
static int read_handler(void *ctx, off_t off, char *buf, size_t *len)
|
||||
{
|
||||
struct line_entry_ctx *entry_ctx = ctx;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
void settings_init(void);
|
||||
|
||||
int settings_backend_init(void);
|
||||
|
||||
#ifdef CONFIG_SETTINGS_FS
|
||||
#include <fs.h>
|
||||
|
||||
|
@ -25,7 +27,7 @@ static struct settings_file config_init_settings_file = {
|
|||
.cf_maxlines = CONFIG_SETTINGS_FS_MAX_LINES
|
||||
};
|
||||
|
||||
static void settings_init_fs(void)
|
||||
int settings_backend_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -40,6 +42,20 @@ static void settings_init_fs(void)
|
|||
}
|
||||
|
||||
settings_mount_fs_backend(&config_init_settings_file);
|
||||
|
||||
/*
|
||||
* Must be called after root FS has been initialized.
|
||||
*/
|
||||
rc = fs_mkdir(CONFIG_SETTINGS_FS_DIR);
|
||||
|
||||
/*
|
||||
* The following lines mask the file exist error.
|
||||
*/
|
||||
if (rc == -EEXIST) {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_SETTINGS_FCB)
|
||||
|
@ -53,7 +69,7 @@ static struct settings_fcb config_init_settings_fcb = {
|
|||
.cf_fcb.f_sectors = settings_fcb_area,
|
||||
};
|
||||
|
||||
static void settings_init_fcb(void)
|
||||
int settings_backend_init(void)
|
||||
{
|
||||
u32_t cnt = CONFIG_SETTINGS_FCB_NUM_AREAS + 1;
|
||||
int rc;
|
||||
|
@ -95,14 +111,20 @@ static void settings_init_fcb(void)
|
|||
}
|
||||
|
||||
settings_mount_fcb_backend(&config_init_settings_fcb);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#elif defined(CONFIG_SETTINGS_NONE)
|
||||
int settings_backend_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int settings_subsys_init(void)
|
||||
{
|
||||
static bool settings_initialized;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (settings_initialized) {
|
||||
return 0;
|
||||
|
@ -110,23 +132,7 @@ int settings_subsys_init(void)
|
|||
|
||||
settings_init();
|
||||
|
||||
#ifdef CONFIG_SETTINGS_FS
|
||||
settings_init_fs(); /* func rises kernel panic once error */
|
||||
|
||||
/*
|
||||
* Must be called after root FS has been initialized.
|
||||
*/
|
||||
err = fs_mkdir(CONFIG_SETTINGS_FS_DIR);
|
||||
/*
|
||||
* The following lines mask the file exist error.
|
||||
*/
|
||||
if (err == -EEXIST) {
|
||||
err = 0;
|
||||
}
|
||||
#elif defined(CONFIG_SETTINGS_FCB)
|
||||
settings_init_fcb(); /* func rises kernel panic once error */
|
||||
err = 0;
|
||||
#endif
|
||||
err = settings_backend_init(); /* func rises kernel panic once error */
|
||||
|
||||
if (!err) {
|
||||
settings_initialized = true;
|
||||
|
|
|
@ -411,7 +411,7 @@ int settings_line_name_read(char *out, size_t len_req, size_t *len_read,
|
|||
}
|
||||
|
||||
|
||||
int settings_entry_copy(void *dst_ctx, off_t dst_off, void *src_ctx,
|
||||
int settings_line_entry_copy(void *dst_ctx, off_t dst_off, void *src_ctx,
|
||||
off_t src_off, size_t len)
|
||||
{
|
||||
int rc;
|
||||
|
@ -451,3 +451,114 @@ void settings_line_io_init(int (*read_cb)(void *ctx, off_t off, char *buf,
|
|||
settings_io_cb.get_len_cb = get_len_cb;
|
||||
settings_io_cb.rwbs = io_rwbs;
|
||||
}
|
||||
|
||||
|
||||
/* val_off - offset of value-string within line entries */
|
||||
static int settings_line_cmp(char const *val, size_t val_len,
|
||||
void *val_read_cb_ctx, off_t val_off)
|
||||
{
|
||||
size_t len_read, exp_len;
|
||||
size_t rem;
|
||||
char buf[16];
|
||||
int rc;
|
||||
off_t off = 0;
|
||||
|
||||
for (rem = val_len; rem > 0; rem -= len_read) {
|
||||
len_read = exp_len = MIN(sizeof(buf), rem);
|
||||
rc = settings_line_val_read(val_off, off, buf, len_read,
|
||||
&len_read, val_read_cb_ctx);
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_read != exp_len) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = memcmp(val, buf, len_read);
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
val += len_read;
|
||||
off += len_read;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void settings_line_dup_check_cb(char *name, void *val_read_cb_ctx,
|
||||
off_t off, void *cb_arg)
|
||||
{
|
||||
struct settings_line_dup_check_arg *cdca;
|
||||
size_t len_read;
|
||||
|
||||
cdca = (struct settings_line_dup_check_arg *)cb_arg;
|
||||
if (strcmp(name, cdca->name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len_read = settings_line_val_get_len(off, val_read_cb_ctx);
|
||||
if (len_read != cdca->val_len) {
|
||||
cdca->is_dup = 0;
|
||||
} else if (len_read == 0) {
|
||||
cdca->is_dup = 1;
|
||||
} else {
|
||||
if (!settings_line_cmp(cdca->val, cdca->val_len,
|
||||
val_read_cb_ctx, off)) {
|
||||
cdca->is_dup = 1;
|
||||
} else {
|
||||
cdca->is_dup = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t settings_line_read_cb(void *cb_arg, void *data, size_t len)
|
||||
{
|
||||
struct settings_line_read_value_cb_ctx *value_context = cb_arg;
|
||||
size_t len_read;
|
||||
int rc;
|
||||
|
||||
rc = settings_line_val_read(value_context->off, 0, data, len,
|
||||
&len_read,
|
||||
value_context->read_cb_ctx);
|
||||
|
||||
if (rc == 0) {
|
||||
return len_read;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void settings_line_load_cb(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg)
|
||||
{
|
||||
int name_argc;
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
struct settings_handler *ch;
|
||||
struct settings_line_read_value_cb_ctx value_ctx;
|
||||
int rc;
|
||||
size_t len;
|
||||
|
||||
ch = settings_parse_and_lookup(name, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return;
|
||||
}
|
||||
|
||||
value_ctx.read_cb_ctx = val_read_cb_ctx;
|
||||
value_ctx.off = off;
|
||||
|
||||
len = settings_line_val_get_len(off, val_read_cb_ctx);
|
||||
|
||||
rc = ch->h_set(name_argc - 1, &name_argv[1], len, settings_line_read_cb,
|
||||
(void *)&value_ctx);
|
||||
|
||||
if (rc != 0) {
|
||||
LOG_ERR("set-value failure. key: %s error(%d)",
|
||||
log_strdup(name), rc);
|
||||
} else {
|
||||
LOG_DBG("set-value OK. key: %s",
|
||||
log_strdup(name));
|
||||
}
|
||||
(void)rc;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,27 @@ int settings_line_write(const char *name, const char *value, size_t val_len,
|
|||
/* Get len of record without alignment to write-block-size */
|
||||
int settings_line_len_calc(const char *name, size_t val_len);
|
||||
|
||||
void settings_line_dup_check_cb(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg);
|
||||
|
||||
void settings_line_load_cb(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg);
|
||||
|
||||
typedef void (*line_load_cb)(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg);
|
||||
|
||||
struct settings_line_read_value_cb_ctx {
|
||||
void *read_cb_ctx;
|
||||
off_t off;
|
||||
};
|
||||
|
||||
struct settings_line_dup_check_arg {
|
||||
const char *name;
|
||||
const char *val;
|
||||
size_t val_len;
|
||||
int is_dup;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SETTINGS_ENCODE_LEN
|
||||
/* in storage line contex */
|
||||
struct line_entry_ctx {
|
||||
|
@ -87,7 +108,7 @@ int settings_line_name_read(char *out, size_t len_req, size_t *len_read,
|
|||
|
||||
size_t settings_line_val_get_len(off_t val_off, void *read_cb_ctx);
|
||||
|
||||
int settings_entry_copy(void *dst_ctx, off_t dst_off, void *src_ctx,
|
||||
int settings_line_entry_copy(void *dst_ctx, off_t dst_off, void *src_ctx,
|
||||
off_t src_off, size_t len);
|
||||
|
||||
void settings_line_io_init(int (*read_cb)(void *ctx, off_t off, char *buf,
|
||||
|
@ -97,37 +118,6 @@ void settings_line_io_init(int (*read_cb)(void *ctx, off_t off, char *buf,
|
|||
size_t (*get_len_cb)(void *ctx),
|
||||
u8_t io_rwbs);
|
||||
|
||||
int settings_set_value_priv(char *name, void *val_read_cb_ctx, off_t off,
|
||||
u8_t is_runtime);
|
||||
|
||||
/*
|
||||
* API for config storage.
|
||||
*/
|
||||
typedef void (*load_cb)(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg);
|
||||
|
||||
struct settings_store_itf {
|
||||
int (*csi_load)(struct settings_store *cs, load_cb cb, void *cb_arg);
|
||||
int (*csi_save_start)(struct settings_store *cs);
|
||||
int (*csi_save)(struct settings_store *cs, const char *name,
|
||||
const char *value, size_t val_len);
|
||||
int (*csi_save_end)(struct settings_store *cs);
|
||||
};
|
||||
|
||||
struct read_value_cb_ctx {
|
||||
void *read_cb_ctx;
|
||||
off_t off;
|
||||
u8_t runtime;
|
||||
};
|
||||
|
||||
/* suports runtime settings_set_value operation */
|
||||
struct runtime_value_ctx {
|
||||
void *p_value;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
void settings_src_register(struct settings_store *cs);
|
||||
void settings_dst_register(struct settings_store *cs);
|
||||
|
||||
extern sys_slist_t settings_load_srcs;
|
||||
extern sys_slist_t settings_handlers;
|
||||
|
|
68
subsys/settings/src/settings_runtime.c
Normal file
68
subsys/settings/src/settings_runtime.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* Copyright (c) 2019 Laczen
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <settings/settings.h>
|
||||
#include "settings_priv.h"
|
||||
|
||||
static ssize_t settings_runtime_read_cb(void *cb_arg, void *data, size_t len)
|
||||
{
|
||||
memcpy(data, cb_arg, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
int settings_runtime_set(const char *name, void *data, size_t len)
|
||||
{
|
||||
struct settings_handler *ch;
|
||||
char name1[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN];
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
int name_argc;
|
||||
|
||||
strcpy(name1, name);
|
||||
ch = settings_parse_and_lookup(name1, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ch->h_set(name_argc - 1, &name_argv[1], len,
|
||||
settings_runtime_read_cb, data);
|
||||
}
|
||||
|
||||
int settings_runtime_get(const char *name, void *data, size_t len)
|
||||
{
|
||||
struct settings_handler *ch;
|
||||
char name1[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN];
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
int name_argc;
|
||||
|
||||
strcpy(name1, name);
|
||||
ch = settings_parse_and_lookup(name1, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ch->h_get(name_argc - 1, &name_argv[1], data, len);
|
||||
}
|
||||
|
||||
int settings_runtime_commit(const char *name)
|
||||
{
|
||||
struct settings_handler *ch;
|
||||
char name1[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN];
|
||||
char *name_argv[SETTINGS_MAX_DIR_DEPTH];
|
||||
int name_argc;
|
||||
|
||||
strcpy(name1, name);
|
||||
ch = settings_parse_and_lookup(name1, &name_argc, name_argv);
|
||||
if (!ch) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ch->h_commit) {
|
||||
return ch->h_commit();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -19,13 +19,6 @@
|
|||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL);
|
||||
|
||||
struct settings_dup_check_arg {
|
||||
const char *name;
|
||||
const char *val;
|
||||
size_t val_len;
|
||||
int is_dup;
|
||||
};
|
||||
|
||||
sys_slist_t settings_load_srcs;
|
||||
struct settings_store *settings_save_dst;
|
||||
|
||||
|
@ -47,21 +40,6 @@ void settings_dst_register(struct settings_store *cs)
|
|||
settings_save_dst = cs;
|
||||
}
|
||||
|
||||
static void settings_load_cb(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg)
|
||||
{
|
||||
int rc = settings_set_value_priv(name, val_read_cb_ctx, off, 0);
|
||||
|
||||
if (rc != 0) {
|
||||
LOG_ERR("set-value failure. key: %s error(%d)",
|
||||
log_strdup(name), rc);
|
||||
} else {
|
||||
LOG_DBG("set-value OK. key: %s",
|
||||
log_strdup(name));
|
||||
}
|
||||
(void)rc;
|
||||
}
|
||||
|
||||
int settings_load(void)
|
||||
{
|
||||
struct settings_store *cs;
|
||||
|
@ -74,69 +52,9 @@ int settings_load(void)
|
|||
*/
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
|
||||
cs->cs_itf->csi_load(cs, settings_load_cb, NULL);
|
||||
}
|
||||
return settings_commit(NULL);
|
||||
}
|
||||
|
||||
/* val_off - offset of value-string within line entries */
|
||||
static int settings_cmp(char const *val, size_t val_len, void *val_read_cb_ctx,
|
||||
off_t val_off)
|
||||
{
|
||||
size_t len_read, exp_len;
|
||||
size_t rem;
|
||||
char buf[16];
|
||||
int rc;
|
||||
off_t off = 0;
|
||||
|
||||
for (rem = val_len; rem > 0; rem -= len_read) {
|
||||
len_read = exp_len = MIN(sizeof(buf), rem);
|
||||
rc = settings_line_val_read(val_off, off, buf, len_read,
|
||||
&len_read, val_read_cb_ctx);
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_read != exp_len) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = memcmp(val, buf, len_read);
|
||||
if (rc) {
|
||||
break;
|
||||
}
|
||||
val += len_read;
|
||||
off += len_read;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void settings_dup_check_cb(char *name, void *val_read_cb_ctx, off_t off,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct settings_dup_check_arg *cdca = (struct settings_dup_check_arg *)
|
||||
cb_arg;
|
||||
size_t len_read;
|
||||
|
||||
if (strcmp(name, cdca->name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
len_read = settings_line_val_get_len(off, val_read_cb_ctx);
|
||||
if (len_read != cdca->val_len) {
|
||||
cdca->is_dup = 0;
|
||||
} else if (len_read == 0) {
|
||||
cdca->is_dup = 1;
|
||||
} else {
|
||||
if (!settings_cmp(cdca->val, cdca->val_len,
|
||||
val_read_cb_ctx, off)) {
|
||||
cdca->is_dup = 1;
|
||||
} else {
|
||||
cdca->is_dup = 0;
|
||||
}
|
||||
cs->cs_itf->csi_load(cs);
|
||||
}
|
||||
return settings_commit();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -145,28 +63,12 @@ static void settings_dup_check_cb(char *name, void *val_read_cb_ctx, off_t off,
|
|||
int settings_save_one(const char *name, void *value, size_t val_len)
|
||||
{
|
||||
struct settings_store *cs;
|
||||
struct settings_dup_check_arg cdca;
|
||||
|
||||
cs = settings_save_dst;
|
||||
if (!cs) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (val_len > 0 && value == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we're writing the same value again.
|
||||
*/
|
||||
cdca.name = name;
|
||||
cdca.val = (char *)value;
|
||||
cdca.is_dup = 0;
|
||||
cdca.val_len = val_len;
|
||||
cs->cs_itf->csi_load(cs, settings_dup_check_cb, &cdca);
|
||||
if (cdca.is_dup == 1) {
|
||||
return 0;
|
||||
}
|
||||
return cs->cs_itf->csi_save(cs, name, (char *)value, val_len);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,5 +7,6 @@ CONFIG_ARM_MPU=n
|
|||
CONFIG_FCB=y
|
||||
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_RUNTIME=y
|
||||
CONFIG_SETTINGS_FCB=y
|
||||
CONFIG_SETTINGS_USE_BASE64=y
|
||||
|
|
|
@ -7,5 +7,6 @@ CONFIG_ARM_MPU=n
|
|||
CONFIG_FCB=y
|
||||
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_RUNTIME=y
|
||||
CONFIG_SETTINGS_FCB=y
|
||||
CONFIG_SETTINGS_USE_BASE64=n
|
||||
|
|
|
@ -24,16 +24,19 @@ int test_export_block;
|
|||
int c2_var_count = 1;
|
||||
|
||||
int c1_handle_get(int argc, char **argv, char *val, int val_len_max);
|
||||
int c1_handle_set(int argc, char **argv, void *value_ctx);
|
||||
int c1_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg);
|
||||
int c1_handle_commit(void);
|
||||
int c1_handle_export(int (*cb)(const char *name, void *value, size_t val_len));
|
||||
|
||||
int c2_handle_get(int argc, char **argv, char *val, int val_len_max);
|
||||
int c2_handle_set(int argc, char **argv, void *value_ctx);
|
||||
int c2_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg);
|
||||
int c2_handle_export(int (*cb)(const char *name, void *value, size_t val_len));
|
||||
|
||||
int c3_handle_get(int argc, char **argv, char *val, int val_len_max);
|
||||
int c3_handle_set(int argc, char **argv, void *value_ctx);
|
||||
int c3_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg);
|
||||
int c3_handle_export(int (*cb)(const char *name, void *value, size_t val_len));
|
||||
|
||||
struct settings_handler c_test_handlers[] = {
|
||||
|
@ -82,29 +85,30 @@ int c1_handle_get(int argc, char **argv, char *val, int val_len_max)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int c1_handle_set(int argc, char **argv, void *value_ctx)
|
||||
int c1_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
size_t val_len;
|
||||
int rc;
|
||||
|
||||
test_set_called = 1;
|
||||
if (argc == 1 && !strcmp(argv[0], "mybar")) {
|
||||
rc = settings_val_read_cb(value_ctx, &val8, sizeof(val8));
|
||||
rc = read_cb(cb_arg, &val8, sizeof(val8));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "mybar64")) {
|
||||
rc = settings_val_read_cb(value_ctx, &val64, sizeof(val64));
|
||||
rc = read_cb(cb_arg, &val64, sizeof(val64));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "unaligned")) {
|
||||
val_len = settings_val_get_len_cb(value_ctx);
|
||||
val_len = len;
|
||||
zassert_equal(val_len, sizeof(val8_un),
|
||||
"value length: %d, ought equal 1", val_len);
|
||||
rc = settings_val_read_cb(value_ctx, &val8_un, sizeof(val8_un));
|
||||
rc = read_cb(cb_arg, &val8_un, sizeof(val8_un));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
@ -241,7 +245,8 @@ int c2_handle_get(int argc, char **argv, char *val, int val_len_max)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int c2_handle_set(int argc, char **argv, void *value_ctx)
|
||||
int c2_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
char *valptr;
|
||||
int rc;
|
||||
|
@ -252,8 +257,7 @@ int c2_handle_set(int argc, char **argv, void *value_ctx)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
rc = settings_val_read_cb(value_ctx, valptr,
|
||||
sizeof(val_string[0]));
|
||||
rc = read_cb(cb_arg, valptr, sizeof(val_string[0]));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
if (rc == 0) {
|
||||
(void)memset(valptr, 0, sizeof(val_string[0]));
|
||||
|
@ -288,16 +292,17 @@ int c3_handle_get(int argc, char **argv, char *val, int val_len_max)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int c3_handle_set(int argc, char **argv, void *value_ctx)
|
||||
int c3_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
int rc;
|
||||
size_t val_len;
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "v")) {
|
||||
val_len = settings_val_get_len_cb(value_ctx);
|
||||
val_len = len;
|
||||
zassert_true(val_len == 4, "bad set-value size");
|
||||
|
||||
rc = settings_val_read_cb(value_ctx, &val32, sizeof(val32));
|
||||
rc = read_cb(cb_arg, &val32, sizeof(val32));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ CONFIG_ARM_MPU=n
|
|||
CONFIG_FCB=y
|
||||
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_RUNTIME=y
|
||||
CONFIG_SETTINGS_FCB=y
|
||||
|
||||
CONFIG_REBOOT=y
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
|
||||
static u32_t val32;
|
||||
|
||||
static int c1_set(int argc, char **argv, void *value_ctx)
|
||||
static int c1_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "val32")) {
|
||||
rc = settings_val_read_cb(value_ctx, &val32, sizeof(val32));
|
||||
rc = read_cb(cb_arg, &val32, sizeof(val32));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,5 +23,6 @@ CONFIG_FILE_SYSTEM_NFFS=y
|
|||
CONFIG_NFFS_FILESYSTEM_MAX_AREAS=12
|
||||
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_RUNTIME=y
|
||||
CONFIG_SETTINGS_FS=y
|
||||
CONFIG_SETTINGS_USE_BASE64=y
|
||||
|
|
|
@ -22,5 +22,6 @@ CONFIG_FILE_SYSTEM_NFFS=y
|
|||
CONFIG_NFFS_FILESYSTEM_MAX_AREAS=12
|
||||
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_RUNTIME=y
|
||||
CONFIG_SETTINGS_FS=y
|
||||
CONFIG_SETTINGS_USE_BASE64=n
|
||||
|
|
|
@ -23,7 +23,8 @@ int test_export_block;
|
|||
int c2_var_count = 1;
|
||||
|
||||
int c1_handle_get(int argc, char **argv, char *val, int val_len_max);
|
||||
int c1_handle_set(int argc, char **argv, void *value_ctx);
|
||||
int c1_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg);
|
||||
int c1_handle_commit(void);
|
||||
int c1_handle_export(int (*cb)(const char *name, void *value, size_t val_len));
|
||||
|
||||
|
@ -64,35 +65,36 @@ int c1_handle_get(int argc, char **argv, char *val, int val_len_max)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
int c1_handle_set(int argc, char **argv, void *value_ctx)
|
||||
int c1_handle_set(int argc, char **argv, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg)
|
||||
{
|
||||
int rc;
|
||||
size_t val_len;
|
||||
|
||||
test_set_called = 1;
|
||||
if (argc == 1 && !strcmp(argv[0], "mybar")) {
|
||||
val_len = settings_val_get_len_cb(value_ctx);
|
||||
val_len = len;
|
||||
zassert_true(val_len == 1, "bad set-value size");
|
||||
|
||||
rc = settings_val_read_cb(value_ctx, &val8, sizeof(val8));
|
||||
rc = read_cb(cb_arg, &val8, sizeof(val8));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "mybar16")) {
|
||||
val_len = settings_val_get_len_cb(value_ctx);
|
||||
val_len = len;
|
||||
zassert_true(val_len == 2, "bad set-value size");
|
||||
|
||||
rc = settings_val_read_cb(value_ctx, &val16, sizeof(val16));
|
||||
rc = read_cb(cb_arg, &val16, sizeof(val16));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 1 && !strcmp(argv[0], "mybar64")) {
|
||||
val_len = settings_val_get_len_cb(value_ctx);
|
||||
val_len = len;
|
||||
zassert_true(val_len == 8, "bad set-value size");
|
||||
|
||||
rc = settings_val_read_cb(value_ctx, &val64, sizeof(val64));
|
||||
rc = read_cb(cb_arg, &val64, sizeof(val64));
|
||||
zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ void config_empty_lookups(void)
|
|||
char tmp[64];
|
||||
|
||||
strcpy(name, "foo/bar");
|
||||
rc = settings_set_value(name, "tmp", 4);
|
||||
zassert_true(rc != 0, "settings_set_value callback");
|
||||
rc = settings_runtime_set(name, "tmp", 4);
|
||||
zassert_true(rc != 0, "settings_runtime_set callback");
|
||||
|
||||
strcpy(name, "foo/bar");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
zassert_true(rc == -EINVAL, "settings_get_value callback");
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_true(rc == -EINVAL, "settings_runtime_get callback");
|
||||
}
|
||||
|
|
|
@ -13,19 +13,19 @@ void test_config_commit(void)
|
|||
int rc;
|
||||
|
||||
strcpy(name, "bar");
|
||||
rc = settings_commit(name);
|
||||
rc = settings_runtime_commit(name);
|
||||
zassert_true(rc, "commit-nonexisting-tree call should succeed");
|
||||
zassert_true(ctest_get_call_state() == 0,
|
||||
"a handler was called unexpectedly");
|
||||
|
||||
rc = settings_commit(NULL);
|
||||
rc = settings_commit();
|
||||
zassert_true(rc == 0, "commit-All call should succeed");
|
||||
zassert_true(test_commit_called == 1,
|
||||
"the COMMIT handler wasn't called");
|
||||
ctest_clear_call_state();
|
||||
|
||||
strcpy(name, "myfoo");
|
||||
rc = settings_commit(name);
|
||||
rc = settings_runtime_commit(name);
|
||||
zassert_true(rc == 0, "commit-a-tree call should succeed");
|
||||
zassert_true(test_commit_called == 1,
|
||||
"the COMMIT handler wasn't called");
|
||||
|
|
|
@ -16,7 +16,7 @@ void test_config_getset_int(void)
|
|||
|
||||
small_value = 42U;
|
||||
strcpy(name, "myfoo/mybar");
|
||||
rc = settings_set_value(name, &small_value, sizeof(small_value));
|
||||
rc = settings_runtime_set(name, &small_value, sizeof(small_value));
|
||||
zassert_true(rc == 0, "can not set key value");
|
||||
zassert_true(test_set_called == 1, "the SET handler wasn't called");
|
||||
zassert_true(val8 == 42,
|
||||
|
@ -24,7 +24,7 @@ void test_config_getset_int(void)
|
|||
ctest_clear_call_state();
|
||||
|
||||
strcpy(name, "myfoo/mybar");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_true(rc == 1, "the key value should been available");
|
||||
zassert_true(test_get_called == 1, "the GET handler wasn't called");
|
||||
zassert_equal(42, tmp[0], "unexpected value fetched");
|
||||
|
|
|
@ -16,7 +16,7 @@ void test_config_getset_int64(void)
|
|||
|
||||
new_val64 = 0x8012345678901234;
|
||||
strcpy(name, "myfoo/mybar64");
|
||||
rc = settings_set_value(name, &new_val64, sizeof(s64_t));
|
||||
rc = settings_runtime_set(name, &new_val64, sizeof(s64_t));
|
||||
zassert_true(rc == 0, "can't set value");
|
||||
zassert_true(test_set_called == 1, "the SET handler wasn't called");
|
||||
zassert_equal(val64, 0x8012345678901234,
|
||||
|
@ -24,7 +24,7 @@ void test_config_getset_int64(void)
|
|||
ctest_clear_call_state();
|
||||
|
||||
strcpy(name, "myfoo/mybar64");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_equal(rc, sizeof(s64_t), "the key value should been available");
|
||||
zassert_true(test_get_called == 1, "the GET handler wasn't called");
|
||||
memcpy(&new_val64, tmp, sizeof(s64_t));
|
||||
|
@ -34,7 +34,7 @@ void test_config_getset_int64(void)
|
|||
|
||||
new_val64 = 1;
|
||||
strcpy(name, "myfoo/mybar64");
|
||||
rc = settings_set_value(name, &new_val64, sizeof(s64_t));
|
||||
rc = settings_runtime_set(name, &new_val64, sizeof(s64_t));
|
||||
zassert_true(rc == 0, "can't set value");
|
||||
zassert_true(test_set_called == 1, "the SET handler wasn't called");
|
||||
zassert_equal(val64, 1,
|
||||
|
@ -42,7 +42,7 @@ void test_config_getset_int64(void)
|
|||
ctest_clear_call_state();
|
||||
|
||||
strcpy(name, "myfoo/mybar64");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_equal(rc, sizeof(s64_t), "the key value should been available");
|
||||
zassert_true(test_get_called == 1, "the GET handler wasn't called");
|
||||
memcpy(&new_val64, tmp, sizeof(s64_t));
|
||||
|
|
|
@ -15,26 +15,26 @@ void test_config_getset_unknown(void)
|
|||
int rc;
|
||||
|
||||
strcpy(name, "foo/bar");
|
||||
rc = settings_set_value(name, "tmp", 4);
|
||||
rc = settings_runtime_set(name, "tmp", 4);
|
||||
zassert_true(rc != 0, "set value should fail");
|
||||
zassert_true(ctest_get_call_state() == 0,
|
||||
"a handler was called unexpectedly");
|
||||
|
||||
strcpy(name, "foo/bar");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_true(rc == -EINVAL, "value should been unreachable");
|
||||
zassert_true(ctest_get_call_state() == 0,
|
||||
"a handler was called unexpectedly");
|
||||
|
||||
strcpy(name, "myfoo/bar");
|
||||
rc = settings_set_value(name, "tmp", 4);
|
||||
rc = settings_runtime_set(name, "tmp", 4);
|
||||
zassert_true(rc == -ENOENT, "unexpected failure retval\n");
|
||||
zassert_true(test_set_called == 1,
|
||||
"the GET handler wasn't called");
|
||||
ctest_clear_call_state();
|
||||
|
||||
strcpy(name, "myfoo/bar");
|
||||
rc = settings_get_value(name, tmp, sizeof(tmp));
|
||||
rc = settings_runtime_get(name, tmp, sizeof(tmp));
|
||||
zassert_true(rc == -ENOENT, "value should been unreachable\n");
|
||||
zassert_true(test_get_called == 1,
|
||||
"the SET handler wasn't called");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue