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