Skip to content
Permalink
Browse files

subsys/settings: Enable handler ROM registration

Add the possibility to register handles to ROM using a new macro
SETTINGS_REGISTER_STATIC(handler), the handler is of type
settings_handler_stat and has to be declared as const:

```
const struct settings_handler_stat test_handler = {
	.name = "test", /* this can also be "ps/data"
	.h_get = get,
	.h_set = set,
	.h_commit = NULL, /* NULL defines can be ommited */
	.h_export = NULL  /* NULL defines can be ommited */
};
SETTINGS_REGISTER_STATIC(test_handler);
```

To maintain support for handlers stored in RAM (dynamic handlers)
`CONFIG_SETTINGS_DYNAMIC_HANDLERS`must be enabled, which is by default.

When registering static handlers there is no check if this handler has
been registered earlier, the latest registered static handler will be
considered valid for any set/get routine, while the commit and export
routines will be executed for both registered handlers.

When a dynamic handler is registered a check is done to see if there was
an earlier registration of the name as a static or dynamic handler
registration will fail.

To get to the lowest possible RAM usage it is advised to set
`CONFIG_SETTINGS_DYNAMIC_HANDLERS=n`.

Updates:

a. Changed usage of RAM to DYNAMIC/dynamic, ROM to STATIC/static
b. Updated settings.h to remove added #if defined()
c. Make static handlers always enabled
d. Corrected error introduced in common-rom.ld.
e. Changed return value of settings_parse_and_lookup to
   settings_handler_stat type to reduce stack usage.
f. Updated the name generated to store a handler item in ROM. It now
   uses the name used to register in combination with the line where
   SETTINGS_REGISTER_STATIC() is called.
g. renamed settings_handler_stat type to settings_handler_static
h. renamed SETTINGS_REGISTER_STATIC to SETTINGS_STATIC_HANDLER_DEFINE()

Signed-off-by: Laczen JMS <laczenjms@gmail.com>
  • Loading branch information...
Laczen authored and carlescufi committed Jun 18, 2019
1 parent f91d838 commit c20ff1150f717d79374997ed3b429b2449d2c3b8
@@ -100,6 +100,15 @@
_bt_services_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)

#if defined(CONFIG_SETTINGS)
SECTION_DATA_PROLOGUE(_settings_handlers_area,,SUBALIGN(4))
{
_settings_handler_static_list_start = .;
KEEP(*(SORT_BY_NAME("._settings_handler_static.static.*")))
_settings_handler_static_list_end = .;
} GROUP_LINK_IN(ROMABLE_REGION)
#endif

#if defined(CONFIG_BT_SETTINGS)
SECTION_DATA_PROLOGUE(_bt_settings_area,,SUBALIGN(4))
{
@@ -42,8 +42,64 @@ typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len);
* These are registered using a call to @ref settings_register.
*/
struct settings_handler {

char *name;
/**< Name of subtree. */

int (*h_get)(const char *key, char *val, int val_len_max);
/**< Get values handler of settings items identified by keyword names.
*
* Parameters:
* - key[in] the name with skipped part that was used as name in
* handler registration
* - val[out] buffer to receive value.
* - val_len_max[in] size of that buffer.
*/

int (*h_set)(const char *key, size_t len, settings_read_cb read_cb,
void *cb_arg);
/**< Set value handler of settings items identified by keyword names.
*
* Parameters:
* - key[in] the name with skipped part that was used as name in
* handler registration
* - len[in] the size of the data found in the backend.
* - read_cb[in] function provided to read the data from the backend.
* - cb_arg[in] arguments for the read function provided by the
* backend.
*/

int (*h_commit)(void);
/**< This handler gets called after settings has been loaded in full.
* User might use it to apply setting to the application.
*/

int (*h_export)(int (*export_func)(const char *name, const void *val,
size_t val_len));
/**< This gets called to dump all current settings items.
*
* This happens when @ref settings_save tries to save the settings.
* Parameters:
* - export_func: the pointer to the internal function which appends
* a single key-value pair to persisted settings. Don't store
* duplicated value. The name is subtree/key string, val is the string
* with value.
*
* @remarks The User might limit a implementations of handler to serving
* only one keyword at one call - what will impose limit to get/set
* values using full subtree/key name.
*/

sys_snode_t node;
/**< Linked list node info for module internal usage. */
};

