1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Runtime Inc
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <stdbool.h>
11 
12 #include <bt_errno.h>
13 #include <ble_os.h>
14 #include "settings/settings.h"
15 #include "settings_priv.h"
16 #include <ble_types/types.h>
17 
18 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SETTINGS)
19 #include <common/log.h>
20 
21 /* mbedtls-base64 lib encodes data to null-terminated string */
22 #define BASE64_ENCODE_SIZE(in_size) ((((((in_size) - 1) / 3) * 4) + 4) + 1)
23 
24 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
25 sys_slist_t settings_handlers;
26 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
27 
28 // K_MUTEX_DEFINE(settings_lock);
29 struct k_mutex settings_lock;
30 
31 void settings_store_init(void);
32 
settings_init(void)33 void settings_init(void)
34 {
35 	k_mutex_init(&settings_lock);
36 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
37 	sys_slist_init(&settings_handlers);
38 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
39 	settings_store_init();
40 }
41 
42 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
settings_register(struct settings_handler * handler)43 int settings_register(struct settings_handler *handler)
44 {
45 	int rc = 0;
46 
47 #if 0
48 	Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
49 		if (strcmp(handler->name, ch->name) == 0) {
50 			return -EEXIST;
51 		}
52 	}
53 #endif
54 
55 	k_mutex_lock(&settings_lock, K_FOREVER);
56 
57 	struct settings_handler *ch;
58 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
59 		if (strcmp(handler->name, ch->name) == 0) {
60 			rc = -EEXIST;
61 			goto end;
62 		}
63 	}
64 	sys_slist_append(&settings_handlers, &handler->node);
65 
66 end:
67 	k_mutex_unlock(&settings_lock);
68 	return rc;
69 }
70 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
71 
settings_name_steq(const char * name,const char * key,const char ** next)72 int settings_name_steq(const char *name, const char *key, const char **next)
73 {
74 	if (next) {
75 		*next = NULL;
76 	}
77 
78 	if ((!name) || (!key)) {
79 		return 0;
80 	}
81 
82 	/* name might come from flash directly, in flash the name would end
83 	 * with '=' or '\0' depending how storage is done. Flash reading is
84 	 * limited to what can be read
85 	 */
86 
87 	while ((*key != '\0') && (*key == *name) &&
88 	       (*name != '\0') && (*name != SETTINGS_NAME_END)) {
89 		key++;
90 		name++;
91 	}
92 
93 	if (*key != '\0') {
94 		return 0;
95 	}
96 
97 	if (*name == SETTINGS_NAME_SEPARATOR) {
98 		if (next) {
99 			*next = name + 1;
100 		}
101 		return 1;
102 	}
103 
104 	if ((*name == SETTINGS_NAME_END) || (*name == '\0')) {
105 		return 1;
106 	}
107 
108 	return 0;
109 }
110 
settings_name_next(const char * name,const char ** next)111 int settings_name_next(const char *name, const char **next)
112 {
113 	int rc = 0;
114 
115 	if (next) {
116 		*next = NULL;
117 	}
118 
119 	if (!name) {
120 		return 0;
121 	}
122 
123 	/* name might come from flash directly, in flash the name would end
124 	 * with '=' or '\0' depending how storage is done. Flash reading is
125 	 * limited to what can be read
126 	 */
127 	while ((*name != '\0') && (*name != SETTINGS_NAME_END) &&
128 	       (*name != SETTINGS_NAME_SEPARATOR)) {
129 		rc++;
130 		name++;
131 	}
132 
133 	if (*name == SETTINGS_NAME_SEPARATOR) {
134 		if (next) {
135 			*next = name + 1;
136 		}
137 		return rc;
138 	}
139 
140 	return rc;
141 }
142 
settings_parse_and_lookup(const char * name,const char ** next)143 struct settings_handler_static *settings_parse_and_lookup(const char *name,
144 							const char **next)
145 {
146 	struct settings_handler_static *bestmatch;
147 	const char *tmpnext;
148 
149 	bestmatch = NULL;
150 	if (next) {
151 		*next = NULL;
152 	}
153 
154 #if 0
155 	Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
156 		if (!settings_name_steq(name, ch->name, &tmpnext)) {
157 			continue;
158 		}
159 		if (!bestmatch) {
160 			bestmatch = ch;
161 			if (next) {
162 				*next = tmpnext;
163 			}
164 			continue;
165 		}
166 		if (settings_name_steq(ch->name, bestmatch->name, NULL)) {
167 			bestmatch = ch;
168 			if (next) {
169 				*next = tmpnext;
170 			}
171 		}
172 	}
173 #endif
174 
175 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
176 	struct settings_handler *ch;
177 
178 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
179 		if (!settings_name_steq(name, ch->name, &tmpnext)) {
180 			continue;
181 		}
182 		if (!bestmatch) {
183 			bestmatch = (struct settings_handler_static *)ch;
184 			if (next) {
185 				*next = tmpnext;
186 			}
187 			continue;
188 		}
189 		if (settings_name_steq(ch->name, bestmatch->name, NULL)) {
190 			bestmatch = (struct settings_handler_static *)ch;
191 			if (next) {
192 				*next = tmpnext;
193 			}
194 		}
195 	}
196 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
197 	return bestmatch;
198 }
199 
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)200 int settings_call_set_handler(const char *name,
201 			      size_t len,
202 			      settings_read_cb read_cb,
203 			      void *read_cb_arg,
204 			      const struct settings_load_arg *load_arg)
205 {
206 	int rc;
207 	const char *name_key = name;
208 
209 	if (load_arg && load_arg->subtree &&
210 	    !settings_name_steq(name, load_arg->subtree, &name_key)) {
211 		return 0;
212 	}
213 
214 	if (load_arg && load_arg->cb) {
215 		rc = load_arg->cb(name_key, len, read_cb, read_cb_arg,
216 				  load_arg->param);
217 	} else {
218 		struct settings_handler_static *ch;
219 
220 		ch = settings_parse_and_lookup(name, &name_key);
221 		if (!ch) {
222 			return 0;
223 		}
224 
225 		rc = ch->h_set(name_key, len, read_cb, read_cb_arg);
226 
227 		if (rc != 0) {
228 			BT_ERR("set-value failure. key: %s error(%d)",
229 				log_strdup(name), rc);
230 			/* Ignoring the error */
231 			rc = 0;
232 		} else {
233 			BT_DBG("set-value OK. key: %s",
234 				log_strdup(name));
235 		}
236 	}
237 	return rc;
238 }
239 
settings_commit(void)240 int settings_commit(void)
241 {
242 	return settings_commit_subtree(NULL);
243 }
244 
settings_commit_subtree(const char * subtree)245 int settings_commit_subtree(const char *subtree)
246 {
247 	int rc;
248 	int rc2;
249 
250 	rc = 0;
251 
252 #if 0
253 	Z_STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
254 		if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
255 			continue;
256 		}
257 		if (ch->h_commit) {
258 			rc2 = ch->h_commit();
259 			if (!rc) {
260 				rc = rc2;
261 			}
262 		}
263 	}
264 #endif
265 
266 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
267 	struct settings_handler *ch;
268 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
269 		if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
270 			continue;
271 		}
272 		if (ch->h_commit) {
273 			rc2 = ch->h_commit();
274 			if (!rc) {
275 				rc = rc2;
276 			}
277 		}
278 	}
279 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
280 
281 	return rc;
282 }
283