1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <zephyr/settings/settings.h>
11 
12 #include <errno.h>
13 #include <zephyr/sys/printk.h>
14 
15 #if defined(CONFIG_SETTINGS_FILE)
16 #include <zephyr/fs/fs.h>
17 #include <zephyr/fs/littlefs.h>
18 #endif
19 
20 #define STORAGE_PARTITION	storage_partition
21 #define STORAGE_PARTITION_ID	FIXED_PARTITION_ID(STORAGE_PARTITION)
22 
23 #define GAMMA_DEFAULT_VAl 0
24 #define FAIL_MSG "fail (err %d)\n"
25 #define SECTION_BEGIN_LINE \
26 	"\n=================================================\n"
27 /* Default values are assigned to settings values consuments
28  * All of them will be overwritten if storage contain proper key-values
29  */
30 uint8_t angle_val;
31 uint64_t length_val = 100;
32 uint16_t length_1_val = 40;
33 uint32_t length_2_val = 60;
34 int32_t voltage_val = -3000;
35 char source_name_val[6] = "";
36 
37 int alpha_handle_set(const char *name, size_t len, settings_read_cb read_cb,
38 		  void *cb_arg);
39 int alpha_handle_commit(void);
40 int alpha_handle_export(int (*cb)(const char *name,
41 			       const void *value, size_t val_len));
42 
43 int beta_handle_set(const char *name, size_t len, settings_read_cb read_cb,
44 		  void *cb_arg);
45 int beta_handle_commit(void);
46 int beta_handle_export(int (*cb)(const char *name,
47 			       const void *value, size_t val_len));
48 int beta_handle_get(const char *name, char *val, int val_len_max);
49 
50 /* dynamic main tree handler */
51 struct settings_handler alph_handler = {
52 		.name = "alpha",
53 		.h_get = NULL,
54 		.h_set = alpha_handle_set,
55 		.h_commit = alpha_handle_commit,
56 		.h_export = alpha_handle_export
57 };
58 
59 /* static subtree handler */
60 SETTINGS_STATIC_HANDLER_DEFINE(beta, "alpha/beta", beta_handle_get,
61 			       beta_handle_set, beta_handle_commit,
62 			       beta_handle_export);
63 
alpha_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)64 int alpha_handle_set(const char *name, size_t len, settings_read_cb read_cb,
65 		  void *cb_arg)
66 {
67 	const char *next;
68 	size_t next_len;
69 	int rc;
70 
71 	if (settings_name_steq(name, "angle/1", &next) && !next) {
72 		if (len != sizeof(angle_val)) {
73 			return -EINVAL;
74 		}
75 		rc = read_cb(cb_arg, &angle_val, sizeof(angle_val));
76 		printk("<alpha/angle/1> = %d\n", angle_val);
77 		return 0;
78 	}
79 
80 	next_len = settings_name_next(name, &next);
81 
82 	if (!next) {
83 		return -ENOENT;
84 	}
85 
86 	if (!strncmp(name, "length", next_len)) {
87 		next_len = settings_name_next(name, &next);
88 
89 		if (!next) {
90 			rc = read_cb(cb_arg, &length_val, sizeof(length_val));
91 			printk("<alpha/length> = %" PRId64 "\n", length_val);
92 			return 0;
93 		}
94 
95 		if (!strncmp(next, "1", next_len)) {
96 			rc = read_cb(cb_arg, &length_1_val,
97 				     sizeof(length_1_val));
98 			printk("<alpha/length/1> = %d\n", length_1_val);
99 			return 0;
100 		}
101 
102 		if (!strncmp(next, "2", next_len)) {
103 			rc = read_cb(cb_arg, &length_2_val,
104 				     sizeof(length_2_val));
105 			printk("<alpha/length/2> = %d\n", length_2_val);
106 			return 0;
107 		}
108 
109 		return -ENOENT;
110 	}
111 
112 	return -ENOENT;
113 }
114 
beta_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)115 int beta_handle_set(const char *name, size_t len, settings_read_cb read_cb,
116 		  void *cb_arg)
117 {
118 	const char *next;
119 	size_t name_len;
120 	int rc;
121 
122 	name_len = settings_name_next(name, &next);
123 
124 	if (!next) {
125 		if (!strncmp(name, "voltage", name_len)) {
126 			rc = read_cb(cb_arg, &voltage_val, sizeof(voltage_val));
127 			printk("<alpha/beta/voltage> = %d\n", voltage_val);
128 			return 0;
129 		}
130 
131 		if (!strncmp(name, "source", name_len)) {
132 			if (len > sizeof(source_name_val) - 1) {
133 				printk("<alpha/beta/source> is not compatible "
134 				       "with the application\n");
135 				return -EINVAL;
136 			}
137 			rc = read_cb(cb_arg, source_name_val,
138 				     sizeof(source_name_val));
139 			if (rc < 0) {
140 				return rc;
141 			} else if (rc > 0) {
142 				printk("<alpha/beta/source> = %s\n",
143 				       source_name_val);
144 			}
145 			return 0;
146 		}
147 	}
148 
149 	return -ENOENT;
150 }
151 
alpha_handle_commit(void)152 int alpha_handle_commit(void)
153 {
154 	printk("loading all settings under <alpha> handler is done\n");
155 	return 0;
156 }
157 
alpha_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))158 int alpha_handle_export(int (*cb)(const char *name,
159 			       const void *value, size_t val_len))
160 {
161 	printk("export keys under <alpha> handler\n");
162 	(void)cb("alpha/angle/1", &angle_val, sizeof(angle_val));
163 	(void)cb("alpha/length", &length_val, sizeof(length_val));
164 	(void)cb("alpha/length/1", &length_1_val, sizeof(length_1_val));
165 	(void)cb("alpha/length/2", &length_2_val, sizeof(length_2_val));
166 
167 	return 0;
168 }
169 
beta_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))170 int beta_handle_export(int (*cb)(const char *name,
171 			       const void *value, size_t val_len))
172 {
173 	printk("export keys under <beta> handler\n");
174 	(void)cb("alpha/beta/voltage", &voltage_val, sizeof(voltage_val));
175 	(void)cb("alpha/beta/source", source_name_val, strlen(source_name_val) +
176 						       1);
177 
178 	return 0;
179 }
180 
beta_handle_commit(void)181 int beta_handle_commit(void)
182 {
183 	printk("loading all settings under <beta> handler is done\n");
184 	return 0;
185 }
186 
beta_handle_get(const char * name,char * val,int val_len_max)187 int beta_handle_get(const char *name, char *val, int val_len_max)
188 {
189 	const char *next;
190 
191 	if (settings_name_steq(name, "source", &next) && !next) {
192 		val_len_max = MIN(val_len_max, strlen(source_name_val));
193 		memcpy(val, source_name_val, val_len_max);
194 		return val_len_max;
195 	}
196 
197 	return -ENOENT;
198 }
199 
example_save_and_load_basic(void)200 static void example_save_and_load_basic(void)
201 {
202 	int i, rc;
203 	int32_t val_s32;
204 
205 	printk(SECTION_BEGIN_LINE);
206 	printk("basic load and save using registered handlers\n");
207 	/* load all key-values at once
208 	 * In case a key-value doesn't exist in the storage
209 	 * default values should be assigned to settings consuments variable
210 	 * before any settings load call
211 	 */
212 	printk("\nload all key-value pairs using registered handlers\n");
213 	settings_load();
214 
215 	val_s32 = voltage_val - 25;
216 	/* save certain key-value directly*/
217 	printk("\nsave <alpha/beta/voltage> key directly: ");
218 	rc = settings_save_one("alpha/beta/voltage", (const void *)&val_s32,
219 			       sizeof(val_s32));
220 	if (rc) {
221 		printk(FAIL_MSG, rc);
222 	}
223 
224 	printk("OK.\n");
225 
226 	printk("\nload <alpha/beta> key-value pairs using registered "
227 	       "handlers\n");
228 	settings_load_subtree("alpha/beta");
229 
230 	/* save only modified values
231 	 * or those that were not saved
232 	 * before
233 	 */
234 	i = strlen(source_name_val);
235 	if (i < sizeof(source_name_val) - 1) {
236 		source_name_val[i] = 'a' + i;
237 		source_name_val[i + 1] = 0;
238 	} else {
239 		source_name_val[0] = 0;
240 	}
241 
242 	angle_val += 1;
243 
244 	printk("\nsave all key-value pairs using registered handlers\n");
245 	settings_save();
246 
247 	if (++length_1_val > 100) {
248 		length_1_val = 0;
249 	}
250 
251 	if (--length_2_val > 100) {
252 		length_2_val = 100;
253 	}
254 
255 	/*---------------------------
256 	 * save only modified values
257 	 * or those that were deleted
258 	 * before
259 	 */
260 	printk("\nload all key-value pairs using registered handlers\n");
261 	settings_save();
262 }
263 
264 struct direct_length_data {
265 	uint64_t length;
266 	uint16_t length_1;
267 	uint32_t length_2;
268 };
269 
direct_loader(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg,void * param)270 static int direct_loader(const char *name, size_t len, settings_read_cb read_cb,
271 			  void *cb_arg, void *param)
272 {
273 	const char *next;
274 	size_t name_len;
275 	int rc;
276 	struct direct_length_data *dest = (struct direct_length_data *)param;
277 
278 	printk("direct load: ");
279 
280 	name_len = settings_name_next(name, &next);
281 
282 	if (name_len == 0) {
283 		rc = read_cb(cb_arg, &(dest->length), sizeof(dest->length));
284 		printk("<alpha/length>\n");
285 		return 0;
286 	}
287 
288 	name_len = settings_name_next(name, &next);
289 	if (next) {
290 		printk("nothing\n");
291 		return -ENOENT;
292 	}
293 
294 	if (!strncmp(name, "1", name_len)) {
295 		rc = read_cb(cb_arg, &(dest->length_1), sizeof(dest->length_1));
296 		printk("<alpha/length/1>\n");
297 		return 0;
298 	}
299 
300 	if (!strncmp(name, "2", name_len)) {
301 		rc = read_cb(cb_arg, &(dest->length_2), sizeof(dest->length_2));
302 		printk("<alpha/length/2>\n");
303 		return 0;
304 	}
305 
306 	printk("nothing\n");
307 	return -ENOENT;
308 }
309 
example_direct_load_subtree(void)310 static void example_direct_load_subtree(void)
311 {
312 	struct direct_length_data dld;
313 	int rc;
314 
315 	/* load subtree directly using call-specific handler `direct_loader'
316 	 * This handler loads subtree values to call-specific structure of type
317 	 * 'direct_length_data`.
318 	 */
319 	printk(SECTION_BEGIN_LINE);
320 	printk("loading subtree to destination provided by the caller\n\n");
321 	rc = settings_load_subtree_direct("alpha/length", direct_loader,
322 					  (void *)&dld);
323 	if (rc == 0) {
324 		printk("  direct.length = %" PRId64 "\n", dld.length);
325 		printk("  direct.length_1 = %d\n", dld.length_1);
326 		printk("  direct.length_2 = %d\n", dld.length_2);
327 	} else {
328 		printk("  direct load fails unexpectedly\n");
329 	}
330 }
331 
332 struct direct_immediate_value {
333 	size_t len;
334 	void *dest;
335 	uint8_t fetched;
336 };
337 
direct_loader_immediate_value(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg,void * param)338 static int direct_loader_immediate_value(const char *name, size_t len,
339 					 settings_read_cb read_cb, void *cb_arg,
340 					 void *param)
341 {
342 	const char *next;
343 	size_t name_len;
344 	int rc;
345 	struct direct_immediate_value *one_value =
346 					(struct direct_immediate_value *)param;
347 
348 	name_len = settings_name_next(name, &next);
349 
350 	if (name_len == 0) {
351 		if (len == one_value->len) {
352 			rc = read_cb(cb_arg, one_value->dest, len);
353 			if (rc >= 0) {
354 				one_value->fetched = 1;
355 				printk("immediate load: OK.\n");
356 				return 0;
357 			}
358 
359 			printk(FAIL_MSG, rc);
360 			return rc;
361 		}
362 		return -EINVAL;
363 	}
364 
365 	/* other keys aren't served by the callback
366 	 * Return success in order to skip them
367 	 * and keep storage processing.
368 	 */
369 	return 0;
370 }
371 
load_immediate_value(const char * name,void * dest,size_t len)372 int load_immediate_value(const char *name, void *dest, size_t len)
373 {
374 	int rc;
375 	struct direct_immediate_value dov;
376 
377 	dov.fetched = 0;
378 	dov.len = len;
379 	dov.dest = dest;
380 
381 	rc = settings_load_subtree_direct(name, direct_loader_immediate_value,
382 					  (void *)&dov);
383 	if (rc == 0) {
384 		if (!dov.fetched) {
385 			rc = -ENOENT;
386 		}
387 	}
388 
389 	return rc;
390 }
391 
example_without_handler(void)392 static void example_without_handler(void)
393 {
394 	uint8_t val_u8;
395 	int rc;
396 
397 	printk(SECTION_BEGIN_LINE);
398 	printk("Service a key-value pair without dedicated handlers\n\n");
399 	rc = load_immediate_value("gamma", &val_u8, sizeof(val_u8));
400 	if (rc == -ENOENT) {
401 		val_u8 = GAMMA_DEFAULT_VAl;
402 		printk("<gamma> = %d (default)\n", val_u8);
403 	} else if (rc == 0) {
404 		printk("<gamma> = %d\n", val_u8);
405 	} else {
406 		printk("unexpected"FAIL_MSG, rc);
407 	}
408 
409 	val_u8++;
410 
411 	printk("save <gamma> key directly: ");
412 	rc = settings_save_one("gamma", (const void *)&val_u8,
413 			       sizeof(val_u8));
414 	if (rc) {
415 		printk(FAIL_MSG, rc);
416 	} else {
417 		printk("OK.\n");
418 	}
419 }
420 
example_initialization(void)421 static void example_initialization(void)
422 {
423 	int rc;
424 
425 #if defined(CONFIG_SETTINGS_FILE)
426 	FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(cstorage);
427 
428 	/* mounting info */
429 	static struct fs_mount_t littlefs_mnt = {
430 	.type = FS_LITTLEFS,
431 	.fs_data = &cstorage,
432 	.storage_dev = (void *)STORAGE_PARTITION_ID,
433 	.mnt_point = "/ff"
434 	};
435 
436 	rc = fs_mount(&littlefs_mnt);
437 	if (rc != 0) {
438 		printk("mounting littlefs error: [%d]\n", rc);
439 	} else {
440 
441 		rc = fs_unlink(CONFIG_SETTINGS_FILE_PATH);
442 		if ((rc != 0) && (rc != -ENOENT)) {
443 			printk("can't delete config file%d\n", rc);
444 		} else {
445 			printk("FS initialized: OK\n");
446 		}
447 	}
448 #endif
449 
450 	rc = settings_subsys_init();
451 	if (rc) {
452 		printk("settings subsys initialization: fail (err %d)\n", rc);
453 		return;
454 	}
455 
456 	printk("settings subsys initialization: OK.\n");
457 
458 	rc = settings_register(&alph_handler);
459 	if (rc) {
460 		printk("subtree <%s> handler registered: fail (err %d)\n",
461 		       alph_handler.name, rc);
462 	}
463 
464 	printk("subtree <%s> handler registered: OK\n", alph_handler.name);
465 	printk("subtree <alpha/beta> has static handler\n");
466 }
467 
example_delete(void)468 static void example_delete(void)
469 {
470 	uint64_t val_u64;
471 	int rc;
472 
473 	printk(SECTION_BEGIN_LINE);
474 	printk("Delete a key-value pair\n\n");
475 
476 	rc = load_immediate_value("alpha/length", &val_u64, sizeof(val_u64));
477 	if (rc == 0) {
478 		printk("  <alpha/length> value exist in the storage\n");
479 	}
480 
481 	printk("delete <alpha/length>: ");
482 	rc = settings_delete("alpha/length");
483 	if (rc) {
484 		printk(FAIL_MSG, rc);
485 	} else {
486 		printk("OK.\n");
487 	}
488 
489 	rc = load_immediate_value("alpha/length", &val_u64, sizeof(val_u64));
490 	if (rc == -ENOENT) {
491 		printk("  Can't to load the <alpha/length> value as "
492 		       "expected\n");
493 	}
494 }
495 
example_runtime_usage(void)496 void example_runtime_usage(void)
497 {
498 	int rc;
499 	uint8_t injected_str[sizeof(source_name_val)] = "RT";
500 
501 	printk(SECTION_BEGIN_LINE);
502 	printk("Inject the value to the setting destination in runtime\n\n");
503 
504 	rc = settings_runtime_set("alpha/beta/source", (void *) injected_str,
505 				  strlen(injected_str) + 1);
506 
507 	printk("injected <alpha/beta/source>: ");
508 	if (rc) {
509 		printk(FAIL_MSG, rc);
510 	} else {
511 		printk("OK.\n");
512 	}
513 
514 	printk("  The settings destination off the key <alpha/beta/source> has "
515 	       "got value: \"%s\"\n\n", source_name_val);
516 
517 	/* set settings destination value "by hand" for next example */
518 	(void) strcpy(source_name_val, "rtos");
519 
520 	printk(SECTION_BEGIN_LINE);
521 	printk("Read a value from the setting destination in runtime\n\n");
522 
523 	rc = settings_runtime_get("alpha/beta/source", (void *) injected_str,
524 				  strlen(injected_str) + 1);
525 	printk("fetched <alpha/beta/source>: ");
526 	if (rc < 0) {
527 		printk(FAIL_MSG, rc);
528 	} else {
529 		printk("OK.\n");
530 	}
531 
532 	printk("  String value \"%s\" was retrieved from the settings "
533 	       "destination off the key <alpha/beta/source>\n",
534 	       source_name_val);
535 }
536 
main(void)537 int main(void)
538 {
539 
540 	int i;
541 
542 	printk("\n*** Settings usage example ***\n\n");
543 
544 	/* settings initialization */
545 	example_initialization();
546 
547 	for (i = 0; i < 6; i++) {
548 		printk("\n##############\n");
549 		printk("# iteration %d", i);
550 		printk("\n##############\n");
551 
552 		/*---------------------------------------------
553 		 * basic save and load using registered handler
554 		 */
555 		example_save_and_load_basic();
556 
557 		/*-------------------------------------------------
558 		 *load subtree directly using call-specific handler
559 		 */
560 		example_direct_load_subtree();
561 
562 		/*-------------------------
563 		 * delete certain key-value
564 		 */
565 		example_delete();
566 
567 		/*---------------------------------------
568 		 * a key-value without dedicated handler
569 		 */
570 		example_without_handler();
571 	}
572 
573 	/*------------------------------------------------------
574 	 * write and read settings destination using runtime API
575 	 */
576 	example_runtime_usage();
577 
578 	printk("\n*** THE END  ***\n");
579 	return 0;
580 }
581