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