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