1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2017 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr.h>
9 #include <debug/stack.h>
10 #include <sys/util.h>
11 
12 #include <net/buf.h>
13 #include <bluetooth/bluetooth.h>
14 #include <bluetooth/hci.h>
15 #include <bluetooth/conn.h>
16 #include <bluetooth/mesh.h>
17 
18 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ADV)
19 #define LOG_MODULE_NAME bt_mesh_adv
20 #include "common/log.h"
21 
22 #include "adv.h"
23 #include "net.h"
24 #include "foundation.h"
25 #include "beacon.h"
26 #include "host/ecc.h"
27 #include "prov.h"
28 #include "proxy.h"
29 
30 /* Window and Interval are equal for continuous scanning */
31 #define MESH_SCAN_INTERVAL    BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_INTERVAL_MS)
32 #define MESH_SCAN_WINDOW      BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_WINDOW_MS)
33 
34 const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = {
35 	[BT_MESH_ADV_PROV]   = BT_DATA_MESH_PROV,
36 	[BT_MESH_ADV_DATA]   = BT_DATA_MESH_MESSAGE,
37 	[BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON,
38 	[BT_MESH_ADV_URI]    = BT_DATA_URI,
39 };
40 
41 K_FIFO_DEFINE(bt_mesh_adv_queue);
42 
adv_buf_destroy(struct net_buf * buf)43 static void adv_buf_destroy(struct net_buf *buf)
44 {
45 	struct bt_mesh_adv adv = *BT_MESH_ADV(buf);
46 
47 	net_buf_destroy(buf);
48 
49 	bt_mesh_adv_send_end(0, &adv);
50 }
51 
52 NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BT_MESH_ADV_BUF_COUNT,
53 		    BT_MESH_ADV_DATA_SIZE, BT_MESH_ADV_USER_DATA_SIZE,
54 		    adv_buf_destroy);
55 
56 static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
57 
adv_alloc(int id)58 static struct bt_mesh_adv *adv_alloc(int id)
59 {
60 	return &adv_pool[id];
61 }
62 
bt_mesh_adv_create_from_pool(struct net_buf_pool * pool,bt_mesh_adv_alloc_t get_id,enum bt_mesh_adv_type type,uint8_t xmit,k_timeout_t timeout)63 struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool,
64 					     bt_mesh_adv_alloc_t get_id,
65 					     enum bt_mesh_adv_type type,
66 					     uint8_t xmit, k_timeout_t timeout)
67 {
68 	struct bt_mesh_adv *adv;
69 	struct net_buf *buf;
70 
71 	if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) {
72 		BT_WARN("Refusing to allocate buffer while suspended");
73 		return NULL;
74 	}
75 
76 	buf = net_buf_alloc(pool, timeout);
77 	if (!buf) {
78 		return NULL;
79 	}
80 
81 	adv = get_id(net_buf_id(buf));
82 	BT_MESH_ADV(buf) = adv;
83 
84 	(void)memset(adv, 0, sizeof(*adv));
85 
86 	adv->type         = type;
87 	adv->xmit         = xmit;
88 
89 	return buf;
90 }
91 
bt_mesh_adv_create(enum bt_mesh_adv_type type,uint8_t xmit,k_timeout_t timeout)92 struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
93 				   k_timeout_t timeout)
94 {
95 	return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, type,
96 					    xmit, timeout);
97 }
98 
bt_mesh_adv_send(struct net_buf * buf,const struct bt_mesh_send_cb * cb,void * cb_data)99 void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
100 		      void *cb_data)
101 {
102 	BT_DBG("type 0x%02x len %u: %s", BT_MESH_ADV(buf)->type, buf->len,
103 	       bt_hex(buf->data, buf->len));
104 
105 	BT_MESH_ADV(buf)->cb = cb;
106 	BT_MESH_ADV(buf)->cb_data = cb_data;
107 	BT_MESH_ADV(buf)->busy = 1U;
108 
109 	net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf));
110 	bt_mesh_adv_buf_ready();
111 }
112 
bt_mesh_scan_cb(const bt_addr_le_t * addr,int8_t rssi,uint8_t adv_type,struct net_buf_simple * buf)113 static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
114 			    uint8_t adv_type, struct net_buf_simple *buf)
115 {
116 	if (adv_type != BT_GAP_ADV_TYPE_ADV_NONCONN_IND) {
117 		return;
118 	}
119 
120 	BT_DBG("len %u: %s", buf->len, bt_hex(buf->data, buf->len));
121 
122 	while (buf->len > 1) {
123 		struct net_buf_simple_state state;
124 		uint8_t len, type;
125 
126 		len = net_buf_simple_pull_u8(buf);
127 		/* Check for early termination */
128 		if (len == 0U) {
129 			return;
130 		}
131 
132 		if (len > buf->len) {
133 			BT_WARN("AD malformed");
134 			return;
135 		}
136 
137 		net_buf_simple_save(buf, &state);
138 
139 		type = net_buf_simple_pull_u8(buf);
140 
141 		buf->len = len - 1;
142 
143 		switch (type) {
144 		case BT_DATA_MESH_MESSAGE:
145 			bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV);
146 			break;
147 #if defined(CONFIG_BT_MESH_PB_ADV)
148 		case BT_DATA_MESH_PROV:
149 			bt_mesh_pb_adv_recv(buf);
150 			break;
151 #endif
152 		case BT_DATA_MESH_BEACON:
153 			bt_mesh_beacon_recv(buf);
154 			break;
155 		default:
156 			break;
157 		}
158 
159 		net_buf_simple_restore(buf, &state);
160 		net_buf_simple_pull(buf, len);
161 	}
162 }
163 
bt_mesh_scan_enable(void)164 int bt_mesh_scan_enable(void)
165 {
166 	struct bt_le_scan_param scan_param = {
167 			.type       = BT_HCI_LE_SCAN_PASSIVE,
168 			.options    = BT_LE_SCAN_OPT_NONE,
169 			.interval   = MESH_SCAN_INTERVAL,
170 			.window     = MESH_SCAN_WINDOW };
171 	int err;
172 
173 	BT_DBG("");
174 
175 	err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
176 	if (err && err != -EALREADY) {
177 		BT_ERR("starting scan failed (err %d)", err);
178 		return err;
179 	}
180 
181 	return 0;
182 }
183 
bt_mesh_scan_disable(void)184 int bt_mesh_scan_disable(void)
185 {
186 	int err;
187 
188 	BT_DBG("");
189 
190 	err = bt_le_scan_stop();
191 	if (err && err != -EALREADY) {
192 		BT_ERR("stopping scan failed (err %d)", err);
193 		return err;
194 	}
195 
196 	return 0;
197 }
198