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 	return settings_save_subtree(NULL);
121 }
122 
settings_save_subtree(const char * subtree)123 int settings_save_subtree(const char *subtree)
124 {
125 	struct settings_store *cs;
126 	int rc;
127 	int rc2;
128 
129 	cs = settings_save_dst;
130 	if (!cs) {
131 		return -ENOENT;
132 	}
133 
134 	if (cs->cs_itf->csi_save_start) {
135 		cs->cs_itf->csi_save_start(cs);
136 	}
137 	rc = 0;
138 
139 	STRUCT_SECTION_FOREACH(settings_handler_static, ch) {
140 		if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
141 			continue;
142 		}
143 		if (ch->h_export) {
144 			rc2 = ch->h_export(settings_save_one);
145 			if (!rc) {
146 				rc = rc2;
147 			}
148 		}
149 	}
150 
151 #if defined(CONFIG_SETTINGS_DYNAMIC_HANDLERS)
152 	struct settings_handler *ch;
153 	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
154 		if (subtree && !settings_name_steq(ch->name, subtree, NULL)) {
155 			continue;
156 		}
157 		if (ch->h_export) {
158 			rc2 = ch->h_export(settings_save_one);
159 			if (!rc) {
160 				rc = rc2;
161 			}
162 		}
163 	}
164 #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */
165 
166 	if (cs->cs_itf->csi_save_end) {
167 		cs->cs_itf->csi_save_end(cs);
168 	}
169 	return rc;
170 }
171 
settings_storage_get(void ** storage)172 int settings_storage_get(void **storage)
173 {
174 	struct settings_store *cs = settings_save_dst;
175 
176 	if (!cs) {
177 		return -ENOENT;
178 	}
179 
180 	if (cs->cs_itf->csi_storage_get) {
181 		*storage = cs->cs_itf->csi_storage_get(cs);
182 	}
183 
184 	return 0;
185 }
186 
settings_store_init(void)187 void settings_store_init(void)
188 {
189 	sys_slist_init(&settings_load_srcs);
190 }
191