1 /* Bluetooth Mesh */
2
3 /*
4 * SPDX-FileCopyrightText: 2017 Intel Corporation
5 * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9 #include <string.h>
10 #include <errno.h>
11
12 #include "mesh.h"
13 #include "adv.h"
14 #include "prov.h"
15 #include "beacon.h"
16 #include "access.h"
17 #include "transport.h"
18 #include "foundation.h"
19 #include "mesh_common.h"
20 #include "proxy_server.h"
21
22 #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \
23 CONFIG_BLE_MESH_GATT_PROXY_SERVER
24
25 #if !CONFIG_BLE_MESH_BQB_TEST
26 /* Not support enabling Proxy Client and Proxy Server simultaneously */
27 _Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) &&IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)),
28 "Not support Proxy Server and Proxy Client simultaneously");
29 #endif
30
31 #define PDU_TYPE(data) (data[0] & BIT_MASK(6))
32 #define PDU_SAR(data) (data[0] >> 6)
33
34 /* Mesh Profile 1.0 Section 6.6:
35 * "The timeout for the SAR transfer is 20 seconds. When the timeout
36 * expires, the Proxy Server shall disconnect."
37 */
38 #define PROXY_SAR_TIMEOUT K_SECONDS(20)
39
40 #define SAR_COMPLETE 0x00
41 #define SAR_FIRST 0x01
42 #define SAR_CONT 0x02
43 #define SAR_LAST 0x03
44
45 #define CFG_FILTER_SET 0x00
46 #define CFG_FILTER_ADD 0x01
47 #define CFG_FILTER_REMOVE 0x02
48 #define CFG_FILTER_STATUS 0x03
49
50 #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6)))
51
52 #define CLIENT_BUF_SIZE 68
53
54 #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME)
55
56 static const struct bt_mesh_adv_param slow_adv_param = {
57 .options = ADV_OPT,
58 .interval_min = BLE_MESH_GAP_ADV_SLOW_INT_MIN,
59 .interval_max = BLE_MESH_GAP_ADV_SLOW_INT_MAX,
60 };
61
62 static const struct bt_mesh_adv_param fast_adv_param = {
63 .options = ADV_OPT,
64 .interval_min = BLE_MESH_GAP_ADV_FAST_INT_MIN_0,
65 .interval_max = BLE_MESH_GAP_ADV_FAST_INT_MAX_0,
66 };
67
68 static bool proxy_adv_enabled;
69
70 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
71 static void proxy_send_beacons(struct k_work *work);
72 static uint16_t proxy_ccc_val;
73 #endif
74
75 #if defined(CONFIG_BLE_MESH_PB_GATT)
76 static uint16_t prov_ccc_val;
77 static bool prov_fast_adv;
78 static uint32_t prov_start_time;
79 #endif
80
81 static struct bt_mesh_proxy_client {
82 struct bt_mesh_conn *conn;
83 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
84 uint16_t filter[CONFIG_BLE_MESH_PROXY_FILTER_SIZE];
85 #endif
86 enum __packed {
87 NONE,
88 WHITELIST,
89 BLACKLIST,
90 PROV,
91 } filter_type;
92 uint8_t msg_type;
93 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
94 struct k_work send_beacons;
95 #endif
96 struct k_delayed_work sar_timer;
97 struct net_buf_simple buf;
98 } clients[BLE_MESH_MAX_CONN];
99
100 static uint8_t client_buf_data[CLIENT_BUF_SIZE * BLE_MESH_MAX_CONN];
101
102 /* Track which service is enabled */
103 static enum {
104 MESH_GATT_NONE,
105 MESH_GATT_PROV,
106 MESH_GATT_PROXY,
107 } gatt_svc = MESH_GATT_NONE;
108
109 static char device_name[DEVICE_NAME_SIZE + 1];
110
bt_mesh_set_device_name(const char * name)111 int bt_mesh_set_device_name(const char *name)
112 {
113 if (!name) {
114 BT_ERR("%s, Invalid parameter", __func__);
115 return -EINVAL;
116 }
117
118 if (strlen(name) > DEVICE_NAME_SIZE) {
119 BT_ERR("Too long device name (len %d)", strlen(name));
120 return -EINVAL;
121 }
122
123 memset(device_name, 0x0, sizeof(device_name));
124 strncpy(device_name, name, DEVICE_NAME_SIZE);
125
126 return bt_mesh_gatts_set_local_device_name(device_name);
127 }
128
find_client(struct bt_mesh_conn * conn)129 static struct bt_mesh_proxy_client *find_client(struct bt_mesh_conn *conn)
130 {
131 int i;
132
133 for (i = 0; i < ARRAY_SIZE(clients); i++) {
134 if (clients[i].conn == conn) {
135 return &clients[i];
136 }
137 }
138
139 return NULL;
140 }
141
proxy_sar_timeout(struct k_work * work)142 static void proxy_sar_timeout(struct k_work *work)
143 {
144 struct bt_mesh_proxy_client *client = NULL;
145
146 BT_WARN("Proxy SAR timeout");
147
148 client = CONTAINER_OF(work, struct bt_mesh_proxy_client, sar_timer.work);
149 if (!client || !client->conn) {
150 BT_ERR("Invalid proxy client parameter");
151 return;
152 }
153
154 net_buf_simple_reset(&client->buf);
155 bt_mesh_gatts_disconnect(client->conn, 0x13);
156 }
157
158 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
159 /**
160 * The following callbacks are used to notify proper information
161 * to the application layer.
162 */
163 static proxy_server_connect_cb_t proxy_server_connect_cb;
164 static proxy_server_disconnect_cb_t proxy_server_disconnect_cb;
165
bt_mesh_proxy_server_set_conn_cb(proxy_server_connect_cb_t cb)166 void bt_mesh_proxy_server_set_conn_cb(proxy_server_connect_cb_t cb)
167 {
168 proxy_server_connect_cb = cb;
169 }
170
bt_mesh_proxy_server_set_disconn_cb(proxy_server_disconnect_cb_t cb)171 void bt_mesh_proxy_server_set_disconn_cb(proxy_server_disconnect_cb_t cb)
172 {
173 proxy_server_disconnect_cb = cb;
174 }
175
176 /* Next subnet in queue to be advertised */
177 static int next_idx;
178
179 static int proxy_segment_and_send(struct bt_mesh_conn *conn, uint8_t type,
180 struct net_buf_simple *msg);
181
filter_set(struct bt_mesh_proxy_client * client,struct net_buf_simple * buf)182 static int filter_set(struct bt_mesh_proxy_client *client,
183 struct net_buf_simple *buf)
184 {
185 uint8_t type = 0U;
186
187 if (buf->len < 1) {
188 BT_WARN("Too short Filter Set message");
189 return -EINVAL;
190 }
191
192 type = net_buf_simple_pull_u8(buf);
193 BT_INFO("Set filter type 0x%02x", type);
194
195 switch (type) {
196 case 0x00:
197 (void)memset(client->filter, 0, sizeof(client->filter));
198 client->filter_type = WHITELIST;
199 break;
200 case 0x01:
201 (void)memset(client->filter, 0, sizeof(client->filter));
202 client->filter_type = BLACKLIST;
203 break;
204 default:
205 BT_WARN("Prohibited Filter Type 0x%02x", type);
206 return -EINVAL;
207 }
208
209 return 0;
210 }
211
filter_add(struct bt_mesh_proxy_client * client,uint16_t addr)212 static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
213 {
214 int i;
215
216 BT_DBG("addr 0x%04x", addr);
217
218 if (addr == BLE_MESH_ADDR_UNASSIGNED) {
219 return;
220 }
221
222 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
223 if (client->filter[i] == addr) {
224 return;
225 }
226 }
227
228 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
229 if (client->filter[i] == BLE_MESH_ADDR_UNASSIGNED) {
230 client->filter[i] = addr;
231 BT_INFO("Add filter addr 0x%04x", addr);
232 return;
233 }
234 }
235
236 BT_WARN("Proxy filter is full!");
237 }
238
filter_remove(struct bt_mesh_proxy_client * client,uint16_t addr)239 static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
240 {
241 int i;
242
243 BT_DBG("addr 0x%04x", addr);
244
245 if (addr == BLE_MESH_ADDR_UNASSIGNED) {
246 return;
247 }
248
249 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
250 if (client->filter[i] == addr) {
251 client->filter[i] = BLE_MESH_ADDR_UNASSIGNED;
252 BT_INFO("Remove filter addr 0x%04x", addr);
253 return;
254 }
255 }
256 }
257
send_filter_status(struct bt_mesh_proxy_client * client,struct bt_mesh_net_rx * rx,struct net_buf_simple * buf)258 static void send_filter_status(struct bt_mesh_proxy_client *client,
259 struct bt_mesh_net_rx *rx,
260 struct net_buf_simple *buf)
261 {
262 struct bt_mesh_net_tx tx = {
263 .sub = rx->sub,
264 .ctx = &rx->ctx,
265 .src = bt_mesh_primary_addr(),
266 };
267 uint16_t filter_size = 0U;
268 int i, err = 0;
269
270 /* Configuration messages always have dst unassigned */
271 tx.ctx->addr = BLE_MESH_ADDR_UNASSIGNED;
272
273 net_buf_simple_reset(buf);
274 net_buf_simple_reserve(buf, 10);
275
276 net_buf_simple_add_u8(buf, CFG_FILTER_STATUS);
277
278 if (client->filter_type == WHITELIST) {
279 net_buf_simple_add_u8(buf, 0x00);
280 } else {
281 net_buf_simple_add_u8(buf, 0x01);
282 }
283
284 for (filter_size = 0U, i = 0; i < ARRAY_SIZE(client->filter); i++) {
285 if (client->filter[i] != BLE_MESH_ADDR_UNASSIGNED) {
286 filter_size++;
287 }
288 }
289
290 net_buf_simple_add_be16(buf, filter_size);
291
292 BT_DBG("%u bytes: %s", buf->len, bt_hex(buf->data, buf->len));
293
294 err = bt_mesh_net_encode(&tx, buf, true);
295 if (err) {
296 BT_ERR("Encoding proxy cfg message failed (err %d)", err);
297 return;
298 }
299
300 err = proxy_segment_and_send(client->conn, BLE_MESH_PROXY_CONFIG, buf);
301 if (err) {
302 BT_ERR("Failed to send proxy cfg message (err %d)", err);
303 }
304 }
305
proxy_cfg(struct bt_mesh_proxy_client * client)306 static void proxy_cfg(struct bt_mesh_proxy_client *client)
307 {
308 NET_BUF_SIMPLE_DEFINE(buf, 29);
309 struct bt_mesh_net_rx rx = {0};
310 uint8_t opcode = 0U;
311 int err = 0;
312
313 if (client->buf.len > 29) {
314 BT_ERR("Too large proxy cfg pdu (len %d)", client->buf.len);
315 return;
316 }
317
318 err = bt_mesh_net_decode(&client->buf, BLE_MESH_NET_IF_PROXY_CFG,
319 &rx, &buf);
320 if (err) {
321 BT_ERR("Failed to decode Proxy Configuration (err %d)", err);
322 return;
323 }
324
325 rx.local_match = 1U;
326
327 if (bt_mesh_rpl_check(&rx, NULL)) {
328 BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
329 rx.ctx.addr, rx.ctx.recv_dst, rx.seq);
330 return;
331 }
332
333 /* Remove network headers */
334 net_buf_simple_pull(&buf, BLE_MESH_NET_HDR_LEN);
335
336 BT_DBG("%u bytes: %s", buf.len, bt_hex(buf.data, buf.len));
337
338 if (buf.len < 1) {
339 BT_WARN("Too short proxy configuration PDU");
340 return;
341 }
342
343 opcode = net_buf_simple_pull_u8(&buf);
344 switch (opcode) {
345 case CFG_FILTER_SET:
346 filter_set(client, &buf);
347 send_filter_status(client, &rx, &buf);
348 break;
349 case CFG_FILTER_ADD:
350 while (buf.len >= 2) {
351 uint16_t addr = 0U;
352
353 addr = net_buf_simple_pull_be16(&buf);
354 filter_add(client, addr);
355 }
356 send_filter_status(client, &rx, &buf);
357 break;
358 case CFG_FILTER_REMOVE:
359 while (buf.len >= 2) {
360 uint16_t addr = 0U;
361
362 addr = net_buf_simple_pull_be16(&buf);
363 filter_remove(client, addr);
364 }
365 send_filter_status(client, &rx, &buf);
366 break;
367 default:
368 BT_WARN("Unhandled configuration OpCode 0x%02x", opcode);
369 break;
370 }
371 }
372
beacon_send(struct bt_mesh_conn * conn,struct bt_mesh_subnet * sub)373 static int beacon_send(struct bt_mesh_conn *conn, struct bt_mesh_subnet *sub)
374 {
375 NET_BUF_SIMPLE_DEFINE(buf, 23);
376
377 net_buf_simple_reserve(&buf, 1);
378 bt_mesh_beacon_create(sub, &buf);
379
380 return proxy_segment_and_send(conn, BLE_MESH_PROXY_BEACON, &buf);
381 }
382
proxy_send_beacons(struct k_work * work)383 static void proxy_send_beacons(struct k_work *work)
384 {
385 struct bt_mesh_proxy_client *client = NULL;
386 int i;
387
388 client = CONTAINER_OF(work, struct bt_mesh_proxy_client, send_beacons);
389
390 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
391 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
392
393 if (sub->net_idx != BLE_MESH_KEY_UNUSED) {
394 beacon_send(client->conn, sub);
395 }
396 }
397 }
398
bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet * sub)399 void bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet *sub)
400 {
401 int i;
402
403 if (!sub) {
404 /* NULL means we send on all subnets */
405 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
406 if (bt_mesh.sub[i].net_idx != BLE_MESH_KEY_UNUSED) {
407 bt_mesh_proxy_server_beacon_send(&bt_mesh.sub[i]);
408 }
409 }
410
411 return;
412 }
413
414 for (i = 0; i < ARRAY_SIZE(clients); i++) {
415 if (clients[i].conn) {
416 beacon_send(clients[i].conn, sub);
417 }
418 }
419 }
420
bt_mesh_proxy_server_identity_start(struct bt_mesh_subnet * sub)421 void bt_mesh_proxy_server_identity_start(struct bt_mesh_subnet *sub)
422 {
423 sub->node_id = BLE_MESH_NODE_IDENTITY_RUNNING;
424 sub->node_id_start = k_uptime_get_32();
425
426 /* Prioritize the recently enabled subnet */
427 next_idx = sub - bt_mesh.sub;
428 }
429
bt_mesh_proxy_server_identity_stop(struct bt_mesh_subnet * sub)430 void bt_mesh_proxy_server_identity_stop(struct bt_mesh_subnet *sub)
431 {
432 sub->node_id = BLE_MESH_NODE_IDENTITY_STOPPED;
433 sub->node_id_start = 0U;
434 }
435
bt_mesh_proxy_identity_enable(void)436 int bt_mesh_proxy_identity_enable(void)
437 {
438 int i, count = 0;
439
440 BT_DBG("%s", __func__);
441
442 if (!bt_mesh_is_provisioned()) {
443 return -EAGAIN;
444 }
445
446 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
447 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
448
449 if (sub->net_idx == BLE_MESH_KEY_UNUSED) {
450 continue;
451 }
452
453 if (sub->node_id == BLE_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
454 continue;
455 }
456
457 bt_mesh_proxy_server_identity_start(sub);
458 count++;
459 }
460
461 if (count) {
462 bt_mesh_adv_update();
463 }
464
465 return 0;
466 }
467
468 #endif /* GATT_PROXY */
469
proxy_complete_pdu(struct bt_mesh_proxy_client * client)470 static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
471 {
472 switch (client->msg_type) {
473 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
474 case BLE_MESH_PROXY_NET_PDU:
475 BT_DBG("Mesh Network PDU");
476 bt_mesh_net_recv(&client->buf, 0, BLE_MESH_NET_IF_PROXY);
477 break;
478 case BLE_MESH_PROXY_BEACON:
479 BT_DBG("Mesh Beacon PDU");
480 bt_mesh_beacon_recv(&client->buf, 0);
481 break;
482 case BLE_MESH_PROXY_CONFIG:
483 BT_DBG("Mesh Configuration PDU");
484 proxy_cfg(client);
485 break;
486 #endif
487 #if defined(CONFIG_BLE_MESH_PB_GATT)
488 case BLE_MESH_PROXY_PROV:
489 BT_DBG("Mesh Provisioning PDU");
490 bt_mesh_pb_gatt_recv(client->conn, &client->buf);
491 break;
492 #endif
493 default:
494 BT_WARN("Unhandled Message Type 0x%02x", client->msg_type);
495 break;
496 }
497
498 net_buf_simple_reset(&client->buf);
499 }
500
501 #define ATTR_IS_PROV(attr) (attr->user_data != NULL)
502
proxy_recv(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)503 static ssize_t proxy_recv(struct bt_mesh_conn *conn,
504 const struct bt_mesh_gatt_attr *attr, const void *buf,
505 uint16_t len, uint16_t offset, uint8_t flags)
506 {
507 struct bt_mesh_proxy_client *client = find_client(conn);
508 const uint8_t *data = buf;
509
510 if (!client) {
511 return -ENOTCONN;
512 }
513
514 if (len < 1) {
515 BT_WARN("Too small Proxy PDU");
516 return -EINVAL;
517 }
518
519 if (ATTR_IS_PROV(attr) != (PDU_TYPE(data) == BLE_MESH_PROXY_PROV)) {
520 BT_WARN("Proxy PDU type doesn't match GATT service");
521 return -EINVAL;
522 }
523
524 if (len - 1 > net_buf_simple_tailroom(&client->buf)) {
525 BT_WARN("Too big proxy PDU");
526 return -EINVAL;
527 }
528
529 switch (PDU_SAR(data)) {
530 case SAR_COMPLETE:
531 if (client->buf.len) {
532 BT_WARN("Complete PDU while a pending incomplete one");
533 return -EINVAL;
534 }
535
536 client->msg_type = PDU_TYPE(data);
537 net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
538 proxy_complete_pdu(client);
539 break;
540
541 case SAR_FIRST:
542 if (client->buf.len) {
543 BT_WARN("First PDU while a pending incomplete one");
544 return -EINVAL;
545 }
546
547 k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT);
548 client->msg_type = PDU_TYPE(data);
549 net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
550 break;
551
552 case SAR_CONT:
553 if (!client->buf.len) {
554 BT_WARN("Continuation with no prior data");
555 return -EINVAL;
556 }
557
558 if (client->msg_type != PDU_TYPE(data)) {
559 BT_WARN("Unexpected message type in continuation");
560 return -EINVAL;
561 }
562
563 k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT);
564 net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
565 break;
566
567 case SAR_LAST:
568 if (!client->buf.len) {
569 BT_WARN("Last SAR PDU with no prior data");
570 return -EINVAL;
571 }
572
573 if (client->msg_type != PDU_TYPE(data)) {
574 BT_WARN("Unexpected message type in last SAR PDU");
575 return -EINVAL;
576 }
577
578 k_delayed_work_cancel(&client->sar_timer);
579 net_buf_simple_add_mem(&client->buf, data + 1, len - 1);
580 proxy_complete_pdu(client);
581 break;
582 }
583
584 return len;
585 }
586
587 static int conn_count;
588
proxy_connected(struct bt_mesh_conn * conn,uint8_t err)589 static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err)
590 {
591 struct bt_mesh_proxy_client *client = NULL;
592 int i;
593
594 BT_DBG("conn %p err 0x%02x", conn, err);
595
596 conn_count++;
597
598 /* Since we use ADV_OPT_ONE_TIME */
599 proxy_adv_enabled = false;
600
601 /* Try to re-enable advertising in case it's possible */
602 if (conn_count < BLE_MESH_MAX_CONN) {
603 bt_mesh_adv_update();
604 }
605
606 for (client = NULL, i = 0; i < ARRAY_SIZE(clients); i++) {
607 if (!clients[i].conn) {
608 client = &clients[i];
609 break;
610 }
611 }
612
613 if (!client) {
614 BT_ERR("No free Proxy Client objects");
615 return;
616 }
617
618 client->conn = bt_mesh_conn_ref(conn);
619 client->filter_type = NONE;
620 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
621 (void)memset(client->filter, 0, sizeof(client->filter));
622
623 if (proxy_server_connect_cb) {
624 proxy_server_connect_cb(conn->handle);
625 }
626 #endif
627 net_buf_simple_reset(&client->buf);
628 }
629
proxy_disconnected(struct bt_mesh_conn * conn,uint8_t reason)630 static void proxy_disconnected(struct bt_mesh_conn *conn, uint8_t reason)
631 {
632 int i;
633
634 BT_DBG("conn %p reason 0x%02x", conn, reason);
635
636 conn_count--;
637
638 for (i = 0; i < ARRAY_SIZE(clients); i++) {
639 struct bt_mesh_proxy_client *client = &clients[i];
640
641 if (client->conn == conn) {
642 #if CONFIG_BLE_MESH_GATT_PROXY_SERVER
643 if (proxy_server_disconnect_cb) {
644 proxy_server_disconnect_cb(conn->handle, reason);
645 }
646 #endif
647 if (IS_ENABLED(CONFIG_BLE_MESH_PB_GATT) &&
648 client->filter_type == PROV) {
649 bt_mesh_pb_gatt_close(conn);
650 }
651
652 k_delayed_work_cancel(&client->sar_timer);
653 bt_mesh_conn_unref(client->conn);
654 client->conn = NULL;
655 break;
656 }
657 }
658
659 bt_mesh_adv_update();
660 }
661
bt_mesh_proxy_server_get_buf(void)662 struct net_buf_simple *bt_mesh_proxy_server_get_buf(void)
663 {
664 struct net_buf_simple *buf = &clients[0].buf;
665
666 net_buf_simple_reset(buf);
667
668 return buf;
669 }
670
671 #if defined(CONFIG_BLE_MESH_PB_GATT)
prov_ccc_write(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)672 static ssize_t prov_ccc_write(struct bt_mesh_conn *conn,
673 const struct bt_mesh_gatt_attr *attr,
674 const void *buf, uint16_t len,
675 uint16_t offset, uint8_t flags)
676 {
677 struct bt_mesh_proxy_client *client = NULL;
678 uint16_t *value = attr->user_data;
679
680 BT_DBG("len %u: %s", len, bt_hex(buf, len));
681
682 if (len != sizeof(*value)) {
683 return BLE_MESH_GATT_ERR(BLE_MESH_ATT_ERR_INVALID_ATTRIBUTE_LEN);
684 }
685
686 *value = sys_get_le16(buf);
687 if (*value != BLE_MESH_GATT_CCC_NOTIFY) {
688 BT_WARN("Client wrote 0x%04x instead enabling notify", *value);
689 return len;
690 }
691
692 /* If a connection exists there must be a client */
693 client = find_client(conn);
694 if (!client) {
695 BT_ERR("No client for connection %p", conn);
696 return 0;
697 }
698
699 if (client->filter_type == NONE) {
700 client->filter_type = PROV;
701 bt_mesh_pb_gatt_open(conn);
702 }
703
704 return len;
705 }
706
prov_ccc_read(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)707 static ssize_t prov_ccc_read(struct bt_mesh_conn *conn,
708 const struct bt_mesh_gatt_attr *attr,
709 void *buf, uint16_t len, uint16_t offset)
710 {
711 uint16_t *value = attr->user_data;
712
713 return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value,
714 sizeof(*value));
715 }
716
717 /* Mesh Provisioning Service Declaration */
718 static struct bt_mesh_gatt_attr prov_attrs[] = {
719 BLE_MESH_GATT_PRIMARY_SERVICE(BLE_MESH_UUID_MESH_PROV),
720
721 BLE_MESH_GATT_CHARACTERISTIC(BLE_MESH_UUID_MESH_PROV_DATA_IN,
722 BLE_MESH_GATT_CHRC_WRITE_WITHOUT_RESP),
723 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_MESH_PROV_DATA_IN, BLE_MESH_GATT_PERM_WRITE,
724 NULL, proxy_recv, (void *)1),
725
726 BLE_MESH_GATT_CHARACTERISTIC(BLE_MESH_UUID_MESH_PROV_DATA_OUT,
727 BLE_MESH_GATT_CHRC_NOTIFY),
728 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_MESH_PROV_DATA_OUT, BLE_MESH_GATT_PERM_NONE,
729 NULL, NULL, NULL),
730 /* Add custom CCC as clients need to be tracked individually */
731 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_GATT_CCC,
732 BLE_MESH_GATT_PERM_WRITE | BLE_MESH_GATT_PERM_READ,
733 prov_ccc_read, prov_ccc_write, &prov_ccc_val),
734 };
735
736 struct bt_mesh_gatt_service prov_svc = BLE_MESH_GATT_SERVICE(prov_attrs);
737
bt_mesh_proxy_server_prov_enable(void)738 int bt_mesh_proxy_server_prov_enable(void)
739 {
740 int i;
741
742 BT_DBG("%s", __func__);
743
744 if (gatt_svc == MESH_GATT_PROV) {
745 BT_WARN("%s, Already", __func__);
746 return -EALREADY;
747 }
748
749 if (gatt_svc != MESH_GATT_NONE) {
750 BT_WARN("%s, Busy", __func__);
751 return -EBUSY;
752 }
753
754 bt_mesh_gatts_service_start(&prov_svc);
755 gatt_svc = MESH_GATT_PROV;
756 prov_fast_adv = true;
757
758 for (i = 0; i < ARRAY_SIZE(clients); i++) {
759 if (clients[i].conn) {
760 clients[i].filter_type = PROV;
761 }
762 }
763
764
765 return 0;
766 }
767
bt_mesh_proxy_server_prov_disable(bool disconnect)768 int bt_mesh_proxy_server_prov_disable(bool disconnect)
769 {
770 int i;
771
772 BT_DBG("%s", __func__);
773
774 if (gatt_svc == MESH_GATT_NONE) {
775 BT_WARN("%s, Already", __func__);
776 return -EALREADY;
777 }
778
779 if (gatt_svc != MESH_GATT_PROV) {
780 BT_WARN("%s, Busy", __func__);
781 return -EBUSY;
782 }
783
784 bt_mesh_gatts_service_stop(&prov_svc);
785 gatt_svc = MESH_GATT_NONE;
786
787 for (i = 0; i < ARRAY_SIZE(clients); i++) {
788 struct bt_mesh_proxy_client *client = &clients[i];
789
790 if (!client->conn || client->filter_type != PROV) {
791 continue;
792 }
793
794 if (disconnect) {
795 bt_mesh_gatts_disconnect(client->conn, 0x13);
796 } else {
797 bt_mesh_pb_gatt_close(client->conn);
798 client->filter_type = NONE;
799 }
800 }
801
802 bt_mesh_adv_update();
803
804 return 0;
805 }
806
807 #endif /* CONFIG_BLE_MESH_PB_GATT */
808
809 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
proxy_ccc_write(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)810 static ssize_t proxy_ccc_write(struct bt_mesh_conn *conn,
811 const struct bt_mesh_gatt_attr *attr,
812 const void *buf, uint16_t len,
813 uint16_t offset, uint8_t flags)
814 {
815 struct bt_mesh_proxy_client *client = NULL;
816 uint16_t value = 0U;
817
818 BT_DBG("len %u: %s", len, bt_hex(buf, len));
819
820 if (len != sizeof(value)) {
821 return BLE_MESH_GATT_ERR(BLE_MESH_ATT_ERR_INVALID_ATTRIBUTE_LEN);
822 }
823
824 value = sys_get_le16(buf);
825 if (value != BLE_MESH_GATT_CCC_NOTIFY) {
826 BT_WARN("Client wrote 0x%04x instead enabling notify", value);
827 return len;
828 }
829
830 /* If a connection exists there must be a client */
831 client = find_client(conn);
832 if (!client) {
833 BT_ERR("No client for connection %p", conn);
834 return 0;
835 }
836
837 if (client->filter_type == NONE) {
838 client->filter_type = WHITELIST;
839 k_work_submit(&client->send_beacons);
840 }
841
842 return len;
843 }
844
proxy_ccc_read(struct bt_mesh_conn * conn,const struct bt_mesh_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)845 static ssize_t proxy_ccc_read(struct bt_mesh_conn *conn,
846 const struct bt_mesh_gatt_attr *attr,
847 void *buf, uint16_t len, uint16_t offset)
848 {
849 uint16_t *value = attr->user_data;
850
851 return bt_mesh_gatts_attr_read(conn, attr, buf, len, offset, value,
852 sizeof(*value));
853 }
854
855 /* Mesh Proxy Service Declaration */
856 static struct bt_mesh_gatt_attr proxy_attrs[] = {
857 BLE_MESH_GATT_PRIMARY_SERVICE(BLE_MESH_UUID_MESH_PROXY),
858
859 BLE_MESH_GATT_CHARACTERISTIC(BLE_MESH_UUID_MESH_PROXY_DATA_IN,
860 BLE_MESH_GATT_CHRC_WRITE_WITHOUT_RESP),
861 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_MESH_PROXY_DATA_IN, BLE_MESH_GATT_PERM_WRITE,
862 NULL, proxy_recv, NULL),
863
864 BLE_MESH_GATT_CHARACTERISTIC(BLE_MESH_UUID_MESH_PROXY_DATA_OUT,
865 BLE_MESH_GATT_CHRC_NOTIFY),
866 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_MESH_PROXY_DATA_OUT, BLE_MESH_GATT_PERM_NONE,
867 NULL, NULL, NULL),
868 /* Add custom CCC as clients need to be tracked individually */
869 BLE_MESH_GATT_DESCRIPTOR(BLE_MESH_UUID_GATT_CCC,
870 BLE_MESH_GATT_PERM_READ | BLE_MESH_GATT_PERM_WRITE,
871 proxy_ccc_read, proxy_ccc_write, &proxy_ccc_val),
872 };
873
874 struct bt_mesh_gatt_service proxy_svc = BLE_MESH_GATT_SERVICE(proxy_attrs);
875
bt_mesh_proxy_server_gatt_enable(void)876 int bt_mesh_proxy_server_gatt_enable(void)
877 {
878 int i;
879
880 BT_DBG("%s", __func__);
881
882 if (gatt_svc == MESH_GATT_PROXY) {
883 BT_WARN("%s, Already", __func__);
884 return -EALREADY;
885 }
886
887 if (gatt_svc != MESH_GATT_NONE) {
888 BT_WARN("%s, Busy", __func__);
889 return -EBUSY;
890 }
891
892 bt_mesh_gatts_service_start(&proxy_svc);
893 gatt_svc = MESH_GATT_PROXY;
894
895 for (i = 0; i < ARRAY_SIZE(clients); i++) {
896 if (clients[i].conn) {
897 clients[i].filter_type = WHITELIST;
898 }
899 }
900
901 return 0;
902 }
903
bt_mesh_proxy_server_gatt_disconnect(void)904 void bt_mesh_proxy_server_gatt_disconnect(void)
905 {
906 int i;
907
908 BT_DBG("%s", __func__);
909
910 for (i = 0; i < ARRAY_SIZE(clients); i++) {
911 struct bt_mesh_proxy_client *client = &clients[i];
912
913 if (client->conn && (client->filter_type == WHITELIST ||
914 client->filter_type == BLACKLIST)) {
915 client->filter_type = NONE;
916 bt_mesh_gatts_disconnect(client->conn, 0x13);
917 }
918 }
919 }
920
bt_mesh_proxy_server_gatt_disable(void)921 int bt_mesh_proxy_server_gatt_disable(void)
922 {
923 BT_DBG("%s", __func__);
924
925 if (gatt_svc == MESH_GATT_NONE) {
926 BT_WARN("%s, Already", __func__);
927 return -EALREADY;
928 }
929
930 if (gatt_svc != MESH_GATT_PROXY) {
931 BT_WARN("%s, Busy", __func__);
932 return -EBUSY;
933 }
934
935 bt_mesh_proxy_server_gatt_disconnect();
936
937 bt_mesh_gatts_service_stop(&proxy_svc);
938 gatt_svc = MESH_GATT_NONE;
939
940 return 0;
941 }
942
bt_mesh_proxy_server_addr_add(struct net_buf_simple * buf,uint16_t addr)943 void bt_mesh_proxy_server_addr_add(struct net_buf_simple *buf, uint16_t addr)
944 {
945 struct bt_mesh_proxy_client *client =
946 CONTAINER_OF(buf, struct bt_mesh_proxy_client, buf);
947
948 BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
949
950 if (client->filter_type == WHITELIST) {
951 filter_add(client, addr);
952 } else if (client->filter_type == BLACKLIST) {
953 filter_remove(client, addr);
954 }
955 }
956
client_filter_match(struct bt_mesh_proxy_client * client,uint16_t addr)957 static bool client_filter_match(struct bt_mesh_proxy_client *client,
958 uint16_t addr)
959 {
960 int i;
961
962 BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr);
963
964 if (client->filter_type == BLACKLIST) {
965 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
966 if (client->filter[i] == addr) {
967 return false;
968 }
969 }
970
971 return true;
972 }
973
974 if (addr == BLE_MESH_ADDR_ALL_NODES) {
975 return true;
976 }
977
978 if (client->filter_type == WHITELIST) {
979 for (i = 0; i < ARRAY_SIZE(client->filter); i++) {
980 if (client->filter[i] == addr) {
981 return true;
982 }
983 }
984 }
985
986 return false;
987 }
988
bt_mesh_proxy_server_relay(struct net_buf_simple * buf,uint16_t dst)989 bool bt_mesh_proxy_server_relay(struct net_buf_simple *buf, uint16_t dst)
990 {
991 bool relayed = false;
992 int i;
993
994 BT_DBG("%u bytes to dst 0x%04x", buf->len, dst);
995
996 for (i = 0; i < ARRAY_SIZE(clients); i++) {
997 struct bt_mesh_proxy_client *client = &clients[i];
998 NET_BUF_SIMPLE_DEFINE(msg, 32);
999
1000 if (!client->conn) {
1001 continue;
1002 }
1003
1004 if (!client_filter_match(client, dst)) {
1005 continue;
1006 }
1007
1008 /* Proxy PDU sending modifies the original buffer,
1009 * so we need to make a copy.
1010 */
1011 net_buf_simple_reserve(&msg, 1);
1012 net_buf_simple_add_mem(&msg, buf->data, buf->len);
1013
1014 bt_mesh_proxy_server_send(client->conn, BLE_MESH_PROXY_NET_PDU, &msg);
1015 relayed = true;
1016 }
1017
1018 return relayed;
1019 }
1020
1021 #endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */
1022
proxy_send(struct bt_mesh_conn * conn,const void * data,uint16_t len)1023 static int proxy_send(struct bt_mesh_conn *conn, const void *data, uint16_t len)
1024 {
1025 BT_DBG("%u bytes: %s", len, bt_hex(data, len));
1026
1027 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1028 if (gatt_svc == MESH_GATT_PROXY) {
1029 return bt_mesh_gatts_notify(conn, &proxy_attrs[4], data, len);
1030 }
1031 #endif
1032
1033 #if defined(CONFIG_BLE_MESH_PB_GATT)
1034 if (gatt_svc == MESH_GATT_PROV) {
1035 return bt_mesh_gatts_notify(conn, &prov_attrs[4], data, len);
1036 }
1037 #endif
1038
1039 return 0;
1040 }
1041
proxy_segment_and_send(struct bt_mesh_conn * conn,uint8_t type,struct net_buf_simple * msg)1042 static int proxy_segment_and_send(struct bt_mesh_conn *conn, uint8_t type,
1043 struct net_buf_simple *msg)
1044 {
1045 uint16_t mtu = 0U;
1046
1047 BT_DBG("conn %p type 0x%02x len %u: %s", conn, type, msg->len,
1048 bt_hex(msg->data, msg->len));
1049
1050 /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */
1051 mtu = bt_mesh_gatt_get_mtu(conn) - 3;
1052 if (mtu > msg->len) {
1053 net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type));
1054 return proxy_send(conn, msg->data, msg->len);
1055 }
1056
1057 net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
1058 proxy_send(conn, msg->data, mtu);
1059 net_buf_simple_pull(msg, mtu);
1060
1061 while (msg->len) {
1062 if (msg->len + 1 < mtu) {
1063 net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type));
1064 proxy_send(conn, msg->data, msg->len);
1065 break;
1066 }
1067
1068 net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
1069 proxy_send(conn, msg->data, mtu);
1070 net_buf_simple_pull(msg, mtu);
1071 }
1072
1073 return 0;
1074 }
1075
bt_mesh_proxy_server_send(struct bt_mesh_conn * conn,uint8_t type,struct net_buf_simple * msg)1076 int bt_mesh_proxy_server_send(struct bt_mesh_conn *conn, uint8_t type,
1077 struct net_buf_simple *msg)
1078 {
1079 struct bt_mesh_proxy_client *client = find_client(conn);
1080
1081 if (!client) {
1082 BT_ERR("No Proxy Client found");
1083 return -ENOTCONN;
1084 }
1085
1086 if ((client->filter_type == PROV) != (type == BLE_MESH_PROXY_PROV)) {
1087 BT_ERR("Invalid PDU type for Proxy Client");
1088 return -EINVAL;
1089 }
1090
1091 return proxy_segment_and_send(conn, type, msg);
1092 }
1093
1094 #if defined(CONFIG_BLE_MESH_PB_GATT)
1095 static uint8_t prov_svc_data[20] = { 0x27, 0x18, };
1096
1097 static const struct bt_mesh_adv_data prov_ad[] = {
1098 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_FLAGS, (BLE_MESH_AD_GENERAL | BLE_MESH_AD_NO_BREDR)),
1099 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x27, 0x18),
1100 BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
1101 };
1102 #endif /* PB_GATT */
1103
1104 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1105
1106 #define ID_TYPE_NET 0x00
1107 #define ID_TYPE_NODE 0x01
1108
1109 #define NODE_ID_LEN 19
1110 #define NET_ID_LEN 11
1111
1112 #define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BLE_MESH_NODE_ID_TIMEOUT)
1113
1114 static uint8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
1115
1116 static const struct bt_mesh_adv_data node_id_ad[] = {
1117 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_FLAGS, (BLE_MESH_AD_GENERAL | BLE_MESH_AD_NO_BREDR)),
1118 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x28, 0x18),
1119 BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN),
1120 };
1121
1122 static const struct bt_mesh_adv_data net_id_ad[] = {
1123 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_FLAGS, (BLE_MESH_AD_GENERAL | BLE_MESH_AD_NO_BREDR)),
1124 BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x28, 0x18),
1125 BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN),
1126 };
1127
gatt_proxy_adv_create(struct bt_mesh_adv_data * proxy_sd)1128 static size_t gatt_proxy_adv_create(struct bt_mesh_adv_data *proxy_sd)
1129 {
1130 const char *name = device_name;
1131 size_t name_len = strlen(name);
1132 /* One octet for Length, and another octet for AD type */
1133 size_t sd_space = 29;
1134
1135 if (name_len > sd_space) {
1136 proxy_sd->type = BLE_MESH_DATA_NAME_SHORTENED;
1137 proxy_sd->data_len = sd_space;
1138 } else {
1139 proxy_sd->type = BLE_MESH_DATA_NAME_COMPLETE;
1140 proxy_sd->data_len = name_len;
1141 }
1142
1143 proxy_sd->data = (const uint8_t *)name;
1144
1145 return 1;
1146 }
1147
node_id_adv(struct bt_mesh_subnet * sub)1148 static int node_id_adv(struct bt_mesh_subnet *sub)
1149 {
1150 struct bt_mesh_adv_data proxy_sd = {0};
1151 size_t proxy_sd_len = 0U;
1152 uint8_t tmp[16] = {0};
1153 int err = 0;
1154
1155 BT_DBG("%s", __func__);
1156
1157 proxy_svc_data[2] = ID_TYPE_NODE;
1158
1159 err = bt_mesh_rand(proxy_svc_data + 11, 8);
1160 if (err) {
1161 return err;
1162 }
1163
1164 (void)memset(tmp, 0, 6);
1165 memcpy(tmp + 6, proxy_svc_data + 11, 8);
1166 sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
1167
1168 err = bt_mesh_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
1169 if (err) {
1170 return err;
1171 }
1172
1173 memcpy(proxy_svc_data + 3, tmp + 8, 8);
1174 proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
1175
1176 err = bt_le_adv_start(&fast_adv_param, node_id_ad,
1177 ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len);
1178 if (err) {
1179 BT_WARN("Failed to advertise using Node ID (err %d)", err);
1180 return err;
1181 }
1182
1183 proxy_adv_enabled = true;
1184
1185 return 0;
1186 }
1187
net_id_adv(struct bt_mesh_subnet * sub)1188 static int net_id_adv(struct bt_mesh_subnet *sub)
1189 {
1190 struct bt_mesh_adv_data proxy_sd = {0};
1191 size_t proxy_sd_len = 0U;
1192 int err = 0;
1193
1194 BT_DBG("%s", __func__);
1195
1196 proxy_svc_data[2] = ID_TYPE_NET;
1197
1198 BT_DBG("Advertising with NetId %s",
1199 bt_hex(sub->keys[sub->kr_flag].net_id, 8));
1200
1201 memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8);
1202 proxy_sd_len = gatt_proxy_adv_create(&proxy_sd);
1203
1204 err = bt_le_adv_start(&slow_adv_param, net_id_ad,
1205 ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len);
1206 if (err) {
1207 BT_WARN("Failed to advertise using Network ID (err %d)", err);
1208 return err;
1209 }
1210
1211 proxy_adv_enabled = true;
1212
1213 return 0;
1214 }
1215
advertise_subnet(struct bt_mesh_subnet * sub)1216 static bool advertise_subnet(struct bt_mesh_subnet *sub)
1217 {
1218 if (sub->net_idx == BLE_MESH_KEY_UNUSED) {
1219 return false;
1220 }
1221
1222 return (sub->node_id == BLE_MESH_NODE_IDENTITY_RUNNING ||
1223 bt_mesh_gatt_proxy_get() != BLE_MESH_GATT_PROXY_NOT_SUPPORTED);
1224 }
1225
next_sub(void)1226 static struct bt_mesh_subnet *next_sub(void)
1227 {
1228 struct bt_mesh_subnet *sub = NULL;
1229 int i;
1230
1231 for (i = next_idx; i < ARRAY_SIZE(bt_mesh.sub); i++) {
1232 sub = &bt_mesh.sub[i];
1233 if (advertise_subnet(sub)) {
1234 next_idx = (i + 1) % ARRAY_SIZE(bt_mesh.sub);
1235 return sub;
1236 }
1237 }
1238
1239 /**
1240 * If among [next_idx, ARRAY_SIZE(bt_mesh.sub)], there is no subnet
1241 * to advertise, then try to start advertising from Primary subnet.
1242 */
1243 for (i = 0; i < next_idx; i++) {
1244 sub = &bt_mesh.sub[i];
1245 if (advertise_subnet(sub)) {
1246 next_idx = (i + 1) % ARRAY_SIZE(bt_mesh.sub);
1247 return sub;
1248 }
1249 }
1250
1251 return NULL;
1252 }
1253
sub_count(void)1254 static int sub_count(void)
1255 {
1256 int i, count = 0;
1257
1258 for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
1259 struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
1260
1261 if (advertise_subnet(sub)) {
1262 count++;
1263 }
1264 }
1265
1266 return count;
1267 }
1268
gatt_proxy_advertise(struct bt_mesh_subnet * sub)1269 static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
1270 {
1271 int32_t remaining = K_FOREVER;
1272 int subnet_count = 0;
1273
1274 BT_DBG("%s", __func__);
1275
1276 if (conn_count == BLE_MESH_MAX_CONN) {
1277 BT_WARN("Connectable advertising deferred (max connections)");
1278 return remaining;
1279 }
1280
1281 if (!sub) {
1282 BT_WARN("No subnets to advertise on");
1283 return remaining;
1284 }
1285
1286 if (sub->node_id == BLE_MESH_NODE_IDENTITY_RUNNING) {
1287 uint32_t active = k_uptime_get_32() - sub->node_id_start;
1288
1289 if (active < NODE_ID_TIMEOUT) {
1290 remaining = NODE_ID_TIMEOUT - active;
1291 BT_DBG("Node ID active for %u ms, %d ms remaining",
1292 active, remaining);
1293 node_id_adv(sub);
1294 } else {
1295 bt_mesh_proxy_server_identity_stop(sub);
1296 BT_DBG("Node ID stopped");
1297 }
1298 }
1299
1300 if (sub->node_id == BLE_MESH_NODE_IDENTITY_STOPPED) {
1301 net_id_adv(sub);
1302 }
1303
1304 subnet_count = sub_count();
1305 BT_DBG("sub_count %u", subnet_count);
1306 if (subnet_count > 1) {
1307 int32_t max_timeout = 0;
1308
1309 /* We use NODE_ID_TIMEOUT as a starting point since it may
1310 * be less than 60 seconds. Divide this period into at least
1311 * 6 slices, but make sure that a slice is at least one
1312 * second long (to avoid excessive rotation).
1313 */
1314 max_timeout = NODE_ID_TIMEOUT / MAX(subnet_count, 6);
1315 max_timeout = MAX(max_timeout, K_SECONDS(1));
1316
1317 if (remaining > max_timeout || remaining < 0) {
1318 remaining = max_timeout;
1319 }
1320 }
1321
1322 BT_DBG("Advertising %d ms for net_idx 0x%04x", remaining, sub->net_idx);
1323
1324 return remaining;
1325 }
1326 #endif /* GATT_PROXY */
1327
1328 #if defined(CONFIG_BLE_MESH_PB_GATT)
gatt_prov_adv_create(struct bt_mesh_adv_data prov_sd[2])1329 static size_t gatt_prov_adv_create(struct bt_mesh_adv_data prov_sd[2])
1330 {
1331 const struct bt_mesh_prov *prov = bt_mesh_prov_get();
1332 const char *name = device_name;
1333 size_t name_len = strlen(name);
1334 size_t prov_sd_len = 0U;
1335 size_t sd_space = 31U;
1336
1337 memcpy(prov_svc_data + 2, prov->uuid, 16);
1338 sys_put_be16(prov->oob_info, prov_svc_data + 18);
1339
1340 if (prov->uri) {
1341 size_t uri_len = strlen(prov->uri);
1342
1343 if (uri_len > 29) {
1344 /* There's no way to shorten an URI */
1345 BT_WARN("Too long URI to fit advertising packet");
1346 } else {
1347 prov_sd[0].type = BLE_MESH_DATA_URI;
1348 prov_sd[0].data_len = uri_len;
1349 prov_sd[0].data = (const uint8_t *)prov->uri;
1350 sd_space -= 2 + uri_len;
1351 prov_sd_len++;
1352 }
1353 }
1354
1355 if (sd_space > 2 && name_len > 0) {
1356 sd_space -= 2;
1357
1358 if (sd_space < name_len) {
1359 prov_sd[prov_sd_len].type = BLE_MESH_DATA_NAME_SHORTENED;
1360 prov_sd[prov_sd_len].data_len = sd_space;
1361 } else {
1362 prov_sd[prov_sd_len].type = BLE_MESH_DATA_NAME_COMPLETE;
1363 prov_sd[prov_sd_len].data_len = name_len;
1364 }
1365
1366 prov_sd[prov_sd_len].data = (const uint8_t *)name;
1367 prov_sd_len++;
1368 }
1369
1370 return prov_sd_len;
1371 }
1372 #endif /* CONFIG_BLE_MESH_PB_GATT */
1373
bt_mesh_proxy_server_adv_start(void)1374 int32_t bt_mesh_proxy_server_adv_start(void)
1375 {
1376 BT_DBG("%s", __func__);
1377
1378 if (gatt_svc == MESH_GATT_NONE) {
1379 return K_FOREVER;
1380 }
1381
1382 #if defined(CONFIG_BLE_MESH_PB_GATT)
1383 if (prov_fast_adv) {
1384 prov_start_time = k_uptime_get_32();
1385 }
1386
1387 if (!bt_mesh_is_provisioned()) {
1388 const struct bt_mesh_adv_param *param;
1389 struct bt_mesh_adv_data prov_sd[2];
1390 size_t prov_sd_len;
1391
1392 if (k_uptime_get_32() - prov_start_time < K_SECONDS(60)) {
1393 param = &fast_adv_param;
1394 } else {
1395 param = &slow_adv_param;
1396 }
1397
1398 prov_sd_len = gatt_prov_adv_create(prov_sd);
1399
1400 if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad),
1401 prov_sd, prov_sd_len) == 0) {
1402 proxy_adv_enabled = true;
1403
1404 /* Advertise 60 seconds using fast interval */
1405 if (prov_fast_adv) {
1406 prov_fast_adv = false;
1407 return K_SECONDS(60);
1408 }
1409 }
1410 }
1411 #endif /* PB_GATT */
1412
1413 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1414 if (bt_mesh_is_provisioned()) {
1415 return gatt_proxy_advertise(next_sub());
1416 }
1417 #endif /* GATT_PROXY */
1418
1419 return K_FOREVER;
1420 }
1421
bt_mesh_proxy_server_adv_stop(void)1422 void bt_mesh_proxy_server_adv_stop(void)
1423 {
1424 int err = 0;
1425
1426 BT_DBG("adv_enabled %u", proxy_adv_enabled);
1427
1428 if (!proxy_adv_enabled) {
1429 return;
1430 }
1431
1432 err = bt_le_adv_stop();
1433 if (err) {
1434 BT_ERR("Failed to stop advertising (err %d)", err);
1435 } else {
1436 proxy_adv_enabled = false;
1437 }
1438 }
1439
1440 static struct bt_mesh_conn_cb conn_callbacks = {
1441 .connected = proxy_connected,
1442 .disconnected = proxy_disconnected,
1443 };
1444
bt_mesh_proxy_server_init(void)1445 int bt_mesh_proxy_server_init(void)
1446 {
1447 int i;
1448
1449 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1450 bt_mesh_gatts_service_register(&proxy_svc);
1451 #endif
1452
1453 #if defined(CONFIG_BLE_MESH_PB_GATT)
1454 bt_mesh_gatts_service_register(&prov_svc);
1455 #endif
1456
1457 /* Initialize the client receive buffers */
1458 for (i = 0; i < ARRAY_SIZE(clients); i++) {
1459 struct bt_mesh_proxy_client *client = &clients[i];
1460
1461 client->buf.size = CLIENT_BUF_SIZE;
1462 client->buf.__buf = client_buf_data + (i * CLIENT_BUF_SIZE);
1463 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1464 k_work_init(&client->send_beacons, proxy_send_beacons);
1465 #endif
1466 k_delayed_work_init(&client->sar_timer, proxy_sar_timeout);
1467 }
1468
1469 bt_mesh_gatts_conn_cb_register(&conn_callbacks);
1470
1471 strncpy(device_name, "ESP-BLE-MESH", DEVICE_NAME_SIZE);
1472 return bt_mesh_gatts_set_local_device_name(device_name);
1473 }
1474
1475 #if CONFIG_BLE_MESH_DEINIT
bt_mesh_proxy_server_deinit(void)1476 int bt_mesh_proxy_server_deinit(void)
1477 {
1478 int i;
1479
1480 proxy_adv_enabled = false;
1481 gatt_svc = MESH_GATT_NONE;
1482
1483 #if defined(CONFIG_BLE_MESH_GATT_PROXY_SERVER)
1484 bt_mesh_gatts_service_deregister(&proxy_svc);
1485 next_idx = 0;
1486 #endif
1487
1488 #if defined(CONFIG_BLE_MESH_PB_GATT)
1489 bt_mesh_gatts_service_deregister(&prov_svc);
1490 #endif
1491
1492 for (i = 0; i < ARRAY_SIZE(clients); i++) {
1493 struct bt_mesh_proxy_client *client = &clients[i];
1494 k_delayed_work_free(&client->sar_timer);
1495 memset(client, 0, sizeof(struct bt_mesh_proxy_client));
1496 }
1497
1498 memset(client_buf_data, 0, sizeof(client_buf_data));
1499 memset(device_name, 0, sizeof(device_name));
1500
1501 bt_mesh_gatts_conn_cb_deregister();
1502 conn_count = 0;
1503
1504 return 0;
1505 }
1506 #endif /* CONFIG_BLE_MESH_DEINIT */
1507
1508 #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */
1509