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