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
11 #if MYNEWT_VAL(BLE_MESH_PROXY) == 1
12
13 #include "mesh/mesh.h"
14
15 #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG_PROXY))
16 #include "host/ble_hs_log.h"
17 #include "host/ble_att.h"
18 #include "services/gatt/ble_svc_gatt.h"
19 #include "../../host/src/ble_hs_priv.h"
20
21 #include "mesh_priv.h"
22 #include "adv.h"
23 #include "net.h"
24 #include "prov.h"
25 #include "beacon.h"
26 #include "foundation.h"
27 #include "access.h"
28 #include "proxy.h"
29
30 #define PDU_TYPE(data) (data[0] & BIT_MASK(6))
31 #define PDU_SAR(data) (data[0] >> 6)
32
33 #define SAR_COMPLETE 0x00
34 #define SAR_FIRST 0x01
35 #define SAR_CONT 0x02
36 #define SAR_LAST 0x03
37
38 #define CFG_FILTER_SET 0x00
39 #define CFG_FILTER_ADD 0x01
40 #define CFG_FILTER_REMOVE 0x02
41 #define CFG_FILTER_STATUS 0x03
42
43 /** @def BT_UUID_MESH_PROV
44 * @brief Mesh Provisioning Service
45 */
46 ble_uuid16_t BT_UUID_MESH_PROV = BLE_UUID16_INIT(0x1827);
47 #define BT_UUID_MESH_PROV_VAL 0x1827
48 /** @def BT_UUID_MESH_PROXY
49 * @brief Mesh Proxy Service
50 */
51 ble_uuid16_t BT_UUID_MESH_PROXY = BLE_UUID16_INIT(0x1828);
52 #define BT_UUID_MESH_PROXY_VAL 0x1828
53 /** @def BT_UUID_GATT_CCC
54 * @brief GATT Client Characteristic Configuration
55 */
56 ble_uuid16_t BT_UUID_GATT_CCC = BLE_UUID16_INIT(0x2902);
57 #define BT_UUID_GATT_CCC_VAL 0x2902
58 /** @def BT_UUID_MESH_PROV_DATA_IN
59 * @brief Mesh Provisioning Data In
60 */
61 ble_uuid16_t BT_UUID_MESH_PROV_DATA_IN = BLE_UUID16_INIT(0x2adb);
62 #define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb
63 /** @def BT_UUID_MESH_PROV_DATA_OUT
64 * @brief Mesh Provisioning Data Out
65 */
66 ble_uuid16_t BT_UUID_MESH_PROV_DATA_OUT = BLE_UUID16_INIT(0x2adc);
67 #define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc
68 /** @def BT_UUID_MESH_PROXY_DATA_IN
69 * @brief Mesh Proxy Data In
70 */
71 ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add);
72 #define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add
73 /** @def BT_UUID_MESH_PROXY_DATA_OUT
74 * @brief Mesh Proxy Data Out
75 */
76 ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade);
77 #define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade
78
79 #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6)))
80
81 #define CLIENT_BUF_SIZE 68
82
83 static const struct ble_gap_adv_params slow_adv_param = {
84 .conn_mode = (BLE_GAP_CONN_MODE_UND),
85 .disc_mode = (BLE_GAP_DISC_MODE_GEN),
86 .itvl_min = BT_GAP_ADV_SLOW_INT_MIN,
87 .itvl_max = BT_GAP_ADV_SLOW_INT_MAX,
88 };
89
90 static const struct ble_gap_adv_params fast_adv_param = {
91 .conn_mode = (BLE_GAP_CONN_MODE_UND),
92 .disc_mode = (BLE_GAP_DISC_MODE_GEN),
93 .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2,
94 .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2,
95 };
96
97 static bool proxy_adv_enabled;
98
99 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
100 static void proxy_send_beacons(struct ble_npl_event *work);
101 #endif
102
103 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
104 static bool prov_fast_adv;
105 #endif
106
107 static struct bt_mesh_proxy_client {
108 uint16_t conn_handle;
109 u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
110 enum __packed {
111 NONE,
112 WHITELIST,
113 BLACKLIST,
114 PROV,
115 } filter_type;
116 u8_t msg_type;
117 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
118 struct ble_npl_callout send_beacons;
119 #endif
120 struct os_mbuf *buf;
121 } clients[MYNEWT_VAL(BLE_MAX_CONNECTIONS)] = {
122 [0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 },
123 };
124
125 /* Track which service is enabled */
126 static enum {
127 MESH_GATT_NONE,
128 MESH_GATT_PROV,
129 MESH_GATT_PROXY,
130 } gatt_svc = MESH_GATT_NONE;
131
132 static struct {
133 uint16_t proxy_h;
134 uint16_t proxy_data_out_h;
135 uint16_t prov_h;
136 uint16_t prov_data_in_h;
137 uint16_t prov_data_out_h;
138 } svc_handles;
139
resolve_svc_handles(void)140 static void resolve_svc_handles(void)
141 {
142 int rc;
143
144 /* Either all handles are already resolved, or none of them */
145 if (svc_handles.prov_data_out_h) {
146 return;
147 }
148
149 /*
150 * We assert if attribute is not found since at this stage all attributes
151 * shall be already registered and thus shall be found.
152 */
153
154 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL),
155 &svc_handles.proxy_h);
156 assert(rc == 0);
157
158 rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL),
159 BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL),
160 NULL, &svc_handles.proxy_data_out_h);
161 assert(rc == 0);
162
163 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL),
164 &svc_handles.prov_h);
165 assert(rc == 0);
166
167 rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL),
168 BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL),
169 NULL, &svc_handles.prov_data_in_h);
170 assert(rc == 0);
171
172 rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL),
173 BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL),
174 NULL, &svc_handles.prov_data_out_h);
175 assert(rc == 0);
176 }
177
find_client(uint16_t conn_handle)178 static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle)
179 {
180 int i;
181
182 for (i = 0; i < ARRAY_SIZE(clients); i++) {
183 if (clients[i].conn_handle == conn_handle) {
184 return &clients[i];
185 }
186 }
187
188 return NULL;
189 }
190
191 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
192 /* Next subnet in queue to be advertised */
193 static int next_idx;
194
195 static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
196 struct os_mbuf *msg);
197
filter_set(struct bt_mesh_proxy_client * client,struct os_mbuf * buf)198 static int filter_set(struct bt_mesh_proxy_client *client,
199 struct os_mbuf *buf)
200 {
201 u8_t type;
202
203 if (buf->om_len < 1) {
204 BT_WARN("Too short Filter Set message");
205 return -EINVAL;
206 }
207
208 type = net_buf_simple_pull_u8(buf);
209 BT_DBG("type 0x%02x", type);
210
211 switch (type) {
212 case 0x00:
213 memset(client->filter, 0, sizeof(client->filter));
214 client->filter_type = WHITELIST;
215 break;
216 case 0x01:
217 memset(client->filter, 0, sizeof(client->filter));
218 client->filter_type = BLACKLIST;
219 break;
220 default:
221 BT_WARN("Prohibited Filter Type 0x%02x", type);
222 return -EINVAL;
223 }
224
225 return 0;
226 }
227
filter_add(struct bt_mesh_proxy_client * client,u16_t addr)228 static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
229 {
230 int i;
231
232 BT_DBG("addr 0x%04x", addr);
233
234 if (addr == BT_MESH_ADDR_UNASSIGNED) {
235 return;
236 }
237
238 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
239 if (client->filter[i] == addr) {
240 return;
241 }
242 }
243
244 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
245 if (client->filter[i] == BT_MESH_ADDR_UNASSIGNED) {
246 client->filter[i] = addr;
247 return;
248 }
249 }
250 }
251
filter_remove(struct bt_mesh_proxy_client * client,u16_t addr)252 static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr)
253 {
254 int i;
255
256 BT_DBG("addr 0x%04x", addr);
257
258 if (addr == BT_MESH_ADDR_UNASSIGNED) {
259 return;
260 }
261
262 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
263 if (client->filter[i] == addr) {
264 client->filter[i] = BT_MESH_ADDR_UNASSIGNED;
265 return;
266 }
267 }
268 }
269
send_filter_status(struct bt_mesh_proxy_client * client,struct bt_mesh_net_rx * rx,struct os_mbuf * buf)270 static void send_filter_status(struct bt_mesh_proxy_client *client,
271 struct bt_mesh_net_rx *rx,
272 struct os_mbuf *buf)
273 {
274 struct bt_mesh_net_tx tx = {
275 .sub = rx->sub,
276 .ctx = &rx->ctx,
277 .src = bt_mesh_primary_addr(),
278 };
279 u16_t filter_size;
280 int i, err;
281
282 /* Configuration messages always have dst unassigned */
283 tx.ctx->addr = BT_MESH_ADDR_UNASSIGNED;
284
285 net_buf_simple_init(buf, 10);
286
287 net_buf_simple_add_u8(buf, CFG_FILTER_STATUS);
288
289 if (client->filter_type == WHITELIST) {
290 net_buf_simple_add_u8(buf, 0x00);
291 } else {
292 net_buf_simple_add_u8(buf, 0x01);
293 }
294
295 for (filter_size = 0, i = 0; i < ARRAY_SIZE(client->filter); i++) {
296 if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) {
297 filter_size++;
298 }
299 }
300
301 net_buf_simple_add_be16(buf, filter_size);
302
303 BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
304
305 err = bt_mesh_net_encode(&tx, buf, true);
306 if (err) {
307 BT_ERR("Encoding Proxy cfg message failed (err %d)", err);
308 return;
309 }
310
311 err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_CONFIG, buf);
312 if (err) {
313 BT_ERR("Failed to send proxy cfg message (err %d)", err);
314 }
315 }
316
proxy_cfg(struct bt_mesh_proxy_client * client)317 static void proxy_cfg(struct bt_mesh_proxy_client *client)
318 {
319 struct os_mbuf *buf = NET_BUF_SIMPLE(29);
320 struct bt_mesh_net_rx rx;
321 u8_t opcode;
322 int err;
323
324 err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG,
325 &rx, buf);
326 if (err) {
327 BT_ERR("Failed to decode Proxy Configuration (err %d)", err);
328 goto done;
329 }
330
331 /* Remove network headers */
332 net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN);
333
334 BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
335
336 if (buf->om_len < 1) {
337 BT_WARN("Too short proxy configuration PDU");
338 goto done;
339 }
340
341 opcode = net_buf_simple_pull_u8(buf);
342 switch (opcode) {
343 case CFG_FILTER_SET:
344 filter_set(client, buf);
345 send_filter_status(client, &rx, buf);
346 break;
347 case CFG_FILTER_ADD:
348 while (buf->om_len >= 2) {
349 u16_t addr;
350
351 addr = net_buf_simple_pull_be16(buf);
352 filter_add(client, addr);
353 }
354 send_filter_status(client, &rx, buf);
355 break;
356 case CFG_FILTER_REMOVE:
357 while (buf->om_len >= 2) {
358 u16_t addr;
359
360 addr = net_buf_simple_pull_be16(buf);
361 filter_remove(client, addr);
362 }
363 send_filter_status(client, &rx, buf);
364 break;
365 default:
366 BT_WARN("Unhandled configuration OpCode 0x%02x", opcode);
367 break;
368 }
369
370 done:
371 os_mbuf_free_chain(buf);
372 }
373
beacon_send(uint16_t conn_handle,struct bt_mesh_subnet * sub)374 static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub)
375 {
376 struct os_mbuf *buf = NET_BUF_SIMPLE(23);
377 int rc;
378
379 net_buf_simple_init(buf, 1);
380 bt_mesh_beacon_create(sub, buf);
381
382 rc = proxy_segment_and_send(conn_handle, BT_MESH_PROXY_BEACON, buf);
383 os_mbuf_free_chain(buf);
384 return rc;
385 }
386
proxy_send_beacons(struct ble_npl_event * work)387 static void proxy_send_beacons(struct ble_npl_event *work)
388 {
389 struct bt_mesh_proxy_client *client;
390 int i;
391
392
393 client = ble_npl_event_get_arg(work);
394
395 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
396 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
397
398 if (sub->net_idx != BT_MESH_KEY_UNUSED) {
399 beacon_send(client->conn_handle, sub);
400 }
401 }
402 }
403
bt_mesh_proxy_beacon_send(struct bt_mesh_subnet * sub)404 void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
405 {
406 int i;
407
408 if (!sub) {
409 /* NULL means we send on all subnets */
410 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
411 if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
412 bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
413 }
414 }
415
416 return;
417 }
418
419 for (i = 0; i < ARRAY_SIZE(clients); i++) {
420 if (clients[i].conn_handle) {
421 beacon_send(clients[i].conn_handle, sub);
422 }
423 }
424 }
425
bt_mesh_proxy_identity_start(struct bt_mesh_subnet * sub)426 void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
427 {
428 sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
429 sub->node_id_start = k_uptime_get_32();
430
431 /* Prioritize the recently enabled subnet */
432 next_idx = sub - bt_mesh.sub;
433 }
434
bt_mesh_proxy_identity_stop(struct bt_mesh_subnet * sub)435 void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
436 {
437 sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
438 sub->node_id_start = 0;
439 }
440
bt_mesh_proxy_identity_enable(void)441 int bt_mesh_proxy_identity_enable(void)
442 {
443 int i, count = 0;
444
445 BT_DBG("");
446
447 if (!bt_mesh_is_provisioned()) {
448 return -EAGAIN;
449 }
450
451 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
452 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
453
454 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
455 continue;
456 }
457
458 if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
459 continue;
460 }
461
462 bt_mesh_proxy_identity_start(sub);
463 count++;
464 }
465
466 if (count) {
467 bt_mesh_adv_update();
468 }
469
470 return 0;
471 }
472
473 #endif /* GATT_PROXY */
474
proxy_complete_pdu(struct bt_mesh_proxy_client * client)475 static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
476 {
477 switch (client->msg_type) {
478 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
479 case BT_MESH_PROXY_NET_PDU:
480 BT_INFO("Mesh Network PDU");
481 bt_mesh_net_recv(client->buf, 0, BT_MESH_NET_IF_PROXY);
482 break;
483 case BT_MESH_PROXY_BEACON:
484 BT_INFO("Mesh Beacon PDU");
485 bt_mesh_beacon_recv(client->buf);
486 break;
487 case BT_MESH_PROXY_CONFIG:
488 BT_INFO("Mesh Configuration PDU");
489 proxy_cfg(client);
490 break;
491 #endif
492 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
493 case BT_MESH_PROXY_PROV:
494 BT_INFO("Mesh Provisioning PDU");
495 bt_mesh_pb_gatt_recv(client->conn_handle, client->buf);
496 break;
497 #endif
498 default:
499 BT_WARN("Unhandled Message Type 0x%02x", client->msg_type);
500 break;
501 }
502
503 net_buf_simple_init(client->buf, 0);
504 }
505
proxy_recv(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)506 static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle,
507 struct ble_gatt_access_ctxt *ctxt, void *arg)
508 {
509 struct bt_mesh_proxy_client *client;
510 const u8_t *data = ctxt->om->om_data;
511 u16_t len = ctxt->om->om_len;
512
513 client = find_client(conn_handle);
514
515 if (!client) {
516 return -ENOTCONN;
517 }
518
519 if (len < 1) {
520 BT_WARN("Too small Proxy PDU");
521 return -EINVAL;
522 }
523
524 if ((attr_handle == svc_handles.prov_data_in_h) !=
525 (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) {
526 BT_WARN("Proxy PDU type doesn't match GATT service");
527 return -EINVAL;
528 }
529
530 if (len - 1 > net_buf_simple_tailroom(client->buf)) {
531 BT_WARN("Too big proxy PDU");
532 return -EINVAL;
533 }
534
535 switch (PDU_SAR(data)) {
536 case SAR_COMPLETE:
537 if (client->buf->om_len) {
538 BT_WARN("Complete PDU while a pending incomplete one");
539 return -EINVAL;
540 }
541
542 client->msg_type = PDU_TYPE(data);
543 net_buf_simple_add_mem(client->buf, data + 1, len - 1);
544 proxy_complete_pdu(client);
545 break;
546
547 case SAR_FIRST:
548 if (client->buf->om_len) {
549 BT_WARN("First PDU while a pending incomplete one");
550 return -EINVAL;
551 }
552
553 client->msg_type = PDU_TYPE(data);
554 net_buf_simple_add_mem(client->buf, data + 1, len - 1);
555 break;
556
557 case SAR_CONT:
558 if (!client->buf->om_len) {
559 BT_WARN("Continuation with no prior data");
560 return -EINVAL;
561 }
562
563 if (client->msg_type != PDU_TYPE(data)) {
564 BT_WARN("Unexpected message type in continuation");
565 return -EINVAL;
566 }
567
568 net_buf_simple_add_mem(client->buf, data + 1, len - 1);
569 break;
570
571 case SAR_LAST:
572 if (!client->buf->om_len) {
573 BT_WARN("Last SAR PDU with no prior data");
574 return -EINVAL;
575 }
576
577 if (client->msg_type != PDU_TYPE(data)) {
578 BT_WARN("Unexpected message type in last SAR PDU");
579 return -EINVAL;
580 }
581
582 net_buf_simple_add_mem(client->buf, data + 1, len - 1);
583 proxy_complete_pdu(client);
584 break;
585 }
586
587 return len;
588 }
589
590 static int conn_count;
591
proxy_connected(uint16_t conn_handle)592 static void proxy_connected(uint16_t conn_handle)
593 {
594 struct bt_mesh_proxy_client *client;
595 int i;
596
597 BT_INFO("conn_handle %d", conn_handle);
598
599 conn_count++;
600
601 /* Since we use ADV_OPT_ONE_TIME */
602 proxy_adv_enabled = false;
603
604 /* Try to re-enable advertising in case it's possible */
605 if (conn_count < CONFIG_BT_MAX_CONN) {
606 bt_mesh_adv_update();
607 }
608
609 for (client = NULL, i = 0; i < ARRAY_SIZE(clients); i++) {
610 if (!clients[i].conn_handle) {
611 client = &clients[i];
612 break;
613 }
614 }
615
616 if (!client) {
617 BT_ERR("No free Proxy Client objects");
618 return;
619 }
620
621 client->conn_handle = conn_handle;
622 client->filter_type = NONE;
623 memset(client->filter, 0, sizeof(client->filter));
624 net_buf_simple_init(client->buf, 0);
625 }
626
proxy_disconnected(uint16_t conn_handle,int reason)627 static void proxy_disconnected(uint16_t conn_handle, int reason)
628 {
629 int i;
630
631 BT_INFO("conn_handle %d reason %d", conn_handle, reason);
632
633 conn_count--;
634
635 for (i = 0; i < ARRAY_SIZE(clients); i++) {
636 struct bt_mesh_proxy_client *client = &clients[i];
637
638 if (client->conn_handle == conn_handle) {
639 if ((MYNEWT_VAL(BLE_MESH_PB_GATT)) &&
640 client->filter_type == PROV) {
641 bt_mesh_pb_gatt_close(conn_handle);
642 }
643
644 client->conn_handle = 0;
645 break;
646 }
647 }
648
649 bt_mesh_adv_update();
650 }
651
bt_mesh_proxy_get_buf(void)652 struct os_mbuf *bt_mesh_proxy_get_buf(void)
653 {
654 struct os_mbuf *buf = clients[0].buf;
655
656 net_buf_simple_init(buf, 0);
657
658 return buf;
659 }
660
661 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
prov_ccc_write(uint16_t conn_handle)662 static void prov_ccc_write(uint16_t conn_handle)
663 {
664 struct bt_mesh_proxy_client *client;
665
666 BT_DBG("conn_handle %d", conn_handle);
667
668 /* If a connection exists there must be a client */
669 client = find_client(conn_handle);
670 __ASSERT(client, "No client for connection");
671
672 if (client->filter_type == NONE) {
673 client->filter_type = PROV;
674 bt_mesh_pb_gatt_open(conn_handle);
675 }
676 }
677
bt_mesh_proxy_prov_enable(void)678 int bt_mesh_proxy_prov_enable(void)
679 {
680 uint16_t handle;
681 int rc;
682 int i;
683
684 BT_DBG("");
685
686 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle);
687 assert(rc == 0);
688 ble_gatts_svc_set_visibility(handle, 1);
689 /* FIXME: figure out end handle */
690 ble_svc_gatt_changed(svc_handles.prov_h, 0xffff);
691
692 gatt_svc = MESH_GATT_PROV;
693 prov_fast_adv = true;
694
695 for (i = 0; i < ARRAY_SIZE(clients); i++) {
696 if (clients[i].conn_handle) {
697 clients[i].filter_type = PROV;
698 }
699 }
700
701
702 return 0;
703 }
704
bt_mesh_proxy_prov_disable(void)705 int bt_mesh_proxy_prov_disable(void)
706 {
707 uint16_t handle;
708 int rc;
709 int i;
710
711 BT_DBG("");
712
713 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle);
714 assert(rc == 0);
715 ble_gatts_svc_set_visibility(handle, 0);
716 /* FIXME: figure out end handle */
717 ble_svc_gatt_changed(svc_handles.prov_h, 0xffff);
718
719 gatt_svc = MESH_GATT_NONE;
720
721 for (i = 0; i < ARRAY_SIZE(clients); i++) {
722 struct bt_mesh_proxy_client *client = &clients[i];
723
724 if (clients->conn_handle && client->filter_type == PROV) {
725 bt_mesh_pb_gatt_close(client->conn_handle);
726 client->filter_type = NONE;
727 }
728 }
729
730 return 0;
731 }
732 #endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
733
734 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
proxy_ccc_write(uint16_t conn_handle)735 static void proxy_ccc_write(uint16_t conn_handle)
736 {
737 struct bt_mesh_proxy_client *client;
738
739 BT_DBG("conn_handle %d", conn_handle);
740
741 client = find_client(conn_handle);
742 __ASSERT(client, "No client for connection");
743
744 if (client->filter_type == NONE) {
745 client->filter_type = WHITELIST;
746 k_work_add_arg(&client->send_beacons, client);
747 k_work_submit(&client->send_beacons);
748 }
749 }
750
bt_mesh_proxy_gatt_enable(void)751 int bt_mesh_proxy_gatt_enable(void)
752 {
753 uint16_t handle;
754 int rc;
755 int i;
756
757 BT_DBG("");
758
759 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle);
760 assert(rc == 0);
761 ble_gatts_svc_set_visibility(handle, 1);
762 /* FIXME: figure out end handle */
763 ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff);
764
765 gatt_svc = MESH_GATT_PROXY;
766
767 for (i = 0; i < ARRAY_SIZE(clients); i++) {
768 if (clients[i].conn_handle) {
769 clients[i].filter_type = WHITELIST;
770 }
771 }
772
773 return 0;
774 }
775
bt_mesh_proxy_gatt_disconnect(void)776 void bt_mesh_proxy_gatt_disconnect(void)
777 {
778 int rc;
779 int i;
780
781 BT_DBG("");
782
783 for (i = 0; i < ARRAY_SIZE(clients); i++) {
784 struct bt_mesh_proxy_client *client = &clients[i];
785
786 if (client->conn_handle && (client->filter_type == WHITELIST ||
787 client->filter_type == BLACKLIST)) {
788 client->filter_type = NONE;
789 rc = ble_gap_terminate(client->conn_handle,
790 BLE_ERR_REM_USER_CONN_TERM);
791 assert(rc == 0);
792 }
793 }
794 }
795
bt_mesh_proxy_gatt_disable(void)796 int bt_mesh_proxy_gatt_disable(void)
797 {
798 uint16_t handle;
799 int rc;
800
801 BT_DBG("");
802
803 bt_mesh_proxy_gatt_disconnect();
804
805 rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle);
806 assert(rc == 0);
807 ble_gatts_svc_set_visibility(handle, 0);
808 /* FIXME: figure out end handle */
809 ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff);
810
811 gatt_svc = MESH_GATT_NONE;
812
813 return 0;
814 }
815
bt_mesh_proxy_addr_add(struct os_mbuf * buf,u16_t addr)816 void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
817 {
818 struct bt_mesh_proxy_client *client = NULL;
819 int i;
820
821 for (i = 0; i < ARRAY_SIZE(clients); i++) {
822 client = &clients[i];
823 if (client->buf == buf) {
824 break;
825 }
826 }
827
828 assert(client);
829
830 BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
831
832 if (client->filter_type == WHITELIST) {
833 filter_add(client, addr);
834 } else if (client->filter_type == BLACKLIST) {
835 filter_remove(client, addr);
836 }
837 }
838
client_filter_match(struct bt_mesh_proxy_client * client,u16_t addr)839 static bool client_filter_match(struct bt_mesh_proxy_client *client,
840 u16_t addr)
841 {
842 int i;
843
844 BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
845
846 if (client->filter_type == WHITELIST) {
847 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
848 if (client->filter[i] == addr) {
849 return true;
850 }
851 }
852
853 return false;
854 }
855
856 if (client->filter_type == BLACKLIST) {
857 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
858 if (client->filter[i] == addr) {
859 return false;
860 }
861 }
862
863 return true;
864 }
865
866 return false;
867 }
868
bt_mesh_proxy_relay(struct os_mbuf * buf,u16_t dst)869 bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
870 {
871 bool relayed = false;
872 int i;
873
874 BT_DBG("%u bytes to dst 0x%04x", buf->om_len, dst);
875
876 for (i = 0; i < ARRAY_SIZE(clients); i++) {
877 struct bt_mesh_proxy_client *client = &clients[i];
878 struct os_mbuf *msg;
879
880 if (!client->conn_handle) {
881 continue;
882 }
883
884 if (!client_filter_match(client, dst)) {
885 continue;
886 }
887
888 /* Proxy PDU sending modifies the original buffer,
889 * so we need to make a copy.
890 */
891 msg = NET_BUF_SIMPLE(32);
892 net_buf_simple_init(msg, 1);
893 net_buf_simple_add_mem(msg, buf->om_data, buf->om_len);
894
895 bt_mesh_proxy_send(client->conn_handle, BT_MESH_PROXY_NET_PDU, msg);
896 os_mbuf_free_chain(msg);
897 relayed = true;
898 }
899
900 return relayed;
901 }
902
903 #endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */
904
proxy_send(uint16_t conn_handle,const void * data,u16_t len)905 static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
906 {
907 struct os_mbuf *om;
908
909 BT_DBG("%u bytes: %s", len, bt_hex(data, len));
910
911 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
912 if (gatt_svc == MESH_GATT_PROXY) {
913 om = ble_hs_mbuf_from_flat(data, len);
914 assert(om);
915 ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
916 }
917 #endif
918
919 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
920 if (gatt_svc == MESH_GATT_PROV) {
921 om = ble_hs_mbuf_from_flat(data, len);
922 assert(om);
923 ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
924 }
925 #endif
926
927 return 0;
928 }
929
proxy_segment_and_send(uint16_t conn_handle,u8_t type,struct os_mbuf * msg)930 static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
931 struct os_mbuf *msg)
932 {
933 u16_t mtu;
934
935 BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len,
936 bt_hex(msg->om_data, msg->om_len));
937
938 /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
939 mtu = ble_att_mtu(conn_handle) - 3;
940 if (mtu > msg->om_len) {
941 net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
942 return proxy_send(conn_handle, msg->om_data, msg->om_len);
943 }
944
945 net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
946 proxy_send(conn_handle, msg->om_data, mtu);
947 net_buf_simple_pull(msg, mtu);
948
949 while (msg->om_len) {
950 if (msg->om_len + 1 < mtu) {
951 net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
952 proxy_send(conn_handle, msg->om_data, msg->om_len);
953 break;
954 }
955
956 net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
957 proxy_send(conn_handle, msg->om_data, mtu);
958 net_buf_simple_pull(msg, mtu);
959 }
960
961 return 0;
962 }
963
bt_mesh_proxy_send(uint16_t conn_handle,u8_t type,struct os_mbuf * msg)964 int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
965 struct os_mbuf *msg)
966 {
967 struct bt_mesh_proxy_client *client = find_client(conn_handle);
968
969 if (!client) {
970 BT_ERR("No Proxy Client found");
971 return -ENOTCONN;
972 }
973
974 if ((client->filter_type == PROV) != (type == BT_MESH_PROXY_PROV)) {
975 BT_ERR("Invalid PDU type for Proxy Client");
976 return -EINVAL;
977 }
978
979 return proxy_segment_and_send(conn_handle, type, msg);
980 }
981
982 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
983 static u8_t prov_svc_data[20] = { 0x27, 0x18, };
984
985 static const struct bt_data prov_ad[] = {
986 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
987 BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x27, 0x18),
988 BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
989 };
990 #endif /* PB_GATT */
991
992 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
993
994 #define ID_TYPE_NET 0x00
995 #define ID_TYPE_NODE 0x01
996
997 #define NODE_ID_LEN 19
998 #define NET_ID_LEN 11
999
1000 #define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT)
1001
1002 static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
1003
1004 static const struct bt_data node_id_ad[] = {
1005 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
1006 BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
1007 BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
1008 };
1009
1010 static const struct bt_data net_id_ad[] = {
1011 BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
1012 BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18),
1013 BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
1014 };
1015
node_id_adv(struct bt_mesh_subnet * sub)1016 static int node_id_adv(struct bt_mesh_subnet *sub)
1017 {
1018 u8_t tmp[16];
1019 int err;
1020
1021 BT_DBG("");
1022
1023 proxy_svc_data[2] = ID_TYPE_NODE;
1024
1025 err = bt_rand(proxy_svc_data + 11, 8);
1026 if (err) {
1027 return err;
1028 }
1029
1030 memset(tmp, 0, 6);
1031 memcpy(tmp + 6, proxy_svc_data + 11, 8);
1032 sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
1033
1034 err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
1035 if (err) {
1036 return err;
1037 }
1038
1039 memcpy(proxy_svc_data + 3, tmp + 8, 8);
1040
1041 err = bt_le_adv_start(&fast_adv_param, node_id_ad,
1042 ARRAY_SIZE(node_id_ad), NULL, 0);
1043 if (err) {
1044 BT_WARN("Failed to advertise using Node ID (err %d)", err);
1045 return err;
1046 }
1047
1048 proxy_adv_enabled = true;
1049
1050 return 0;
1051 }
1052
net_id_adv(struct bt_mesh_subnet * sub)1053 static int net_id_adv(struct bt_mesh_subnet *sub)
1054 {
1055 int err;
1056
1057 BT_DBG("");
1058
1059 proxy_svc_data[2] = ID_TYPE_NET;
1060
1061 BT_DBG("Advertising with NetId %s",
1062 bt_hex(sub->keys[sub->kr_flag].net_id, 8));
1063
1064 memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
1065
1066 err = bt_le_adv_start(&slow_adv_param, net_id_ad,
1067 ARRAY_SIZE(net_id_ad), NULL, 0);
1068 if (err) {
1069 BT_WARN("Failed to advertise using Network ID (err %d)", err);
1070 return err;
1071 }
1072
1073 proxy_adv_enabled = true;
1074
1075 return 0;
1076 }
1077
advertise_subnet(struct bt_mesh_subnet * sub)1078 static bool advertise_subnet(struct bt_mesh_subnet *sub)
1079 {
1080 if (sub->net_idx == BT_MESH_KEY_UNUSED) {
1081 return false;
1082 }
1083
1084 return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
1085 bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
1086 }
1087
next_sub(void)1088 static struct bt_mesh_subnet *next_sub(void)
1089 {
1090 int i;
1091
1092 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
1093 struct bt_mesh_subnet *sub;
1094
1095 sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
1096 if (advertise_subnet(sub)) {
1097 next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
1098 return sub;
1099 }
1100 }
1101
1102 return NULL;
1103 }
1104
sub_count(void)1105 static int sub_count(void)
1106 {
1107 int i, count = 0;
1108
1109 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
1110 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
1111
1112 if (advertise_subnet(sub)) {
1113 count++;
1114 }
1115 }
1116
1117 return count;
1118 }
1119
gatt_proxy_advertise(struct bt_mesh_subnet * sub)1120 static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
1121 {
1122 s32_t remaining = K_FOREVER;
1123 int subnet_count;
1124
1125 BT_DBG("");
1126
1127 if (conn_count == CONFIG_BT_MAX_CONN) {
1128 BT_WARN("Connectable advertising deferred (max connections)");
1129 return remaining;
1130 }
1131
1132 if (!sub) {
1133 BT_WARN("No subnets to advertise on");
1134 return remaining;
1135 }
1136
1137 if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
1138 u32_t active = k_uptime_get_32() - sub->node_id_start;
1139
1140 if (active < NODE_ID_TIMEOUT) {
1141 remaining = NODE_ID_TIMEOUT - active;
1142 BT_DBG("Node ID active for %u ms, %d ms remaining",
1143 active, remaining);
1144 node_id_adv(sub);
1145 } else {
1146 bt_mesh_proxy_identity_stop(sub);
1147 BT_DBG("Node ID stopped");
1148 }
1149 }
1150
1151 if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) {
1152 if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
1153 net_id_adv(sub);
1154 } else {
1155 return gatt_proxy_advertise(next_sub());
1156 }
1157 }
1158
1159 subnet_count = sub_count();
1160 BT_DBG("sub_count %u", subnet_count);
1161 if (subnet_count > 1) {
1162 s32_t max_timeout;
1163
1164 /* We use NODE_ID_TIMEOUT as a starting point since it may
1165 * be less than 60 seconds. Divide this period into at least
1166 * 6 slices, but make sure that a slice is at least one
1167 * second long (to avoid excessive rotation).
1168 */
1169 max_timeout = NODE_ID_TIMEOUT / max(subnet_count, 6);
1170 max_timeout = max(max_timeout, K_SECONDS(1));
1171
1172 if (remaining > max_timeout || remaining < 0) {
1173 remaining = max_timeout;
1174 }
1175 }
1176
1177 BT_DBG("Advertising %d ms for net_idx 0x%04x", remaining, sub->net_idx);
1178
1179 return remaining;
1180 }
1181 #endif /* GATT_PROXY */
1182
1183 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
gatt_prov_adv_create(struct bt_data prov_sd[2])1184 static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
1185 {
1186 const struct bt_mesh_prov *prov = bt_mesh_prov_get();
1187 const char *name = CONFIG_BT_DEVICE_NAME;
1188 size_t name_len = strlen(name);
1189 size_t prov_sd_len = 0;
1190 size_t sd_space = 31;
1191
1192 memcpy(prov_svc_data + 2, prov->uuid, 16);
1193 sys_put_be16(prov->oob_info, prov_svc_data + 18);
1194
1195 if (prov->uri) {
1196 size_t uri_len = strlen(prov->uri);
1197
1198 if (uri_len > 29) {
1199 /* There's no way to shorten an URI */
1200 BT_WARN("Too long URI to fit advertising packet");
1201 } else {
1202 prov_sd[0].type = BT_DATA_URI;
1203 prov_sd[0].data_len = uri_len;
1204 prov_sd[0].data = (void *)prov->uri;
1205 sd_space -= 2 + uri_len;
1206 prov_sd_len++;
1207 }
1208 }
1209
1210 if (sd_space > 2 && name_len > 0) {
1211 sd_space -= 2;
1212
1213 if (sd_space < name_len) {
1214 prov_sd[prov_sd_len].type = BT_DATA_NAME_SHORTENED;
1215 prov_sd[prov_sd_len].data_len = sd_space;
1216 } else {
1217 prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE;
1218 prov_sd[prov_sd_len].data_len = name_len;
1219 }
1220
1221 prov_sd[prov_sd_len].data = (void *)name;
1222 prov_sd_len++;
1223 }
1224
1225 return prov_sd_len;
1226 }
1227 #endif /* PB_GATT */
1228
bt_mesh_proxy_adv_start(void)1229 s32_t bt_mesh_proxy_adv_start(void)
1230 {
1231 BT_DBG("");
1232
1233 if (gatt_svc == MESH_GATT_NONE) {
1234 return K_FOREVER;
1235 }
1236
1237 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
1238 if (!bt_mesh_is_provisioned()) {
1239 const struct ble_gap_adv_params *param;
1240 struct bt_data prov_sd[2];
1241 size_t prov_sd_len;
1242
1243 if (prov_fast_adv) {
1244 param = &fast_adv_param;
1245 } else {
1246 param = &slow_adv_param;
1247 }
1248
1249 prov_sd_len = gatt_prov_adv_create(prov_sd);
1250
1251 if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad),
1252 prov_sd, prov_sd_len) == 0) {
1253 proxy_adv_enabled = true;
1254
1255 /* Advertise 60 seconds using fast interval */
1256 if (prov_fast_adv) {
1257 prov_fast_adv = false;
1258 return K_SECONDS(60);
1259 }
1260 }
1261 }
1262 #endif /* PB_GATT */
1263
1264 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
1265 if (bt_mesh_is_provisioned()) {
1266 return gatt_proxy_advertise(next_sub());
1267 }
1268 #endif /* GATT_PROXY */
1269
1270 return K_FOREVER;
1271 }
1272
bt_mesh_proxy_adv_stop(void)1273 void bt_mesh_proxy_adv_stop(void)
1274 {
1275 int err;
1276
1277 BT_DBG("adv_enabled %u", proxy_adv_enabled);
1278
1279 if (!proxy_adv_enabled) {
1280 return;
1281 }
1282
1283 err = bt_le_adv_stop(true);
1284 if (err) {
1285 BT_ERR("Failed to stop advertising (err %d)", err);
1286 } else {
1287 proxy_adv_enabled = false;
1288 }
1289 }
1290
1291 int
ble_mesh_proxy_gap_event(struct ble_gap_event * event,void * arg)1292 ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg)
1293 {
1294 // BT_DBG("event %d", event->type);
1295
1296 if (event->type == BLE_GAP_EVENT_CONNECT) {
1297 proxy_connected(event->connect.conn_handle);
1298 } else if (event->type == BLE_GAP_EVENT_DISCONNECT) {
1299 proxy_disconnected(event->disconnect.conn.conn_handle,
1300 event->disconnect.reason);
1301 } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) {
1302 if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) {
1303 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
1304 proxy_ccc_write(event->subscribe.conn_handle);
1305 #endif
1306 } else if (event->subscribe.attr_handle ==
1307 svc_handles.prov_data_out_h) {
1308 #if (MYNEWT_VAL(BLE_MESH_PB_GATT))
1309 prov_ccc_write(event->subscribe.conn_handle);
1310 #endif
1311 }
1312 }
1313
1314 return 0;
1315 }
1316
1317 static int
dummy_access_cb(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)1318 dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle,
1319 struct ble_gatt_access_ctxt *ctxt, void *arg)
1320 {
1321 /*
1322 * We should never never enter this callback - it's attached to notify-only
1323 * characteristic which are notified directly from mbuf. And we can't pass
1324 * NULL as access_cb because gatts will assert on init...
1325 */
1326 BLE_HS_DBG_ASSERT(0);
1327 return 0;
1328 }
1329
1330 static const struct ble_gatt_svc_def svc_defs [] = {
1331 {
1332 .type = BLE_GATT_SVC_TYPE_PRIMARY,
1333 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL),
1334 .characteristics = (struct ble_gatt_chr_def[]) { {
1335 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL),
1336 .access_cb = proxy_recv,
1337 .flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
1338 }, {
1339 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL),
1340 .access_cb = dummy_access_cb,
1341 .flags = BLE_GATT_CHR_F_NOTIFY,
1342 }, {
1343 0, /* No more characteristics in this service. */
1344 } },
1345 }, {
1346 .type = BLE_GATT_SVC_TYPE_PRIMARY,
1347 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL),
1348 .characteristics = (struct ble_gatt_chr_def[]) { {
1349 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL),
1350 .access_cb = proxy_recv,
1351 .flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
1352 }, {
1353 .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL),
1354 .access_cb = dummy_access_cb,
1355 .flags = BLE_GATT_CHR_F_NOTIFY,
1356 }, {
1357 0, /* No more characteristics in this service. */
1358 } },
1359 }, {
1360 0, /* No more services. */
1361 },
1362 };
1363
bt_mesh_proxy_svcs_register(void)1364 int bt_mesh_proxy_svcs_register(void)
1365 {
1366 int rc;
1367
1368 rc = ble_gatts_count_cfg(svc_defs);
1369 assert(rc == 0);
1370
1371 rc = ble_gatts_add_svcs(svc_defs);
1372 assert(rc == 0);
1373
1374 return 0;
1375 }
1376
bt_mesh_proxy_init(void)1377 int bt_mesh_proxy_init(void)
1378 {
1379 int i;
1380
1381 for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) {
1382 #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
1383 k_work_init(&clients[i].send_beacons, proxy_send_beacons);
1384 #endif
1385 clients[i].buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE);
1386 }
1387
1388 resolve_svc_handles();
1389
1390 ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0);
1391 ble_gatts_svc_set_visibility(svc_handles.prov_h, 0);
1392
1393 return 0;
1394 }
1395
1396 #endif //MYNEWT_VAL(BLE_MESH_PROXY)
1397