xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/proxy.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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