blob: e112374b63794782b742717705dec3ddebac720d [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
9#include <zephyr.h>
10#include <settings/settings.h>
11
12#include <bluetooth/bluetooth.h>
13#include <bluetooth/conn.h>
14
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
Johan Hedberg470349c2018-04-27 13:24:02 +030022/* Linker-defined symbols bound to the bt_settings_handler structs */
23extern const struct bt_settings_handler _bt_settings_start[];
24extern const struct bt_settings_handler _bt_settings_end[];
25
Johan Hedbergf36ea832018-04-27 20:01:51 +030026void bt_settings_encode_key(char *path, size_t path_size, const char *subsys,
27 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
Johan Hedberg16311e22019-02-21 09:44:43 +020043 BT_DBG("Encoded path %s", log_strdup(path));
Johan Hedbergf36ea832018-04-27 20:01:51 +030044}
45
46int bt_settings_decode_key(char *key, bt_addr_le_t *addr)
47{
48 bool high;
49 int i;
50
51 if (strlen(key) != 13) {
52 return -EINVAL;
53 }
54
55 if (key[12] == '0') {
56 addr->type = BT_ADDR_LE_PUBLIC;
57 } else if (key[12] == '1') {
58 addr->type = BT_ADDR_LE_RANDOM;
59 } else {
60 return -EINVAL;
61 }
62
63 for (i = 5, high = true; i >= 0; key++) {
64 u8_t nibble;
65
66 if (*key >= '0' && *key <= '9') {
67 nibble = *key - '0';
68 } else if (*key >= 'a' && *key <= 'f') {
69 nibble = *key - 'a' + 10;
70 } else {
71 return -EINVAL;
72 }
73
74 if (high) {
75 addr->a.val[i] = nibble << 4;
76 high = false;
77 } else {
78 addr->a.val[i] |= nibble;
79 high = true;
80 i--;
81 }
82 }
83
Filip Kubicze44011b2019-02-21 11:44:23 +010084 BT_DBG("Decoded %s as %s", log_strdup(key), bt_addr_le_str(addr));
Johan Hedbergf36ea832018-04-27 20:01:51 +030085
86 return 0;
87}
88
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +010089static int set(int argc, char **argv, void *value_ctx)
Johan Hedbergb997a282018-04-26 22:05:26 +030090{
91 int len;
92
Johan Hedberg470349c2018-04-27 13:24:02 +030093 if (argc > 1) {
94 const struct bt_settings_handler *h;
95
96 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
97 if (!strcmp(argv[0], h->name)) {
98 argc--;
99 argv++;
100
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100101 return h->set(argc, argv, value_ctx);
Johan Hedberg470349c2018-04-27 13:24:02 +0300102 }
103 }
104
Johan Hedbergb997a282018-04-26 22:05:26 +0300105 return -ENOENT;
106 }
107
108 if (!strcmp(argv[0], "id")) {
Johan Hedberge70c5562018-07-16 14:39:06 +0300109 /* Any previously provided identities supersede flash */
110 if (atomic_test_bit(bt_dev.flags, BT_DEV_PRESET_ID)) {
111 BT_WARN("Ignoring identities stored in flash");
112 return 0;
113 }
114
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200115 len = settings_val_read_cb(value_ctx, &bt_dev.id_addr,
116 sizeof(bt_dev.id_addr));
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100117
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300118 if (len < sizeof(bt_dev.id_addr[0])) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100119 if (len < 0) {
120 BT_ERR("Failed to read ID address from storage"
121 " (err %d)", len);
122 } else {
123 BT_ERR("Invalid length ID address in storage");
124 BT_HEXDUMP_DBG(&bt_dev.id_addr, len,
125 "data read");
126 }
Flavio Ceolinda49f2e2018-09-11 19:09:03 -0700127 (void)memset(bt_dev.id_addr, 0,
128 sizeof(bt_dev.id_addr));
Patrik Flyktb97db522018-11-29 11:23:03 -0800129 bt_dev.id_count = 0U;
Johan Hedbergae829b22018-06-04 20:56:51 +0200130 } else {
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300131 int i;
132
133 bt_dev.id_count = len / sizeof(bt_dev.id_addr[0]);
134 for (i = 0; i < bt_dev.id_count; i++) {
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200135 BT_DBG("ID[%d] %s", i,
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300136 bt_addr_le_str(&bt_dev.id_addr[i]));
137 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200138 }
139
Johan Hedbergb997a282018-04-26 22:05:26 +0300140 return 0;
141 }
142
Szymon Janc504584a2018-07-31 19:57:08 +0200143#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300144 if (!strcmp(argv[0], "name")) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100145 len = settings_val_read_cb(value_ctx, &bt_dev.name,
146 sizeof(bt_dev.name) - 1);
147 if (len < 0) {
148 BT_ERR("Failed to read device name from storage"
149 " (err %d)", len);
150 } else {
151 bt_dev.name[len] = '\0';
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300152
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100153 BT_DBG("Name set to %s", bt_dev.name);
154 }
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300155 return 0;
156 }
Szymon Janc504584a2018-07-31 19:57:08 +0200157#endif
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300158
Johan Hedbergb997a282018-04-26 22:05:26 +0300159#if defined(CONFIG_BT_PRIVACY)
160 if (!strcmp(argv[0], "irk")) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100161 len = settings_val_read_cb(value_ctx, bt_dev.irk,
162 sizeof(bt_dev.irk));
Johan Hedberg5708f1e2018-07-04 12:58:10 +0300163 if (len < sizeof(bt_dev.irk[0])) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100164 if (len < 0) {
165 BT_ERR("Failed to read IRK from storage"
166 " (err %d)", len);
167 } else {
168 BT_ERR("Invalid length IRK in storage");
169 (void)memset(bt_dev.irk, 0, sizeof(bt_dev.irk));
170 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200171 } else {
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200172 int i, count;
173
174 count = len / sizeof(bt_dev.irk[0]);
175 for (i = 0; i < count; i++) {
176 BT_DBG("IRK[%d] %s", i,
177 bt_hex(bt_dev.irk[i], 16));
178 }
Johan Hedbergae829b22018-06-04 20:56:51 +0200179 }
180
Johan Hedbergb997a282018-04-26 22:05:26 +0300181 return 0;
182 }
183#endif /* CONFIG_BT_PRIVACY */
184
185 return 0;
186}
187
Johan Hedberge70c5562018-07-16 14:39:06 +0300188#define ID_DATA_LEN(array) (bt_dev.id_count * sizeof(array[0]))
189
190static void save_id(struct k_work *work)
Johan Hedbergb997a282018-04-26 22:05:26 +0300191{
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200192 int err;
193
194 err = settings_save_one("bt/id", &bt_dev.id_addr,
195 ID_DATA_LEN(bt_dev.id_addr));
196 if (err) {
197 BT_ERR("Failed to save ID (err %d)", err);
198 }
Johan Hedbergb997a282018-04-26 22:05:26 +0300199
200#if defined(CONFIG_BT_PRIVACY)
Johan Hedberg35ebacb2019-03-22 21:11:01 +0200201 err = settings_save_one("bt/irk", bt_dev.irk, ID_DATA_LEN(bt_dev.irk));
202 if (err) {
203 BT_ERR("Failed to save IRK (err %d)", err);
204 }
Johan Hedberge70c5562018-07-16 14:39:06 +0300205#endif
Johan Hedbergb997a282018-04-26 22:05:26 +0300206}
Johan Hedberge70c5562018-07-16 14:39:06 +0300207
208K_WORK_DEFINE(save_id_work, save_id);
209
210void bt_settings_save_id(void)
211{
212 k_work_submit(&save_id_work);
213}
Johan Hedbergb997a282018-04-26 22:05:26 +0300214
215static int commit(void)
216{
Johan Hedberg470349c2018-04-27 13:24:02 +0300217 const struct bt_settings_handler *h;
218
Johan Hedbergb997a282018-04-26 22:05:26 +0300219 BT_DBG("");
220
Szymon Janc504584a2018-07-31 19:57:08 +0200221#if defined(CONFIG_BT_DEVICE_NAME_DYNAMIC)
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300222 if (bt_dev.name[0] == '\0') {
223 bt_set_name(CONFIG_BT_DEVICE_NAME);
224 }
225#endif
Johan Hedberge70c5562018-07-16 14:39:06 +0300226 if (!bt_dev.id_count) {
227 int err;
Luiz Augusto von Dentz2637c972018-07-09 15:12:04 +0300228
Johan Hedberge70c5562018-07-16 14:39:06 +0300229 err = bt_setup_id_addr();
230 if (err) {
231 BT_ERR("Unable to setup an identity address");
232 return err;
Johan Hedbergb997a282018-04-26 22:05:26 +0300233 }
234 }
Johan Hedbergb997a282018-04-26 22:05:26 +0300235
Johan Hedberg12a41372019-03-22 12:45:09 +0200236 if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
237 bt_finalize_init();
238 }
239
Johan Hedberg470349c2018-04-27 13:24:02 +0300240 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
241 if (h->commit) {
242 h->commit();
243 }
244 }
245
Johan Hedbergb997a282018-04-26 22:05:26 +0300246 return 0;
247}
248
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100249static int export(int (*export_func)(const char *name, void *val,
250 size_t val_len))
251
Johan Hedberg470349c2018-04-27 13:24:02 +0300252{
253 const struct bt_settings_handler *h;
254
Johan Hedberg470349c2018-04-27 13:24:02 +0300255 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
256 if (h->export) {
Andrzej Puzdrowskibfb60742018-11-24 16:32:41 +0100257 h->export(export_func);
Johan Hedberg470349c2018-04-27 13:24:02 +0300258 }
259 }
260
261 return 0;
262}
263
Johan Hedbergb997a282018-04-26 22:05:26 +0300264static struct settings_handler bt_settings = {
265 .name = "bt",
266 .h_set = set,
267 .h_commit = commit,
Johan Hedberg470349c2018-04-27 13:24:02 +0300268 .h_export = export,
Johan Hedbergb997a282018-04-26 22:05:26 +0300269};
270
271int bt_settings_init(void)
272{
273 int err;
274
275 BT_DBG("");
276
277 err = settings_subsys_init();
278 if (err) {
279 BT_ERR("settings_subsys_init failed (err %d)", err);
280 return err;
281 }
282
283 err = settings_register(&bt_settings);
284 if (err) {
285 BT_ERR("settings_register failed (err %d)", err);
286 return err;
287 }
288
289 return 0;
290}