1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Runtime Inc
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <string.h>
9 #include <stdio.h>
10 
11 #include <zephyr/types.h>
12 #include <stddef.h>
13 #include <sys/types.h>
14 #include <errno.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/sys/iterable_sections.h>
17 #include <zephyr/settings/settings.h>
18 #include "settings_priv.h"
19 
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL);
22 
23 sys_slist_t settings_load_srcs;
24 struct settings_store *settings_save_dst;
25 extern struct k_mutex settings_lock;
26 
settings_src_register(struct settings_store * cs)27 void settings_src_register(struct settings_store *cs)
28 {
29 	sys_slist_append(&settings_load_srcs, &cs->cs_next);
30 }
31 
settings_dst_register(struct settings_store * cs)32 void settings_dst_register(struct settings_store *cs)
33 {
34 	settings_save_dst = cs;
35 }
36 
settings_load(void)37 int settings_load(void)
38 {
39 	return settings_load_subtree(NULL);
40 }
41 
settings_load_subtree(const char * subtree)42 int settings_load_subtree(const char *subtree)
43 {
44 	struct settings_store *cs;
45 	int rc;
46 	const struct settings_load_arg arg = {
47 		.subtree = subtree
48 	};
49 
50 	/*
51 	 * for every config store
52 	 *    load config
53 	 *    apply config
54 	 *    commit all
55 	 */
56 	k_mutex_lock(&settings_lock, K_FOREVER);
57 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
58 		cs->cs_itf->csi_load(cs, &arg);
59 	}
60 	rc = settings_commit_subtree(subtree);
61 	k_mutex_unlock(&settings_lock);
62 	return rc;
63 }
64 
settings_load_subtree_direct(const char * subtree,settings_load_direct_cb cb,void * param)65 int settings_load_subtree_direct(
66 	const char             *subtree,
67 	settings_load_direct_cb cb,
68 	void                   *param)
69 {
70 	struct settings_store *cs;
71 
72 	const struct settings_load_arg arg = {
73 		.subtree = subtree,
74 		.cb = cb,
75 		.param = param
76 	};
77 	/*
78 	 * for every config store
79 	 *    load config
80 	 *    apply config
81 	 *    commit all
82 	 */
83 	k_mutex_lock(&settings_lock, K_FOREVER);
84 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
85 		cs->cs_itf->csi_load(cs, &arg);
86 	}
87 	k_mutex_unlock(&settings_lock);
88 	return 0;
89 }
90 
91 /*
92  * Append a single value to persisted config. Don't store duplicate value.
93  */
settings_save_one(const char * name,const void * value,size_t val_len)94 int settings_save_one(const char *name, const void *value, size_t val_len)
95 {
96 	int rc;
97 	struct settings_store *cs;
98 
99 	cs = settings_save_dst;
100 	if (!cs) {
101 		return -ENOENT;
102 	}
103 
104 	k_mutex_lock(&settings_lock, K_FOREVER);
105 
106 	rc = cs->cs_itf->csi_save(cs, name, (char *)value, val_len);
107 
108 	k_mutex_unlock(&settings_lock);
109 
110 	return rc;
111 }
112 
settings_delete(const char * name)113 int settings_delete(const char *name)
114 {
115 	return settings_save_one(name, NULL, 0);
116 }
117 
settings_save(void)118 int settings_save(void)
119 {
120 	struct settings_store *cs;
121 	int rc;
122 	int rc2;
123 
124 	cs = settings_save_dst;
125 	if (!cs) {
126 		return -ENOENT;
127 	}
128 
129 	if (cs->cs_itf->csi_save_start) {
130 		cs->cs_itf->csi_save_start(cs);
131 	}
132 	rc = 0;
133 
134 	STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
135 		if (ch->h_export) {
136 			rc2 = ch->h_export(settings_save_one);
137 			if (!rc) {
138 				rc = rc2;
139 			}
140 		}
141 	}
142 
143 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
144 	struct settings_handler *ch;
145 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
146 		if (ch->h_export) {
147 			rc2 = ch->h_export(settings_save_one);
148 			if (!rc) {
149 				rc = rc2;
150 			}
151 		}
152 	}
153 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
154 
155 	if (cs->cs_itf->csi_save_end) {
156 		cs->cs_itf->csi_save_end(cs);
157 	}
158 	return rc;
159 }
160 
settings_storage_get(void ** storage)161 int settings_storage_get(void **storage)
162 {
163 	struct settings_store *cs = settings_save_dst;
164 
165 	if (!cs) {
166 		return -ENOENT;
167 	}
168 
169 	if (cs->cs_itf->csi_storage_get) {
170 		*storage = cs->cs_itf->csi_storage_get(cs);
171 	}
172 
173 	return 0;
174 }
175 
settings_store_init(void)176 void settings_store_init(void)
177 {
178 	sys_slist_init(&settings_load_srcs);
179 }
180