blob: 284250a145d5b29349ad6f6c15b5c7eb43f0cc05 [file] [log] [blame]
Johan Hedbergb997a282018-04-26 22:05:26 +03001/*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <errno.h>
8
Gerard Marull-Paretas5113c142022-05-06 11:12:04 +02009#include <zephyr/zephyr.h>
10#include <zephyr/settings/settings.h>
Johan Hedbergb997a282018-04-26 22:05:26 +030011
Gerard Marull-Paretas5113c142022-05-06 11:12:04 +020012#include <zephyr/bluetooth/bluetooth.h>
13#include <zephyr/bluetooth/conn.h>
Johan Hedbergb997a282018-04-26 22:05:26 +030014
15#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SETTINGS)
Johan Hedberg343c53e2018-07-17 10:35:52 +030016#define LOG_MODULE_NAME bt_settings
Johan Hedbergb997a282018-04-26 22:05:26 +030017#include "common/log.h"
18
19#include "hci_core.h"
20#include "settings.h"
21
Ulf Magnusson91dc6292019-10-18 17:54:59 +020022#if defined(CONFIG_BT_SETTINGS_USE_PRINTK)
Johan Hedbergf36ea832018-04-27 20:01:51 +030023void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
Luiz Augusto von Dentzbd5048c2020-02-13 11:14:54 -080024 const bt_addr_le_t *addr, const char *key)
Johan Hedbergf36ea832018-04-27 20:01:51 +030025{
26 if (key) {
27 snprintk(path, path_size,
28 "bt/%s/%02x%02x%02x%02x%02x%02x%u/%s", subsys,
29 addr->a.val[5], addr->a.val[4], addr->a.val[3],
30 addr->a.val[2], addr->a.val[1], addr->a.val[0],
31 addr->type, key);
32 } else {
33 snprintk(path, path_size,
34 "bt/%s/%02x%02x%02x%02x%02x%02x%u", subsys,
35 addr->a.val[5], addr->a.val[4], addr->a.val[3],
36 addr->a.val[2], addr->a.val[1], addr->a.val[0],
37 addr->type);
38 }
39
Krzysztof Chruscinski041f0e52022-06-20 07:43:37 +020040 BT_DBG("Encoded path %s", path);
Johan Hedbergf36ea832018-04-27 20:01:51 +030041}
Kim Sekkelund04502632019-09-13 14:06:22 +020042#else
43void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
Luiz Augusto von Dentzbd5048c2020-02-13 11:14:54 -080044 const bt_addr_le_t *addr, const char *key)
Kim Sekkelund04502632019-09-13 14:06:22 +020045{
46 size_t len = 3;
47
48 /* Skip if path_size is less than 3; strlen("bt/") */
49 if (len < path_size) {
50 /* Key format:
51 * "bt/<subsys>/<addr><type>/<key>", "/<key>" is optional
52 */
53 strcpy(path, "bt/");
54 strncpy(&path[len], subsys, path_size - len);
55 len = strlen(path);
56 if (len < path_size) {
57 path[len] = '/';
58 len++;
59 }
60
Kumar Galaa1b77fd2020-05-27 11:26:57 -050061 for (int8_t i = 5; i >= 0 && len < path_size; i--) {
Kim Sekkelund04502632019-09-13 14:06:22 +020062 len += bin2hex(&addr->a.val[i], 1, &path[len],
63 path_size - len);
64 }
65
66 if (len < path_size) {
67 /* Type can be either BT_ADDR_LE_PUBLIC or
68 * BT_ADDR_LE_RANDOM (value 0 or 1)
69 */
70 path[len] = '0' + addr->type;
71 len++;
72 }
73
74 if (key && len < path_size) {
75 path[len] = '/';
76 len++;
77 strncpy(&path[len], key, path_size - len);
78 len += strlen(&path[len]);
79 }
80
81 if (len >= path_size) {
82 /* Truncate string */
83 path[path_size - 1] = '\0';
84 }
85 } else if (path_size > 0) {
86 *path = '\0';
87 }
88
Krzysztof Chruscinski041f0e52022-06-20 07:43:37 +020089 BT_DBG("Encoded path %s", path);
Kim Sekkelund04502632019-09-13 14:06:22 +020090}
91#endif
Johan Hedbergf36ea832018-04-27 20:01:51 +030092
Laczen JMS8ca87082019-06-14 18:23:39 +020093int bt_settings_decode_key(const char *key, bt_addr_le_t *addr)
Johan Hedbergf36ea832018-04-27 20:01:51 +030094{
Laczen JMS8ca87082019-06-14 18:23:39 +020095 if (settings_name_next(key, NULL) != 13) {
Johan Hedbergf36ea832018-04-27 20:01:51 +030096 return -EINVAL;
97 }
98
99 if (key[12] == '0') {
100 addr->type = BT_ADDR_LE_PUBLIC;
101 } else if (key[12] == '1') {
102 addr->type = BT_ADDR_LE_RANDOM;
103 } else {
104 return -EINVAL;
105 }
106
Kumar Galaa1b77fd2020-05-27 11:26:57 -0500107 for (uint8_t i = 0; i < 6; i++) {
Kim Sekkelund04502632019-09-13 14:06:22 +0200108 hex2bin(&key[i * 2], 2, &addr->a.val[5 - i], 1);
Johan Hedbergf36ea832018-04-27 20:01:51 +0300109 }
110
Krzysztof Chruscinski041f0e52022-06-20 07:43:37 +0200111 BT_DBG("Decoded %s as %s", key, bt_addr_le_str(addr));
Johan Hedbergf36ea832018-04-27 20:01:51 +0300112
113 return 0;
114}
115
Laczen JMS8ca87082019-06-14 18:23:39 +0200116static int set(const char *name, size_t len_rd, settings_read_cb read_cb,
François Delawarde94451b22019-04-02 11:06:05 +0200117 void *cb_arg)
Johan Hedbergb997a282018-04-26 22:05:26 +0300118{
Johan Hedberge69b4be2019-05-01 08:47:58 +0300119 ssize_t len;
Laczen JMS8ca87082019-06-14 18:23:39 +0200120 const char *next;
121
Aleksander Wasaznik299fac82022-01-27 12:37:40 +0100122 if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) {
123 /* The Bluetooth settings loader needs to communicate with the Bluetooth
124 * controller to setup identities. This will not work before
125 * bt_enable(). The doc on @ref bt_enable requires the "bt/" settings
126 * tree to be loaded after @ref bt_enable is completed, so this handler
127 * will be called again later.
128 */
129 return 0;
130 }
131
Laczen JMS8ca87082019-06-14 18:23:39 +0200132 if (!name) {
133 BT_ERR("Insufficient number of arguments");
134 return -ENOENT;
135 }
136
137 len = settings_name_next(name, &next);
Johan Hedbergb997a282018-04-26 22:05:26 +0300138
Laczen JMS8ca87082019-06-14 18:23:39 +0200139 if (!strncmp(name, "id", len)) {
Johan Hedberge70c5562018-07-16 14:39:06 +0300140 /* Any previously provided identities supersede flash */
141 if (atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
142 BT_WARN("Ignoring identities stored in flash");
143 return 0;
144 }
145
François Delawarde94451b22019-04-02 11:06:05 +0200146 len = read_cb(cb_arg, &bt_dev.id_addr, sizeof(bt_dev.id_addr));
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300147 if (len < sizeof(bt_dev.id_addr[0])) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100148 if (len < 0) {
149 BT_ERR("Failed to read ID address from storage"
Joakim Andersson93f644e2020-04-03 16:55:52 +0200150 " (err %zd)", len);
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100151 } else {
152 BT_ERR("Invalid length ID address in storage");
153 BT_HEXDUMP_DBG(&bt_dev.id_addr, len,
154 "data read");
155 }
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700156 (void)memset(bt_dev.id_addr, 0,
157 sizeof(bt_dev.id_addr));
Patrik Flyktb97db522018-11-29 11:23:03 -0800158 bt_dev.id_count = 0U;
Johan Hedbergae829b22018-06-04 20:56:51 +0200159 } else {
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300160 int i;
161
162 bt_dev.id_count = len / sizeof(bt_dev.id_addr[0]);
163 for (i = 0; i < bt_dev.id_count; i++) {
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200164 BT_DBG("ID[%d] %s", i,
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300165 bt_addr_le_str(&bt_dev.id_addr[i]));
166 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200167 }
168
Johan Hedbergb997a282018-04-26 22:05:26 +0300169 return 0;
170 }
171
Szymon Janc504584a2018-07-31 19:57:08 +0200172#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
Laczen JMS8ca87082019-06-14 18:23:39 +0200173 if (!strncmp(name, "name", len)) {
François Delawarde94451b22019-04-02 11:06:05 +0200174 len = read_cb(cb_arg, &bt_dev.name, sizeof(bt_dev.name) - 1);
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100175 if (len < 0) {
176 BT_ERR("Failed to read device name from storage"
Joakim Andersson93f644e2020-04-03 16:55:52 +0200177 " (err %zd)", len);
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100178 } else {
179 bt_dev.name[len] = '\0';
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300180
Krzysztof Chruscinski041f0e52022-06-20 07:43:37 +0200181 BT_DBG("Name set to %s", bt_dev.name);
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100182 }
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300183 return 0;
184 }
Szymon Janc504584a2018-07-31 19:57:08 +0200185#endif
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300186
Aleksander Wasaznika713f212021-11-24 12:56:13 +0100187#if defined(CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC)
188 if (!strncmp(name, "appearance", len)) {
189 if (len != sizeof(bt_dev.appearance)) {
190 BT_ERR("Ignoring settings entry 'bt/appearance'. Wrong length.");
191 return -EINVAL;
192 }
193
194 len = read_cb(cb_arg, &bt_dev.appearance, sizeof(bt_dev.appearance));
195 if (len < 0) {
196 return len;
197 }
198
199 return 0;
200 }
201#endif
202
Johan Hedbergb997a282018-04-26 22:05:26 +0300203#if defined(CONFIG_BT_PRIVACY)
Laczen JMS8ca87082019-06-14 18:23:39 +0200204 if (!strncmp(name, "irk", len)) {
François Delawarde94451b22019-04-02 11:06:05 +0200205 len = read_cb(cb_arg, bt_dev.irk, sizeof(bt_dev.irk));
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300206 if (len < sizeof(bt_dev.irk[0])) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100207 if (len < 0) {
208 BT_ERR("Failed to read IRK from storage"
Joakim Andersson93f644e2020-04-03 16:55:52 +0200209 " (err %zd)", len);
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100210 } else {
211 BT_ERR("Invalid length IRK in storage");
212 (void)memset(bt_dev.irk, 0, sizeof(bt_dev.irk));
213 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200214 } else {
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200215 int i, count;
216
217 count = len / sizeof(bt_dev.irk[0]);
218 for (i = 0; i < count; i++) {
219 BT_DBG("IRK[%d] %s", i,
220 bt_hex(bt_dev.irk[i], 16));
221 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200222 }
223
Johan Hedbergb997a282018-04-26 22:05:26 +0300224 return 0;
225 }
226#endif /* CONFIG_BT_PRIVACY */
227
Luiz Augusto von Dentzf7b40692019-04-11 15:15:57 +0300228 return -ENOENT;
Johan Hedbergb997a282018-04-26 22:05:26 +0300229}
230
Johan Hedberge70c5562018-07-16 14:39:06 +0300231#define ID_DATA_LEN(array) (bt_dev.id_count * sizeof(array[0]))
232
233static void save_id(struct k_work *work)
Johan Hedbergb997a282018-04-26 22:05:26 +0300234{
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200235 int err;
Laczen JMS8ca87082019-06-14 18:23:39 +0200236 BT_INFO("Saving ID");
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200237 err = settings_save_one("bt/id", &bt_dev.id_addr,
238 ID_DATA_LEN(bt_dev.id_addr));
239 if (err) {
240 BT_ERR("Failed to save ID (err %d)", err);
241 }
Johan Hedbergb997a282018-04-26 22:05:26 +0300242
243#if defined(CONFIG_BT_PRIVACY)
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200244 err = settings_save_one("bt/irk", bt_dev.irk, ID_DATA_LEN(bt_dev.irk));
245 if (err) {
246 BT_ERR("Failed to save IRK (err %d)", err);
247 }
Johan Hedberge70c5562018-07-16 14:39:06 +0300248#endif
Johan Hedbergb997a282018-04-26 22:05:26 +0300249}
Johan Hedberge70c5562018-07-16 14:39:06 +0300250
251K_WORK_DEFINE(save_id_work, save_id);
252
253void bt_settings_save_id(void)
254{
255 k_work_submit(&save_id_work);
256}
Johan Hedbergb997a282018-04-26 22:05:26 +0300257
258static int commit(void)
259{
Joakim Anderssonb08e5722021-09-24 14:19:03 +0200260 int err;
261
Johan Hedbergb997a282018-04-26 22:05:26 +0300262 BT_DBG("");
263
Aleksander Wasaznik299fac82022-01-27 12:37:40 +0100264 if (!atomic_test_bit(bt_dev.flags, BT_DEV_ENABLE)) {
265 /* The Bluetooth settings loader needs to communicate with the Bluetooth
266 * controller to setup identities. This will not work before
267 * bt_enable(). The doc on @ref bt_enable requires the "bt/" settings
268 * tree to be loaded after @ref bt_enable is completed, so this handler
269 * will be called again later.
270 */
271 return 0;
272 }
273
Szymon Janc504584a2018-07-31 19:57:08 +0200274#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300275 if (bt_dev.name[0] == '\0') {
276 bt_set_name(CONFIG_BT_DEVICE_NAME);
277 }
278#endif
Johan Hedberge70c5562018-07-16 14:39:06 +0300279 if (!bt_dev.id_count) {
Joakim Anderssonb08e5722021-09-24 14:19:03 +0200280 err = bt_setup_public_id_addr();
281 if (err) {
282 BT_ERR("Unable to setup an identity address");
283 return err;
284 }
Joakim Anderssona34d4af2019-12-05 13:50:55 +0100285 }
286
287 if (!bt_dev.id_count) {
Joakim Anderssona34d4af2019-12-05 13:50:55 +0100288 err = bt_setup_random_id_addr();
Johan Hedberge70c5562018-07-16 14:39:06 +0300289 if (err) {
290 BT_ERR("Unable to setup an identity address");
291 return err;
Johan Hedbergb997a282018-04-26 22:05:26 +0300292 }
293 }
Johan Hedbergb997a282018-04-26 22:05:26 +0300294
Johan Hedberg12a41372019-03-22 12:45:09 +0200295 if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
296 bt_finalize_init();
297 }
298
Joakim Anderssona34d4af2019-12-05 13:50:55 +0100299 /* If any part of the Identity Information of the device has been
300 * generated this Identity needs to be saved persistently.
301 */
302 if (atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_STORE_ID)) {
303 BT_DBG("Storing Identity Information");
304 bt_settings_save_id();
305 }
306
Johan Hedbergb997a282018-04-26 22:05:26 +0300307 return 0;
308}
309
Laczen JMS5f19c812019-06-20 11:52:18 +0200310SETTINGS_STATIC_HANDLER_DEFINE(bt, "bt", NULL, set, commit, NULL);
Johan Hedbergb997a282018-04-26 22:05:26 +0300311
312int bt_settings_init(void)
313{
314 int err;
315
316 BT_DBG("");
317
318 err = settings_subsys_init();
319 if (err) {
320 BT_ERR("settings_subsys_init failed (err %d)", err);
321 return err;
322 }
323
Johan Hedbergb997a282018-04-26 22:05:26 +0300324 return 0;
325}