blob: 4f5406fe400f7b777588bc2cf1af45168d80b174 [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)
16#include "common/log.h"
17
18#include "hci_core.h"
19#include "settings.h"
20
Johan Hedberg470349c2018-04-27 13:24:02 +030021/* Linker-defined symbols bound to the bt_settings_handler structs */
22extern const struct bt_settings_handler _bt_settings_start[];
23extern const struct bt_settings_handler _bt_settings_end[];
24
Johan Hedbergb997a282018-04-26 22:05:26 +030025static int set(int argc, char **argv, char *val)
26{
27 int len;
28
29 BT_DBG("argc %d argv[0] %s val %s", argc, argv[0], val);
30
Johan Hedberg470349c2018-04-27 13:24:02 +030031 if (argc > 1) {
32 const struct bt_settings_handler *h;
33
34 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
35 if (!strcmp(argv[0], h->name)) {
36 argc--;
37 argv++;
38
39 return h->set(argc, argv, val);
40 }
41 }
42
Johan Hedbergb997a282018-04-26 22:05:26 +030043 return -ENOENT;
44 }
45
46 if (!strcmp(argv[0], "id")) {
47 len = sizeof(bt_dev.id_addr);
48 settings_bytes_from_str(val, &bt_dev.id_addr, &len);
49 BT_DBG("ID Addr set to %s", bt_addr_le_str(&bt_dev.id_addr));
50 return 0;
51 }
52
53#if defined(CONFIG_BT_PRIVACY)
54 if (!strcmp(argv[0], "irk")) {
55 len = sizeof(bt_dev.irk);
56 settings_bytes_from_str(val, bt_dev.irk, &len);
57 BT_DBG("IRK set to %s", bt_hex(bt_dev.irk, 16));
58 return 0;
59 }
60#endif /* CONFIG_BT_PRIVACY */
61
62 return 0;
63}
64
65static void generate_static_addr(void)
66{
67 char buf[13];
68 char *str;
69
70 BT_DBG("Generating new static random address");
71
72 if (bt_addr_le_create_static(&bt_dev.id_addr)) {
73 BT_ERR("Failed to generate static addr");
74 return;
75 }
76
Johan Hedbergd22b7c92018-04-27 10:31:13 +030077 bt_set_static_addr();
Johan Hedbergb997a282018-04-26 22:05:26 +030078
79 BT_DBG("New ID Addr: %s", bt_addr_le_str(&bt_dev.id_addr));
80
81 str = settings_str_from_bytes(&bt_dev.id_addr, sizeof(bt_dev.id_addr),
82 buf, sizeof(buf));
83 if (!str) {
84 BT_ERR("Unable to encode ID Addr as value");
85 return;
86 }
87
88 BT_DBG("Saving ID addr as value %s", str);
89 settings_save_one("bt/id", str);
90}
91
92#if defined(CONFIG_BT_PRIVACY)
93static void generate_irk(void)
94{
95 char buf[25];
96 char *str;
97
98 BT_DBG("Generating new IRK");
99
100 if (bt_rand(bt_dev.irk, sizeof(bt_dev.irk))) {
101 BT_ERR("Failed to generate IRK");
102 return;
103 }
104
105 BT_DBG("New local IRK: %s", bt_hex(bt_dev.irk, 16));
106
107 str = settings_str_from_bytes(bt_dev.irk, 16, buf, sizeof(buf));
108 if (!str) {
109 BT_ERR("Unable to encode IRK as value");
110 return;
111 }
112
113 BT_DBG("Saving IRK as value %s", str);
114 settings_save_one("bt/irk", str);
115}
116#endif /* CONFIG_BT_PRIVACY */
117
118static int commit(void)
119{
Johan Hedberg470349c2018-04-27 13:24:02 +0300120 const struct bt_settings_handler *h;
121
Johan Hedbergb997a282018-04-26 22:05:26 +0300122 BT_DBG("");
123
124 if (!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_ANY) ||
125 !bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_NONE)) {
126 generate_static_addr();
127 }
128
129#if defined(CONFIG_BT_PRIVACY)
130 {
131 u8_t zero[16] = { 0 };
132
133 if (!memcmp(bt_dev.irk, zero, 16)) {
134 generate_irk();
135 }
136 }
137#endif /* CONFIG_BT_PRIVACY */
138
Johan Hedberg470349c2018-04-27 13:24:02 +0300139 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
140 if (h->commit) {
141 h->commit();
142 }
143 }
144
Johan Hedbergb997a282018-04-26 22:05:26 +0300145 bt_dev_show_info();
146
147 return 0;
148}
149
Johan Hedberg470349c2018-04-27 13:24:02 +0300150static int export(int (*func)(const char *name, char *val),
151 enum settings_export_tgt tgt)
152{
153 const struct bt_settings_handler *h;
154
155 if (tgt != SETTINGS_EXPORT_PERSIST) {
156 BT_WARN("Only persist target supported");
157 return -ENOTSUP;
158 }
159
160 for (h = _bt_settings_start; h < _bt_settings_end; h++) {
161 if (h->export) {
162 h->export(func);
163 }
164 }
165
166 return 0;
167}
168
Johan Hedbergb997a282018-04-26 22:05:26 +0300169static struct settings_handler bt_settings = {
170 .name = "bt",
171 .h_set = set,
172 .h_commit = commit,
Johan Hedberg470349c2018-04-27 13:24:02 +0300173 .h_export = export,
Johan Hedbergb997a282018-04-26 22:05:26 +0300174};
175
176int bt_settings_init(void)
177{
178 int err;
179
180 BT_DBG("");
181
182 err = settings_subsys_init();
183 if (err) {
184 BT_ERR("settings_subsys_init failed (err %d)", err);
185 return err;
186 }
187
188 err = settings_register(&bt_settings);
189 if (err) {
190 BT_ERR("settings_register failed (err %d)", err);
191 return err;
192 }
193
194 return 0;
195}