/**
* @struct settings_handler_static
* Config handlers without the node element, used for static handlers.
* These are registered using a call to SETTINGS_REGISTER_STATIC().
*/
struct settings_handler_static {

char *name;
/**< Name of subtree. */
@@ -93,6 +149,19 @@ struct settings_handler {
*/
};

/**
* Register a static handler for settings items
*
* @param _handler Structure containing registration info, this must be const
* The handler name in ROM needs to be unique, it is generated from
* _handler and the linenumber of SETTINGS_REGISTER_STATIC()
*
*/
#define SETTINGS_STATIC_HANDLER_DEFINE(_handler) \
const Z_STRUCT_SECTION_ITERABLE(settings_handler_static, \
_CONCAT(_handler, __LINE__))\
= _handler

/**
* Initialization of settings and backend
*
@@ -105,7 +174,7 @@ struct settings_handler {
int settings_subsys_init(void);

/**
* Register a handler for settings items.
* Register a handler for settings items stored in RAM.
*
* @param cf Structure containing registration info.
*
@@ -274,10 +343,10 @@ void settings_dst_register(struct settings_store *cs);
* @param[in] name in string format
* @param[out] next remaining of name after matched handler
*
* @return settings_handler node on success, NULL on failure.
* @return settings_handler_static on success, NULL on failure.
*/
struct settings_handler *settings_parse_and_lookup(const char *name,
const char **next);
struct settings_handler_static *settings_parse_and_lookup(const char *name,
const char **next);


/*
@@ -24,6 +24,13 @@ config SETTINGS_RUNTIME
help
Enables runtime storage back-end.

config SETTINGS_DYNAMIC_HANDLERS
bool "dynamic settings handlers"
depends on SETTINGS
default y
help
Enables the use of dynamic settings handlers

# Hidden option to enable encoding length into settings entry
config SETTINGS_ENCODE_LEN
depends on SETTINGS
@@ -17,25 +17,38 @@
#include <logging/log.h>
LOG_MODULE_REGISTER(settings, CONFIG_SETTINGS_LOG_LEVEL);

#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
sys_slist_t settings_handlers;
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */

struct k_mutex settings_lock;


void settings_store_init(void);

void settings_init(void)
{
#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
sys_slist_init(&settings_handlers);
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
settings_store_init();
}

#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
int settings_register(struct settings_handler *handler)
{
int rc;
struct settings_handler *ch;

k_mutex_lock(&settings_lock, K_FOREVER);

Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (strcmp(handler->name, ch->name) == 0) {
rc = -EEXIST;
goto end;
}
}

struct settings_handler *ch;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (strcmp(handler->name, ch->name) == 0) {
rc = -EEXIST;
@@ -48,6 +61,7 @@ int settings_register(struct settings_handler *handler)
k_mutex_unlock(&settings_lock);
return rc;
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */

int settings_name_steq(const char *name, const char *key, const char **next)
{
@@ -120,58 +134,87 @@ int settings_name_next(const char *name, const char **next)
return rc;
}

struct settings_handler *settings_parse_and_lookup(const char *name,
const char **next)
struct settings_handler_static *settings_parse_and_lookup(const char *name,
const char **next)
{
struct settings_handler *ch, *bestmatch;
struct settings_handler_static *bestmatch;
const char *tmpnext;

bestmatch = NULL;
if (next) {
*next = NULL;
}

Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (!settings_name_steq(name, ch->name, &tmpnext)) {
continue;
}
if (!bestmatch) {
bestmatch = ch;
if (next) {
*next = tmpnext;
}
continue;
}
if (settings_name_steq(ch->name, bestmatch->name, NULL)) {
bestmatch = ch;
if (next) {
*next = tmpnext;
}
}
}

#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
struct settings_handler *ch;

SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (settings_name_steq(name, ch->name, &tmpnext)) {
if ((!bestmatch) ||
(settings_name_steq(ch->name,
bestmatch->name, NULL))) {
bestmatch = ch;
if (next) {
*next = tmpnext;
}
if (!settings_name_steq(name, ch->name, &tmpnext)) {
continue;
}
if (!bestmatch) {
bestmatch = (struct settings_handler_static *)ch;
if (next) {
*next = tmpnext;
}
continue;
}
if (settings_name_steq(ch->name, bestmatch->name, NULL)) {
bestmatch = (struct settings_handler_static *)ch;
if (next) {
*next = tmpnext;
}
}
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
return bestmatch;
}

int settings_commit(void)
{
struct settings_handler *ch;
return settings_commit_subtree(NULL);
}

int settings_commit_subtree(const char *subtree)
{
int rc;
int rc2;

rc = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {

Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
}
if (ch->h_commit) {
rc2 = ch->h_commit();
if (!rc) {
rc = rc2;
}
}
}
return rc;
}

int settings_commit_subtree(const char *subtree)
{
#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
struct settings_handler *ch;

int rc;
int rc2;

rc = 0;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
continue;
@@ -183,5 +226,7 @@ int settings_commit_subtree(const char *subtree)
}
}
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */

return rc;
}
@@ -534,7 +534,7 @@ void settings_line_load_cb(const char *name, void *val_read_cb_ctx, off_t off,
void *cb_arg)
{
const char *name_key;
struct settings_handler *ch;
struct settings_handler_static *ch;
struct settings_line_read_value_cb_ctx value_ctx;
int rc;
size_t len;
@@ -17,7 +17,7 @@ static ssize_t settings_runtime_read_cb(void *cb_arg, void *data, size_t len)

int settings_runtime_set(const char *name, void *data, size_t len)
{
struct settings_handler *ch;
struct settings_handler_static *ch;
const char *name_key;

ch = settings_parse_and_lookup(name, &name_key);
@@ -30,7 +30,7 @@ int settings_runtime_set(const char *name, void *data, size_t len)

int settings_runtime_get(const char *name, void *data, size_t len)
{
struct settings_handler *ch;
struct settings_handler_static *ch;
const char *name_key;

ch = settings_parse_and_lookup(name, &name_key);
@@ -43,7 +43,7 @@ int settings_runtime_get(const char *name, void *data, size_t len)

int settings_runtime_commit(const char *name)
{
struct settings_handler *ch;
struct settings_handler_static *ch;
const char *name_key;

ch = settings_parse_and_lookup(name, &name_key);
@@ -96,7 +96,6 @@ int settings_delete(const char *name)
int settings_save(void)
{
struct settings_store *cs;
struct settings_handler *ch;
int rc;
int rc2;

@@ -110,6 +109,17 @@ int settings_save(void)
}
rc = 0;

Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
if (ch->h_export) {
rc2 = ch->h_export(settings_save_one);
if (!rc) {
rc = rc2;
}
}
}

#if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
struct settings_handler *ch;
SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
if (ch->h_export) {
rc2 = ch->h_export(settings_save_one);
@@ -118,6 +128,8 @@ int settings_save(void)
}
}
}
#endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */

if (cs->cs_itf->csi_save_end) {
cs->cs_itf->csi_save_end(cs);
}

0 comments on commit c20ff11

Please sign in to comment.
You can’t perform that action at this time.