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