1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <errno.h>
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/settings/settings.h>
11
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/conn.h>
14 #include <zephyr/bluetooth/hci.h>
15
16 #include "common/bt_str.h"
17
18 #include "hci_core.h"
19 #include "settings.h"
20
21 #define LOG_LEVEL CONFIG_BT_SETTINGS_LOG_LEVEL
22 #include <zephyr/logging/log.h>
23 LOG_MODULE_REGISTER(bt_settings);
24
25 #if defined(CONFIG_BT_SETTINGS_USE_PRINTK)
bt_settings_encode_key(char * path,size_t path_size,const char * subsys,const bt_addr_le_t * addr,const char * key)26 void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
27 const bt_addr_le_t *addr, const char *key)
28 {
29 if (key) {
30 snprintk(path, path_size,
31 "bt/%s/%02x%02x%02x%02x%02x%02x%u/%s", subsys,
32 addr->a.val[5], addr->a.val[4], addr->a.val[3],
33 addr->a.val[2], addr->a.val[1], addr->a.val[0],
34 addr->type, key);
35 } else {
36 snprintk(path, path_size,
37 "bt/%s/%02x%02x%02x%02x%02x%02x%u", subsys,
38 addr->a.val[5], addr->a.val[4], addr->a.val[3],
39 addr->a.val[2], addr->a.val[1], addr->a.val[0],
40 addr->type);
41 }
42
43 LOG_DBG("Encoded path %s", path);
44 }
45 #else
bt_settings_encode_key(char * path,size_t path_size,const char * subsys,const bt_addr_le_t * addr,const char * key)46 void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
47 const bt_addr_le_t *addr, const char *key)
48 {
49 size_t len = 3;
50
51 /* Skip if path_size is less than 3; strlen("bt/") */
52 if (len < path_size) {
53 /* Key format:
54 * "bt/<subsys>/<addr><type>/<key>", "/<key>" is optional
55 */
56 strcpy(path, "bt/");
57 strncpy(&path[len], subsys, path_size - len);
58 len = strlen(path);
59 if (len < path_size) {
60 path[len] = '/';
61 len++;
62 }
63
64 for (int8_t i = 5; i >= 0 && len < path_size; i--) {
65 len += bin2hex(&addr->a.val[i], 1, &path[len],
66 path_size - len);
67 }
68
69 if (len < path_size) {
70 /* Type can be either BT_ADDR_LE_PUBLIC or
71 * BT_ADDR_LE_RANDOM (value 0 or 1)
72 */
73 path[len] = '0' + addr->type;
74 len++;
75 }
76
77 if (key && len < path_size) {
78 path[len] = '/';
79 len++;
80 strncpy(&path[len], key, path_size - len);
81 len += strlen(&path[len]);
82 }
83
84 if (len >= path_size) {
85 /* Truncate string */
86 path[path_size - 1] = '\0';
87 }
88 } else if (path_size > 0) {
89 *path = '\0';
90 }
91
92 LOG_DBG("Encoded path %s", path);
93 }
94 #endif
95
bt_settings_decode_key(const char * key,bt_addr_le_t * addr)96 int bt_settings_decode_key(const char *key, bt_addr_le_t *addr)
97 {
98 if (settings_name_next(key, NULL) != 13) {
99 return -EINVAL;
100 }
101
102 if (key[12] == '0') {
103 addr->type = BT_ADDR_LE_PUBLIC;
104 } else if (key[12] == '1') {
105 addr->type = BT_ADDR_LE_RANDOM;
106 } else {
107 return -EINVAL;
108 }
109
110 for (uint8_t i = 0; i < 6; i++) {
111 hex2bin(&key[i * 2], 2, &addr->a.val[5 - i], 1);
112 }
113
114 LOG_DBG("Decoded %s as %s", key, bt_addr_le_str(addr));
115
116 return 0;
117 }
118
set_setting(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)119 static int set_setting(const char *name, size_t len_rd, settings_read_cb read_cb,
120 void *cb_arg)
121 {
122 ssize_t len;
123 const char *next;
124
125 if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) {
126 /* The Bluetooth settings loader needs to communicate with the Bluetooth
127 * controller to setup identities. This will not work before
128 * bt_enable(). The doc on @ref bt_enable requires the "bt/" settings
129 * tree to be loaded after @ref bt_enable is completed, so this handler
130 * will be called again later.
131 */
132 return 0;
133 }
134
135 if (!name) {
136 LOG_ERR("Insufficient number of arguments");
137 return -ENOENT;
138 }
139
140 len = settings_name_next(name, &next);
141
142 if (!strncmp(name, "id", len)) {
143 /* Any previously provided identities supersede flash */
144 if (atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
145 LOG_WRN("Ignoring identities stored in flash");
146 return 0;
147 }
148
149 len = read_cb(cb_arg, &bt_dev.id_addr, sizeof(bt_dev.id_addr));
150 if (len < sizeof(bt_dev.id_addr[0])) {
151 if (len < 0) {
152 LOG_ERR("Failed to read ID address from storage"
153 " (err %zd)", len);
154 } else {
155 LOG_ERR("Invalid length ID address in storage");
156 LOG_HEXDUMP_DBG(&bt_dev.id_addr, len, "data read");
157 }
158 (void)memset(bt_dev.id_addr, 0,
159 sizeof(bt_dev.id_addr));
160 bt_dev.id_count = 0U;
161 } else {
162 int i;
163
164 bt_dev.id_count = len / sizeof(bt_dev.id_addr[0]);
165 for (i = 0; i < bt_dev.id_count; i++) {
166 LOG_DBG("ID[%d] %s", i, bt_addr_le_str(&bt_dev.id_addr[i]));
167 }
168 }
169
170 return 0;
171 }
172
173 #if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
174 if (!strncmp(name, "name", len)) {
175 len = read_cb(cb_arg, &bt_dev.name, sizeof(bt_dev.name) - 1);
176 if (len < 0) {
177 LOG_ERR("Failed to read device name from storage"
178 " (err %zd)", len);
179 } else {
180 bt_dev.name[len] = '\0';
181
182 LOG_DBG("Name set to %s", bt_dev.name);
183 }
184 return 0;
185 }
186 #endif
187
188 #if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
189 if (!strncmp(name, "appearance", len)) {
190 if (len_rd != sizeof(bt_dev.appearance)) {
191 LOG_ERR("Ignoring settings entry 'bt/appearance'. Wrong length.");
192 return -EINVAL;
193 }
194
195 len = read_cb(cb_arg, &bt_dev.appearance, sizeof(bt_dev.appearance));
196 if (len < 0) {
197 return len;
198 }
199
200 return 0;
201 }
202 #endif
203
204 #if defined(CONFIG_BT_PRIVACY)
205 if (!strncmp(name, "irk", len)) {
206 len = read_cb(cb_arg, bt_dev.irk, sizeof(bt_dev.irk));
207 if (len < sizeof(bt_dev.irk[0])) {
208 if (len < 0) {
209 LOG_ERR("Failed to read IRK from storage"
210 " (err %zd)", len);
211 } else {
212 LOG_ERR("Invalid length IRK in storage");
213 (void)memset(bt_dev.irk, 0, sizeof(bt_dev.irk));
214 }
215 } else {
216 int i, count;
217
218 count = len / sizeof(bt_dev.irk[0]);
219 for (i = 0; i < count; i++) {
220 LOG_DBG("IRK[%d] %s", i, bt_hex(bt_dev.irk[i], 16));
221 }
222 }
223
224 return 0;
225 }
226 #endif /* CONFIG_BT_PRIVACY */
227
228 return -ENOENT;
229 }
230
commit_settings(void)231 static int commit_settings(void)
232 {
233 int err;
234
235 LOG_DBG("");
236
237 if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) {
238 /* The Bluetooth settings loader needs to communicate with the Bluetooth
239 * controller to setup identities. This will not work before
240 * bt_enable(). The doc on @ref bt_enable requires the "bt/" settings
241 * tree to be loaded after @ref bt_enable is completed, so this handler
242 * will be called again later.
243 */
244 return 0;
245 }
246
247 #if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
248 if (bt_dev.name[0] == '\0') {
249 bt_set_name(CONFIG_BT_DEVICE_NAME);
250 }
251 #endif
252 if (!bt_dev.id_count) {
253 err = bt_setup_public_id_addr();
254 if (err) {
255 LOG_ERR("Unable to setup an identity address");
256 return err;
257 }
258 }
259
260 if (!bt_dev.id_count) {
261 err = bt_setup_random_id_addr();
262 if (err) {
263 LOG_ERR("Unable to setup an identity address");
264 return err;
265 }
266 }
267
268 if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
269 bt_finalize_init();
270 }
271
272 /* If any part of the Identity Information of the device has been
273 * generated this Identity needs to be saved persistently.
274 */
275 if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_STORE_ID)) {
276 LOG_DBG("Storing Identity Information");
277 bt_settings_store_id();
278 bt_settings_store_irk();
279 }
280
281 return 0;
282 }
283
284 SETTINGS_STATIC_HANDLER_DEFINE(bt, "bt", NULL, set_setting, commit_settings, NULL);
285
bt_settings_init(void)286 int bt_settings_init(void)
287 {
288 int err;
289
290 LOG_DBG("");
291
292 err = settings_subsys_init();
293 if (err) {
294 LOG_ERR("settings_subsys_init failed (err %d)", err);
295 return err;
296 }
297
298 return 0;
299 }
300
bt_settings_store(const char * key,uint8_t id,const bt_addr_le_t * addr,const void * value,size_t val_len)301 int bt_settings_store(const char *key, uint8_t id, const bt_addr_le_t *addr, const void *value,
302 size_t val_len)
303 {
304 int err;
305 char id_str[4];
306 char key_str[BT_SETTINGS_KEY_MAX];
307
308 if (addr) {
309 if (id) {
310 u8_to_dec(id_str, sizeof(id_str), id);
311 }
312
313 bt_settings_encode_key(key_str, sizeof(key_str), key, addr, (id ? id_str : NULL));
314 } else {
315 err = snprintk(key_str, sizeof(key_str), "bt/%s", key);
316 if (err < 0) {
317 return -EINVAL;
318 }
319 }
320
321 return settings_save_one(key_str, value, val_len);
322 }
323
bt_settings_delete(const char * key,uint8_t id,const bt_addr_le_t * addr)324 int bt_settings_delete(const char *key, uint8_t id, const bt_addr_le_t *addr)
325 {
326 int err;
327 char id_str[4];
328 char key_str[BT_SETTINGS_KEY_MAX];
329
330 if (addr) {
331 if (id) {
332 u8_to_dec(id_str, sizeof(id_str), id);
333 }
334
335 bt_settings_encode_key(key_str, sizeof(key_str), key, addr, (id ? id_str : NULL));
336 } else {
337 err = snprintk(key_str, sizeof(key_str), "bt/%s", key);
338 if (err < 0) {
339 return -EINVAL;
340 }
341 }
342
343 return settings_delete(key_str);
344 }
345
bt_settings_store_sc(uint8_t id,const bt_addr_le_t * addr,const void * value,size_t val_len)346 int bt_settings_store_sc(uint8_t id, const bt_addr_le_t *addr, const void *value, size_t val_len)
347 {
348 return bt_settings_store("sc", id, addr, value, val_len);
349 }
350
bt_settings_delete_sc(uint8_t id,const bt_addr_le_t * addr)351 int bt_settings_delete_sc(uint8_t id, const bt_addr_le_t *addr)
352 {
353 return bt_settings_delete("sc", id, addr);
354 }
355
bt_settings_store_cf(uint8_t id,const bt_addr_le_t * addr,const void * value,size_t val_len)356 int bt_settings_store_cf(uint8_t id, const bt_addr_le_t *addr, const void *value, size_t val_len)
357 {
358 return bt_settings_store("cf", id, addr, value, val_len);
359 }
360
bt_settings_delete_cf(uint8_t id,const bt_addr_le_t * addr)361 int bt_settings_delete_cf(uint8_t id, const bt_addr_le_t *addr)
362 {
363 return bt_settings_delete("cf", id, addr);
364 }
365
bt_settings_store_ccc(uint8_t id,const bt_addr_le_t * addr,const void * value,size_t val_len)366 int bt_settings_store_ccc(uint8_t id, const bt_addr_le_t *addr, const void *value, size_t val_len)
367 {
368 return bt_settings_store("ccc", id, addr, value, val_len);
369 }
370
bt_settings_delete_ccc(uint8_t id,const bt_addr_le_t * addr)371 int bt_settings_delete_ccc(uint8_t id, const bt_addr_le_t *addr)
372 {
373 return bt_settings_delete("ccc", id, addr);
374 }
375
bt_settings_store_hash(const void * value,size_t val_len)376 int bt_settings_store_hash(const void *value, size_t val_len)
377 {
378 return bt_settings_store("hash", 0, NULL, value, val_len);
379 }
380
bt_settings_delete_hash(void)381 int bt_settings_delete_hash(void)
382 {
383 return bt_settings_delete("hash", 0, NULL);
384 }
385
bt_settings_store_name(const void * value,size_t val_len)386 int bt_settings_store_name(const void *value, size_t val_len)
387 {
388 return bt_settings_store("name", 0, NULL, value, val_len);
389 }
390
bt_settings_delete_name(void)391 int bt_settings_delete_name(void)
392 {
393 return bt_settings_delete("name", 0, NULL);
394 }
395
bt_settings_store_appearance(const void * value,size_t val_len)396 int bt_settings_store_appearance(const void *value, size_t val_len)
397 {
398 return bt_settings_store("appearance", 0, NULL, value, val_len);
399 }
400
bt_settings_delete_appearance(void)401 int bt_settings_delete_appearance(void)
402 {
403 return bt_settings_delete("appearance", 0, NULL);
404 }
405
do_store_id(struct k_work * work)406 static void do_store_id(struct k_work *work)
407 {
408 int err = bt_settings_store("id", 0, NULL, &bt_dev.id_addr, ID_DATA_LEN(bt_dev.id_addr));
409
410 if (err) {
411 LOG_ERR("Failed to save ID (err %d)", err);
412 }
413 }
414
415 K_WORK_DEFINE(store_id_work, do_store_id);
416
bt_settings_store_id(void)417 int bt_settings_store_id(void)
418 {
419 k_work_submit(&store_id_work);
420
421 return 0;
422 }
423
bt_settings_delete_id(void)424 int bt_settings_delete_id(void)
425 {
426 return bt_settings_delete("id", 0, NULL);
427 }
428
do_store_irk(struct k_work * work)429 static void do_store_irk(struct k_work *work)
430 {
431 #if defined(CONFIG_BT_PRIVACY)
432 int err = bt_settings_store("irk", 0, NULL, bt_dev.irk, ID_DATA_LEN(bt_dev.irk));
433
434 if (err) {
435 LOG_ERR("Failed to save IRK (err %d)", err);
436 }
437 #endif
438 }
439
440 K_WORK_DEFINE(store_irk_work, do_store_irk);
441
bt_settings_store_irk(void)442 int bt_settings_store_irk(void)
443 {
444 #if defined(CONFIG_BT_PRIVACY)
445 k_work_submit(&store_irk_work);
446 #endif /* defined(CONFIG_BT_PRIVACY) */
447 return 0;
448 }
449
bt_settings_delete_irk(void)450 int bt_settings_delete_irk(void)
451 {
452 return bt_settings_delete("irk", 0, NULL);
453 }
454
bt_settings_store_link_key(const bt_addr_le_t * addr,const void * value,size_t val_len)455 int bt_settings_store_link_key(const bt_addr_le_t *addr, const void *value, size_t val_len)
456 {
457 return bt_settings_store("link_key", 0, addr, value, val_len);
458 }
459
bt_settings_delete_link_key(const bt_addr_le_t * addr)460 int bt_settings_delete_link_key(const bt_addr_le_t *addr)
461 {
462 return bt_settings_delete("link_key", 0, addr);
463 }
464
bt_settings_store_keys(uint8_t id,const bt_addr_le_t * addr,const void * value,size_t val_len)465 int bt_settings_store_keys(uint8_t id, const bt_addr_le_t *addr, const void *value, size_t val_len)
466 {
467 return bt_settings_store("keys", id, addr, value, val_len);
468 }
469
bt_settings_delete_keys(uint8_t id,const bt_addr_le_t * addr)470 int bt_settings_delete_keys(uint8_t id, const bt_addr_le_t *addr)
471 {
472 return bt_settings_delete("keys", id, addr);
473 }
474