1 /* Bluetooth Mesh */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include "syscfg/syscfg.h"
10 #define MESH_LOG_MODULE BLE_MESH_LOG
11
12 #include <stdbool.h>
13 #include <errno.h>
14
15 #include "os/os_mbuf.h"
16 #include "host/ble_uuid.h"
17 #include "mesh/mesh.h"
18
19 #include "adv.h"
20 #include "prov.h"
21 #include "net.h"
22 #include "beacon.h"
23 #include "lpn.h"
24 #include "friend.h"
25 #include "transport.h"
26 #include "access.h"
27 #include "foundation.h"
28 #include "proxy.h"
29 #include "shell.h"
30 #include "mesh_priv.h"
31 #include "settings.h"
32
33 u8_t g_mesh_addr_type;
34 static struct ble_gap_event_listener mesh_event_listener;
35
bt_mesh_provision(const u8_t net_key[16],u16_t net_idx,u8_t flags,u32_t iv_index,u16_t addr,const u8_t dev_key[16])36 int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
37 u8_t flags, u32_t iv_index, u16_t addr,
38 const u8_t dev_key[16])
39 {
40 bool pb_gatt_enabled;
41 int err;
42 BT_INFO("Primary Element: 0x%04x", addr);
43 BT_DBG("net_idx 0x%04x flags 0x%02x iv_index 0x%04x",
44 net_idx, flags, (unsigned) iv_index);
45
46 if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_VALID)) {
47 return -EALREADY;
48 }
49
50 if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
51 if (bt_mesh_proxy_prov_disable(false) == 0) {
52 pb_gatt_enabled = true;
53 } else {
54 pb_gatt_enabled = false;
55 }
56 } else {
57 pb_gatt_enabled = false;
58 }
59
60 err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
61 if (err) {
62 atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
63
64 if (MYNEWT_VAL(BLE_MESH_PB_GATT) && pb_gatt_enabled) {
65 bt_mesh_proxy_prov_enable();
66 }
67
68 return err;
69 }
70
71 bt_mesh.seq = 0;
72 bt_mesh_comp_provision(addr);
73 memcpy(bt_mesh.dev_key, dev_key, 16); // 16:size
74
75 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
76 BT_DBG("Storing network information persistently");
77 bt_mesh_store_net();
78 bt_mesh_store_subnet(&bt_mesh.sub[0]);
79 bt_mesh_store_iv(false);
80 }
81
82 bt_mesh_net_start();
83 return 0;
84 }
85
bt_mesh_provision_adv(const u8_t uuid[16],u16_t net_idx,u16_t addr,u8_t attention_duration)86 int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
87 u8_t attention_duration)
88 {
89 if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
90 return -EINVAL;
91 }
92
93 if (bt_mesh_subnet_get(net_idx) == NULL) {
94 return -EINVAL;
95 }
96
97 if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
98 IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
99 return bt_mesh_pb_adv_open(uuid, net_idx, addr,
100 attention_duration);
101 }
102
103 return -ENOTSUP;
104 }
105
bt_mesh_reset(void)106 void bt_mesh_reset(void)
107 {
108 if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
109 return;
110 }
111
112 bt_mesh.iv_index = 0U;
113 bt_mesh.seq = 0U;
114 memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags));
115 k_delayed_work_cancel(&bt_mesh.ivu_timer);
116 bt_mesh_cfg_reset();
117 bt_mesh_rx_reset();
118 bt_mesh_tx_reset();
119
120 if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
121 bt_mesh_lpn_disable(true);
122 }
123
124 if ((MYNEWT_VAL(BLE_MESH_FRIEND))) {
125 bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
126 }
127
128 if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
129 bt_mesh_proxy_gatt_disable();
130 }
131
132 if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
133 bt_mesh_proxy_prov_enable();
134 }
135
136 if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
137 bt_mesh_clear_net();
138 }
139
140 memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key));
141 bt_mesh_scan_disable();
142 bt_mesh_beacon_disable();
143 bt_mesh_comp_unprovision();
144
145 if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
146 bt_mesh_prov_reset();
147 }
148 }
149
bt_mesh_is_provisioned(void)150 bool bt_mesh_is_provisioned(void)
151 {
152 return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
153 }
154
bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)155 int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
156 {
157 if (bt_mesh_is_provisioned()) {
158 return -EALREADY;
159 }
160
161 char uuid_buf[BLE_UUID_STR_LEN];
162 const struct bt_mesh_prov *prov = bt_mesh_prov_get();
163 ble_uuid_t *uuid = BLE_UUID128_DECLARE();
164 memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16); // 16:len
165 BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
166
167 if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
168 (bearers & BT_MESH_PROV_ADV)) {
169 /* Make sure we're scanning for provisioning inviations */
170 bt_mesh_scan_enable();
171 /* Enable unprovisioned beacon sending */
172 bt_mesh_beacon_enable();
173 }
174
175 if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
176 (bearers & BT_MESH_PROV_GATT)) {
177 bt_mesh_proxy_prov_enable();
178 bt_mesh_adv_update();
179 }
180
181 return 0;
182 }
183
bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)184 int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
185 {
186 if (bt_mesh_is_provisioned()) {
187 return -EALREADY;
188 }
189
190 if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
191 (bearers & BT_MESH_PROV_ADV)) {
192 bt_mesh_beacon_disable();
193 bt_mesh_scan_disable();
194 }
195
196 if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
197 (bearers & BT_MESH_PROV_GATT)) {
198 bt_mesh_proxy_prov_disable(true);
199 }
200
201 return 0;
202 }
203
bt_mesh_gap_event(struct ble_gap_event * event,void * arg)204 static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg)
205 {
206 ble_adv_gap_mesh_cb(event, arg);
207 #if (MYNEWT_VAL(BLE_MESH_PROXY))
208 ble_mesh_proxy_gap_event(event, arg);
209 #endif
210 return 0;
211 }
212
model_suspend(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)213 static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
214 bool vnd, bool primary, void *user_data)
215 {
216 if (mod->pub && mod->pub->update) {
217 mod->pub->count = 0;
218 k_delayed_work_cancel(&mod->pub->timer);
219 }
220 }
221
bt_mesh_suspend(void)222 int bt_mesh_suspend(void)
223 {
224 int err;
225
226 if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
227 return -EINVAL;
228 }
229
230 if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
231 return -EALREADY;
232 }
233
234 err = bt_mesh_scan_disable();
235 if (err) {
236 atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
237 BT_WARN("Disabling scanning failed (err %d)", err);
238 return err;
239 }
240
241 bt_mesh_hb_pub_disable();
242
243 if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
244 bt_mesh_beacon_disable();
245 }
246
247 bt_mesh_model_foreach(model_suspend, NULL);
248 return 0;
249 }
250
model_resume(struct bt_mesh_model * mod,struct bt_mesh_elem * elem,bool vnd,bool primary,void * user_data)251 static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
252 bool vnd, bool primary, void *user_data)
253 {
254 if (mod->pub && mod->pub->update) {
255 s32_t period_ms = bt_mesh_model_pub_period_get(mod);
256 if (period_ms) {
257 k_delayed_work_submit(&mod->pub->timer, period_ms);
258 }
259 }
260 }
261
bt_mesh_resume(void)262 int bt_mesh_resume(void)
263 {
264 int err;
265
266 if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
267 return -EINVAL;
268 }
269
270 if (!atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
271 return -EALREADY;
272 }
273
274 err = bt_mesh_scan_enable();
275 if (err) {
276 BT_WARN("Re-enabling scanning failed (err %d)", err);
277 atomic_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED);
278 return err;
279 }
280
281 if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
282 bt_mesh_beacon_enable();
283 }
284
285 bt_mesh_model_foreach(model_resume, NULL);
286 return err;
287 }
288
bt_mesh_init(uint8_t own_addr_type,const struct bt_mesh_prov * prov,const struct bt_mesh_comp * comp)289 int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
290 const struct bt_mesh_comp *comp)
291 {
292 int err;
293 g_mesh_addr_type = own_addr_type;
294 /* initialize SM alg ECC subsystem (it is used directly from mesh code) */
295 ble_sm_alg_ecc_init();
296 err = bt_mesh_comp_register(comp);
297 if (err) {
298 return err;
299 }
300
301 #if (MYNEWT_VAL(BLE_MESH_PROV))
302 err = bt_mesh_prov_init(prov);
303 if (err) {
304 return err;
305 }
306
307 #endif
308 #if (MYNEWT_VAL(BLE_MESH_PROXY))
309 bt_mesh_proxy_init();
310 #endif
311 #if (MYNEWT_VAL(BLE_MESH_PROV))
312 /* Need this to proper link.rx.buf allocation */
313 bt_mesh_prov_reset_link();
314 #endif
315 bt_mesh_net_init();
316 bt_mesh_trans_init();
317 bt_mesh_beacon_init();
318 bt_mesh_adv_init();
319 #if (MYNEWT_VAL(BLE_MESH_PB_ADV))
320 /* Make sure we're scanning for provisioning inviations */
321 bt_mesh_scan_enable();
322 /* Enable unprovisioned beacon sending */
323 bt_mesh_beacon_enable();
324 #endif
325 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
326 bt_mesh_proxy_prov_enable();
327 #endif
328 ble_gap_event_listener_register(&mesh_event_listener,
329 bt_mesh_gap_event, NULL);
330 #if (MYNEWT_VAL(BLE_MESH_SETTINGS))
331 bt_mesh_settings_init();
332 #endif
333 return 0;
334 }
335