|  | /* | 
|  | * Copyright (c) 2018 Nordic Semiconductor ASA | 
|  | * Copyright (c) 2015 Runtime Inc | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #ifndef ZEPHYR_INCLUDE_SETTINGS_SETTINGS_H_ | 
|  | #define ZEPHYR_INCLUDE_SETTINGS_SETTINGS_H_ | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <sys/util.h> | 
|  | #include <sys/slist.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /** | 
|  | * @defgroup file_system_storage File System Storage | 
|  | * @{ | 
|  | * @} | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * @defgroup settings Settings | 
|  | * @ingroup file_system_storage | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | #define SETTINGS_MAX_DIR_DEPTH	8	/* max depth of settings tree */ | 
|  | #define SETTINGS_MAX_NAME_LEN	(8 * SETTINGS_MAX_DIR_DEPTH) | 
|  | #define SETTINGS_MAX_VAL_LEN	256 | 
|  | #define SETTINGS_NAME_SEPARATOR	'/' | 
|  | #define SETTINGS_NAME_END '=' | 
|  |  | 
|  | /* pleace for settings additions: | 
|  | * up to 7 separators, '=', '\0' | 
|  | */ | 
|  | #define SETTINGS_EXTRA_LEN ((SETTINGS_MAX_DIR_DEPTH - 1) + 2) | 
|  |  | 
|  | /** | 
|  | * Function used to read the data from the settings storage in | 
|  | * h_set handler implementations. | 
|  | * | 
|  | * @param[in] cb_arg  arguments for the read function. Appropriate cb_arg is | 
|  | *                    transferred to h_set handler implementation by | 
|  | *                    the backend. | 
|  | * @param[out] data  the destination buffer | 
|  | * @param[in] len    length of read | 
|  | * | 
|  | * @return positive: Number of bytes read, 0: key-value pair is deleted. | 
|  | *                   On error returns -ERRNO code. | 
|  | */ | 
|  | typedef ssize_t (*settings_read_cb)(void *cb_arg, void *data, size_t len); | 
|  |  | 
|  | /** | 
|  | * @struct settings_handler | 
|  | * Config handlers for subtree implement a set of handler functions. | 
|  | * 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. | 
|  | * | 
|  | * Return: length of data read on success, negative on failure. | 
|  | */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | *  Return: 0 on success, non-zero on failure. | 
|  | */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * Return: 0 on success, non-zero on failure. | 
|  | */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * Return: 0 on success, non-zero on failure. | 
|  | */ | 
|  |  | 
|  | 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. */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * Return: length of data read on success, negative on failure. | 
|  | */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * Return: 0 on success, non-zero on failure. | 
|  | */ | 
|  |  | 
|  | 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. | 
|  | * | 
|  | * Return: 0 on success, non-zero on failure. | 
|  | */ | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Define a static handler for settings items | 
|  | * | 
|  | * @param _hname handler name | 
|  | * @param _tree subtree name | 
|  | * @param _get get routine (can be NULL) | 
|  | * @param _set set routine (can be NULL) | 
|  | * @param _commit commit routine (can be NULL) | 
|  | * @param _export export routine (can be NULL) | 
|  | * | 
|  | * This creates a variable _hname prepended by settings_handler_. | 
|  | * | 
|  | */ | 
|  |  | 
|  | #define SETTINGS_STATIC_HANDLER_DEFINE(_hname, _tree, _get, _set, _commit,   \ | 
|  | _export)				     \ | 
|  | const Z_STRUCT_SECTION_ITERABLE(settings_handler_static,	     \ | 
|  | settings_handler_ ## _hname) = {     \ | 
|  | .name = _tree,						     \ | 
|  | .h_get = _get,						     \ | 
|  | .h_set = _set,						     \ | 
|  | .h_commit = _commit,					     \ | 
|  | .h_export = _export,					     \ | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Initialization of settings and backend | 
|  | * | 
|  | * Can be called at application startup. | 
|  | * In case the backend is a FS Remember to call it after the FS was mounted. | 
|  | * For FCB backend it can be called without such a restriction. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_subsys_init(void); | 
|  |  | 
|  | /** | 
|  | * Register a handler for settings items stored in RAM. | 
|  | * | 
|  | * @param cf Structure containing registration info. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_register(struct settings_handler *cf); | 
|  |  | 
|  | /** | 
|  | * Load serialized items from registered persistence sources. Handlers for | 
|  | * serialized item subtrees registered earlier will be called for encountered | 
|  | * values. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_load(void); | 
|  |  | 
|  | /** | 
|  | * Load limited set of serialized items from registered persistence sources. | 
|  | * Handlers for serialized item subtrees registered earlier will be called for | 
|  | * encountered values that belong to the subtree. | 
|  | * | 
|  | * @param[in] subtree name of the subtree to be loaded. | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_load_subtree(const char *subtree); | 
|  |  | 
|  | /** | 
|  | * Callback function used for direct loading. | 
|  | * Used by @ref settings_load_subtree_direct function. | 
|  | * | 
|  | * @param[in]     key     the name with skipped part that was used as name in | 
|  | *                        handler registration | 
|  | * @param[in]     len     the size of the data found in the backend. | 
|  | * @param[in]     read_cb function provided to read the data from the backend. | 
|  | * @param[in,out] cb_arg  arguments for the read function provided by the | 
|  | *                        backend. | 
|  | * @param[in,out] param   parameter given to the | 
|  | *                        @ref settings_load_subtree_direct function. | 
|  | * | 
|  | *  - 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. | 
|  | * | 
|  | * @return When nonzero value is returned, further subtree searching is stopped. | 
|  | *         Use with care as some settings backends would iterate through old | 
|  | *         values, and the current value is returned last. | 
|  | */ | 
|  | typedef int (*settings_load_direct_cb)( | 
|  | const char      *key, | 
|  | size_t           len, | 
|  | settings_read_cb read_cb, | 
|  | void            *cb_arg, | 
|  | void            *param); | 
|  |  | 
|  | /** | 
|  | * Load limited set of serialized items using given callback. | 
|  | * | 
|  | * This function bypasses the normal data workflow in settings module. | 
|  | * All the settings values that are found are passed to the given callback. | 
|  | * | 
|  | * @note | 
|  | * This function does not call commit function. | 
|  | * It works as a blocking function, so it is up to the user to call | 
|  | * any kind of commit function when this operation ends. | 
|  | * | 
|  | * @param[in]     subtree subtree name of the subtree to be loaded. | 
|  | * @param[in]     cb      pointer to the callback function. | 
|  | * @param[in,out] param   parameter to be passed when callback | 
|  | *                        function is called. | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_load_subtree_direct( | 
|  | const char             *subtree, | 
|  | settings_load_direct_cb cb, | 
|  | void                   *param); | 
|  |  | 
|  | /** | 
|  | * Save currently running serialized items. All serialized items which are | 
|  | * different from currently persisted values will be saved. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_save(void); | 
|  |  | 
|  | /** | 
|  | * Write a single serialized value to persisted storage (if it has | 
|  | * changed value). | 
|  | * | 
|  | * @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_export handler implementation. | 
|  | * @param val_len Length of the value. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_save_one(const char *name, const void *value, size_t val_len); | 
|  |  | 
|  | /** | 
|  | * Delete a single serialized in persisted storage. | 
|  | * | 
|  | * Deleting an existing key-value pair in the settings mean | 
|  | * to set its value to NULL. | 
|  | * | 
|  | * @param name Name/key of the settings item. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_delete(const char *name); | 
|  |  | 
|  | /** | 
|  | * Call commit for all settings handler. This should apply all | 
|  | * settings which has been set, but not applied yet. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_commit(void); | 
|  |  | 
|  | /** | 
|  | * Call commit for settings handler that belong to subtree. | 
|  | * This should apply all settings which has been set, but not applied yet. | 
|  | * | 
|  | * @param[in] subtree name of the subtree to be committed. | 
|  | * | 
|  | * @return 0 on success, non-zero on failure. | 
|  | */ | 
|  | int settings_commit_subtree(const char *subtree); | 
|  |  | 
|  | /** | 
|  | * @} settings | 
|  | */ | 
|  |  | 
|  |  | 
|  | /** | 
|  | * @defgroup settings_backend Settings backend interface | 
|  | * @ingroup settings | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * API for config storage | 
|  | */ | 
|  |  | 
|  | struct settings_store_itf; | 
|  |  | 
|  | /** | 
|  | * 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. */ | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Arguments for data loading. | 
|  | * Holds all parameters that changes the way data should be loaded from backend. | 
|  | */ | 
|  | struct settings_load_arg { | 
|  | /** | 
|  | * @brief Name of the subtree to be loaded | 
|  | * | 
|  | * If NULL, all values would be loaded. | 
|  | */ | 
|  | const char *subtree; | 
|  | /** | 
|  | * @brief Pointer to the callback function. | 
|  | * | 
|  | * If NULL then matching registered function would be used. | 
|  | */ | 
|  | settings_load_direct_cb cb; | 
|  | /** | 
|  | * @brief Parameter for callback function | 
|  | * | 
|  | * Parameter to be passed to the callback function. | 
|  | */ | 
|  | void *param; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * 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, | 
|  | const struct settings_load_arg *arg); | 
|  | /**< Loads values from storage limited to subtree defined by subtree. | 
|  | * | 
|  | * Parameters: | 
|  | *  - cs - Corresponding backend handler node, | 
|  | *  - arg - Structure that holds additional data for data loading. | 
|  | * | 
|  | * @note | 
|  | * Backend is expected not to provide duplicates of the entities. | 
|  | * It means that if the backend does not contain any functionality to | 
|  | * really delete old keys, it has to filter out old entities and call | 
|  | * load callback only on the final entity. | 
|  | */ | 
|  |  | 
|  | 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[in] name in string format | 
|  | * @param[out] next remaining of name after matched handler | 
|  | * | 
|  | * @return settings_handler_static on success, NULL on failure. | 
|  | */ | 
|  | struct settings_handler_static *settings_parse_and_lookup(const char *name, | 
|  | const char **next); | 
|  |  | 
|  | /** | 
|  | * Calls settings handler. | 
|  | * | 
|  | * @param[in]     name        The name of the data found in the backend. | 
|  | * @param[in]     len         The size of the data found in the backend. | 
|  | * @param[in]     read_cb     Function provided to read the data from | 
|  | *                            the backend. | 
|  | * @param[in,out] read_cb_arg Arguments for the read function provided by | 
|  | *                            the backend. | 
|  | * @param[in,out] load_arg    Arguments for data loading. | 
|  | * | 
|  | * @return 0 or negative error code | 
|  | */ | 
|  | int settings_call_set_handler(const char *name, | 
|  | size_t len, | 
|  | settings_read_cb read_cb, | 
|  | void *read_cb_arg, | 
|  | const struct settings_load_arg *load_arg); | 
|  | /** | 
|  | * @} | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * @defgroup settings_name_proc Settings name processing | 
|  | * @brief API for const name processing | 
|  | * @ingroup settings | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * Compares the start of name with a key | 
|  | * | 
|  | * @param[in] name in string format | 
|  | * @param[in] key comparison string | 
|  | * @param[out] next pointer to remaining of name, when the remaining part | 
|  | *             starts with a separator the separator is removed from next | 
|  | * | 
|  | * Some examples: | 
|  | * settings_name_steq("bt/btmesh/iv", "b", &next) returns 1, next="t/btmesh/iv" | 
|  | * settings_name_steq("bt/btmesh/iv", "bt", &next) returns 1, next="btmesh/iv" | 
|  | * settings_name_steq("bt/btmesh/iv", "bt/", &next) returns 0, next=NULL | 
|  | * settings_name_steq("bt/btmesh/iv", "bta", &next) returns 0, next=NULL | 
|  | * | 
|  | * REMARK: This routine could be simplified if the settings_handler names | 
|  | * would include a separator at the end. | 
|  | * | 
|  | * @return 0: no match | 
|  | *         1: match, next can be used to check if match is full | 
|  | */ | 
|  | int settings_name_steq(const char *name, const char *key, const char **next); | 
|  |  | 
|  | /** | 
|  | * determine the number of characters before the first separator | 
|  | * | 
|  | * @param[in] name in string format | 
|  | * @param[out] next pointer to remaining of name (excluding separator) | 
|  | * | 
|  | * @return index of the first separator, in case no separator was found this | 
|  | * is the size of name | 
|  | * | 
|  | */ | 
|  | int settings_name_next(const char *name, const char **next); | 
|  | /** | 
|  | * @} | 
|  | */ | 
|  |  | 
|  | #ifdef CONFIG_SETTINGS_RUNTIME | 
|  |  | 
|  | /** | 
|  | * @defgroup settings_rt Settings subsystem runtime | 
|  | * @brief API for runtime settings | 
|  | * @ingroup settings | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * 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 requested value length in bytes. | 
|  | * | 
|  | * @return length of data read on success, negative 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 | 
|  |  | 
|  | #endif /* ZEPHYR_INCLUDE_SETTINGS_SETTINGS_H_ */ |