1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <assert.h>
21 #include <string.h>
22 #include <errno.h>
23 #include "securec.h"
24 #include "nimble/nimble_opt.h"
25 #include "host/ble_hs_adv.h"
26 #include "host/ble_hs_hci.h"
27 #include "ble_hs_priv.h"
28
29 #if MYNEWT
30 #include "bsp/bsp.h"
31 #else
32 #define bssnz_t
33 #endif
34
35 /**
36 * GAP - Generic Access Profile.
37 *
38 * Design overview:
39 *
40 * GAP procedures are initiated by the application via function calls. Such
41 * functions return when either of the following happens:
42 *
43 * (1) The procedure completes (success or failure).
44 * (2) The procedure cannot proceed until a BLE peer responds.
45 *
46 * For (1), the result of the procedure if fully indicated by the function
47 * return code.
48 * For (2), the procedure result is indicated by an application-configured
49 * callback. The callback is executed when the procedure completes.
50 *
51 * The GAP is always in one of two states:
52 * 1. Free
53 * 2. Preempted
54 *
55 * While GAP is in the free state, new procedures can be started at will.
56 * While GAP is in the preempted state, no new procedures are allowed. The
57 * host sets GAP to the preempted state when it needs to ensure no ongoing
58 * procedures, a condition required for some HCI commands to succeed. The host
59 * must take care to take GAP out of the preempted state as soon as possible.
60 *
61 * Notes on thread-safety:
62 * 1. The ble_hs mutex must always be unlocked when an application callback is
63 * executed. The purpose of this requirement is to allow callbacks to
64 * initiate additional host procedures, which may require locking of the
65 * mutex.
66 * 2. Functions called directly by the application never call callbacks.
67 * Generally, these functions lock the ble_hs mutex at the start, and only
68 * unlock it at return.
69 * 3. Functions which do call callbacks (receive handlers and timer
70 * expirations) generally only lock the mutex long enough to modify
71 * affected state and make copies of data needed for the callback. A copy
72 * of various pieces of data is called a "snapshot" (struct
73 * ble_gap_snapshot). The sole purpose of snapshots is to allow callbacks
74 * to be executed after unlocking the mutex.
75 */
76
77 /** GAP procedure op codes. */
78 #define BLE_GAP_OP_NULL 0
79 #define BLE_GAP_OP_M_DISC 1
80 #define BLE_GAP_OP_M_CONN 2
81 #define BLE_GAP_OP_S_ADV 1
82 #define BLE_GAP_OP_S_PERIODIC_ADV 2
83 #define BLE_GAP_OP_SYNC 1
84
85 /**
86 * If an attempt to cancel an active procedure fails, the attempt is retried
87 * at this rate (ms).
88 */
89 #define BLE_GAP_CANCEL_RETRY_TIMEOUT_MS 100 /* ms */
90
91 #define BLE_GAP_UPDATE_TIMEOUT_MS 40000 /* ms */
92
93 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
94 static const struct ble_gap_conn_params ble_gap_conn_params_dflt = {
95 .scan_itvl = 0x0010,
96 .scan_window = 0x0010,
97 .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN,
98 .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX,
99 .latency = BLE_GAP_INITIAL_CONN_LATENCY,
100 .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT,
101 .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN,
102 .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN,
103 };
104 #endif
105
106 /**
107 * The state of the in-progress master connection. If no master connection is
108 * currently in progress, then the op field is set to BLE_GAP_OP_NULL.
109 */
110 struct ble_gap_master_state {
111 uint8_t op;
112
113 uint8_t exp_set : 1;
114 ble_npl_time_t exp_os_ticks;
115
116 ble_gap_event_fn *cb;
117 void *cb_arg;
118
119 /**
120 * Indicates the type of master procedure that was preempted, or
121 * BLE_GAP_OP_NULL if no procedure was preempted.
122 */
123 uint8_t preempted_op;
124 #if NIMBLE_BLE_CONNECT
125 union {
126 struct {
127 #if MYNEWT_VAL(BLE_WHITELIST)
128 uint8_t using_wl : 1;
129 #endif
130 uint8_t our_addr_type : 2;
131 uint8_t cancel : 1;
132 } conn;
133 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
134 struct {
135 uint8_t limited : 1;
136 } disc;
137 #endif
138 };
139 #endif
140 };
141 static bssnz_t struct ble_gap_master_state ble_gap_master;
142
143 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
144 /**
145 * The state of the in-progress sync creation. If no sync creation connection is
146 * currently in progress, then the op field is set to BLE_GAP_OP_NULL.
147 */
148 struct ble_gap_sync_state {
149 uint8_t op;
150 struct ble_hs_periodic_sync *psync;
151
152 ble_gap_event_fn *cb;
153 void *cb_arg;
154 };
155
156 static bssnz_t struct ble_gap_sync_state ble_gap_sync;
157 #endif
158
159 /**
160 * The state of the in-progress slave connection. If no slave connection is
161 * currently in progress, then the op field is set to BLE_GAP_OP_NULL.
162 */
163 struct ble_gap_slave_state {
164 uint8_t op;
165 #if NIMBLE_BLE_CONNECT
166 unsigned int our_addr_type : 2;
167 unsigned int preempted : 1; /** Set to 1 if advertising was preempted. */
168 unsigned int connectable : 1;
169 #endif
170 #if MYNEWT_VAL(BLE_EXT_ADV)
171 unsigned int configured : 1; /** If instance is configured */
172 unsigned int scannable : 1;
173 unsigned int directed : 1;
174 unsigned int high_duty_directed : 1;
175 unsigned int legacy_pdu : 1;
176 unsigned int rnd_addr_set : 1;
177 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
178 unsigned int periodic_configured : 1;
179 uint8_t periodic_op;
180 #endif
181 uint8_t rnd_addr[6];
182 #else
183 /* timer is used only with legacy advertising */
184 unsigned int exp_set : 1;
185 ble_npl_time_t exp_os_ticks;
186 #endif
187
188 ble_gap_event_fn *cb;
189 void *cb_arg;
190 };
191
192 static bssnz_t struct ble_gap_slave_state ble_gap_slave[BLE_ADV_INSTANCES];
193
194 struct ble_gap_update_entry {
195 SLIST_ENTRY(ble_gap_update_entry) next;
196 struct ble_gap_upd_params params;
197 ble_npl_time_t exp_os_ticks;
198 uint16_t conn_handle;
199 };
200 SLIST_HEAD(ble_gap_update_entry_list, ble_gap_update_entry);
201
202 struct ble_gap_snapshot {
203 struct ble_gap_conn_desc *desc;
204 ble_gap_event_fn *cb;
205 void *cb_arg;
206 };
207
208 static SLIST_HEAD(ble_gap_hook_list, ble_gap_event_listener) ble_gap_event_listener_list;
209 static os_membuf_t ble_gap_update_entry_mem[
210 OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE),
211 sizeof(struct ble_gap_update_entry))];
212 static struct os_mempool ble_gap_update_entry_pool;
213 static struct ble_gap_update_entry_list ble_gap_update_entries;
214
215 static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry);
216
217 #if NIMBLE_BLE_CONNECT
218 static struct ble_gap_update_entry *ble_gap_update_entry_find(uint16_t conn_handle,
219 struct ble_gap_update_entry **out_prev);
220
221 static void ble_gap_update_l2cap_cb(uint16_t conn_handle, int status, void *arg);
222 #endif
223
224 static struct ble_gap_update_entry *ble_gap_update_entry_remove(uint16_t conn_handle);
225
226 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
227 static int ble_gap_adv_enable_tx(int enable);
228 #endif
229
230 static int ble_gap_conn_cancel_tx(void);
231
232 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
233 static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
234 #endif
235
236 STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
237 STATS_NAME_START(ble_gap_stats)
STATS_NAME(ble_gap_stats,wl_set)238 STATS_NAME(ble_gap_stats, wl_set)
239 STATS_NAME(ble_gap_stats, wl_set_fail)
240 STATS_NAME(ble_gap_stats, adv_stop)
241 STATS_NAME(ble_gap_stats, adv_stop_fail)
242 STATS_NAME(ble_gap_stats, adv_start)
243 STATS_NAME(ble_gap_stats, adv_start_fail)
244 STATS_NAME(ble_gap_stats, adv_set_data)
245 STATS_NAME(ble_gap_stats, adv_set_data_fail)
246 STATS_NAME(ble_gap_stats, adv_rsp_set_data)
247 STATS_NAME(ble_gap_stats, adv_rsp_set_data_fail)
248 STATS_NAME(ble_gap_stats, discover)
249 STATS_NAME(ble_gap_stats, discover_fail)
250 STATS_NAME(ble_gap_stats, initiate)
251 STATS_NAME(ble_gap_stats, initiate_fail)
252 STATS_NAME(ble_gap_stats, terminate)
253 STATS_NAME(ble_gap_stats, terminate_fail)
254 STATS_NAME(ble_gap_stats, cancel)
255 STATS_NAME(ble_gap_stats, cancel_fail)
256 STATS_NAME(ble_gap_stats, update)
257 STATS_NAME(ble_gap_stats, update_fail)
258 STATS_NAME(ble_gap_stats, connect_mst)
259 STATS_NAME(ble_gap_stats, connect_slv)
260 STATS_NAME(ble_gap_stats, disconnect)
261 STATS_NAME(ble_gap_stats, rx_disconnect)
262 STATS_NAME(ble_gap_stats, rx_update_complete)
263 STATS_NAME(ble_gap_stats, rx_adv_report)
264 STATS_NAME(ble_gap_stats, rx_conn_complete)
265 STATS_NAME(ble_gap_stats, discover_cancel)
266 STATS_NAME(ble_gap_stats, discover_cancel_fail)
267 STATS_NAME(ble_gap_stats, security_initiate)
268 STATS_NAME(ble_gap_stats, security_initiate_fail)
269 STATS_NAME_END(ble_gap_stats)
270
271 /*****************************************************************************
272 * $debug *
273 *****************************************************************************/
274
275 #if MYNEWT_VAL(BLE_HS_DEBUG)
276 int ble_gap_dbg_update_active(uint16_t conn_handle)
277 {
278 const struct ble_gap_update_entry *entry;
279 ble_hs_lock();
280 entry = ble_gap_update_entry_find(conn_handle, NULL);
281 ble_hs_unlock();
282 return entry != NULL;
283 }
284 #endif
285
286 /*****************************************************************************
287 * $log *
288 *****************************************************************************/
289
290 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_log_duration(int32_t duration_ms)291 static void ble_gap_log_duration(int32_t duration_ms)
292 {
293 if (duration_ms == BLE_HS_FOREVER) {
294 BLE_HS_LOG(INFO, "duration=forever");
295 } else {
296 BLE_HS_LOG(INFO, "duration=%dms", duration_ms);
297 }
298 }
299 #endif
300
301 #if MYNEWT_VAL(BLE_ROLE_CENTRAL) && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_log_conn(uint8_t own_addr_type,const ble_addr_t * peer_addr,const struct ble_gap_conn_params * params)302 static void ble_gap_log_conn(uint8_t own_addr_type, const ble_addr_t *peer_addr,
303 const struct ble_gap_conn_params *params)
304 {
305 if (peer_addr != NULL) {
306 BLE_HS_LOG(INFO, "peer_addr_type=%d peer_addr=", peer_addr->type);
307 BLE_HS_LOG_ADDR(INFO, peer_addr->val);
308 }
309
310 BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d "
311 "latency=%d supervision_timeout=%d min_ce_len=%d "
312 "max_ce_len=%d own_addr_type=%d",
313 params->scan_itvl, params->scan_window, params->itvl_min,
314 params->itvl_max, params->latency, params->supervision_timeout,
315 params->min_ce_len, params->max_ce_len, own_addr_type);
316 }
317 #endif
318
319 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_log_disc(uint8_t own_addr_type,int32_t duration_ms,const struct ble_gap_disc_params * disc_params)320 static void ble_gap_log_disc(uint8_t own_addr_type, int32_t duration_ms,
321 const struct ble_gap_disc_params *disc_params)
322 {
323 BLE_HS_LOG(INFO, "own_addr_type=%d filter_policy=%d passive=%d limited=%d "
324 "filter_duplicates=%d ",
325 own_addr_type, disc_params->filter_policy, disc_params->passive,
326 disc_params->limited, disc_params->filter_duplicates);
327 ble_gap_log_duration(duration_ms);
328 }
329 #endif
330
331 #if NIMBLE_BLE_CONNECT
ble_gap_log_update(uint16_t conn_handle,const struct ble_gap_upd_params * params)332 static void ble_gap_log_update(uint16_t conn_handle, const struct ble_gap_upd_params *params)
333 {
334 BLE_HS_LOG(INFO, "connection parameter update; "
335 "conn_handle=%d itvl_min=%d itvl_max=%d latency=%d "
336 "supervision_timeout=%d min_ce_len=%d max_ce_len=%d",
337 conn_handle, params->itvl_min, params->itvl_max,
338 params->latency, params->supervision_timeout,
339 params->min_ce_len, params->max_ce_len);
340 }
341 #endif
342
343 #if MYNEWT_VAL(BLE_WHITELIST)
ble_gap_log_wl(const ble_addr_t * addr,uint8_t white_list_count)344 static void ble_gap_log_wl(const ble_addr_t *addr, uint8_t white_list_count)
345 {
346 int i;
347 BLE_HS_LOG(INFO, "count=%d ", white_list_count);
348
349 for (i = 0; i < white_list_count; i++, addr++) {
350 BLE_HS_LOG(INFO, "entry-%d={addr_type=%d addr=", i, addr->type);
351 BLE_HS_LOG_ADDR(INFO, addr->val);
352 BLE_HS_LOG(INFO, "} ");
353 }
354 }
355 #endif
356
357 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_log_adv(uint8_t own_addr_type,const ble_addr_t * direct_addr,const struct ble_gap_adv_params * adv_params)358 static void ble_gap_log_adv(uint8_t own_addr_type, const ble_addr_t *direct_addr,
359 const struct ble_gap_adv_params *adv_params)
360 {
361 BLE_HS_LOG(INFO, "disc_mode=%d", adv_params->disc_mode);
362
363 if (direct_addr) {
364 BLE_HS_LOG(INFO, " direct_addr_type=%d direct_addr=",
365 direct_addr->type);
366 BLE_HS_LOG_ADDR(INFO, direct_addr->val);
367 }
368
369 BLE_HS_LOG(INFO, " adv_channel_map=%d own_addr_type=%d "
370 "adv_filter_policy=%d adv_itvl_min=%d adv_itvl_max=%d",
371 adv_params->channel_map,
372 own_addr_type,
373 adv_params->filter_policy,
374 adv_params->itvl_min,
375 adv_params->itvl_max);
376 }
377 #endif
378
379 /*****************************************************************************
380 * $snapshot *
381 *****************************************************************************/
382
ble_gap_fill_conn_desc(struct ble_hs_conn * conn,struct ble_gap_conn_desc * desc)383 static void ble_gap_fill_conn_desc(struct ble_hs_conn *conn, struct ble_gap_conn_desc *desc)
384 {
385 struct ble_hs_conn_addrs addrs;
386 ble_hs_conn_addrs(conn, &addrs);
387 desc->our_id_addr = addrs.our_id_addr;
388 desc->peer_id_addr = addrs.peer_id_addr;
389 desc->our_ota_addr = addrs.our_ota_addr;
390 desc->peer_ota_addr = addrs.peer_ota_addr;
391 desc->conn_handle = conn->bhc_handle;
392 desc->conn_itvl = conn->bhc_itvl;
393 desc->conn_latency = conn->bhc_latency;
394 desc->supervision_timeout = conn->bhc_supervision_timeout;
395 desc->master_clock_accuracy = conn->bhc_master_clock_accuracy;
396 desc->sec_state = conn->bhc_sec_state;
397
398 if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
399 desc->role = BLE_GAP_ROLE_MASTER;
400 } else {
401 desc->role = BLE_GAP_ROLE_SLAVE;
402 }
403 }
404
ble_gap_conn_to_snapshot(struct ble_hs_conn * conn,struct ble_gap_snapshot * snap)405 static void ble_gap_conn_to_snapshot(struct ble_hs_conn *conn, struct ble_gap_snapshot *snap)
406 {
407 ble_gap_fill_conn_desc(conn, snap->desc);
408 snap->cb = conn->bhc_cb;
409 snap->cb_arg = conn->bhc_cb_arg;
410 }
411
ble_gap_find_snapshot(uint16_t handle,struct ble_gap_snapshot * snap)412 static int ble_gap_find_snapshot(uint16_t handle, struct ble_gap_snapshot *snap)
413 {
414 struct ble_hs_conn *conn;
415 ble_hs_lock();
416 conn = ble_hs_conn_find(handle);
417 if (conn != NULL) {
418 ble_gap_conn_to_snapshot(conn, snap);
419 }
420
421 ble_hs_unlock();
422
423 if (conn == NULL) {
424 return BLE_HS_ENOTCONN;
425 } else {
426 return 0;
427 }
428 }
429
ble_gap_conn_find(uint16_t handle,struct ble_gap_conn_desc * out_desc)430 int ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc)
431 {
432 struct ble_hs_conn *conn;
433 ble_hs_lock();
434 conn = ble_hs_conn_find(handle);
435 if (conn != NULL && out_desc != NULL) {
436 ble_gap_fill_conn_desc(conn, out_desc);
437 }
438
439 ble_hs_unlock();
440
441 if (conn == NULL) {
442 return BLE_HS_ENOTCONN;
443 } else {
444 return 0;
445 }
446 }
447
ble_gap_conn_find_by_addr(const ble_addr_t * addr,struct ble_gap_conn_desc * out_desc)448 int ble_gap_conn_find_by_addr(const ble_addr_t *addr, struct ble_gap_conn_desc *out_desc)
449 {
450 struct ble_hs_conn *conn;
451 ble_hs_lock();
452 conn = ble_hs_conn_find_by_addr(addr);
453 if (conn != NULL && out_desc != NULL) {
454 ble_gap_fill_conn_desc(conn, out_desc);
455 }
456
457 ble_hs_unlock();
458
459 if (conn == NULL) {
460 return BLE_HS_ENOTCONN;
461 }
462
463 return 0;
464 }
465
ble_gap_extract_conn_cb(uint16_t conn_handle,ble_gap_event_fn ** out_cb,void ** out_cb_arg)466 static int ble_gap_extract_conn_cb(uint16_t conn_handle, ble_gap_event_fn **out_cb, void **out_cb_arg)
467 {
468 const struct ble_hs_conn *conn;
469 BLE_HS_DBG_ASSERT(conn_handle <= BLE_HCI_LE_CONN_HANDLE_MAX);
470 ble_hs_lock();
471 conn = ble_hs_conn_find(conn_handle);
472 if (conn != NULL) {
473 *out_cb = conn->bhc_cb;
474 *out_cb_arg = conn->bhc_cb_arg;
475 } else {
476 *out_cb = NULL;
477 *out_cb_arg = NULL;
478 }
479
480 ble_hs_unlock();
481
482 if (conn == NULL) {
483 return BLE_HS_ENOTCONN;
484 } else {
485 return 0;
486 }
487 }
488
ble_gap_set_priv_mode(const ble_addr_t * peer_addr,uint8_t priv_mode)489 int ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode)
490 {
491 return ble_hs_pvcy_set_mode(peer_addr, priv_mode);
492 }
493
ble_gap_read_le_phy(uint16_t conn_handle,uint8_t * tx_phy,uint8_t * rx_phy)494 int ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy)
495 {
496 struct ble_hci_le_rd_phy_cp cmd;
497 struct ble_hci_le_rd_phy_rp rsp;
498 struct ble_hs_conn *conn;
499 int rc;
500 ble_hs_lock();
501 conn = ble_hs_conn_find(conn_handle);
502 ble_hs_unlock();
503
504 if (conn == NULL) {
505 return BLE_HS_ENOTCONN;
506 }
507
508 cmd.conn_handle = htole16(conn_handle);
509 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PHY),
510 &cmd, sizeof(cmd), &rsp, sizeof(rsp));
511 if (rc != 0) {
512 return rc;
513 }
514
515 /* sanity check for response */
516 if (le16toh(rsp.conn_handle) != conn_handle) {
517 return BLE_HS_ECONTROLLER;
518 }
519
520 *tx_phy = rsp.tx_phy;
521 *rx_phy = rsp.rx_phy;
522 return 0;
523 }
524
ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask,uint8_t rx_phys_mask)525 int ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask)
526 {
527 struct ble_hci_le_set_default_phy_cp cmd;
528
529 if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
530 BLE_HCI_LE_PHY_2M_PREF_MASK |
531 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
532 return BLE_ERR_INV_HCI_CMD_PARMS;
533 }
534
535 if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
536 BLE_HCI_LE_PHY_2M_PREF_MASK |
537 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
538 return BLE_ERR_INV_HCI_CMD_PARMS;
539 }
540
541 memset_s(&cmd, sizeof(cmd), 0, sizeof(cmd));
542
543 if (tx_phys_mask == 0) {
544 cmd.all_phys |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK;
545 } else {
546 cmd.tx_phys = tx_phys_mask;
547 }
548
549 if (rx_phys_mask == 0) {
550 cmd.all_phys |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK;
551 } else {
552 cmd.rx_phys = rx_phys_mask;
553 }
554
555 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
556 BLE_HCI_OCF_LE_SET_DEFAULT_PHY),
557 &cmd, sizeof(cmd), NULL, 0);
558 }
559
ble_gap_set_prefered_le_phy(uint16_t conn_handle,uint8_t tx_phys_mask,uint8_t rx_phys_mask,uint16_t phy_opts)560 int ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
561 uint8_t rx_phys_mask, uint16_t phy_opts)
562 {
563 struct ble_hci_le_set_phy_cp cmd;
564 struct ble_hs_conn *conn;
565 ble_hs_lock();
566 conn = ble_hs_conn_find(conn_handle);
567 ble_hs_unlock();
568
569 if (conn == NULL) {
570 return BLE_HS_ENOTCONN;
571 }
572
573 if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
574 BLE_HCI_LE_PHY_2M_PREF_MASK |
575 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
576 return BLE_ERR_INV_HCI_CMD_PARMS;
577 }
578
579 if (rx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
580 BLE_HCI_LE_PHY_2M_PREF_MASK |
581 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
582 return BLE_ERR_INV_HCI_CMD_PARMS;
583 }
584
585 if (phy_opts > BLE_HCI_LE_PHY_CODED_S8_PREF) {
586 return BLE_ERR_INV_HCI_CMD_PARMS;
587 }
588
589 memset_s(&cmd, sizeof(cmd), 0, sizeof(cmd));
590 cmd.conn_handle = htole16(conn_handle);
591
592 if (tx_phys_mask == 0) {
593 cmd.all_phys |= BLE_HCI_LE_PHY_NO_TX_PREF_MASK;
594 } else {
595 cmd.tx_phys = tx_phys_mask;
596 }
597
598 if (rx_phys_mask == 0) {
599 cmd.all_phys |= BLE_HCI_LE_PHY_NO_RX_PREF_MASK;
600 } else {
601 cmd.rx_phys = rx_phys_mask;
602 }
603
604 cmd.phy_options = htole16(phy_opts);
605 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PHY),
606 &cmd, sizeof(cmd), NULL, 0);
607 }
608
609 /*****************************************************************************
610 * $misc *
611 *****************************************************************************/
612
613 static int ble_gap_event_listener_call(struct ble_gap_event *event);
614
ble_gap_call_event_cb(struct ble_gap_event * event,ble_gap_event_fn * cb,void * cb_arg)615 static int ble_gap_call_event_cb(struct ble_gap_event *event, ble_gap_event_fn *cb, void *cb_arg)
616 {
617 int rc;
618 BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
619
620 if (cb != NULL) {
621 rc = cb(event, cb_arg);
622 } else {
623 if (event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ) {
624 /* Just copy peer parameters back into the reply. */
625 *event->conn_update_req.self_params =
626 *event->conn_update_req.peer_params;
627 }
628
629 rc = 0;
630 }
631
632 return rc;
633 }
634
ble_gap_call_conn_event_cb(struct ble_gap_event * event,uint16_t conn_handle)635 static int ble_gap_call_conn_event_cb(struct ble_gap_event *event, uint16_t conn_handle)
636 {
637 ble_gap_event_fn *cb;
638 void *cb_arg;
639 int rc;
640 rc = ble_gap_extract_conn_cb(conn_handle, &cb, &cb_arg);
641 if (rc != 0) {
642 return rc;
643 }
644
645 rc = ble_gap_call_event_cb(event, cb, cb_arg);
646 if (rc != 0) {
647 return rc;
648 }
649
650 return 0;
651 }
652
ble_gap_is_preempted(void)653 static bool ble_gap_is_preempted(void)
654 {
655 int i;
656 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
657
658 if (ble_gap_master.preempted_op != BLE_GAP_OP_NULL) {
659 return true;
660 }
661
662 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
663 if (ble_gap_slave[i].preempted) {
664 return true;
665 }
666 }
667
668 return false;
669 }
670
671 #if NIMBLE_BLE_CONNECT
ble_gap_master_reset_state(void)672 static void ble_gap_master_reset_state(void)
673 {
674 ble_gap_master.op = BLE_GAP_OP_NULL;
675 ble_gap_master.exp_set = 0;
676 ble_gap_master.conn.cancel = 0;
677 ble_hs_timer_resched();
678 }
679 #endif
680
ble_gap_slave_reset_state(uint8_t instance)681 static void ble_gap_slave_reset_state(uint8_t instance)
682 {
683 ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
684 #if !MYNEWT_VAL(BLE_EXT_ADV)
685 ble_gap_slave[instance].exp_set = 0;
686 ble_hs_timer_resched();
687 #endif
688 }
689
690 #if NIMBLE_BLE_CONNECT
ble_gap_has_client(struct ble_gap_master_state * out_state)691 static bool ble_gap_has_client(struct ble_gap_master_state *out_state)
692 {
693 if (!out_state) {
694 return 0;
695 }
696
697 return (out_state->cb != NULL);
698 }
699
ble_gap_master_extract_state(struct ble_gap_master_state * out_state,int reset_state)700 static void ble_gap_master_extract_state(struct ble_gap_master_state *out_state, int reset_state)
701 {
702 ble_hs_lock();
703 *out_state = ble_gap_master;
704
705 if (reset_state) {
706 ble_gap_master_reset_state();
707 ble_gap_master.preempted_op = BLE_GAP_OP_NULL;
708 }
709
710 ble_hs_unlock();
711 }
712 #endif
713
ble_gap_slave_extract_cb(uint8_t instance,ble_gap_event_fn ** out_cb,void ** out_cb_arg)714 static void ble_gap_slave_extract_cb(uint8_t instance, ble_gap_event_fn **out_cb, void **out_cb_arg)
715 {
716 ble_hs_lock();
717 *out_cb = ble_gap_slave[instance].cb;
718 *out_cb_arg = ble_gap_slave[instance].cb_arg;
719 ble_gap_slave_reset_state(instance);
720 ble_hs_unlock();
721 }
722
ble_gap_adv_finished(uint8_t instance,int reason,uint16_t conn_handle,uint8_t num_events)723 static void ble_gap_adv_finished(uint8_t instance, int reason, uint16_t conn_handle, uint8_t num_events)
724 {
725 struct ble_gap_event event;
726 ble_gap_event_fn *cb;
727 void *cb_arg;
728 memset_s(&event, sizeof(event), 0, sizeof(event));
729 event.type = BLE_GAP_EVENT_ADV_COMPLETE;
730 event.adv_complete.reason = reason;
731 #if MYNEWT_VAL(BLE_EXT_ADV)
732 event.adv_complete.instance = instance;
733 event.adv_complete.conn_handle = conn_handle;
734 event.adv_complete.num_ext_adv_events = num_events;
735 #endif
736 ble_gap_event_listener_call(&event);
737 ble_gap_slave_extract_cb(instance, &cb, &cb_arg);
738
739 if (cb != NULL) {
740 cb(&event, cb_arg);
741 }
742 }
743
744 #if NIMBLE_BLE_CONNECT
ble_gap_master_connect_failure(int status)745 static int ble_gap_master_connect_failure(int status)
746 {
747 struct ble_gap_master_state state;
748 struct ble_gap_event event;
749 int rc;
750 ble_gap_master_extract_state(&state, 1);
751
752 if (ble_gap_has_client(&state)) {
753 memset_s(&event, sizeof(event), 0, sizeof(event));
754 event.type = BLE_GAP_EVENT_CONNECT;
755 event.connect.status = status;
756 rc = state.cb(&event, state.cb_arg);
757 } else {
758 rc = 0;
759 }
760
761 return rc;
762 }
763
ble_gap_master_connect_cancelled(void)764 static void ble_gap_master_connect_cancelled(void)
765 {
766 struct ble_gap_master_state state;
767 struct ble_gap_event event;
768 ble_gap_master_extract_state(&state, 1);
769
770 if (state.cb != NULL) {
771 memset_s(&event, sizeof(event), 0, sizeof(event));
772 event.type = BLE_GAP_EVENT_CONNECT;
773 event.connect.conn_handle = BLE_HS_CONN_HANDLE_NONE;
774
775 if (state.conn.cancel) {
776 /* Connect procedure successfully cancelled. */
777 event.connect.status = BLE_HS_EAPP;
778 } else {
779 /* Connect procedure timed out. */
780 event.connect.status = BLE_HS_ETIMEOUT;
781 }
782
783 state.cb(&event, state.cb_arg);
784 }
785 }
786 #endif
787
788 #if NIMBLE_BLE_SCAN
ble_gap_disc_report(void * desc)789 static void ble_gap_disc_report(void *desc)
790 {
791 struct ble_gap_master_state state;
792 struct ble_gap_event event;
793 memset_s(&event, sizeof(event), 0, sizeof(event));
794 #if MYNEWT_VAL(BLE_EXT_ADV)
795 event.type = BLE_GAP_EVENT_EXT_DISC;
796 event.ext_disc = *((struct ble_gap_ext_disc_desc *)desc);
797 #else
798 event.type = BLE_GAP_EVENT_DISC;
799 event.disc = *((struct ble_gap_disc_desc *)desc);
800 #endif
801 ble_gap_master_extract_state(&state, 0);
802
803 if (ble_gap_has_client(&state)) {
804 state.cb(&event, state.cb_arg);
805 }
806
807 ble_gap_event_listener_call(&event);
808 }
809
ble_gap_disc_complete(void)810 static void ble_gap_disc_complete(void)
811 {
812 struct ble_gap_master_state state;
813 struct ble_gap_event event;
814 memset_s(&event, sizeof(event), 0, sizeof(event));
815 event.type = BLE_GAP_EVENT_DISC_COMPLETE;
816 event.disc_complete.reason = 0;
817 ble_gap_master_extract_state(&state, 1);
818
819 if (ble_gap_has_client(&state)) {
820 ble_gap_call_event_cb(&event, state.cb, state.cb_arg);
821 }
822
823 ble_gap_event_listener_call(&event);
824 }
825 #endif
826
ble_gap_update_notify(uint16_t conn_handle,int status)827 static void ble_gap_update_notify(uint16_t conn_handle, int status)
828 {
829 struct ble_gap_event event;
830 memset_s(&event, sizeof(event), 0, sizeof(event));
831 event.type = BLE_GAP_EVENT_CONN_UPDATE;
832 event.conn_update.conn_handle = conn_handle;
833 event.conn_update.status = status;
834 ble_gap_event_listener_call(&event);
835 ble_gap_call_conn_event_cb(&event, conn_handle);
836
837 /* Terminate the connection on procedure timeout. */
838 if (status == BLE_HS_ETIMEOUT) {
839 ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
840 }
841 }
842
ble_gap_master_ticks_until_exp(void)843 static uint32_t ble_gap_master_ticks_until_exp(void)
844 {
845 ble_npl_stime_t ticks;
846
847 if (ble_gap_master.op == BLE_GAP_OP_NULL || !ble_gap_master.exp_set) {
848 /* Timer not set; infinity ticks until next event. */
849 return BLE_HS_FOREVER;
850 }
851
852 ticks = ble_gap_master.exp_os_ticks - ble_npl_time_get();
853 if (ticks > 0) {
854 /* Timer not expired yet. */
855 return ticks;
856 }
857
858 /* Timer just expired. */
859 return 0;
860 }
861
862 #if !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_slave_ticks_until_exp(void)863 static uint32_t ble_gap_slave_ticks_until_exp(void)
864 {
865 ble_npl_stime_t ticks;
866
867 if (ble_gap_slave[0].op == BLE_GAP_OP_NULL || !ble_gap_slave[0].exp_set) {
868 /* Timer not set; infinity ticks until next event. */
869 return BLE_HS_FOREVER;
870 }
871
872 ticks = ble_gap_slave[0].exp_os_ticks - ble_npl_time_get();
873 if (ticks > 0) {
874 /* Timer not expired yet. */
875 return ticks;
876 }
877
878 /* Timer just expired. */
879 return 0;
880 }
881 #endif
882
883 /**
884 * Finds the update procedure that expires soonest.
885 *
886 * @param out_ticks_from_now On success, the ticks until the update
887 * procedure's expiry time gets written here.
888 *
889 * @return The connection handle of the update procedure
890 * that expires soonest, or
891 * BLE_HS_CONN_HANDLE_NONE if there are no
892 * active update procedures.
893 */
ble_gap_update_next_exp(int32_t * out_ticks_from_now)894 static uint16_t ble_gap_update_next_exp(int32_t *out_ticks_from_now)
895 {
896 struct ble_gap_update_entry *entry;
897 ble_npl_time_t now;
898 uint16_t conn_handle;
899 int32_t best_ticks;
900 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
901 conn_handle = BLE_HS_CONN_HANDLE_NONE;
902 best_ticks = BLE_HS_FOREVER;
903 now = ble_npl_time_get();
904 SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
905 int32_t ticks = entry->exp_os_ticks - now;
906 if (ticks <= 0) {
907 ticks = 0;
908 }
909
910 if (ticks < best_ticks) {
911 conn_handle = entry->conn_handle;
912 best_ticks = ticks;
913 }
914 }
915
916 if (out_ticks_from_now != NULL) {
917 *out_ticks_from_now = best_ticks;
918 }
919
920 return conn_handle;
921 }
922
923 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
ble_gap_master_set_timer(uint32_t ticks_from_now)924 static void ble_gap_master_set_timer(uint32_t ticks_from_now)
925 {
926 ble_gap_master.exp_os_ticks = ble_npl_time_get() + ticks_from_now;
927 ble_gap_master.exp_set = 1;
928 ble_hs_timer_resched();
929 }
930 #endif
931
932 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_slave_set_timer(uint32_t ticks_from_now)933 static void ble_gap_slave_set_timer(uint32_t ticks_from_now)
934 {
935 ble_gap_slave[0].exp_os_ticks = ble_npl_time_get() + ticks_from_now;
936 ble_gap_slave[0].exp_set = 1;
937 ble_hs_timer_resched();
938 }
939 #endif
940
941 #if NIMBLE_BLE_CONNECT
942 /**
943 * Called when an error is encountered while the master-connection-fsm is
944 * active.
945 */
ble_gap_master_failed(int status)946 static void ble_gap_master_failed(int status)
947 {
948 switch (ble_gap_master.op) {
949 case BLE_GAP_OP_M_CONN:
950 STATS_INC(ble_gap_stats, initiate_fail);
951 ble_gap_master_connect_failure(status);
952 break;
953
954 default:
955 BLE_HS_DBG_ASSERT(0);
956 break;
957 }
958 }
959
ble_gap_update_failed(uint16_t conn_handle,int status)960 static void ble_gap_update_failed(uint16_t conn_handle, int status)
961 {
962 struct ble_gap_update_entry *entry;
963 STATS_INC(ble_gap_stats, update_fail);
964 ble_hs_lock();
965 entry = ble_gap_update_entry_remove(conn_handle);
966 ble_hs_unlock();
967 ble_gap_update_entry_free(entry);
968 ble_gap_update_notify(conn_handle, status);
969 }
970 #endif
971
ble_gap_conn_broken(uint16_t conn_handle,int reason)972 void ble_gap_conn_broken(uint16_t conn_handle, int reason)
973 {
974 struct ble_gap_update_entry *entry;
975 struct ble_gap_snapshot snap;
976 struct ble_gap_event event;
977 int rc;
978 memset_s(&event, sizeof(event), 0, sizeof(event));
979 snap.desc = &event.disconnect.conn;
980 rc = ble_gap_find_snapshot(conn_handle, &snap);
981 if (rc != 0) {
982 /* No longer connected. */
983 return;
984 }
985
986 /* If there was a connection update in progress, indicate to the
987 * application that it did not complete.
988 */
989 ble_hs_lock();
990 entry = ble_gap_update_entry_remove(conn_handle);
991 ble_hs_unlock();
992
993 if (entry != NULL) {
994 ble_gap_update_notify(conn_handle, reason);
995 ble_gap_update_entry_free(entry);
996 }
997
998 /* Indicate the connection termination to each module. The order matters
999 * here: gatts must come before gattc to ensure the application does not
1000 * get informed of spurious notify-tx events.
1001 */
1002 ble_l2cap_sig_conn_broken(conn_handle, reason);
1003 ble_sm_connection_broken(conn_handle);
1004 ble_gatts_connection_broken(conn_handle);
1005 ble_gattc_connection_broken(conn_handle);
1006 ble_hs_flow_connection_broken(conn_handle);
1007 ble_hs_atomic_conn_delete(conn_handle);
1008 event.type = BLE_GAP_EVENT_DISCONNECT;
1009 event.disconnect.reason = reason;
1010 ble_gap_event_listener_call(&event);
1011 ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg);
1012 STATS_INC(ble_gap_stats, disconnect);
1013 }
1014
1015 #if NIMBLE_BLE_CONNECT
ble_gap_update_to_l2cap(const struct ble_gap_upd_params * params,struct ble_l2cap_sig_update_params * l2cap_params)1016 static void ble_gap_update_to_l2cap(const struct ble_gap_upd_params *params,
1017 struct ble_l2cap_sig_update_params *l2cap_params)
1018 {
1019 l2cap_params->itvl_min = params->itvl_min;
1020 l2cap_params->itvl_max = params->itvl_max;
1021 l2cap_params->slave_latency = params->latency;
1022 l2cap_params->timeout_multiplier = params->supervision_timeout;
1023 }
1024 #endif
1025
ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp * ev)1026 void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev)
1027 {
1028 #if NIMBLE_BLE_CONNECT
1029 struct ble_gap_event event;
1030 uint16_t handle = le16toh(ev->conn_handle);
1031 STATS_INC(ble_gap_stats, rx_disconnect);
1032
1033 if (ev->status == 0) {
1034 ble_gap_conn_broken(handle, BLE_HS_HCI_ERR(ev->reason));
1035 } else {
1036 memset_s(&event, sizeof(event), 0, sizeof(event));
1037 event.type = BLE_GAP_EVENT_TERM_FAILURE;
1038 event.term_failure.conn_handle = handle;
1039 event.term_failure.status = BLE_HS_HCI_ERR(ev->status);
1040 ble_gap_event_listener_call(&event);
1041 ble_gap_call_conn_event_cb(&event, handle);
1042 }
1043
1044 #endif
1045 }
1046
ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete * ev)1047 void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev)
1048 {
1049 #if NIMBLE_BLE_CONNECT
1050 struct ble_gap_update_entry *entry;
1051 struct ble_l2cap_sig_update_params l2cap_params;
1052 struct ble_gap_event event;
1053 struct ble_hs_conn *conn;
1054 uint16_t conn_handle;
1055 int cb_status;
1056 int call_cb;
1057 STATS_INC(ble_gap_stats, rx_update_complete);
1058 memset_s(&event, sizeof(event), 0, sizeof(event));
1059 memset_s(&l2cap_params, sizeof(l2cap_params), 0, sizeof(l2cap_params));
1060 ble_hs_lock();
1061 conn_handle = le16toh(ev->conn_handle);
1062 conn = ble_hs_conn_find(conn_handle);
1063 if (conn != NULL) {
1064 switch (ev->status) {
1065 case 0:
1066 /* Connection successfully updated. */
1067 conn->bhc_itvl = le16toh(ev->conn_itvl);
1068 conn->bhc_latency = le16toh(ev->conn_latency);
1069 conn->bhc_supervision_timeout = le16toh(ev->supervision_timeout);
1070 break;
1071
1072 case BLE_ERR_UNSUPP_REM_FEATURE:
1073 /* Peer reports that it doesn't support the procedure. This should
1074 * only happen if our controller sent the 4.1 Connection Parameters
1075 * Request Procedure. If we are the slave, fail over to the L2CAP
1076 * update procedure.
1077 */
1078 entry = ble_gap_update_entry_find(conn_handle, NULL);
1079 if (entry != NULL && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
1080 ble_gap_update_to_l2cap(&entry->params, &l2cap_params);
1081 entry->exp_os_ticks = ble_npl_time_get() +
1082 ble_npl_time_ms_to_ticks32(BLE_GAP_UPDATE_TIMEOUT_MS);
1083 }
1084
1085 break;
1086
1087 default:
1088 break;
1089 }
1090 }
1091
1092 /* We aren't failing over to L2CAP, the update procedure is complete. */
1093 if (l2cap_params.itvl_min == 0) {
1094 entry = ble_gap_update_entry_remove(conn_handle);
1095 ble_gap_update_entry_free(entry);
1096 }
1097
1098 ble_hs_unlock();
1099
1100 if (l2cap_params.itvl_min != 0) {
1101 int rc = ble_l2cap_sig_update(conn_handle, &l2cap_params,
1102 ble_gap_update_l2cap_cb, NULL);
1103 if (rc == 0) {
1104 call_cb = 0;
1105 } else {
1106 call_cb = 1;
1107 cb_status = rc;
1108 }
1109 } else {
1110 call_cb = 1;
1111 cb_status = BLE_HS_HCI_ERR(ev->status);
1112 }
1113
1114 if (call_cb) {
1115 ble_gap_update_notify(conn_handle, cb_status);
1116 }
1117
1118 #endif
1119 }
1120
1121 /**
1122 * Tells you if there is an active central GAP procedure (connect or discover).
1123 */
ble_gap_master_in_progress(void)1124 int ble_gap_master_in_progress(void)
1125 {
1126 return ble_gap_master.op != BLE_GAP_OP_NULL;
1127 }
1128
ble_gap_adv_active_instance(uint8_t instance)1129 static int ble_gap_adv_active_instance(uint8_t instance)
1130 {
1131 /* Assume read is atomic; mutex not necessary. */
1132 return ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV;
1133 }
1134
1135 #if NIMBLE_BLE_CONNECT
ble_gap_accept_master_conn(void)1136 static int ble_gap_accept_master_conn(void)
1137 {
1138 int rc;
1139
1140 switch (ble_gap_master.op) {
1141 case BLE_GAP_OP_NULL:
1142 case BLE_GAP_OP_M_DISC:
1143 rc = BLE_HS_ENOENT;
1144 break;
1145
1146 case BLE_GAP_OP_M_CONN:
1147 rc = 0;
1148 break;
1149
1150 default:
1151 BLE_HS_DBG_ASSERT(0);
1152 rc = BLE_HS_ENOENT;
1153 break;
1154 }
1155
1156 if (rc == 0) {
1157 STATS_INC(ble_gap_stats, connect_mst);
1158 }
1159
1160 return rc;
1161 }
1162
ble_gap_accept_slave_conn(uint8_t instance)1163 static int ble_gap_accept_slave_conn(uint8_t instance)
1164 {
1165 int rc;
1166
1167 if (instance >= BLE_ADV_INSTANCES) {
1168 rc = BLE_HS_ENOENT;
1169 } else if (!ble_gap_adv_active_instance(instance)) {
1170 rc = BLE_HS_ENOENT;
1171 } else {
1172 if (ble_gap_slave[instance].connectable) {
1173 rc = 0;
1174 } else {
1175 rc = BLE_HS_ENOENT;
1176 }
1177 }
1178
1179 if (rc == 0) {
1180 STATS_INC(ble_gap_stats, connect_slv);
1181 }
1182
1183 return rc;
1184 }
1185 #endif
1186
1187 #if NIMBLE_BLE_SCAN
ble_gap_rx_adv_report_sanity_check(const uint8_t * adv_data,uint8_t adv_data_len)1188 static int ble_gap_rx_adv_report_sanity_check(const uint8_t *adv_data, uint8_t adv_data_len)
1189 {
1190 const struct ble_hs_adv_field *flags;
1191 STATS_INC(ble_gap_stats, rx_adv_report);
1192
1193 if (ble_gap_master.op != BLE_GAP_OP_M_DISC) {
1194 return -1;
1195 }
1196
1197 /* If a limited discovery procedure is active, discard non-limited
1198 * advertisements.
1199 */
1200 if (ble_gap_master.disc.limited) {
1201 int rc = ble_hs_adv_find_field(BLE_HS_ADV_TYPE_FLAGS, adv_data,
1202 adv_data_len, &flags);
1203 if ((rc == 0) && (flags->length == 2) && // 2:byte alignment
1204 !(flags->value[0] & BLE_HS_ADV_F_DISC_LTD)) {
1205 return -1;
1206 }
1207 }
1208
1209 return 0;
1210 }
1211 #endif
1212
ble_gap_rx_adv_report(struct ble_gap_disc_desc * desc)1213 void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
1214 {
1215 #if NIMBLE_BLE_SCAN
1216
1217 if (ble_gap_rx_adv_report_sanity_check(desc->data, desc->length_data)) {
1218 return;
1219 }
1220
1221 ble_gap_disc_report(desc);
1222 #endif
1223 }
1224
1225 #if MYNEWT_VAL(BLE_EXT_ADV)
1226 #if NIMBLE_BLE_SCAN
ble_gap_rx_le_scan_timeout(void)1227 void ble_gap_rx_le_scan_timeout(void)
1228 {
1229 ble_gap_disc_complete();
1230 }
1231
ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc * desc)1232 void ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc)
1233 {
1234 if (ble_gap_rx_adv_report_sanity_check(desc->data, desc->length_data)) {
1235 return;
1236 }
1237
1238 ble_gap_disc_report(desc);
1239 }
1240 #endif
1241
ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated * ev)1242 void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev)
1243 {
1244 uint16_t conn_handle;
1245 int reason;
1246
1247 /* Currently spec allows only 0x3c and 0x43 when advertising was stopped
1248 * due to timeout or events limit, mp this for timeout error for now */
1249 if (ev->status) {
1250 reason = BLE_HS_ETIMEOUT;
1251 conn_handle = 0;
1252 } else {
1253 reason = 0;
1254 conn_handle = le16toh(ev->conn_handle);
1255 }
1256
1257 ble_gap_adv_finished(ev->adv_handle, reason, conn_handle, ev->num_events);
1258 }
1259
ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd * ev)1260 void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev)
1261 {
1262 struct ble_gap_event event;
1263 ble_gap_event_fn *cb;
1264 void *cb_arg;
1265 ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg);
1266
1267 if (cb != NULL) {
1268 memset_s(&event, sizeof(event), 0, sizeof(event));
1269 event.type = BLE_GAP_EVENT_SCAN_REQ_RCVD;
1270 event.scan_req_rcvd.instance = ev->adv_handle;
1271 event.scan_req_rcvd.scan_addr.type = ev->peer_addr_type;
1272 memcpy_s(event.scan_req_rcvd.scan_addr.val, sizeof(event.scan_req_rcvd.scan_addr.val),
1273 ev->peer_addr, BLE_DEV_ADDR_LEN);
1274 cb(&event, cb_arg);
1275 }
1276 }
1277 #endif
1278
1279 /* Periodic adv events */
1280 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
1281
ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab * ev)1282 void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev)
1283 {
1284 uint16_t sync_handle;
1285 struct ble_gap_event event;
1286 ble_gap_event_fn *cb;
1287 void *cb_arg;
1288 memset_s(&event, sizeof(event), 0, sizeof(event));
1289 event.type = BLE_GAP_EVENT_PERIODIC_SYNC;
1290 event.periodic_sync.status = ev->status;
1291 ble_hs_lock();
1292 BLE_HS_DBG_ASSERT(ble_gap_sync.psync);
1293
1294 if (!ev->status) {
1295 sync_handle = le16toh(ev->sync_handle);
1296 ble_gap_sync.psync->sync_handle = sync_handle;
1297 ble_gap_sync.psync->adv_sid = ev->sid;
1298 memcpy_s(ble_gap_sync.psync->advertiser_addr.val, sizeof(ble_gap_sync.psync->advertiser_addr.val),
1299 ev->peer_addr, 6); // 6:count
1300 ble_gap_sync.psync->advertiser_addr.type = ev->peer_addr_type;
1301 ble_gap_sync.psync->cb = ble_gap_sync.cb;
1302 ble_gap_sync.psync->cb_arg = ble_gap_sync.cb_arg;
1303 event.periodic_sync.sync_handle = sync_handle;
1304 event.periodic_sync.sid = ev->sid;
1305 event.periodic_sync.adv_addr = ble_gap_sync.psync->advertiser_addr;
1306 event.periodic_sync.adv_phy = ev->phy;
1307 event.periodic_sync.per_adv_ival = ev->interval;
1308 event.periodic_sync.adv_clk_accuracy = ev->aca;
1309 ble_hs_periodic_sync_insert(ble_gap_sync.psync);
1310 } else {
1311 ble_hs_periodic_sync_free(ble_gap_sync.psync);
1312 }
1313
1314 cb = ble_gap_sync.cb;
1315 cb_arg = ble_gap_sync.cb_arg;
1316 ble_gap_sync.op = BLE_GAP_OP_NULL;
1317 ble_gap_sync.cb_arg = NULL;
1318 ble_gap_sync.cb_arg = NULL;
1319 ble_gap_sync.psync = NULL;
1320 ble_hs_unlock();
1321 ble_gap_event_listener_call(&event);
1322
1323 if (cb) {
1324 cb(&event, cb_arg);
1325 }
1326 }
1327
ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt * ev)1328 void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *ev)
1329 {
1330 struct ble_hs_periodic_sync *psync;
1331 struct ble_gap_event event;
1332 ble_gap_event_fn *cb;
1333 void *cb_arg;
1334 ble_hs_lock();
1335 psync = ble_hs_periodic_sync_find_by_handle(le16toh(ev->sync_handle));
1336 if (psync) {
1337 cb = psync->cb;
1338 cb_arg = psync->cb_arg;
1339 }
1340
1341 ble_hs_unlock();
1342
1343 if (!psync || !cb) {
1344 return;
1345 }
1346
1347 memset_s(&event, sizeof(event), 0, sizeof(event));
1348 event.type = BLE_GAP_EVENT_PERIODIC_REPORT;
1349 event.periodic_report.sync_handle = psync->sync_handle;
1350 event.periodic_report.tx_power = ev->tx_power;
1351 event.periodic_report.rssi = ev->rssi;
1352 event.periodic_report.data_status = ev->data_status;
1353 event.periodic_report.data_length = ev->data_len;
1354 event.periodic_report.data = ev->data;
1355 cb(&event, cb_arg);
1356 }
1357
ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost * ev)1358 void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev)
1359 {
1360 struct ble_hs_periodic_sync *psync;
1361 struct ble_gap_event event;
1362 ble_gap_event_fn *cb;
1363 void *cb_arg;
1364 ble_hs_lock();
1365 /* The handle must be in the list */
1366 psync = ble_hs_periodic_sync_find_by_handle(le16toh(ev->sync_handle));
1367 BLE_HS_DBG_ASSERT(psync);
1368 cb = psync->cb;
1369 cb_arg = psync->cb_arg;
1370 /* Remove the handle from the list */
1371 ble_hs_periodic_sync_remove(psync);
1372 ble_hs_unlock();
1373 memset_s(&event, sizeof(event), 0, sizeof(event));
1374 event.type = BLE_GAP_EVENT_PERIODIC_SYNC_LOST;
1375 event.periodic_sync_lost.sync_handle = psync->sync_handle;
1376 event.periodic_sync_lost.reason = BLE_HS_ETIMEOUT;
1377 /* remove any sync_lost event from queue */
1378 ble_npl_eventq_remove(ble_hs_evq_get(), &psync->lost_ev);
1379 /* Free the memory occupied by psync as it is no longer needed */
1380 ble_hs_periodic_sync_free(psync);
1381 ble_gap_event_listener_call(&event);
1382
1383 if (cb) {
1384 cb(&event, cb_arg);
1385 }
1386 }
1387 #endif
1388
1389 #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
periodic_adv_transfer_disable(uint16_t conn_handle)1390 static int periodic_adv_transfer_disable(uint16_t conn_handle)
1391 {
1392 struct ble_hci_le_periodic_adv_sync_transfer_params_cp cmd;
1393 struct ble_hci_le_periodic_adv_sync_transfer_params_rp rsp;
1394 uint16_t opcode;
1395 int rc;
1396 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS);
1397 cmd.conn_handle = htole16(conn_handle);
1398 cmd.sync_cte_type = 0x00;
1399 cmd.mode = 0x00;
1400 cmd.skip = 0x0000;
1401 cmd.sync_timeout = 0x000a;
1402 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
1403 if (!rc) {
1404 BLE_HS_DBG_ASSERT(le16toh(rsp.conn_handle) == conn_handle);
1405 }
1406
1407 return rc;
1408 }
1409
ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer * ev)1410 void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev)
1411 {
1412 struct ble_hci_le_periodic_adv_term_sync_cp cmd_term;
1413 struct ble_gap_event event;
1414 struct ble_hs_conn *conn;
1415 ble_gap_event_fn *cb;
1416 uint16_t sync_handle;
1417 uint16_t conn_handle;
1418 uint16_t opcode;
1419 void *cb_arg;
1420 conn_handle = le16toh(ev->conn_handle);
1421 ble_hs_lock();
1422 /* Unfortunately spec sucks here as it doesn't explicitly stop
1423 * transfer reception on first transfer... for now just disable it on
1424 * every transfer event we get.
1425 */
1426 periodic_adv_transfer_disable(conn_handle);
1427 conn = ble_hs_conn_find(le16toh(ev->conn_handle));
1428 if (!conn || !conn->psync) {
1429 /* terminate sync if we didn't expect it */
1430 if (!ev->status) {
1431 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC);
1432 cmd_term.sync_handle = ev->sync_handle;
1433 ble_hs_hci_cmd_tx(opcode, &cmd_term, sizeof(cmd_term), NULL, 0);
1434 }
1435
1436 ble_hs_unlock();
1437 return;
1438 }
1439
1440 cb = conn->psync->cb;
1441 cb_arg = conn->psync->cb_arg;
1442 memset_s(&event, sizeof(event), 0, sizeof(event));
1443 event.type = BLE_GAP_EVENT_PERIODIC_TRANSFER;
1444 event.periodic_transfer.status = ev->status;
1445
1446 /* only sync handle is not valid on error */
1447 if (ev->status) {
1448 sync_handle = 0;
1449 ble_hs_periodic_sync_free(conn->psync);
1450 } else {
1451 sync_handle = le16toh(ev->sync_handle);
1452 conn->psync->sync_handle = sync_handle;
1453 conn->psync->adv_sid = ev->sid;
1454 memcpy_s(conn->psync->advertiser_addr.val, sizeof(conn->psync->advertiser_addr.val),
1455 ev->peer_addr, 6); // 6:size
1456 conn->psync->advertiser_addr.type = ev->peer_addr_type;
1457 ble_hs_periodic_sync_insert(conn->psync);
1458 }
1459
1460 conn->psync = NULL;
1461 event.periodic_transfer.sync_handle = sync_handle;
1462 event.periodic_transfer.conn_handle = conn_handle;
1463 event.periodic_transfer.service_data = le16toh(ev->service_data);
1464 event.periodic_transfer.sid = ev->sid;
1465 memcpy_s(event.periodic_transfer.adv_addr.val, sizeof(event.periodic_transfer.adv_addr.val),
1466 ev->peer_addr, 6); // 6:size
1467 event.periodic_transfer.adv_addr.type = ev->peer_addr_type;
1468 event.periodic_transfer.adv_phy = ev->phy;
1469 event.periodic_transfer.per_adv_itvl = le16toh(ev->interval);
1470 event.periodic_transfer.adv_clk_accuracy = ev->aca;
1471 ble_hs_unlock();
1472 ble_gap_event_listener_call(&event);
1473
1474 if (cb) {
1475 cb(&event, cb_arg);
1476 }
1477 }
1478 #endif
1479
1480 #if NIMBLE_BLE_CONNECT
ble_gap_rd_rem_sup_feat_tx(uint16_t handle)1481 static int ble_gap_rd_rem_sup_feat_tx(uint16_t handle)
1482 {
1483 struct ble_hci_le_rd_rem_feat_cp cmd;
1484 cmd.conn_handle = htole16(handle);
1485 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1486 BLE_HCI_OCF_LE_RD_REM_FEAT),
1487 &cmd, sizeof(cmd), NULL, 0);
1488 }
1489 #endif
1490
1491 /**
1492 * Processes an incoming connection-complete HCI event.
1493 * instance parameter is valid only for slave connection.
1494 */
ble_gap_rx_conn_complete(struct ble_gap_conn_complete * evt,uint8_t instance)1495 int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance)
1496 {
1497 #if NIMBLE_BLE_CONNECT
1498 struct ble_gap_event event;
1499 struct ble_hs_conn *conn;
1500 int rc;
1501 STATS_INC(ble_gap_stats, rx_conn_complete);
1502
1503 /* in that case *only* status field is valid so we determine role
1504 * based on error code
1505 */
1506 if (evt->status != BLE_ERR_SUCCESS) {
1507 switch (evt->status) {
1508 case BLE_ERR_DIR_ADV_TMO:
1509 /* slave role (HD directed advertising)
1510 *
1511 * with ext advertising this is send from set terminated event
1512 */
1513 #if !MYNEWT_VAL(BLE_EXT_ADV)
1514 if (ble_gap_adv_active()) {
1515 ble_gap_adv_finished(0, 0, 0, 0);
1516 }
1517
1518 #endif
1519 break;
1520
1521 case BLE_ERR_UNK_CONN_ID:
1522
1523 /* master role */
1524 if (ble_gap_master_in_progress()) {
1525 /* Connect procedure successfully cancelled. */
1526 if (ble_gap_master.preempted_op == BLE_GAP_OP_M_CONN) {
1527 ble_gap_master_failed(BLE_HS_EPREEMPTED);
1528 } else {
1529 ble_gap_master_connect_cancelled();
1530 }
1531 }
1532
1533 break;
1534
1535 default:
1536 /* this should never happen, unless controller is broken */
1537 BLE_HS_LOG(INFO, "controller reported invalid error code in conn"
1538 "complete event: %u", evt->status);
1539 assert(0);
1540 break;
1541 }
1542
1543 return 0;
1544 }
1545
1546 /* Apply the event to the existing connection if it exists. */
1547 if (ble_hs_atomic_conn_flags(evt->connection_handle, NULL) == 0) {
1548 /* XXX: Does this ever happen? */
1549 return 0;
1550 }
1551
1552 /* This event refers to a new connection. */
1553
1554 switch (evt->role) {
1555 case BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER:
1556 rc = ble_gap_accept_master_conn();
1557 if (rc != 0) {
1558 return rc;
1559 }
1560
1561 break;
1562
1563 case BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE:
1564 rc = ble_gap_accept_slave_conn(instance);
1565 if (rc != 0) {
1566 return rc;
1567 }
1568
1569 break;
1570
1571 default:
1572 BLE_HS_DBG_ASSERT(0);
1573 break;
1574 }
1575
1576 /* We verified that there is a free connection when the procedure began. */
1577 conn = ble_hs_conn_alloc(evt->connection_handle);
1578 BLE_HS_DBG_ASSERT(conn != NULL);
1579 conn->bhc_itvl = evt->conn_itvl;
1580 conn->bhc_latency = evt->conn_latency;
1581 conn->bhc_supervision_timeout = evt->supervision_timeout;
1582 conn->bhc_master_clock_accuracy = evt->master_clk_acc;
1583
1584 if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER) {
1585 conn->bhc_cb = ble_gap_master.cb;
1586 conn->bhc_cb_arg = ble_gap_master.cb_arg;
1587 conn->bhc_flags |= BLE_HS_CONN_F_MASTER;
1588 conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type;
1589 ble_gap_master_reset_state();
1590 } else {
1591 conn->bhc_cb = ble_gap_slave[instance].cb;
1592 conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg;
1593 conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type;
1594 #if MYNEWT_VAL(BLE_EXT_ADV)
1595 memcpy_s(conn->bhc_our_rnd_addr, sizeof(conn->bhc_our_rnd_addr),
1596 ble_gap_slave[instance].rnd_addr, 6); // 6:size
1597 #endif
1598 ble_gap_slave_reset_state(instance);
1599 }
1600
1601 conn->bhc_peer_addr.type = evt->peer_addr_type;
1602 memcpy_s(conn->bhc_peer_addr.val, sizeof(conn->bhc_peer_addr.val), evt->peer_addr, 6); // 6:size
1603 conn->bhc_our_rpa_addr.type = BLE_ADDR_RANDOM;
1604 memcpy_s(conn->bhc_our_rpa_addr.val, sizeof(conn->bhc_our_rpa_addr.val), evt->local_rpa, 6); // 6:size
1605
1606 /* If peer RPA is not set in the event and peer address
1607 * is RPA then store the peer RPA address so when the peer
1608 * address is resolved, the RPA is not forgotten.
1609 */
1610 if (memcmp(BLE_ADDR_ANY->val, evt->peer_rpa, 6) == 0) { // 6:size
1611 if (BLE_ADDR_IS_RPA(&conn->bhc_peer_addr)) {
1612 conn->bhc_peer_rpa_addr = conn->bhc_peer_addr;
1613 }
1614 } else {
1615 conn->bhc_peer_rpa_addr.type = BLE_ADDR_RANDOM;
1616 memcpy_s(conn->bhc_peer_rpa_addr.val, sizeof(conn->bhc_peer_rpa_addr.val), evt->peer_rpa, 6); // 6:size
1617 }
1618
1619 ble_hs_lock();
1620 memset_s(&event, sizeof(event), 0, sizeof(event));
1621 ble_hs_conn_insert(conn);
1622 ble_hs_unlock();
1623 event.type = BLE_GAP_EVENT_CONNECT;
1624 event.connect.conn_handle = evt->connection_handle;
1625 event.connect.status = 0;
1626 ble_gap_event_listener_call(&event);
1627 ble_gap_call_conn_event_cb(&event, evt->connection_handle);
1628 ble_gap_rd_rem_sup_feat_tx(evt->connection_handle);
1629 return 0;
1630 #else
1631 return BLE_HS_ENOTSUP;
1632 #endif
1633 }
1634
ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat * ev)1635 void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev)
1636 {
1637 #if NIMBLE_BLE_CONNECT
1638 struct ble_hs_conn *conn;
1639 ble_hs_lock();
1640 conn = ble_hs_conn_find(le16toh(ev->conn_handle));
1641 if ((conn != NULL) && (ev->status == 0)) {
1642 conn->supported_feat = get_le32(ev->features);
1643 }
1644
1645 ble_hs_unlock();
1646 #endif
1647 }
1648
ble_gap_rx_l2cap_update_req(uint16_t conn_handle,struct ble_gap_upd_params * params)1649 int ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
1650 struct ble_gap_upd_params *params)
1651 {
1652 struct ble_gap_event event;
1653 int rc;
1654 memset_s(&event, sizeof(event), 0, sizeof(event));
1655 event.type = BLE_GAP_EVENT_L2CAP_UPDATE_REQ;
1656 event.conn_update_req.conn_handle = conn_handle;
1657 event.conn_update_req.peer_params = params;
1658 rc = ble_gap_call_conn_event_cb(&event, conn_handle);
1659 return rc;
1660 }
1661
ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete * ev)1662 void ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev)
1663 {
1664 struct ble_gap_event event;
1665 uint16_t conn_handle = le16toh(ev->conn_handle);
1666 memset_s(&event, sizeof(event), 0, sizeof(event));
1667 event.type = BLE_GAP_EVENT_PHY_UPDATE_COMPLETE;
1668 event.phy_updated.status = ev->status;
1669 event.phy_updated.conn_handle = conn_handle;
1670 event.phy_updated.tx_phy = ev->tx_phy;
1671 event.phy_updated.rx_phy = ev->rx_phy;
1672 ble_gap_event_listener_call(&event);
1673 ble_gap_call_conn_event_cb(&event, conn_handle);
1674 }
1675
ble_gap_master_timer(void)1676 static int32_t ble_gap_master_timer(void)
1677 {
1678 uint32_t ticks_until_exp;
1679 int rc;
1680 ticks_until_exp = ble_gap_master_ticks_until_exp();
1681 if (ticks_until_exp != 0) {
1682 /* Timer not expired yet. */
1683 return ticks_until_exp;
1684 }
1685
1686 /*** Timer expired; process event. */
1687
1688 switch (ble_gap_master.op) {
1689 case BLE_GAP_OP_M_CONN:
1690 rc = ble_gap_conn_cancel_tx();
1691 if (rc != 0) {
1692 /* Failed to stop connecting; try again in 100 ms. */
1693 return ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
1694 } else {
1695 /* Stop the timer now that the cancel command has been acked. */
1696 ble_gap_master.exp_set = 0;
1697 /* Timeout gets reported when we receive a connection complete
1698 * event indicating the connect procedure has been cancelled.
1699 */
1700 /* XXX: Set a timer to reset the controller if a connection
1701 * complete event isn't received within a reasonable interval.
1702 */
1703 }
1704
1705 break;
1706
1707 case BLE_GAP_OP_M_DISC:
1708 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
1709 /* When a discovery procedure times out, it is not a failure. */
1710 rc = ble_gap_disc_enable_tx(0, 0);
1711 if (rc != 0) {
1712 /* Failed to stop discovery; try again in 100 ms. */
1713 return ble_npl_time_ms_to_ticks32(BLE_GAP_CANCEL_RETRY_TIMEOUT_MS);
1714 }
1715
1716 ble_gap_disc_complete();
1717 #else
1718 assert(0);
1719 #endif
1720 break;
1721
1722 default:
1723 BLE_HS_DBG_ASSERT(0);
1724 break;
1725 }
1726
1727 return BLE_HS_FOREVER;
1728 }
1729
1730 #if !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_slave_timer(void)1731 static int32_t ble_gap_slave_timer(void)
1732 {
1733 uint32_t ticks_until_exp;
1734 int rc;
1735 ticks_until_exp = ble_gap_slave_ticks_until_exp();
1736 if (ticks_until_exp != 0) {
1737 /* Timer not expired yet. */
1738 return ticks_until_exp;
1739 }
1740
1741 /*** Timer expired; process event. */
1742 /* Stop advertising. */
1743 rc = ble_gap_adv_enable_tx(0);
1744 if (rc != 0) {
1745 /* Failed to stop advertising; try again in 100 ms. */
1746 return 100;
1747 }
1748
1749 /* Clear the timer and cancel the current procedure. */
1750 ble_gap_slave_reset_state(0);
1751 /* Indicate to application that advertising has stopped. */
1752 ble_gap_adv_finished(0, BLE_HS_ETIMEOUT, 0, 0);
1753 return BLE_HS_FOREVER;
1754 }
1755 #endif
1756
ble_gap_update_timer(void)1757 static int32_t ble_gap_update_timer(void)
1758 {
1759 struct ble_gap_update_entry *entry;
1760 int32_t ticks_until_exp;
1761
1762 do {
1763 ble_hs_lock();
1764 uint16_t conn_handle = ble_gap_update_next_exp(&ticks_until_exp);
1765
1766 if (ticks_until_exp == 0) {
1767 entry = ble_gap_update_entry_remove(conn_handle);
1768 } else {
1769 entry = NULL;
1770 }
1771
1772 ble_hs_unlock();
1773
1774 if (entry != NULL) {
1775 ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
1776 ble_gap_update_entry_free(entry);
1777 }
1778 } while (entry != NULL);
1779
1780 return ticks_until_exp;
1781 }
1782
ble_gap_set_event_cb(uint16_t conn_handle,ble_gap_event_fn * cb,void * cb_arg)1783 int ble_gap_set_event_cb(uint16_t conn_handle, ble_gap_event_fn *cb, void *cb_arg)
1784 {
1785 struct ble_hs_conn *conn;
1786 ble_hs_lock();
1787 conn = ble_hs_conn_find(conn_handle);
1788 if (conn != NULL) {
1789 conn->bhc_cb = cb;
1790 conn->bhc_cb_arg = cb_arg;
1791 }
1792
1793 ble_hs_unlock();
1794
1795 if (conn == NULL) {
1796 return BLE_HS_ENOTCONN;
1797 }
1798
1799 return 0;
1800 }
1801
1802 /**
1803 * Handles timed-out GAP procedures.
1804 *
1805 * @return The number of ticks until this function should
1806 * be called again.
1807 */
ble_gap_timer(void)1808 int32_t ble_gap_timer(void)
1809 {
1810 int32_t update_ticks;
1811 int32_t master_ticks;
1812 int32_t min_ticks;
1813 master_ticks = ble_gap_master_timer();
1814 update_ticks = ble_gap_update_timer();
1815 min_ticks = min(master_ticks, update_ticks);
1816 #if !MYNEWT_VAL(BLE_EXT_ADV)
1817 min_ticks = min(min_ticks, ble_gap_slave_timer());
1818 #endif
1819 return min_ticks;
1820 }
1821
1822 /*****************************************************************************
1823 * $white list *
1824 *****************************************************************************/
1825
1826 #if MYNEWT_VAL(BLE_WHITELIST)
ble_gap_wl_busy(void)1827 static int ble_gap_wl_busy(void)
1828 {
1829 /* Check if an auto or selective connection establishment procedure is in
1830 * progress.
1831 */
1832 return ble_gap_master.op == BLE_GAP_OP_M_CONN &&
1833 ble_gap_master.conn.using_wl;
1834 }
1835
ble_gap_wl_tx_add(const ble_addr_t * addr)1836 static int ble_gap_wl_tx_add(const ble_addr_t *addr)
1837 {
1838 struct ble_hci_le_add_whte_list_cp cmd;
1839
1840 memcpy_s(cmd.addr, sizeof(cmd.addr), addr->val, BLE_DEV_ADDR_LEN);
1841 cmd.addr_type = addr->type;
1842 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1843 BLE_HCI_OCF_LE_ADD_WHITE_LIST),
1844 &cmd, sizeof(cmd), NULL, 0);
1845 }
1846
ble_gap_wl_tx_clear(void)1847 static int ble_gap_wl_tx_clear(void)
1848 {
1849 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1850 BLE_HCI_OCF_LE_CLEAR_WHITE_LIST),
1851 NULL, 0, NULL, 0);
1852 }
1853 #endif
1854
ble_gap_wl_set(const ble_addr_t * addrs,uint8_t white_list_count)1855 int ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count)
1856 {
1857 #if MYNEWT_VAL(BLE_WHITELIST)
1858 int rc;
1859 int i;
1860 STATS_INC(ble_gap_stats, wl_set);
1861 ble_hs_lock();
1862
1863 if (white_list_count == 0) {
1864 rc = BLE_HS_EINVAL;
1865 goto done;
1866 }
1867
1868 if (ble_gap_wl_busy()) {
1869 rc = BLE_HS_EBUSY;
1870 goto done;
1871 }
1872
1873 BLE_HS_LOG(INFO, "GAP procedure initiated: set whitelist; ");
1874 ble_gap_log_wl(addrs, white_list_count);
1875 BLE_HS_LOG(INFO, "\r\n");
1876 rc = ble_gap_wl_tx_clear();
1877 if (rc != 0) {
1878 goto done;
1879 }
1880
1881 for (i = 0; i < white_list_count; i++) {
1882 rc = ble_gap_wl_tx_add(addrs + i);
1883 if (rc != 0) {
1884 goto done;
1885 }
1886 }
1887
1888 rc = 0;
1889 done:
1890 ble_hs_unlock();
1891
1892 if (rc != 0) {
1893 STATS_INC(ble_gap_stats, wl_set_fail);
1894 }
1895
1896 return rc;
1897 #else
1898 return BLE_HS_ENOTSUP;
1899 #endif
1900 }
1901
1902 /*****************************************************************************
1903 * $stop advertise *
1904 *****************************************************************************/
1905 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_adv_enable_tx(int enable)1906 static int ble_gap_adv_enable_tx(int enable)
1907 {
1908 struct ble_hci_le_set_adv_enable_cp cmd;
1909 cmd.enable = !!enable;
1910 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1911 BLE_HCI_OCF_LE_SET_ADV_ENABLE),
1912 &cmd, sizeof(cmd), NULL, 0);
1913 }
1914
ble_gap_adv_stop_no_lock(void)1915 static int ble_gap_adv_stop_no_lock(void)
1916 {
1917 bool active;
1918 int rc = 0;
1919 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
1920 STATS_INC(ble_gap_stats, adv_stop);
1921 active = ble_gap_adv_active();
1922 if (active) {
1923 BLE_HS_LOG(INFO, "GAP procedure initiated: stop advertising\r\n");
1924 rc = ble_gap_adv_enable_tx(0);
1925 }
1926
1927 if (rc != 0) {
1928 goto done;
1929 }
1930
1931 ble_gap_slave_reset_state(0);
1932
1933 if (!active) {
1934 rc = BLE_HS_EALREADY;
1935 } else {
1936 rc = 0;
1937 }
1938
1939 done:
1940
1941 if (rc != 0) {
1942 STATS_INC(ble_gap_stats, adv_stop_fail);
1943 }
1944
1945 return rc;
1946 }
1947 #endif
1948
ble_gap_adv_stop(void)1949 int ble_gap_adv_stop(void)
1950 {
1951 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
1952 int rc;
1953 ble_hs_lock();
1954 rc = ble_gap_adv_stop_no_lock();
1955 ble_hs_unlock();
1956 return rc;
1957 #else
1958 return BLE_HS_ENOTSUP;
1959 #endif
1960 }
1961
1962 /*****************************************************************************
1963 * $advertise *
1964 *****************************************************************************/
1965 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_adv_type(const struct ble_gap_adv_params * adv_params)1966 static int ble_gap_adv_type(const struct ble_gap_adv_params *adv_params)
1967 {
1968 switch (adv_params->conn_mode) {
1969 case BLE_GAP_CONN_MODE_NON:
1970 if (adv_params->disc_mode == BLE_GAP_DISC_MODE_NON) {
1971 return BLE_HCI_ADV_TYPE_ADV_NONCONN_IND;
1972 } else {
1973 return BLE_HCI_ADV_TYPE_ADV_SCAN_IND;
1974 }
1975
1976 case BLE_GAP_CONN_MODE_UND:
1977 return BLE_HCI_ADV_TYPE_ADV_IND;
1978
1979 case BLE_GAP_CONN_MODE_DIR:
1980 if (adv_params->high_duty_cycle) {
1981 return BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD;
1982 } else {
1983 return BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD;
1984 }
1985
1986 default:
1987 BLE_HS_DBG_ASSERT(0);
1988 return BLE_HCI_ADV_TYPE_ADV_IND;
1989 }
1990 }
1991
ble_gap_adv_dflt_itvls(uint8_t conn_mode,uint16_t * out_itvl_min,uint16_t * out_itvl_max)1992 static void ble_gap_adv_dflt_itvls(uint8_t conn_mode, uint16_t *out_itvl_min, uint16_t *out_itvl_max)
1993 {
1994 switch (conn_mode) {
1995 case BLE_GAP_CONN_MODE_NON:
1996 *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL2_MIN;
1997 *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL2_MAX;
1998 break;
1999
2000 case BLE_GAP_CONN_MODE_UND:
2001 *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
2002 *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
2003 break;
2004
2005 case BLE_GAP_CONN_MODE_DIR:
2006 *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
2007 *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
2008 break;
2009
2010 default:
2011 BLE_HS_DBG_ASSERT(0);
2012 *out_itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN;
2013 *out_itvl_max = BLE_GAP_ADV_FAST_INTERVAL1_MAX;
2014 break;
2015 }
2016 }
2017
ble_gap_adv_params_tx(uint8_t own_addr_type,const ble_addr_t * peer_addr,const struct ble_gap_adv_params * adv_params)2018 static int ble_gap_adv_params_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr,
2019 const struct ble_gap_adv_params *adv_params)
2020
2021 {
2022 const ble_addr_t *peer_any = BLE_ADDR_ANY;
2023 struct ble_hci_le_set_adv_params_cp cmd;
2024 uint16_t opcode;
2025 uint16_t min;
2026 uint16_t max;
2027
2028 /* Fill optional fields if application did not specify them. */
2029 if ((adv_params->itvl_min == 0) && (adv_params->itvl_max == 0)) {
2030 ble_gap_adv_dflt_itvls(adv_params->conn_mode, &min, &max);
2031 cmd.min_interval = htole16(min);
2032 cmd.max_interval = htole16(max);
2033 } else {
2034 cmd.min_interval = htole16(adv_params->itvl_min);
2035 cmd.max_interval = htole16(adv_params->itvl_max);
2036 }
2037
2038 cmd.type = ble_gap_adv_type(adv_params);
2039 cmd.own_addr_type = own_addr_type;
2040
2041 if (peer_addr == NULL) {
2042 peer_addr = peer_any;
2043 }
2044
2045 cmd.peer_addr_type = peer_addr->type;
2046 memcpy_s(&cmd.peer_addr, sizeof(cmd.peer_addr), peer_addr->val, sizeof(cmd.peer_addr));
2047
2048 if (adv_params->channel_map == 0) {
2049 cmd.chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP;
2050 } else {
2051 cmd.chan_map = adv_params->channel_map;
2052 }
2053
2054 /* Zero is the default value for filter policy and high duty cycle */
2055 cmd.filter_policy = adv_params->filter_policy;
2056 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_PARAMS);
2057 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
2058 }
2059
ble_gap_adv_validate(uint8_t own_addr_type,const ble_addr_t * peer_addr,const struct ble_gap_adv_params * adv_params)2060 static int ble_gap_adv_validate(uint8_t own_addr_type, const ble_addr_t *peer_addr,
2061 const struct ble_gap_adv_params *adv_params)
2062 {
2063 if (adv_params == NULL) {
2064 return BLE_HS_EINVAL;
2065 }
2066
2067 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
2068 return BLE_HS_EINVAL;
2069 }
2070
2071 if (adv_params->disc_mode >= BLE_GAP_DISC_MODE_MAX) {
2072 return BLE_HS_EINVAL;
2073 }
2074
2075 if (ble_gap_slave[0].op != BLE_GAP_OP_NULL) {
2076 return BLE_HS_EALREADY;
2077 }
2078
2079 switch (adv_params->conn_mode) {
2080 case BLE_GAP_CONN_MODE_NON:
2081
2082 /* High duty cycle only allowed for directed advertising. */
2083 if (adv_params->high_duty_cycle) {
2084 return BLE_HS_EINVAL;
2085 }
2086
2087 break;
2088
2089 case BLE_GAP_CONN_MODE_UND:
2090
2091 /* High duty cycle only allowed for directed advertising. */
2092 if (adv_params->high_duty_cycle) {
2093 return BLE_HS_EINVAL;
2094 }
2095
2096 /* Don't allow connectable advertising if we won't be able to allocate
2097 * a new connection.
2098 */
2099 if (!ble_hs_conn_can_alloc()) {
2100 return BLE_HS_ENOMEM;
2101 }
2102
2103 break;
2104
2105 case BLE_GAP_CONN_MODE_DIR:
2106 if (peer_addr == NULL) {
2107 return BLE_HS_EINVAL;
2108 }
2109
2110 if (peer_addr->type != BLE_ADDR_PUBLIC &&
2111 peer_addr->type != BLE_ADDR_RANDOM &&
2112 peer_addr->type != BLE_ADDR_PUBLIC_ID &&
2113 peer_addr->type != BLE_ADDR_RANDOM_ID) {
2114 return BLE_HS_EINVAL;
2115 }
2116
2117 /* Don't allow connectable advertising if we won't be able to allocate
2118 * a new connection.
2119 */
2120 if (!ble_hs_conn_can_alloc()) {
2121 return BLE_HS_ENOMEM;
2122 }
2123
2124 break;
2125
2126 default:
2127 return BLE_HS_EINVAL;
2128 }
2129
2130 return 0;
2131 }
2132 #endif
2133
ble_gap_adv_start(uint8_t own_addr_type,const ble_addr_t * direct_addr,int32_t duration_ms,const struct ble_gap_adv_params * adv_params,ble_gap_event_fn * cb,void * cb_arg)2134 int ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
2135 int32_t duration_ms,
2136 const struct ble_gap_adv_params *adv_params,
2137 ble_gap_event_fn *cb, void *cb_arg)
2138 {
2139 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
2140 uint32_t duration_ticks;
2141 int rc;
2142 STATS_INC(ble_gap_stats, adv_start);
2143 ble_hs_lock();
2144 rc = ble_gap_adv_validate(own_addr_type, direct_addr, adv_params);
2145 if (rc != 0) {
2146 goto done;
2147 }
2148
2149 if (duration_ms != BLE_HS_FOREVER) {
2150 rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
2151 if (rc != 0) {
2152 /* Duration too great. */
2153 rc = BLE_HS_EINVAL;
2154 goto done;
2155 }
2156 }
2157
2158 if (!ble_hs_is_enabled()) {
2159 rc = BLE_HS_EDISABLED;
2160 goto done;
2161 }
2162
2163 if (ble_gap_is_preempted()) {
2164 rc = BLE_HS_EPREEMPTED;
2165 goto done;
2166 }
2167
2168 rc = ble_hs_id_use_addr(own_addr_type);
2169 if (rc != 0) {
2170 goto done;
2171 }
2172
2173 BLE_HS_LOG(INFO, "GAP procedure initiated: advertise; ");
2174 ble_gap_log_adv(own_addr_type, direct_addr, adv_params);
2175 BLE_HS_LOG(INFO, "\r\n");
2176 ble_gap_slave[0].cb = cb;
2177 ble_gap_slave[0].cb_arg = cb_arg;
2178 ble_gap_slave[0].our_addr_type = own_addr_type;
2179
2180 if (adv_params->conn_mode != BLE_GAP_CONN_MODE_NON) {
2181 ble_gap_slave[0].connectable = 1;
2182 } else {
2183 ble_gap_slave[0].connectable = 0;
2184 }
2185
2186 rc = ble_gap_adv_params_tx(own_addr_type, direct_addr, adv_params);
2187 if (rc != 0) {
2188 goto done;
2189 }
2190
2191 ble_gap_slave[0].op = BLE_GAP_OP_S_ADV;
2192 rc = ble_gap_adv_enable_tx(1);
2193 if (rc != 0) {
2194 ble_gap_slave_reset_state(0);
2195 goto done;
2196 }
2197
2198 if (duration_ms != BLE_HS_FOREVER) {
2199 ble_gap_slave_set_timer(duration_ticks);
2200 }
2201
2202 rc = 0;
2203 done:
2204 ble_hs_unlock();
2205
2206 if (rc != 0) {
2207 STATS_INC(ble_gap_stats, adv_start_fail);
2208 }
2209
2210 return rc;
2211 #else
2212 return BLE_HS_ENOTSUP;
2213 #endif
2214 }
2215
ble_gap_adv_set_data(const uint8_t * data,int data_len)2216 int ble_gap_adv_set_data(const uint8_t *data, int data_len)
2217 {
2218 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
2219 struct ble_hci_le_set_adv_data_cp cmd;
2220 uint16_t opcode;
2221 STATS_INC(ble_gap_stats, adv_set_data);
2222
2223 /* Check for valid parameters */
2224 if (((data == NULL) && (data_len != 0)) ||
2225 (data_len > BLE_HCI_MAX_ADV_DATA_LEN)) {
2226 return BLE_ERR_INV_HCI_CMD_PARMS;
2227 }
2228
2229 memcpy_s(cmd.adv_data, sizeof(cmd.adv_data), data, data_len);
2230 cmd.adv_data_len = data_len;
2231 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_DATA);
2232 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
2233 #else
2234 return BLE_HS_ENOTSUP;
2235 #endif
2236 }
2237
ble_gap_adv_rsp_set_data(const uint8_t * data,int data_len)2238 int ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len)
2239 {
2240 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
2241 struct ble_hci_le_set_scan_rsp_data_cp cmd;
2242 uint16_t opcode;
2243
2244 /* Check for valid parameters */
2245 if (((data == NULL) && (data_len != 0)) ||
2246 (data_len > BLE_HCI_MAX_SCAN_RSP_DATA_LEN)) {
2247 return BLE_HS_EINVAL;
2248 }
2249
2250 memcpy_s(cmd.scan_rsp, sizeof(cmd.scan_rsp), data, data_len);
2251 cmd.scan_rsp_len = data_len;
2252 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA);
2253 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
2254 #else
2255 return BLE_HS_ENOTSUP;
2256 #endif
2257 }
2258
ble_gap_adv_set_fields(const struct ble_hs_adv_fields * adv_fields)2259 int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields)
2260 {
2261 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
2262 uint8_t buf[BLE_HS_ADV_MAX_SZ];
2263 uint8_t buf_sz;
2264 int rc;
2265 rc = ble_hs_adv_set_fields(adv_fields, buf, &buf_sz, sizeof buf);
2266 if (rc != 0) {
2267 return rc;
2268 }
2269
2270 rc = ble_gap_adv_set_data(buf, buf_sz);
2271 if (rc != 0) {
2272 return rc;
2273 }
2274
2275 return 0;
2276 #else
2277 return BLE_HS_ENOTSUP;
2278 #endif
2279 }
2280
ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields * rsp_fields)2281 int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
2282 {
2283 #if NIMBLE_BLE_ADVERTISE && !MYNEWT_VAL(BLE_EXT_ADV)
2284 uint8_t buf[BLE_HS_ADV_MAX_SZ];
2285 uint8_t buf_sz;
2286 int rc;
2287 rc = ble_hs_adv_set_fields(rsp_fields, buf, &buf_sz, sizeof buf);
2288 if (rc != 0) {
2289 return rc;
2290 }
2291
2292 rc = ble_gap_adv_rsp_set_data(buf, buf_sz);
2293 if (rc != 0) {
2294 return rc;
2295 }
2296
2297 return 0;
2298 #else
2299 return BLE_HS_ENOTSUP;
2300 #endif
2301 }
2302
ble_gap_adv_active(void)2303 int ble_gap_adv_active(void)
2304 {
2305 return ble_gap_adv_active_instance(0);
2306 }
2307
2308 #if MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_ext_adv_params_tx(uint8_t instance,const struct ble_gap_ext_adv_params * params,int8_t * selected_tx_power)2309 static int ble_gap_ext_adv_params_tx(uint8_t instance,
2310 const struct ble_gap_ext_adv_params *params,
2311 int8_t *selected_tx_power)
2312
2313 {
2314 struct ble_hci_le_set_ext_adv_params_cp cmd;
2315 struct ble_hci_le_set_ext_adv_params_rp rsp;
2316 int rc;
2317 memset_s(&cmd, sizeof(cmd), 0, sizeof(cmd));
2318 cmd.adv_handle = instance;
2319
2320 if (params->connectable) {
2321 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE;
2322 }
2323
2324 if (params->scannable) {
2325 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
2326 }
2327
2328 if (params->directed) {
2329 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED;
2330 cmd.peer_addr_type = params->peer.type;
2331 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), params->peer.val, BLE_DEV_ADDR_LEN);
2332 }
2333
2334 if (params->high_duty_directed) {
2335 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED;
2336 }
2337
2338 if (params->legacy_pdu) {
2339 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY;
2340 }
2341
2342 if (params->anonymous) {
2343 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV;
2344 }
2345
2346 if (params->include_tx_power) {
2347 cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR;
2348 }
2349
2350 /* Fill optional fields if application did not specify them. */
2351 if (params->itvl_min == 0 && params->itvl_max == 0) {
2352 /* for now limited to legacy values */
2353 put_le24(cmd.pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN);
2354 put_le24(cmd.pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX);
2355 } else {
2356 put_le24(cmd.pri_itvl_min, params->itvl_min);
2357 put_le24(cmd.pri_itvl_max, params->itvl_max);
2358 }
2359
2360 if (params->channel_map == 0) {
2361 cmd.pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP;
2362 } else {
2363 cmd.pri_chan_map = params->channel_map;
2364 }
2365
2366 /* Zero is the default value for filter policy and high duty cycle */
2367 cmd.filter_policy = params->filter_policy;
2368 cmd.tx_power = params->tx_power;
2369
2370 if (params->legacy_pdu) {
2371 cmd.pri_phy = BLE_HCI_LE_PHY_1M;
2372 cmd.sec_phy = BLE_HCI_LE_PHY_1M;
2373 } else {
2374 cmd.pri_phy = params->primary_phy;
2375 cmd.sec_phy = params->secondary_phy;
2376 }
2377
2378 cmd.own_addr_type = params->own_addr_type;
2379 cmd.sec_max_skip = 0;
2380 cmd.sid = params->sid;
2381 cmd.scan_req_notif = params->scan_req_notif;
2382 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
2383 BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM),
2384 &cmd, sizeof(cmd), &rsp, sizeof(rsp));
2385 if (rc != 0) {
2386 return rc;
2387 }
2388
2389 if (selected_tx_power) {
2390 *selected_tx_power = rsp.tx_power;
2391 }
2392
2393 return 0;
2394 }
2395
ble_gap_ext_adv_params_validate(const struct ble_gap_ext_adv_params * params)2396 static int ble_gap_ext_adv_params_validate(const struct ble_gap_ext_adv_params *params)
2397 {
2398 if (!params) {
2399 return BLE_HS_EINVAL;
2400 }
2401
2402 if (params->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
2403 return BLE_HS_EINVAL;
2404 }
2405
2406 /* Don't allow connectable advertising if we won't be able to allocate
2407 * a new connection.
2408 */
2409 if (params->connectable && !ble_hs_conn_can_alloc()) {
2410 return BLE_HS_ENOMEM;
2411 }
2412
2413 if (params->legacy_pdu) {
2414 /* not allowed for legacy PDUs */
2415 if (params->anonymous || params->include_tx_power) {
2416 return BLE_HS_EINVAL;
2417 }
2418 }
2419
2420 if (params->directed) {
2421 if (params->scannable && params->connectable) {
2422 return BLE_HS_EINVAL;
2423 }
2424 }
2425
2426 if (!params->legacy_pdu) {
2427 /* not allowed for extended advertising PDUs */
2428 if (params->connectable && params->scannable) {
2429 return BLE_HS_EINVAL;
2430 }
2431
2432 /* HD directed advertising allowed only for legacy PDUs */
2433 if (params->high_duty_directed) {
2434 return BLE_HS_EINVAL;
2435 }
2436 }
2437
2438 return 0;
2439 }
2440
ble_gap_ext_adv_configure(uint8_t instance,const struct ble_gap_ext_adv_params * params,int8_t * selected_tx_power,ble_gap_event_fn * cb,void * cb_arg)2441 int ble_gap_ext_adv_configure(uint8_t instance,
2442 const struct ble_gap_ext_adv_params *params,
2443 int8_t *selected_tx_power,
2444 ble_gap_event_fn *cb, void *cb_arg)
2445 {
2446 int rc;
2447
2448 if (instance >= BLE_ADV_INSTANCES) {
2449 return BLE_HS_EINVAL;
2450 }
2451
2452 rc = ble_gap_ext_adv_params_validate(params);
2453 if (rc) {
2454 return rc;
2455 }
2456
2457 ble_hs_lock();
2458
2459 if (ble_gap_adv_active_instance(instance)) {
2460 ble_hs_unlock();
2461 return BLE_HS_EBUSY;
2462 }
2463
2464 rc = ble_gap_ext_adv_params_tx(instance, params, selected_tx_power);
2465 if (rc) {
2466 ble_hs_unlock();
2467 return rc;
2468 }
2469
2470 ble_gap_slave[instance].configured = 1;
2471 ble_gap_slave[instance].cb = cb;
2472 ble_gap_slave[instance].cb_arg = cb_arg;
2473 ble_gap_slave[instance].our_addr_type = params->own_addr_type;
2474 ble_gap_slave[instance].connectable = params->connectable;
2475 ble_gap_slave[instance].scannable = params->scannable;
2476 ble_gap_slave[instance].directed = params->directed;
2477 ble_gap_slave[instance].high_duty_directed = params->high_duty_directed;
2478 ble_gap_slave[instance].legacy_pdu = params->legacy_pdu;
2479 ble_hs_unlock();
2480 return 0;
2481 }
2482
ble_gap_ext_adv_set_addr_no_lock(uint8_t instance,const uint8_t * addr)2483 static int ble_gap_ext_adv_set_addr_no_lock(uint8_t instance, const uint8_t *addr)
2484 {
2485 struct ble_hci_le_set_adv_set_rnd_addr_cp cmd;
2486 int rc;
2487 cmd.adv_handle = instance;
2488 memcpy_s(cmd.addr, sizeof(cmd.addr), addr, BLE_DEV_ADDR_LEN);
2489 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
2490 BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR),
2491 &cmd, sizeof(cmd), NULL, 0);
2492 if (rc != 0) {
2493 return rc;
2494 }
2495
2496 ble_gap_slave[instance].rnd_addr_set = 1;
2497 memcpy_s(ble_gap_slave[instance].rnd_addr, sizeof(ble_gap_slave[instance].rnd_addr), addr, 6); // 6:size
2498 return 0;
2499 }
2500
ble_gap_ext_adv_set_addr(uint8_t instance,const ble_addr_t * addr)2501 int ble_gap_ext_adv_set_addr(uint8_t instance, const ble_addr_t *addr)
2502 {
2503 int rc;
2504
2505 if (instance >= BLE_ADV_INSTANCES || addr->type != BLE_ADDR_RANDOM) {
2506 return BLE_HS_EINVAL;
2507 }
2508
2509 ble_hs_lock();
2510 rc = ble_gap_ext_adv_set_addr_no_lock(instance, addr->val);
2511 ble_hs_unlock();
2512 return rc;
2513 }
2514
ble_gap_ext_adv_start(uint8_t instance,int duration,int max_events)2515 int ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events)
2516 {
2517 struct ble_hci_le_set_ext_adv_enable_cp *cmd;
2518 uint8_t buf[sizeof(*cmd) + sizeof(cmd->sets[0])];
2519 const uint8_t *rnd_addr;
2520 uint16_t opcode;
2521 int rc;
2522
2523 if (instance >= BLE_ADV_INSTANCES) {
2524 return BLE_HS_EINVAL;
2525 }
2526
2527 ble_hs_lock();
2528
2529 if (!ble_gap_slave[instance].configured) {
2530 ble_hs_unlock();
2531 return BLE_HS_EINVAL;
2532 }
2533
2534 if (ble_gap_slave[instance].op != BLE_GAP_OP_NULL) {
2535 ble_hs_unlock();
2536 return BLE_HS_EALREADY;
2537 }
2538
2539 /* HD directed duration shall not be 0 or larger than >1.28s */
2540 if (ble_gap_slave[instance].high_duty_directed &&
2541 ((duration == 0) || (duration > 128))) { // 128:Analyzing conditions
2542 ble_hs_unlock();
2543 return BLE_HS_EINVAL;
2544 }
2545
2546 /* verify own address type if random address for instance wasn't explicitly
2547 * set
2548 */
2549 switch (ble_gap_slave[instance].our_addr_type) {
2550 case BLE_OWN_ADDR_RANDOM:
2551 case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
2552 if (ble_gap_slave[instance].rnd_addr_set) {
2553 break;
2554 }
2555
2556 /* fall through */
2557 case BLE_OWN_ADDR_PUBLIC:
2558 case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
2559 default:
2560 rc = ble_hs_id_use_addr(ble_gap_slave[instance].our_addr_type);
2561 if (rc) {
2562 ble_hs_unlock();
2563 return BLE_HS_EINVAL;
2564 }
2565
2566 break;
2567 }
2568
2569 /* fallback to ID static random address if using random address and instance
2570 * wasn't configured with own address
2571 */
2572 if (!ble_gap_slave[instance].rnd_addr_set) {
2573 switch (ble_gap_slave[instance].our_addr_type) {
2574 case BLE_OWN_ADDR_RANDOM:
2575 case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
2576 rc = ble_hs_id_addr(BLE_ADDR_RANDOM, &rnd_addr, NULL);
2577 if (rc != 0) {
2578 ble_hs_unlock();
2579 return rc;
2580 }
2581
2582 rc = ble_gap_ext_adv_set_addr_no_lock(instance, rnd_addr);
2583 if (rc != 0) {
2584 ble_hs_unlock();
2585 return rc;
2586 }
2587
2588 break;
2589
2590 default:
2591 break;
2592 }
2593 }
2594
2595 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE);
2596 cmd = (void *) buf;
2597 cmd->enable = 0x01;
2598 cmd->num_sets = 1;
2599 cmd->sets[0].adv_handle = instance;
2600 cmd->sets[0].duration = htole16(duration);
2601 cmd->sets[0].max_events = max_events;
2602 rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(buf), NULL, 0);
2603 if (rc != 0) {
2604 ble_hs_unlock();
2605 return rc;
2606 }
2607
2608 ble_gap_slave[instance].op = BLE_GAP_OP_S_ADV;
2609 ble_hs_unlock();
2610 return 0;
2611 }
2612
ble_gap_ext_adv_stop_no_lock(uint8_t instance)2613 static int ble_gap_ext_adv_stop_no_lock(uint8_t instance)
2614 {
2615 struct ble_hci_le_set_ext_adv_enable_cp *cmd;
2616 uint8_t buf[sizeof(*cmd) + sizeof(cmd->sets[0])];
2617 uint16_t opcode;
2618 bool active;
2619 int rc;
2620
2621 if (!ble_gap_slave[instance].configured) {
2622 return BLE_HS_EINVAL;
2623 }
2624
2625 active = ble_gap_adv_active_instance(instance);
2626 cmd = (void *) buf;
2627 cmd->enable = 0x00;
2628 cmd->num_sets = 1;
2629 cmd->sets[0].adv_handle = instance;
2630 cmd->sets[0].duration = 0x0000;
2631 cmd->sets[0].max_events = 0x00;
2632 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE);
2633 rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(buf), NULL, 0);
2634 if (rc != 0) {
2635 return rc;
2636 }
2637
2638 ble_gap_slave[instance].op = BLE_GAP_OP_NULL;
2639
2640 if (!active) {
2641 return BLE_HS_EALREADY;
2642 } else {
2643 return 0;
2644 }
2645 }
2646
ble_gap_ext_adv_stop(uint8_t instance)2647 int ble_gap_ext_adv_stop(uint8_t instance)
2648 {
2649 int rc;
2650
2651 if (instance >= BLE_ADV_INSTANCES) {
2652 return BLE_HS_EINVAL;
2653 }
2654
2655 ble_hs_lock();
2656 rc = ble_gap_ext_adv_stop_no_lock(instance);
2657 ble_hs_unlock();
2658 return rc;
2659 }
2660
ble_gap_ext_adv_set_data_validate(uint8_t instance,struct os_mbuf * data)2661 static int ble_gap_ext_adv_set_data_validate(uint8_t instance, struct os_mbuf *data)
2662 {
2663 uint16_t len = OS_MBUF_PKTLEN(data);
2664
2665 if (!ble_gap_slave[instance].configured) {
2666 return BLE_HS_EINVAL;
2667 }
2668
2669 /* not allowed with directed advertising for legacy */
2670 if (ble_gap_slave[instance].legacy_pdu && ble_gap_slave[instance].directed) {
2671 return BLE_HS_EINVAL;
2672 }
2673
2674 /* always allowed with legacy PDU but limited to legacy length */
2675 if (ble_gap_slave[instance].legacy_pdu) {
2676 if (len > BLE_HS_ADV_MAX_SZ) {
2677 return BLE_HS_EINVAL;
2678 }
2679
2680 return 0;
2681 }
2682
2683 /* if already advertising, data must fit in single HCI command
2684 * as per BT 5.0 Vol 2, Part E, 7.8.54. Don't bother Controller with such
2685 * a request.
2686 */
2687 if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
2688 if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) { // 251:Analyzing conditions
2689 return BLE_HS_EINVAL;
2690 }
2691 }
2692
2693 /* not allowed with scannable advertising */
2694 if (ble_gap_slave[instance].scannable) {
2695 return BLE_HS_EINVAL;
2696 }
2697
2698 return 0;
2699 }
2700
ble_gap_ext_adv_set(uint8_t instance,uint16_t opcode,struct os_mbuf ** data)2701 static int ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf **data)
2702 {
2703 /* in that case we always fit all data in single HCI command 3005 */
2704 #if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_EXT_ADV_DATA_LEN
2705 static uint8_t buf[sizeof(struct ble_hci_le_set_ext_adv_data_cp) + \
2706 MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
2707 struct ble_hci_le_set_ext_adv_data_cp *cmd = (void *)buf;
2708 uint16_t len = OS_MBUF_PKTLEN(*data);
2709 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
2710 cmd->adv_handle = instance;
2711 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE;
2712 cmd->fragment_pref = 0;
2713 cmd->adv_data_len = len;
2714 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
2715 os_mbuf_adj(*data, len);
2716 *data = os_mbuf_trim_front(*data);
2717 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
2718 NULL, 0);
2719 #else
2720 static uint8_t buf[sizeof(struct ble_hci_le_set_ext_adv_data_cp) + \
2721 BLE_HCI_MAX_EXT_ADV_DATA_LEN];
2722 struct ble_hci_le_set_ext_adv_data_cp *cmd = (void *)buf;
2723 uint16_t len = OS_MBUF_PKTLEN(*data);
2724 uint8_t op;
2725 int rc;
2726 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode);
2727 cmd->adv_handle = instance;
2728
2729 /* complete data */
2730 if (len <= BLE_HCI_MAX_EXT_ADV_DATA_LEN) {
2731 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE;
2732 cmd->fragment_pref = 0;
2733 cmd->adv_data_len = len;
2734 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
2735 os_mbuf_adj(*data, len);
2736 *data = os_mbuf_trim_front(*data);
2737 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
2738 NULL, 0);
2739 }
2740
2741 /* first fragment */
2742 op = BLE_HCI_LE_SET_DATA_OPER_FIRST;
2743
2744 do {
2745 cmd->operation = op;
2746 cmd->fragment_pref = 0;
2747 cmd->adv_data_len = BLE_HCI_MAX_EXT_ADV_DATA_LEN;
2748 os_mbuf_copydata(*data, 0, BLE_HCI_MAX_EXT_ADV_DATA_LEN, cmd->adv_data);
2749 os_mbuf_adj(*data, BLE_HCI_MAX_EXT_ADV_DATA_LEN);
2750 *data = os_mbuf_trim_front(*data);
2751 rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
2752 NULL, 0);
2753 if (rc) {
2754 return rc;
2755 }
2756
2757 len -= BLE_HCI_MAX_EXT_ADV_DATA_LEN;
2758 op = BLE_HCI_LE_SET_DATA_OPER_INT;
2759 } while (len > BLE_HCI_MAX_EXT_ADV_DATA_LEN);
2760
2761 /* last fragment */
2762 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_LAST;
2763 cmd->fragment_pref = 0;
2764 cmd->adv_data_len = len;
2765 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
2766 os_mbuf_adj(*data, len);
2767 *data = os_mbuf_trim_front(*data);
2768 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
2769 NULL, 0);
2770 #endif
2771 }
2772
ble_gap_ext_adv_set_data(uint8_t instance,struct os_mbuf * data)2773 int ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data)
2774 {
2775 int rc;
2776
2777 if (instance >= BLE_ADV_INSTANCES) {
2778 rc = BLE_HS_EINVAL;
2779 goto done;
2780 }
2781
2782 ble_hs_lock();
2783 rc = ble_gap_ext_adv_set_data_validate(instance, data);
2784 if (rc != 0) {
2785 ble_hs_unlock();
2786 goto done;
2787 }
2788
2789 rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_ADV_DATA, &data);
2790 ble_hs_unlock();
2791 done:
2792 os_mbuf_free_chain(data);
2793 return rc;
2794 }
2795
ble_gap_ext_adv_rsp_set_validate(uint8_t instance,struct os_mbuf * data)2796 static int ble_gap_ext_adv_rsp_set_validate(uint8_t instance, struct os_mbuf *data)
2797 {
2798 uint16_t len = OS_MBUF_PKTLEN(data);
2799
2800 if (!ble_gap_slave[instance].configured) {
2801 return BLE_HS_EINVAL;
2802 }
2803
2804 /* not allowed with directed advertising */
2805 if (ble_gap_slave[instance].directed && ble_gap_slave[instance].connectable) {
2806 return BLE_HS_EINVAL;
2807 }
2808
2809 /* only allowed with scannable advertising */
2810 if (!ble_gap_slave[instance].scannable) {
2811 return BLE_HS_EINVAL;
2812 }
2813
2814 /* with legacy PDU limited to legacy length */
2815 if (ble_gap_slave[instance].legacy_pdu) {
2816 if (len > BLE_HS_ADV_MAX_SZ) {
2817 return BLE_HS_EINVAL;
2818 }
2819
2820 return 0;
2821 }
2822
2823 /* if already advertising, data must fit in single HCI command
2824 * as per BT 5.0 Vol 2, Part E, 7.8.55. Don't bother Controller with such
2825 * a request.
2826 */
2827 if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
2828 if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) { // 251:Analyzing conditions
2829 return BLE_HS_EINVAL;
2830 }
2831 }
2832
2833 return 0;
2834 }
2835
ble_gap_ext_adv_rsp_set_data(uint8_t instance,struct os_mbuf * data)2836 int ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data)
2837 {
2838 int rc;
2839
2840 if (instance >= BLE_ADV_INSTANCES) {
2841 rc = BLE_HS_EINVAL;
2842 goto done;
2843 }
2844
2845 ble_hs_lock();
2846 rc = ble_gap_ext_adv_rsp_set_validate(instance, data);
2847 if (rc != 0) {
2848 ble_hs_unlock();
2849 goto done;
2850 }
2851
2852 rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA,
2853 &data);
2854 ble_hs_unlock();
2855 done:
2856 os_mbuf_free_chain(data);
2857 return rc;
2858 }
2859
ble_gap_ext_adv_remove(uint8_t instance)2860 int ble_gap_ext_adv_remove(uint8_t instance)
2861 {
2862 struct ble_hci_le_remove_adv_set_cp cmd;
2863 uint16_t opcode;
2864 int rc;
2865
2866 if (instance >= BLE_ADV_INSTANCES) {
2867 return BLE_HS_EINVAL;
2868 }
2869
2870 ble_hs_lock();
2871
2872 if (!ble_gap_slave[instance].configured) {
2873 ble_hs_unlock();
2874 return BLE_HS_EALREADY;
2875 }
2876
2877 if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) {
2878 ble_hs_unlock();
2879 return BLE_HS_EBUSY;
2880 }
2881
2882 cmd.adv_handle = instance;
2883 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REMOVE_ADV_SET);
2884 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
2885 if (rc != 0) {
2886 ble_hs_unlock();
2887 return rc;
2888 }
2889
2890 memset_s(&ble_gap_slave[instance], sizeof(struct ble_gap_slave_state), 0, sizeof(struct ble_gap_slave_state));
2891 ble_hs_unlock();
2892 return 0;
2893 }
2894
ble_gap_ext_adv_clear(void)2895 int ble_gap_ext_adv_clear(void)
2896 {
2897 int rc;
2898 uint8_t instance;
2899 uint16_t opcode;
2900 ble_hs_lock();
2901
2902 for (instance = 0; instance < BLE_ADV_INSTANCES; instance++) {
2903 /* If there is an active instance or periodic adv instance,
2904 * Don't send the command
2905 * */
2906 if ((ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV)) {
2907 ble_hs_unlock();
2908 return BLE_HS_EBUSY;
2909 }
2910
2911 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
2912
2913 if (ble_gap_slave[instance].periodic_op == BLE_GAP_OP_S_PERIODIC_ADV) {
2914 ble_hs_unlock();
2915 return BLE_HS_EBUSY;
2916 }
2917 #endif
2918 }
2919
2920 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_ADV_SETS);
2921 rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0);
2922 if (rc != 0) {
2923 ble_hs_unlock();
2924 return rc;
2925 }
2926
2927 memset_s(ble_gap_slave, sizeof(ble_gap_slave), 0, sizeof(ble_gap_slave));
2928 ble_hs_unlock();
2929 return 0;
2930 }
2931
2932 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
ble_gap_periodic_adv_params_tx(uint8_t instance,const struct ble_gap_periodic_adv_params * params)2933 static int ble_gap_periodic_adv_params_tx(uint8_t instance,
2934 const struct ble_gap_periodic_adv_params *params)
2935 {
2936 struct ble_hci_le_set_periodic_adv_params_cp cmd;
2937 uint16_t opcode;
2938 cmd.adv_handle = instance;
2939
2940 /* Fill optional fields if application did not specify them. */
2941 if (params->itvl_min == 0 && params->itvl_max == 0) {
2942 cmd.min_itvl = htole16(30 / 1.25); // 30:30 ms
2943 cmd.max_itvl = htole16(60 / 1.25); // 60:150 ms
2944 } else {
2945 cmd.min_itvl = htole16(params->itvl_min);
2946 cmd.max_itvl = htole16(params->itvl_max);
2947 }
2948
2949 if (params->include_tx_power) {
2950 cmd.props = BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR;
2951 } else {
2952 cmd.props = 0;
2953 }
2954
2955 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS);
2956 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
2957 }
2958
ble_gap_periodic_adv_params_validate(const struct ble_gap_periodic_adv_params * params)2959 static int ble_gap_periodic_adv_params_validate(const struct ble_gap_periodic_adv_params *params)
2960 {
2961 if (!params) {
2962 return BLE_HS_EINVAL;
2963 }
2964
2965 if (params->itvl_min && params->itvl_min < 6) { // 6: Analyzing conditions
2966 return BLE_HS_EINVAL;
2967 }
2968
2969 if (params->itvl_max && params->itvl_max < 6) { // 6: Analyzing conditions
2970 return BLE_HS_EINVAL;
2971 }
2972
2973 return 0;
2974 }
2975
ble_gap_periodic_adv_configure(uint8_t instance,const struct ble_gap_periodic_adv_params * params)2976 int ble_gap_periodic_adv_configure(uint8_t instance, const struct ble_gap_periodic_adv_params *params)
2977 {
2978 int rc;
2979
2980 if (instance >= BLE_ADV_INSTANCES) {
2981 return BLE_HS_EINVAL;
2982 }
2983
2984 rc = ble_gap_periodic_adv_params_validate(params);
2985 if (rc) {
2986 return rc;
2987 }
2988
2989 ble_hs_lock();
2990
2991 /* The corresponding extended advertising instance should be configured */
2992 if (!ble_gap_slave[instance].configured) {
2993 ble_hs_unlock();
2994 return ENOMEM;
2995 }
2996
2997 /* Periodic advertising shall not be configured while it is already
2998 * running.
2999 * Bluetooth Core Specification, Section 7.8.61
3000 */
3001 if (ble_gap_slave[instance].periodic_op == BLE_GAP_OP_S_PERIODIC_ADV) {
3002 ble_hs_unlock();
3003 return BLE_HS_EINVAL;
3004 }
3005
3006 rc = ble_gap_periodic_adv_params_tx(instance, params);
3007 if (rc) {
3008 ble_hs_unlock();
3009 return rc;
3010 }
3011
3012 ble_gap_slave[instance].periodic_configured = 1;
3013 ble_hs_unlock();
3014 return 0;
3015 }
3016
ble_gap_periodic_adv_start(uint8_t instance)3017 int ble_gap_periodic_adv_start(uint8_t instance)
3018 {
3019 struct ble_hci_le_set_periodic_adv_enable_cp cmd;
3020 uint16_t opcode;
3021 int rc;
3022
3023 if (instance >= BLE_ADV_INSTANCES) {
3024 return BLE_HS_EINVAL;
3025 }
3026
3027 ble_hs_lock();
3028
3029 /* Periodic advertising cannot start unless it is configured before */
3030 if (!ble_gap_slave[instance].periodic_configured) {
3031 ble_hs_unlock();
3032 return BLE_HS_EINVAL;
3033 }
3034
3035 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE);
3036 cmd.enable = 0x01;
3037 cmd.adv_handle = instance;
3038 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3039 if (rc != 0) {
3040 ble_hs_unlock();
3041 return rc;
3042 }
3043
3044 ble_gap_slave[instance].periodic_op = BLE_GAP_OP_S_PERIODIC_ADV;
3045 ble_hs_unlock();
3046 return 0;
3047 }
3048
ble_gap_periodic_adv_set(uint8_t instance,struct os_mbuf ** data)3049 static int ble_gap_periodic_adv_set(uint8_t instance, struct os_mbuf **data)
3050 {
3051 /* In that case we always fit all data in single HCI command */
3052 #if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN
3053 static uint8_t buf[sizeof(struct ble_hci_le_set_periodic_adv_data_cp) +
3054 MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)];
3055 struct ble_hci_le_set_periodic_adv_data_cp *cmd = (void *) buf;
3056 uint16_t len = OS_MBUF_PKTLEN(*data);
3057 uint16_t opcode;
3058 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA);
3059 cmd->adv_handle = instance;
3060 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE;
3061 cmd->adv_data_len = len;
3062 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
3063 os_mbuf_adj(*data, len);
3064 *data = os_mbuf_trim_front(*data);
3065 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
3066 NULL, 0);
3067 #else
3068 static uint8_t buf[sizeof(struct ble_hci_le_set_periodic_adv_data_cp) +
3069 BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN];
3070 struct ble_hci_le_set_periodic_adv_data_cp *cmd = (void *) buf;
3071 uint16_t len = OS_MBUF_PKTLEN(*data);
3072 uint16_t opcode;
3073 uint8_t op;
3074 int rc;
3075 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_DATA);
3076 cmd->adv_handle = instance;
3077
3078 /* Complete data */
3079 if (len <= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN) {
3080 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_COMPLETE;
3081 cmd->adv_data_len = len;
3082 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
3083 os_mbuf_adj(*data, len);
3084 *data = os_mbuf_trim_front(*data);
3085 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
3086 NULL, 0);
3087 }
3088
3089 /* If the periodic advertising is already enabled, the periodic advertising
3090 * the op code shall be nothing but 0x03
3091 * Bluetooth Core Specification, section 7.8.62
3092 */
3093 if (ble_gap_slave[instance].periodic_op == BLE_GAP_OP_S_PERIODIC_ADV) {
3094 return BLE_HS_EINVAL;
3095 }
3096
3097 /* First fragment */
3098 op = BLE_HCI_LE_SET_DATA_OPER_FIRST;
3099
3100 do {
3101 cmd->operation = op;
3102 cmd->adv_data_len = BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN;
3103 os_mbuf_copydata(*data, 0, BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN,
3104 cmd->adv_data);
3105 os_mbuf_adj(*data, BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN);
3106 *data = os_mbuf_trim_front(*data);
3107 rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
3108 NULL, 0);
3109 if (rc) {
3110 return rc;
3111 }
3112
3113 len -= BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN;
3114 op = BLE_HCI_LE_SET_DATA_OPER_INT;
3115 } while (len > BLE_HCI_MAX_PERIODIC_ADV_DATA_LEN);
3116
3117 /* Last fragment */
3118 cmd->operation = BLE_HCI_LE_SET_DATA_OPER_LAST;
3119 cmd->adv_data_len = len;
3120 os_mbuf_copydata(*data, 0, len, cmd->adv_data);
3121 os_mbuf_adj(*data, len);
3122 *data = os_mbuf_trim_front(*data);
3123 return ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + cmd->adv_data_len,
3124 NULL, 0);
3125 #endif
3126 }
3127
ble_gap_periodic_adv_set_data_validate(uint8_t instance,struct os_mbuf * data)3128 static int ble_gap_periodic_adv_set_data_validate(uint8_t instance, struct os_mbuf *data)
3129 {
3130 /* The corresponding extended advertising instance should be configured */
3131 if (!ble_gap_slave[instance].configured) {
3132 return BLE_HS_EINVAL;
3133 }
3134
3135 if (ble_gap_slave[instance].legacy_pdu) {
3136 return BLE_HS_EINVAL;
3137 }
3138
3139 /* One more check states that if the periodic advertising is already
3140 * enabled, the operation shall be 0x03 (Complete).
3141 * This check is handled during sending the data to the controller, as the
3142 * length checks are already checked there, so this saves duplicate code
3143 */
3144 return 0;
3145 }
3146
ble_gap_periodic_adv_set_data(uint8_t instance,struct os_mbuf * data)3147 int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data)
3148 {
3149 int rc;
3150
3151 if (instance >= BLE_ADV_INSTANCES) {
3152 rc = BLE_HS_EINVAL;
3153 goto done;
3154 }
3155
3156 ble_hs_lock();
3157 rc = ble_gap_periodic_adv_set_data_validate(instance, data);
3158 if (rc != 0) {
3159 ble_hs_unlock();
3160 goto done;
3161 }
3162
3163 rc = ble_gap_periodic_adv_set(instance, &data);
3164 ble_hs_unlock();
3165 done:
3166 os_mbuf_free_chain(data);
3167 return rc;
3168 }
3169
ble_gap_periodic_adv_stop_no_lock(uint8_t instance)3170 static int ble_gap_periodic_adv_stop_no_lock(uint8_t instance)
3171 {
3172 struct ble_hci_le_set_periodic_adv_enable_cp cmd;
3173 uint16_t opcode;
3174 int rc;
3175 cmd.enable = 0x00;
3176 cmd.adv_handle = instance;
3177 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_ENABLE);
3178 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3179 if (rc != 0) {
3180 return rc;
3181 }
3182
3183 ble_gap_slave[instance].periodic_op = BLE_GAP_OP_NULL;
3184 return 0;
3185 }
3186
ble_gap_periodic_adv_stop(uint8_t instance)3187 int ble_gap_periodic_adv_stop(uint8_t instance)
3188 {
3189 int rc;
3190
3191 if (instance >= BLE_ADV_INSTANCES) {
3192 return BLE_HS_EINVAL;
3193 }
3194
3195 ble_hs_lock();
3196 rc = ble_gap_periodic_adv_stop_no_lock(instance);
3197 ble_hs_unlock();
3198 return rc;
3199 }
3200
ble_gap_npl_sync_lost(struct ble_npl_event * ev)3201 static void ble_gap_npl_sync_lost(struct ble_npl_event *ev)
3202 {
3203 struct ble_hs_periodic_sync *psync;
3204 struct ble_gap_event event;
3205 ble_gap_event_fn *cb;
3206 void *cb_arg;
3207 /* this psync is no longer on list so no lock needed */
3208 psync = ble_npl_event_get_arg(ev);
3209 cb = psync->cb;
3210 cb_arg = psync->cb_arg;
3211 memset_s(&event, sizeof(event), 0, sizeof(event));
3212 event.type = BLE_GAP_EVENT_PERIODIC_SYNC_LOST;
3213 event.periodic_sync_lost.sync_handle = psync->sync_handle;
3214 event.periodic_sync_lost.reason = BLE_HS_EDONE;
3215 /* Free the memory occupied by psync as it is no longer needed */
3216 ble_hs_periodic_sync_free(psync);
3217 ble_gap_event_listener_call(&event);
3218
3219 if (cb) {
3220 cb(&event, cb_arg);
3221 }
3222 }
3223
ble_gap_periodic_adv_sync_create(const ble_addr_t * addr,uint8_t adv_sid,const struct ble_gap_periodic_sync_params * params,ble_gap_event_fn * cb,void * cb_arg)3224 int ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid,
3225 const struct ble_gap_periodic_sync_params *params,
3226 ble_gap_event_fn *cb, void *cb_arg)
3227 {
3228 struct ble_hci_le_periodic_adv_create_sync_cp cmd;
3229 struct ble_hs_periodic_sync *psync;
3230 uint16_t opcode;
3231 int rc;
3232
3233 if (addr && (addr->type > BLE_ADDR_RANDOM)) {
3234 return BLE_HS_EINVAL;
3235 }
3236
3237 if (adv_sid > 0x0f) {
3238 return BLE_HS_EINVAL;
3239 }
3240
3241 if ((params->skip > 0x1f3) || (params->sync_timeout > 0x4000) ||
3242 (params->sync_timeout < 0x0A)) {
3243 return BLE_HS_EINVAL;
3244 }
3245
3246 ble_hs_lock();
3247
3248 /* No sync can be created if another sync is still pending */
3249 if (ble_gap_sync.op == BLE_GAP_OP_SYNC) {
3250 ble_hs_unlock();
3251 return BLE_HS_EBUSY;
3252 }
3253
3254 /* cannot create another sync if already synchronized */
3255 if (ble_hs_periodic_sync_find(addr, adv_sid)) {
3256 ble_hs_unlock();
3257 return BLE_HS_EALREADY;
3258 }
3259
3260 /* preallocate sync element */
3261 psync = ble_hs_periodic_sync_alloc();
3262 if (!psync) {
3263 ble_hs_unlock();
3264 return BLE_HS_ENOMEM;
3265 }
3266
3267 ble_npl_event_init(&psync->lost_ev, ble_gap_npl_sync_lost, psync);
3268
3269 if (addr) {
3270 cmd.options = 0x00;
3271 cmd.peer_addr_type = addr->type;
3272 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), addr->val, BLE_DEV_ADDR_LEN);
3273 } else {
3274 cmd.options = 0x01;
3275 cmd.peer_addr_type = BLE_ADDR_ANY->type;
3276 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), BLE_ADDR_ANY->val, BLE_DEV_ADDR_LEN);
3277 }
3278
3279 cmd.sid = adv_sid;
3280 cmd.skip = params->skip;
3281 cmd.sync_timeout = htole16(params->sync_timeout);
3282 cmd.sync_cte_type = 0x00;
3283 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC);
3284 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3285 if (!rc) {
3286 /* This shall be reset upon receiving sync_established event,
3287 * or if the sync is cancelled before receiving that event.
3288 */
3289 ble_gap_sync.op = BLE_GAP_OP_SYNC;
3290 ble_gap_sync.cb = cb;
3291 ble_gap_sync.cb_arg = cb_arg;
3292 ble_gap_sync.psync = psync;
3293 } else {
3294 ble_hs_periodic_sync_free(psync);
3295 }
3296
3297 ble_hs_unlock();
3298 return rc;
3299 }
3300
ble_gap_periodic_adv_sync_create_cancel(void)3301 int ble_gap_periodic_adv_sync_create_cancel(void)
3302 {
3303 uint16_t opcode;
3304 int rc = 0;
3305 ble_hs_lock();
3306
3307 if (ble_gap_sync.op != BLE_GAP_OP_SYNC) {
3308 ble_hs_unlock();
3309 return BLE_HS_EBUSY;
3310 }
3311
3312 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
3313 BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL);
3314 rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0);
3315 ble_hs_unlock();
3316 return rc;
3317 }
3318
ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle)3319 int ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle)
3320 {
3321 struct ble_hci_le_periodic_adv_term_sync_cp cmd;
3322 struct ble_hs_periodic_sync *psync;
3323 uint16_t opcode;
3324 int rc;
3325 ble_hs_lock();
3326
3327 if (ble_gap_sync.op == BLE_GAP_OP_SYNC) {
3328 ble_hs_unlock();
3329 return BLE_HS_EBUSY;
3330 }
3331
3332 /* The handle must be in the list. If it doesn't exist, it means
3333 * that the sync may have been lost at the same moment in which
3334 * the app wants to terminate that sync handle
3335 */
3336 psync = ble_hs_periodic_sync_find_by_handle(sync_handle);
3337 if (!psync) {
3338 /* Sync already terminated. */
3339 ble_hs_unlock();
3340 return BLE_HS_ENOTCONN;
3341 }
3342
3343 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC);
3344 cmd.sync_handle = htole16(sync_handle);
3345 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3346 if (rc == 0) {
3347 /* Remove the handle from the list */
3348 ble_hs_periodic_sync_remove(psync);
3349 /* send sync_lost event, this is to mimic connection behavior and thus
3350 * simplify application error handling
3351 */
3352 ble_npl_eventq_put(ble_hs_evq_get(), &psync->lost_ev);
3353 }
3354
3355 ble_hs_unlock();
3356 return rc;
3357 }
3358 #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle,bool enable)3359 int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable)
3360 {
3361 struct ble_hci_le_periodic_adv_receive_enable_cp cmd;
3362 struct ble_hs_periodic_sync *psync;
3363 uint16_t opcode;
3364 int rc;
3365 ble_hs_lock();
3366
3367 if (ble_gap_sync.op == BLE_GAP_OP_SYNC) {
3368 ble_hs_unlock();
3369 return BLE_HS_EBUSY;
3370 }
3371
3372 psync = ble_hs_periodic_sync_find_by_handle(sync_handle);
3373 if (!psync) {
3374 ble_hs_unlock();
3375 return BLE_HS_ENOTCONN;
3376 }
3377
3378 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE);
3379 cmd.sync_handle = htole16(sync_handle);
3380 cmd.enable = enable ? 0x01 : 0x00;
3381 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3382 ble_hs_unlock();
3383 return rc;
3384 }
3385
ble_gap_periodic_adv_sync_transfer(uint16_t sync_handle,uint16_t conn_handle,uint16_t service_data)3386 int ble_gap_periodic_adv_sync_transfer(uint16_t sync_handle, uint16_t conn_handle, uint16_t service_data)
3387 {
3388 struct ble_hci_le_periodic_adv_sync_transfer_cp cmd;
3389 struct ble_hci_le_periodic_adv_sync_transfer_rp rsp;
3390 struct ble_hs_periodic_sync *psync;
3391 struct ble_hs_conn *conn;
3392 uint16_t opcode;
3393 int rc;
3394 ble_hs_lock();
3395 conn = ble_hs_conn_find(conn_handle);
3396 if (!conn) {
3397 ble_hs_unlock();
3398 return BLE_HS_ENOTCONN;
3399 }
3400
3401 psync = ble_hs_periodic_sync_find_by_handle(sync_handle);
3402 if (!psync) {
3403 ble_hs_unlock();
3404 return BLE_HS_ENOTCONN;
3405 }
3406
3407 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER);
3408 cmd.conn_handle = htole16(conn_handle);
3409 cmd.sync_handle = htole16(sync_handle);
3410 cmd.service_data = htole16(service_data);
3411 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
3412 if (!rc) {
3413 BLE_HS_DBG_ASSERT(le16toh(rsp.conn_handle) == conn_handle);
3414 }
3415
3416 ble_hs_unlock();
3417 return rc;
3418 }
3419
ble_gap_periodic_adv_sync_set_info(uint8_t instance,uint16_t conn_handle,uint16_t service_data)3420 int ble_gap_periodic_adv_sync_set_info(uint8_t instance, uint16_t conn_handle, uint16_t service_data)
3421 {
3422 struct ble_hci_le_periodic_adv_set_info_transfer_cp cmd;
3423 struct ble_hci_le_periodic_adv_set_info_transfer_rp rsp;
3424 struct ble_hs_conn *conn;
3425 uint16_t opcode;
3426 int rc;
3427
3428 if (instance >= BLE_ADV_INSTANCES) {
3429 return BLE_HS_EINVAL;
3430 }
3431
3432 ble_hs_lock();
3433
3434 if (ble_gap_slave[instance].periodic_op != BLE_GAP_OP_S_PERIODIC_ADV) {
3435 /* periodic adv not enabled */
3436 ble_hs_unlock();
3437 return BLE_HS_EINVAL;
3438 }
3439
3440 conn = ble_hs_conn_find(conn_handle);
3441 if (!conn) {
3442 ble_hs_unlock();
3443 return BLE_HS_ENOTCONN;
3444 }
3445
3446 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER);
3447 cmd.conn_handle = htole16(conn_handle);
3448 cmd.adv_handle = instance;
3449 cmd.service_data = htole16(service_data);
3450 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
3451 if (!rc) {
3452 BLE_HS_DBG_ASSERT(le16toh(rsp.conn_handle) == conn_handle);
3453 }
3454
3455 ble_hs_unlock();
3456 return rc;
3457 }
3458
periodic_adv_transfer_enable(uint16_t conn_handle,const struct ble_gap_periodic_sync_params * params)3459 static int periodic_adv_transfer_enable(uint16_t conn_handle,
3460 const struct ble_gap_periodic_sync_params *params)
3461 {
3462 struct ble_hci_le_periodic_adv_sync_transfer_params_cp cmd;
3463 struct ble_hci_le_periodic_adv_sync_transfer_params_rp rsp;
3464 uint16_t opcode;
3465 int rc;
3466 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS);
3467 cmd.conn_handle = htole16(conn_handle);
3468 cmd.sync_cte_type = 0x00;
3469 cmd.mode = params->reports_disabled ? 0x01 : 0x02;
3470 cmd.skip = htole16(params->skip);
3471 cmd.sync_timeout = htole16(params->sync_timeout);
3472 rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp));
3473 if (!rc) {
3474 BLE_HS_DBG_ASSERT(le16toh(rsp.conn_handle) == conn_handle);
3475 }
3476
3477 return rc;
3478 }
3479
ble_gap_periodic_adv_sync_receive(uint16_t conn_handle,const struct ble_gap_periodic_sync_params * params,ble_gap_event_fn * cb,void * cb_arg)3480 int ble_gap_periodic_adv_sync_receive(uint16_t conn_handle,
3481 const struct ble_gap_periodic_sync_params *params,
3482 ble_gap_event_fn *cb, void *cb_arg)
3483 {
3484 struct ble_hs_conn *conn;
3485 int rc;
3486 ble_hs_lock();
3487 conn = ble_hs_conn_find(conn_handle);
3488 if (!conn) {
3489 ble_hs_unlock();
3490 return BLE_HS_ENOTCONN;
3491 }
3492
3493 if (params) {
3494 if (conn->psync) {
3495 ble_hs_unlock();
3496 return BLE_HS_EALREADY;
3497 }
3498
3499 conn->psync = ble_hs_periodic_sync_alloc();
3500 if (!conn->psync) {
3501 ble_hs_unlock();
3502 return BLE_HS_ENOMEM;
3503 }
3504
3505 rc = periodic_adv_transfer_enable(conn_handle, params);
3506 if (rc) {
3507 ble_hs_periodic_sync_free(conn->psync);
3508 conn->psync = NULL;
3509 } else {
3510 conn->psync->cb = cb;
3511 conn->psync->cb_arg = cb_arg;
3512 ble_npl_event_init(&conn->psync->lost_ev, ble_gap_npl_sync_lost,
3513 conn->psync);
3514 }
3515 } else {
3516 if (!conn->psync) {
3517 ble_hs_unlock();
3518 return BLE_HS_EALREADY;
3519 }
3520
3521 rc = periodic_adv_transfer_disable(conn_handle);
3522 if (!rc) {
3523 ble_hs_periodic_sync_free(conn->psync);
3524 conn->psync = NULL;
3525 }
3526 }
3527
3528 ble_hs_unlock();
3529 return rc;
3530 }
3531 #endif
3532
ble_gap_add_dev_to_periodic_adv_list(const ble_addr_t * peer_addr,uint8_t adv_sid)3533 int ble_gap_add_dev_to_periodic_adv_list(const ble_addr_t *peer_addr, uint8_t adv_sid)
3534 {
3535 struct ble_hci_le_add_dev_to_periodic_adv_list_cp cmd;
3536 uint16_t opcode;
3537
3538 if ((peer_addr->type > BLE_ADDR_RANDOM) || (adv_sid > 0x0f)) {
3539 return BLE_ERR_INV_HCI_CMD_PARMS;
3540 }
3541
3542 cmd.peer_addr_type = peer_addr->type;
3543 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), peer_addr->val, BLE_DEV_ADDR_LEN);
3544 cmd.sid = adv_sid;
3545 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
3546 BLE_HCI_OCF_LE_ADD_DEV_TO_PERIODIC_ADV_LIST);
3547 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3548 }
3549
ble_gap_rem_dev_from_periodic_adv_list(const ble_addr_t * peer_addr,uint8_t adv_sid)3550 int ble_gap_rem_dev_from_periodic_adv_list(const ble_addr_t *peer_addr, uint8_t adv_sid)
3551 {
3552 struct ble_hci_le_rem_dev_from_periodic_adv_list_cp cmd;
3553 uint16_t opcode;
3554
3555 if ((peer_addr->type > BLE_ADDR_RANDOM) || (adv_sid > 0x0f)) {
3556 return BLE_ERR_INV_HCI_CMD_PARMS;
3557 }
3558
3559 cmd.peer_addr_type = peer_addr->type;
3560 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), peer_addr->val, BLE_DEV_ADDR_LEN);
3561 cmd.sid = adv_sid;
3562 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE,
3563 BLE_HCI_OCF_LE_REM_DEV_FROM_PERIODIC_ADV_LIST);
3564 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3565 }
3566
ble_gap_clear_periodic_adv_list(void)3567 int ble_gap_clear_periodic_adv_list(void)
3568 {
3569 uint16_t opcode;
3570 int rc = 0;
3571 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLEAR_PERIODIC_ADV_LIST);
3572 rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, NULL, 0);
3573 return rc;
3574 }
3575
ble_gap_read_periodic_adv_list_size(uint8_t * per_adv_list_size)3576 int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size)
3577 {
3578 struct ble_hci_le_rd_periodic_adv_list_size_rp rsp;
3579 uint16_t opcode;
3580 int rc = 0;
3581 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_PERIODIC_ADV_LIST_SIZE);
3582 rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, &rsp, sizeof(rsp));
3583 if (rc != 0) {
3584 return rc;
3585 }
3586
3587 *per_adv_list_size = rsp.list_size;
3588 return 0;
3589 }
3590 #endif
3591
3592 /*****************************************************************************
3593 * $discovery procedures *
3594 *****************************************************************************/
3595
3596 #if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
ble_gap_ext_disc_tx_params(uint8_t own_addr_type,uint8_t filter_policy,const struct ble_hs_hci_ext_scan_param * uncoded_params,const struct ble_hs_hci_ext_scan_param * coded_params)3597 static int ble_gap_ext_disc_tx_params(uint8_t own_addr_type, uint8_t filter_policy,
3598 const struct ble_hs_hci_ext_scan_param *uncoded_params,
3599 const struct ble_hs_hci_ext_scan_param *coded_params)
3600 {
3601 struct ble_hci_le_set_ext_scan_params_cp *cmd;
3602 struct scan_params *params;
3603 uint8_t buf[sizeof(*cmd) + 2 * sizeof(*params)]; // 2: byte alignment
3604 uint8_t len = sizeof(*cmd);
3605
3606 /* Check own addr type */
3607 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
3608 return BLE_ERR_INV_HCI_CMD_PARMS;
3609 }
3610
3611 /* Check scanner filter policy */
3612 if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
3613 return BLE_ERR_INV_HCI_CMD_PARMS;
3614 }
3615
3616 cmd = (void *) buf;
3617 params = cmd->scans;
3618 cmd->filter_policy = filter_policy;
3619 cmd->own_addr_type = own_addr_type;
3620 cmd->phys = 0;
3621
3622 if (uncoded_params) {
3623 cmd->phys |= BLE_HCI_LE_PHY_1M_PREF_MASK;
3624 params->type = uncoded_params->scan_type;
3625 params->itvl = htole16(uncoded_params->scan_itvl);
3626 params->window = htole16(uncoded_params->scan_window);
3627 len += sizeof(*params);
3628 params++;
3629 }
3630
3631 if (coded_params) {
3632 cmd->phys |= BLE_HCI_LE_PHY_CODED_PREF_MASK;
3633 params->type = coded_params->scan_type;
3634 params->itvl = htole16(coded_params->scan_itvl);
3635 params->window = htole16(coded_params->scan_window);
3636 len += sizeof(*params);
3637 params++;
3638 }
3639
3640 if (!cmd->phys) {
3641 return BLE_ERR_INV_HCI_CMD_PARMS;
3642 }
3643
3644 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM), cmd, len, NULL, 0);
3645 }
3646
ble_gap_ext_disc_enable_tx(uint8_t enable,uint8_t filter_duplicates,uint16_t duration,uint16_t period)3647 static int ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates,
3648 uint16_t duration, uint16_t period)
3649 {
3650 struct ble_hci_le_set_ext_scan_enable_cp cmd;
3651 cmd.enable = enable;
3652 cmd.filter_dup = filter_duplicates;
3653 cmd.duration = htole16(duration);
3654 cmd.period = htole16(period);
3655 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
3656 BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE), &cmd, sizeof(cmd), NULL, 0);
3657 }
3658 #endif
3659 #endif
3660 #if NIMBLE_BLE_SCAN
3661 #if !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_disc_enable_tx(int enable,int filter_duplicates)3662 static int ble_gap_disc_enable_tx(int enable, int filter_duplicates)
3663 {
3664 struct ble_hci_le_set_scan_enable_cp cmd;
3665 uint16_t opcode;
3666 cmd.enable = !!enable;
3667 cmd.filter_duplicates = !!filter_duplicates;
3668 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_ENABLE);
3669 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3670 }
3671
ble_gap_disc_tx_params(uint8_t own_addr_type,const struct ble_gap_disc_params * disc_params)3672 static int ble_gap_disc_tx_params(uint8_t own_addr_type, const struct ble_gap_disc_params *disc_params)
3673 {
3674 struct ble_hci_le_set_scan_params_cp cmd;
3675 uint16_t opcode;
3676
3677 if (disc_params->passive) {
3678 cmd.scan_type = BLE_HCI_SCAN_TYPE_PASSIVE;
3679 } else {
3680 cmd.scan_type = BLE_HCI_SCAN_TYPE_ACTIVE;
3681 }
3682
3683 cmd.scan_itvl = htole16(disc_params->itvl);
3684 cmd.scan_window = htole16(disc_params->window);
3685 cmd.own_addr_type = own_addr_type;
3686 cmd.filter_policy = disc_params->filter_policy;
3687 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_SCAN_PARAMS);
3688 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
3689 }
3690 #endif
3691
ble_gap_disc_disable_tx(void)3692 static int ble_gap_disc_disable_tx(void)
3693 {
3694 #if MYNEWT_VAL(BLE_EXT_ADV)
3695 return ble_gap_ext_disc_enable_tx(0, 0, 0, 0);
3696 #else
3697 return ble_gap_disc_enable_tx(0, 0);
3698 #endif
3699 }
3700
ble_gap_disc_cancel_no_lock(void)3701 static int ble_gap_disc_cancel_no_lock(void)
3702 {
3703 int rc;
3704 STATS_INC(ble_gap_stats, discover_cancel);
3705
3706 if (!ble_gap_disc_active()) {
3707 rc = BLE_HS_EALREADY;
3708 goto done;
3709 }
3710
3711 rc = ble_gap_disc_disable_tx();
3712 if (rc != 0) {
3713 goto done;
3714 }
3715
3716 ble_gap_master_reset_state();
3717 done:
3718
3719 if (rc != 0) {
3720 STATS_INC(ble_gap_stats, discover_cancel_fail);
3721 }
3722
3723 return rc;
3724 }
3725 #endif
3726
ble_gap_disc_cancel(void)3727 int ble_gap_disc_cancel(void)
3728 {
3729 #if NIMBLE_BLE_SCAN
3730 int rc;
3731 ble_hs_lock();
3732 rc = ble_gap_disc_cancel_no_lock();
3733 ble_hs_unlock();
3734 return rc;
3735 #else
3736 return BLE_HS_ENOTSUP;
3737 #endif
3738 }
3739
3740 #if NIMBLE_BLE_SCAN
ble_gap_disc_ext_validate(uint8_t own_addr_type)3741 static int ble_gap_disc_ext_validate(uint8_t own_addr_type)
3742 {
3743 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
3744 return BLE_HS_EINVAL;
3745 }
3746
3747 if (ble_gap_conn_active()) {
3748 return BLE_HS_EBUSY;
3749 }
3750
3751 if (ble_gap_disc_active()) {
3752 return BLE_HS_EALREADY;
3753 }
3754
3755 if (!ble_hs_is_enabled()) {
3756 return BLE_HS_EDISABLED;
3757 }
3758
3759 if (ble_gap_is_preempted()) {
3760 return BLE_HS_EPREEMPTED;
3761 }
3762
3763 return 0;
3764 }
3765 #endif
3766
3767 #if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN
ble_gap_ext_disc_fill_dflts(uint8_t limited,struct ble_hs_hci_ext_scan_param * disc_params)3768 static void ble_gap_ext_disc_fill_dflts(uint8_t limited, struct ble_hs_hci_ext_scan_param *disc_params)
3769 {
3770 if (disc_params->scan_itvl == 0) {
3771 if (limited) {
3772 disc_params->scan_itvl = BLE_GAP_LIM_DISC_SCAN_INT;
3773 } else {
3774 disc_params->scan_itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN;
3775 }
3776 }
3777
3778 if (disc_params->scan_window == 0) {
3779 if (limited) {
3780 disc_params->scan_window = BLE_GAP_LIM_DISC_SCAN_WINDOW;
3781 } else {
3782 disc_params->scan_window = BLE_GAP_SCAN_FAST_WINDOW;
3783 }
3784 }
3785 }
3786
ble_gap_ext_scan_params_to_hci(const struct ble_gap_ext_disc_params * params,struct ble_hs_hci_ext_scan_param * hci_params)3787 static void ble_gap_ext_scan_params_to_hci(const struct ble_gap_ext_disc_params *params,
3788 struct ble_hs_hci_ext_scan_param *hci_params)
3789 {
3790 memset_s(hci_params, sizeof(*hci_params), 0, sizeof(*hci_params));
3791
3792 if (params->passive) {
3793 hci_params->scan_type = BLE_HCI_SCAN_TYPE_PASSIVE;
3794 } else {
3795 hci_params->scan_type = BLE_HCI_SCAN_TYPE_ACTIVE;
3796 }
3797
3798 hci_params->scan_itvl = params->itvl;
3799 hci_params->scan_window = params->window;
3800 }
3801 #endif
3802
ble_gap_ext_disc(uint8_t own_addr_type,uint16_t duration,uint16_t period,uint8_t filter_duplicates,uint8_t filter_policy,uint8_t limited,const struct ble_gap_ext_disc_params * uncoded_params,const struct ble_gap_ext_disc_params * coded_params,ble_gap_event_fn * cb,void * cb_arg)3803 int ble_gap_ext_disc(uint8_t own_addr_type, uint16_t duration, uint16_t period,
3804 uint8_t filter_duplicates, uint8_t filter_policy,
3805 uint8_t limited,
3806 const struct ble_gap_ext_disc_params *uncoded_params,
3807 const struct ble_gap_ext_disc_params *coded_params,
3808 ble_gap_event_fn *cb, void *cb_arg)
3809 {
3810 #if NIMBLE_BLE_SCAN && MYNEWT_VAL(BLE_EXT_ADV)
3811 struct ble_hs_hci_ext_scan_param ucp;
3812 struct ble_hs_hci_ext_scan_param cp;
3813 int rc;
3814 STATS_INC(ble_gap_stats, discover);
3815 ble_hs_lock();
3816 rc = ble_gap_disc_ext_validate(own_addr_type);
3817 if (rc != 0) {
3818 goto done;
3819 }
3820
3821 /* Make a copy of the parameter structure and fill unspecified values with
3822 * defaults.
3823 */
3824
3825 if (uncoded_params) {
3826 ble_gap_ext_scan_params_to_hci(uncoded_params, &ucp);
3827 ble_gap_ext_disc_fill_dflts(limited, &ucp);
3828
3829 /* XXX: We should do it only once */
3830 if (!uncoded_params->passive) {
3831 rc = ble_hs_id_use_addr(own_addr_type);
3832 if (rc != 0) {
3833 goto done;
3834 }
3835 }
3836 }
3837
3838 if (coded_params) {
3839 ble_gap_ext_scan_params_to_hci(coded_params, &cp);
3840 ble_gap_ext_disc_fill_dflts(limited, &cp);
3841
3842 /* XXX: We should do it only once */
3843 if (!coded_params->passive) {
3844 rc = ble_hs_id_use_addr(own_addr_type);
3845 if (rc != 0) {
3846 goto done;
3847 }
3848 }
3849 }
3850
3851 ble_gap_master.disc.limited = limited;
3852 ble_gap_master.cb = cb;
3853 ble_gap_master.cb_arg = cb_arg;
3854 rc = ble_gap_ext_disc_tx_params(own_addr_type, filter_policy,
3855 uncoded_params ? &ucp : NULL,
3856 coded_params ? &cp : NULL);
3857 if (rc != 0) {
3858 goto done;
3859 }
3860
3861 ble_gap_master.op = BLE_GAP_OP_M_DISC;
3862 rc = ble_gap_ext_disc_enable_tx(1, filter_duplicates, duration, period);
3863 if (rc != 0) {
3864 ble_gap_master_reset_state();
3865 goto done;
3866 }
3867
3868 rc = 0;
3869 done:
3870 ble_hs_unlock();
3871
3872 if (rc != 0) {
3873 STATS_INC(ble_gap_stats, discover_fail);
3874 }
3875
3876 return rc;
3877 #else
3878 return BLE_HS_ENOTSUP;
3879 #endif
3880 }
3881
3882 #if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
ble_gap_disc_fill_dflts(struct ble_gap_disc_params * disc_params)3883 static void ble_gap_disc_fill_dflts(struct ble_gap_disc_params *disc_params)
3884 {
3885 if (disc_params->itvl == 0) {
3886 if (disc_params->limited) {
3887 disc_params->itvl = BLE_GAP_LIM_DISC_SCAN_INT;
3888 } else {
3889 disc_params->itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN;
3890 }
3891 }
3892
3893 if (disc_params->window == 0) {
3894 if (disc_params->limited) {
3895 disc_params->window = BLE_GAP_LIM_DISC_SCAN_WINDOW;
3896 } else {
3897 disc_params->window = BLE_GAP_SCAN_FAST_WINDOW;
3898 }
3899 }
3900 }
3901
ble_gap_disc_validate(uint8_t own_addr_type,const struct ble_gap_disc_params * disc_params)3902 static int ble_gap_disc_validate(uint8_t own_addr_type, const struct ble_gap_disc_params *disc_params)
3903 {
3904 if (disc_params == NULL) {
3905 return BLE_HS_EINVAL;
3906 }
3907
3908 /* Check interval and window */
3909 if ((disc_params->itvl < BLE_HCI_SCAN_ITVL_MIN) ||
3910 (disc_params->itvl > BLE_HCI_SCAN_ITVL_MAX) ||
3911 (disc_params->window < BLE_HCI_SCAN_WINDOW_MIN) ||
3912 (disc_params->window > BLE_HCI_SCAN_WINDOW_MAX) ||
3913 (disc_params->itvl < disc_params->window)) {
3914 return BLE_HS_EINVAL;
3915 }
3916
3917 /* Check scanner filter policy */
3918 if (disc_params->filter_policy > BLE_HCI_SCAN_FILT_MAX) {
3919 return BLE_HS_EINVAL;
3920 }
3921
3922 return ble_gap_disc_ext_validate(own_addr_type);
3923 }
3924 #endif
3925
ble_gap_disc(uint8_t own_addr_type,int32_t duration_ms,const struct ble_gap_disc_params * disc_params,ble_gap_event_fn * cb,void * cb_arg)3926 int ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
3927 const struct ble_gap_disc_params *disc_params,
3928 ble_gap_event_fn *cb, void *cb_arg)
3929 {
3930 #if NIMBLE_BLE_SCAN
3931 #if MYNEWT_VAL(BLE_EXT_ADV)
3932 struct ble_gap_ext_disc_params p = {0};
3933 p.itvl = disc_params->itvl;
3934 p.passive = disc_params->passive;
3935 p.window = disc_params->window;
3936
3937 if (duration_ms == BLE_HS_FOREVER) {
3938 duration_ms = 0;
3939 } else if (duration_ms == 0) {
3940 duration_ms = BLE_GAP_DISC_DUR_DFLT;
3941 }
3942
3943 return ble_gap_ext_disc(own_addr_type, duration_ms / 10, 0, // 10: byte alignment
3944 disc_params->filter_duplicates,
3945 disc_params->filter_policy, disc_params->limited,
3946 &p, NULL, cb, cb_arg);
3947 #else
3948 struct ble_gap_disc_params params;
3949 uint32_t duration_ticks = 0;
3950 int rc;
3951 STATS_INC(ble_gap_stats, discover);
3952 ble_hs_lock();
3953 /* Make a copy of the parameter strcuture and fill unspecified values with
3954 * defaults.
3955 */
3956 params = *disc_params;
3957 ble_gap_disc_fill_dflts(¶ms);
3958 rc = ble_gap_disc_validate(own_addr_type, ¶ms);
3959 if (rc != 0) {
3960 goto done;
3961 }
3962
3963 if (duration_ms == 0) {
3964 duration_ms = BLE_GAP_DISC_DUR_DFLT;
3965 }
3966
3967 if (duration_ms != BLE_HS_FOREVER) {
3968 rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
3969 if (rc != 0) {
3970 /* Duration too great. */
3971 rc = BLE_HS_EINVAL;
3972 goto done;
3973 }
3974 }
3975
3976 if (!params.passive) {
3977 rc = ble_hs_id_use_addr(own_addr_type);
3978 if (rc != 0) {
3979 goto done;
3980 }
3981 }
3982
3983 ble_gap_master.disc.limited = params.limited;
3984 ble_gap_master.cb = cb;
3985 ble_gap_master.cb_arg = cb_arg;
3986 BLE_HS_LOG(INFO, "GAP procedure initiated: discovery; ");
3987 ble_gap_log_disc(own_addr_type, duration_ms, ¶ms);
3988 BLE_HS_LOG(INFO, "\r\n");
3989 rc = ble_gap_disc_tx_params(own_addr_type, ¶ms);
3990 if (rc != 0) {
3991 goto done;
3992 }
3993
3994 ble_gap_master.op = BLE_GAP_OP_M_DISC;
3995 rc = ble_gap_disc_enable_tx(1, params.filter_duplicates);
3996 if (rc != 0) {
3997 ble_gap_master_reset_state();
3998 goto done;
3999 }
4000
4001 if (duration_ms != BLE_HS_FOREVER) {
4002 ble_gap_master_set_timer(duration_ticks);
4003 }
4004
4005 rc = 0;
4006 done:
4007 ble_hs_unlock();
4008
4009 if (rc != 0) {
4010 STATS_INC(ble_gap_stats, discover_fail);
4011 }
4012
4013 return rc;
4014 #endif
4015 #else
4016 return BLE_HS_ENOTSUP;
4017 #endif
4018 }
4019
ble_gap_disc_active(void)4020 int ble_gap_disc_active(void)
4021 {
4022 /* Assume read is atomic; mutex not necessary. */
4023 return ble_gap_master.op == BLE_GAP_OP_M_DISC;
4024 }
4025
4026 #if MYNEWT_VAL(BLE_ROLE_CENTRAL) && !MYNEWT_VAL(BLE_EXT_ADV)
4027 /*****************************************************************************
4028 * $connection establishment procedures *
4029 *****************************************************************************/
4030
ble_gap_conn_create_tx(uint8_t own_addr_type,const ble_addr_t * peer_addr,const struct ble_gap_conn_params * params)4031 static int ble_gap_conn_create_tx(uint8_t own_addr_type, const ble_addr_t *peer_addr,
4032 const struct ble_gap_conn_params *params)
4033 {
4034 struct ble_hci_le_create_conn_cp cmd;
4035 uint16_t opcode;
4036 cmd.scan_itvl = htole16(params->scan_itvl);
4037 cmd.scan_window = htole16(params->scan_window);
4038
4039 if (peer_addr == NULL) {
4040 /* Application wants to connect to any device in the white list. The
4041 * peer address type and peer address fields are ignored by the
4042 * controller; fill them with dummy values.
4043 */
4044 cmd.filter_policy = BLE_HCI_CONN_FILT_USE_WL;
4045 cmd.peer_addr_type = 0;
4046 memset_s(cmd.peer_addr, sizeof(cmd.peer_addr), 0, sizeof(cmd.peer_addr));
4047 } else {
4048 cmd.filter_policy = BLE_HCI_CONN_FILT_NO_WL;
4049 cmd.peer_addr_type = peer_addr->type;
4050 memcpy_s(cmd.peer_addr, sizeof(cmd.peer_addr), peer_addr->val, sizeof(cmd.peer_addr));
4051 }
4052
4053 cmd.own_addr_type = own_addr_type;
4054 cmd.min_conn_itvl = htole16(params->itvl_min);
4055 cmd.max_conn_itvl = htole16(params->itvl_max);
4056 cmd.conn_latency = htole16(params->latency);
4057 cmd.tmo = htole16(params->supervision_timeout);
4058 cmd.min_ce = htole16(params->min_ce_len);
4059 cmd.max_ce = htole16(params->max_ce_len);
4060 opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN);
4061 return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0);
4062 }
4063 #endif
4064
4065 #if MYNEWT_VAL(BLE_EXT_ADV)
4066 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
ble_gap_check_conn_params(uint8_t phy,const struct ble_gap_conn_params * params)4067 static int ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params)
4068 {
4069 if (phy != BLE_HCI_LE_PHY_2M) {
4070 /* Check scan interval and window */
4071 if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
4072 (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
4073 (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
4074 (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
4075 (params->scan_itvl < params->scan_window)) {
4076 return BLE_ERR_INV_HCI_CMD_PARMS;
4077 }
4078 }
4079
4080 /* Check connection interval min */
4081 if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
4082 (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) {
4083 return BLE_ERR_INV_HCI_CMD_PARMS;
4084 }
4085
4086 /* Check connection interval max */
4087 if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) ||
4088 (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
4089 (params->itvl_max < params->itvl_min)) {
4090 return BLE_ERR_INV_HCI_CMD_PARMS;
4091 }
4092
4093 /* Check connection latency */
4094 if ((params->latency < BLE_HCI_CONN_LATENCY_MIN) ||
4095 (params->latency > BLE_HCI_CONN_LATENCY_MAX)) {
4096 return BLE_ERR_INV_HCI_CMD_PARMS;
4097 }
4098
4099 /* Check supervision timeout */
4100 if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
4101 (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
4102 return BLE_ERR_INV_HCI_CMD_PARMS;
4103 }
4104
4105 /* Check connection event length */
4106 if (params->min_ce_len > params->max_ce_len) {
4107 return BLE_ERR_INV_HCI_CMD_PARMS;
4108 }
4109
4110 return 0;
4111 }
4112
ble_gap_ext_conn_create_tx(uint8_t own_addr_type,const ble_addr_t * peer_addr,uint8_t phy_mask,const struct ble_gap_conn_params * phy_1m_conn_params,const struct ble_gap_conn_params * phy_2m_conn_params,const struct ble_gap_conn_params * phy_coded_conn_params)4113 static int ble_gap_ext_conn_create_tx(
4114 uint8_t own_addr_type, const ble_addr_t *peer_addr, uint8_t phy_mask,
4115 const struct ble_gap_conn_params *phy_1m_conn_params,
4116 const struct ble_gap_conn_params *phy_2m_conn_params,
4117 const struct ble_gap_conn_params *phy_coded_conn_params)
4118 {
4119 struct ble_hci_le_ext_create_conn_cp *cmd;
4120 struct conn_params *params;
4121 uint8_t buf[sizeof(*cmd) + 3 * sizeof(*params)]; // 3:byte alignment
4122 uint8_t len = sizeof(*cmd);
4123 int rc;
4124
4125 /* Check own addr type */
4126 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
4127 return BLE_ERR_INV_HCI_CMD_PARMS;
4128 }
4129
4130 if (phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
4131 BLE_HCI_LE_PHY_2M_PREF_MASK |
4132 BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
4133 return BLE_ERR_INV_HCI_CMD_PARMS;
4134 }
4135
4136 cmd = (void *) buf;
4137 params = cmd->conn_params;
4138
4139 if (peer_addr == NULL) {
4140 /* Application wants to connect to any device in the white list. The
4141 * peer address type and peer address fields are ignored by the
4142 * controller; fill them with dummy values.
4143 */
4144 cmd->filter_policy = BLE_HCI_CONN_FILT_USE_WL;
4145 cmd->peer_addr_type = 0;
4146 memset_s(cmd->peer_addr, sizeof(cmd->peer_addr), 0, sizeof(cmd->peer_addr));
4147 } else {
4148 /* Check peer addr type */
4149 if (peer_addr->type > BLE_HCI_CONN_PEER_ADDR_MAX) {
4150 return BLE_ERR_INV_HCI_CMD_PARMS;
4151 }
4152
4153 cmd->filter_policy = BLE_HCI_CONN_FILT_NO_WL;
4154 cmd->peer_addr_type = peer_addr->type;
4155 memcpy_s(cmd->peer_addr, sizeof(cmd->peer_addr), peer_addr->val, sizeof(cmd->peer_addr));
4156 }
4157
4158 cmd->own_addr_type = own_addr_type;
4159 cmd->init_phy_mask = phy_mask;
4160
4161 if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) {
4162 rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_1M, phy_1m_conn_params);
4163 if (rc) {
4164 return rc;
4165 }
4166
4167 params->scan_itvl = htole16(phy_1m_conn_params->scan_itvl);
4168 params->scan_window = htole16(phy_1m_conn_params->scan_window);
4169 params->conn_min_itvl = htole16(phy_1m_conn_params->itvl_min);
4170 params->conn_max_itvl = htole16(phy_1m_conn_params->itvl_max);
4171 params->conn_latency = htole16(phy_1m_conn_params->latency);
4172 params->supervision_timeout = htole16(phy_1m_conn_params->supervision_timeout);
4173 params->min_ce = htole16(phy_1m_conn_params->min_ce_len);
4174 params->max_ce = htole16(phy_1m_conn_params->max_ce_len);
4175 params++;
4176 len += sizeof(*params);
4177 }
4178
4179 if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) {
4180 rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_2M, phy_2m_conn_params);
4181 if (rc) {
4182 return rc;
4183 }
4184
4185 params->scan_itvl = htole16(phy_2m_conn_params->scan_itvl);
4186 params->scan_window = htole16(phy_2m_conn_params->scan_window);
4187 params->conn_min_itvl = htole16(phy_2m_conn_params->itvl_min);
4188 params->conn_max_itvl = htole16(phy_2m_conn_params->itvl_max);
4189 params->conn_latency = htole16(phy_2m_conn_params->latency);
4190 params->supervision_timeout = htole16(phy_2m_conn_params->supervision_timeout);
4191 params->min_ce = htole16(phy_2m_conn_params->min_ce_len);
4192 params->max_ce = htole16(phy_2m_conn_params->max_ce_len);
4193 params++;
4194 len += sizeof(*params);
4195 }
4196
4197 if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) {
4198 rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_CODED, phy_coded_conn_params);
4199 if (rc) {
4200 return rc;
4201 }
4202
4203 params->scan_itvl = htole16(phy_coded_conn_params->scan_itvl);
4204 params->scan_window = htole16(phy_coded_conn_params->scan_window);
4205 params->conn_min_itvl = htole16(phy_coded_conn_params->itvl_min);
4206 params->conn_max_itvl = htole16(phy_coded_conn_params->itvl_max);
4207 params->conn_latency = htole16(phy_coded_conn_params->latency);
4208 params->supervision_timeout = htole16(phy_coded_conn_params->supervision_timeout);
4209 params->min_ce = htole16(phy_coded_conn_params->min_ce_len);
4210 params->max_ce = htole16(phy_coded_conn_params->max_ce_len);
4211 params++;
4212 len += sizeof(*params);
4213 }
4214
4215 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
4216 BLE_HCI_OCF_LE_EXT_CREATE_CONN),
4217 cmd, len, NULL, 0);
4218 }
4219 #endif
4220
4221 /**
4222 * Initiates a connect procedure.
4223 *
4224 * @param own_addr_type The type of address the stack should use for
4225 * itself during connection establishment.
4226 * o BLE_OWN_ADDR_PUBLIC
4227 * o BLE_OWN_ADDR_RANDOM
4228 * o BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT
4229 * o BLE_OWN_ADDR_RPA_RANDOM_DEFAULT
4230 * @param peer_addr The address of the peer to connect to.
4231 * If this parameter is NULL, the white list
4232 * is used.
4233 * @param duration_ms The duration of the discovery procedure.
4234 * On expiration, the procedure ends and a
4235 * BLE_GAP_EVENT_DISC_COMPLETE event is
4236 * reported. Units are milliseconds.
4237 * @param phy_mask Define on which PHYs connection attempt should
4238 * be done
4239 * @param phy_1m_conn_params Additional arguments specifying the
4240 * particulars of the connect procedure. When
4241 * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask
4242 * this parameter can be specify to null for
4243 * default values.
4244 * @param phy_2m_conn_params Additional arguments specifying the
4245 * particulars of the connect procedure. When
4246 * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask
4247 * this parameter can be specify to null for
4248 * default values.
4249 * @param phy_coded_conn_params Additional arguments specifying the
4250 * particulars of the connect procedure. When
4251 * BLE_GAP_LE_PHY_CODED_MASK is set in
4252 * phy_mask this parameter can be specify to
4253 * null for default values.
4254 * @param cb The callback to associate with this connect
4255 * procedure. When the connect procedure
4256 * completes, the result is reported through
4257 * this callback. If the connect procedure
4258 * succeeds, the connection inherits this
4259 * callback as its event-reporting mechanism.
4260 * @param cb_arg The optional argument to pass to the callback
4261 * function.
4262 *
4263 * @return 0 on success;
4264 * BLE_HS_EALREADY if a connection attempt is
4265 * already in progress;
4266 * BLE_HS_EBUSY if initiating a connection is not
4267 * possible because scanning is in progress;
4268 * BLE_HS_EDONE if the specified peer is already
4269 * connected;
4270 * Other nonzero on error.
4271 */
ble_gap_ext_connect(uint8_t own_addr_type,const ble_addr_t * peer_addr,int32_t duration_ms,uint8_t phy_mask,const struct ble_gap_conn_params * phy_1m_conn_params,const struct ble_gap_conn_params * phy_2m_conn_params,const struct ble_gap_conn_params * phy_coded_conn_params,ble_gap_event_fn * cb,void * cb_arg)4272 int ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
4273 int32_t duration_ms, uint8_t phy_mask,
4274 const struct ble_gap_conn_params *phy_1m_conn_params,
4275 const struct ble_gap_conn_params *phy_2m_conn_params,
4276 const struct ble_gap_conn_params *phy_coded_conn_params,
4277 ble_gap_event_fn *cb, void *cb_arg)
4278 {
4279 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
4280 ble_npl_time_t duration_ticks;
4281 int rc;
4282 STATS_INC(ble_gap_stats, initiate);
4283 ble_hs_lock();
4284
4285 if (ble_gap_conn_active()) {
4286 rc = BLE_HS_EALREADY;
4287 goto done;
4288 }
4289
4290 if (ble_gap_disc_active()) {
4291 rc = BLE_HS_EBUSY;
4292 goto done;
4293 }
4294
4295 if (!ble_hs_is_enabled()) {
4296 return BLE_HS_EDISABLED;
4297 }
4298
4299 if (ble_gap_is_preempted()) {
4300 rc = BLE_HS_EPREEMPTED;
4301 goto done;
4302 }
4303
4304 if (!ble_hs_conn_can_alloc()) {
4305 rc = BLE_HS_ENOMEM;
4306 goto done;
4307 }
4308
4309 if (peer_addr &&
4310 peer_addr->type != BLE_ADDR_PUBLIC &&
4311 peer_addr->type != BLE_ADDR_RANDOM &&
4312 peer_addr->type != BLE_ADDR_PUBLIC_ID &&
4313 peer_addr->type != BLE_ADDR_RANDOM_ID) {
4314 rc = BLE_HS_EINVAL;
4315 goto done;
4316 }
4317
4318 if ((phy_mask & BLE_GAP_LE_PHY_1M_MASK) && phy_1m_conn_params == NULL) {
4319 phy_1m_conn_params = &ble_gap_conn_params_dflt;
4320 }
4321
4322 if ((phy_mask & BLE_GAP_LE_PHY_2M_MASK) && phy_2m_conn_params == NULL) {
4323 phy_2m_conn_params = &ble_gap_conn_params_dflt;
4324 }
4325
4326 if ((phy_mask & BLE_GAP_LE_PHY_CODED_MASK) &&
4327 phy_coded_conn_params == NULL) {
4328 phy_coded_conn_params = &ble_gap_conn_params_dflt;
4329 }
4330
4331 if (duration_ms == 0) {
4332 duration_ms = BLE_GAP_CONN_DUR_DFLT;
4333 }
4334
4335 if (duration_ms != BLE_HS_FOREVER) {
4336 rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
4337 if (rc != 0) {
4338 /* Duration too great. */
4339 rc = BLE_HS_EINVAL;
4340 goto done;
4341 }
4342 }
4343
4344 /* Verify peer not already connected. */
4345 if (ble_hs_conn_find_by_addr(peer_addr) != NULL) {
4346 rc = BLE_HS_EDONE;
4347 goto done;
4348 }
4349
4350 /* XXX: Verify conn_params. */
4351 rc = ble_hs_id_use_addr(own_addr_type);
4352 if (rc != 0) {
4353 goto done;
4354 }
4355
4356 ble_gap_master.cb = cb;
4357 ble_gap_master.cb_arg = cb_arg;
4358 ble_gap_master.conn.using_wl = peer_addr == NULL;
4359 ble_gap_master.conn.our_addr_type = own_addr_type;
4360 ble_gap_master.op = BLE_GAP_OP_M_CONN;
4361 rc = ble_gap_ext_conn_create_tx(own_addr_type, peer_addr, phy_mask,
4362 phy_1m_conn_params, phy_2m_conn_params,
4363 phy_coded_conn_params);
4364 if (rc != 0) {
4365 ble_gap_master_reset_state();
4366 goto done;
4367 }
4368
4369 if (duration_ms != BLE_HS_FOREVER) {
4370 ble_gap_master_set_timer(duration_ticks);
4371 }
4372
4373 rc = 0;
4374 done:
4375 ble_hs_unlock();
4376
4377 if (rc != 0) {
4378 STATS_INC(ble_gap_stats, initiate_fail);
4379 }
4380
4381 return rc;
4382 #else
4383 return BLE_HS_ENOTSUP;
4384 #endif
4385 }
4386 #endif
4387
ble_gap_connect(uint8_t own_addr_type,const ble_addr_t * peer_addr,int32_t duration_ms,const struct ble_gap_conn_params * conn_params,ble_gap_event_fn * cb,void * cb_arg)4388 int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
4389 int32_t duration_ms,
4390 const struct ble_gap_conn_params *conn_params,
4391 ble_gap_event_fn *cb, void *cb_arg)
4392 {
4393 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
4394 #if MYNEWT_VAL(BLE_EXT_ADV)
4395 return ble_gap_ext_connect(own_addr_type, peer_addr, duration_ms,
4396 BLE_GAP_LE_PHY_1M_MASK,
4397 conn_params, NULL, NULL, cb, cb_arg);
4398 #else
4399 uint32_t duration_ticks;
4400 int rc;
4401 STATS_INC(ble_gap_stats, initiate);
4402 ble_hs_lock();
4403
4404 if (ble_gap_conn_active()) {
4405 rc = BLE_HS_EALREADY;
4406 goto done;
4407 }
4408
4409 if (ble_gap_disc_active()) {
4410 rc = BLE_HS_EBUSY;
4411 goto done;
4412 }
4413
4414 if (!ble_hs_is_enabled()) {
4415 rc = BLE_HS_EDISABLED;
4416 goto done;
4417 }
4418
4419 if (ble_gap_is_preempted()) {
4420 rc = BLE_HS_EPREEMPTED;
4421 goto done;
4422 }
4423
4424 if (!ble_hs_conn_can_alloc()) {
4425 rc = BLE_HS_ENOMEM;
4426 goto done;
4427 }
4428
4429 if (peer_addr &&
4430 peer_addr->type != BLE_ADDR_PUBLIC &&
4431 peer_addr->type != BLE_ADDR_RANDOM &&
4432 peer_addr->type != BLE_ADDR_PUBLIC_ID &&
4433 peer_addr->type != BLE_ADDR_RANDOM_ID) {
4434 rc = BLE_HS_EINVAL;
4435 goto done;
4436 }
4437
4438 if (conn_params == NULL) {
4439 conn_params = &ble_gap_conn_params_dflt;
4440 }
4441
4442 if (duration_ms == 0) {
4443 duration_ms = BLE_GAP_CONN_DUR_DFLT;
4444 }
4445
4446 if (duration_ms != BLE_HS_FOREVER) {
4447 rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks);
4448 if (rc != 0) {
4449 /* Duration too great. */
4450 rc = BLE_HS_EINVAL;
4451 goto done;
4452 }
4453 }
4454
4455 /* Verify peer not already connected. */
4456 if (ble_hs_conn_find_by_addr(peer_addr) != NULL) {
4457 rc = BLE_HS_EDONE;
4458 goto done;
4459 }
4460
4461 /* XXX: Verify conn_params. */
4462 rc = ble_hs_id_use_addr(own_addr_type);
4463 if (rc != 0) {
4464 goto done;
4465 }
4466
4467 BLE_HS_LOG(INFO, "GAP procedure initiated: connect; ");
4468 ble_gap_log_conn(own_addr_type, peer_addr, conn_params);
4469 BLE_HS_LOG(INFO, "\r\n");
4470 ble_gap_master.cb = cb;
4471 ble_gap_master.cb_arg = cb_arg;
4472 ble_gap_master.conn.using_wl = peer_addr == NULL;
4473 ble_gap_master.conn.our_addr_type = own_addr_type;
4474 ble_gap_master.op = BLE_GAP_OP_M_CONN;
4475 rc = ble_gap_conn_create_tx(own_addr_type, peer_addr,
4476 conn_params);
4477 if (rc != 0) {
4478 ble_gap_master_reset_state();
4479 goto done;
4480 }
4481
4482 if (duration_ms != BLE_HS_FOREVER) {
4483 ble_gap_master_set_timer(duration_ticks);
4484 }
4485
4486 rc = 0;
4487 done:
4488 ble_hs_unlock();
4489
4490 if (rc != 0) {
4491 STATS_INC(ble_gap_stats, initiate_fail);
4492 }
4493
4494 return rc;
4495 #endif
4496 #else
4497 return BLE_HS_ENOTSUP;
4498 #endif
4499 }
4500
ble_gap_init_conn_params(struct ble_gap_conn_params * conn_params)4501 void ble_gap_init_conn_params(struct ble_gap_conn_params *conn_params)
4502 {
4503 memcpy_s(conn_params, sizeof(conn_params), &ble_gap_conn_params_dflt, sizeof(struct ble_gap_conn_params));
4504 }
4505
ble_gap_conn_active(void)4506 int ble_gap_conn_active(void)
4507 {
4508 /* Assume read is atomic; mutex not necessary. */
4509 return ble_gap_master.op == BLE_GAP_OP_M_CONN;
4510 }
4511
4512 /*****************************************************************************
4513 * $terminate connection procedure *
4514 *****************************************************************************/
ble_gap_terminate_with_conn(struct ble_hs_conn * conn,uint8_t hci_reason)4515 int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason)
4516 {
4517 struct ble_hci_lc_disconnect_cp cmd;
4518 int rc;
4519 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
4520
4521 if (conn->bhc_flags & BLE_HS_CONN_F_TERMINATING) {
4522 return BLE_HS_EALREADY;
4523 }
4524
4525 BLE_HS_LOG(INFO, "GAP procedure initiated: terminate connection; "
4526 "conn_handle=%d hci_reason=%d\r\n",
4527 conn->bhc_handle, hci_reason);
4528 cmd.conn_handle = htole16(conn->bhc_handle);
4529 cmd.reason = hci_reason;
4530 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL,
4531 BLE_HCI_OCF_DISCONNECT_CMD),
4532 &cmd, sizeof(cmd), NULL, 0);
4533 if (rc != 0) {
4534 return rc;
4535 }
4536
4537 conn->bhc_flags |= BLE_HS_CONN_F_TERMINATING;
4538 return 0;
4539 }
4540
ble_gap_terminate(uint16_t conn_handle,uint8_t hci_reason)4541 int ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason)
4542 {
4543 struct ble_hs_conn *conn;
4544 int rc;
4545 STATS_INC(ble_gap_stats, terminate);
4546 ble_hs_lock();
4547 conn = ble_hs_conn_find(conn_handle);
4548 if (conn == NULL) {
4549 rc = BLE_HS_ENOTCONN;
4550 goto done;
4551 }
4552
4553 rc = ble_gap_terminate_with_conn(conn, hci_reason);
4554 done:
4555 ble_hs_unlock();
4556
4557 if (rc != 0) {
4558 STATS_INC(ble_gap_stats, terminate_fail);
4559 }
4560
4561 return rc;
4562 }
4563
ble_gap_set_data_length(uint16_t conn_handle,uint16_t tx_octets,uint16_t tx_time)4564 int ble_gap_set_data_length(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time)
4565 {
4566 int rc;
4567 ble_hs_lock();
4568 rc = ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time);
4569 ble_hs_unlock();
4570 return rc;
4571 }
4572
4573 /*****************************************************************************
4574 * $cancel *
4575 *****************************************************************************/
4576
ble_gap_conn_cancel_tx(void)4577 static int ble_gap_conn_cancel_tx(void)
4578 {
4579 int rc;
4580 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
4581 BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
4582 NULL, 0, NULL, 0);
4583 if (rc != 0) {
4584 return rc;
4585 }
4586
4587 return 0;
4588 }
4589
4590 #if NIMBLE_BLE_CONNECT
ble_gap_conn_cancel_no_lock(void)4591 static int ble_gap_conn_cancel_no_lock(void)
4592 {
4593 int rc;
4594 STATS_INC(ble_gap_stats, cancel);
4595
4596 if (!ble_gap_conn_active()) {
4597 rc = BLE_HS_EALREADY;
4598 goto done;
4599 }
4600
4601 BLE_HS_LOG(INFO, "GAP procedure initiated: cancel connection\r\n");
4602 rc = ble_gap_conn_cancel_tx();
4603 if (rc != 0) {
4604 goto done;
4605 }
4606
4607 ble_gap_master.conn.cancel = 1;
4608 rc = 0;
4609 done:
4610
4611 if (rc != 0) {
4612 STATS_INC(ble_gap_stats, cancel_fail);
4613 }
4614
4615 return rc;
4616 }
4617 #endif
4618
ble_gap_conn_cancel(void)4619 int ble_gap_conn_cancel(void)
4620 {
4621 #if MYNEWT_VAL(BLE_ROLE_CENTRAL)
4622 int rc;
4623 ble_hs_lock();
4624 rc = ble_gap_conn_cancel_no_lock();
4625 ble_hs_unlock();
4626 return rc;
4627 #else
4628 return BLE_HS_ENOTSUP;
4629 #endif
4630 }
4631
4632 /*****************************************************************************
4633 * $update connection parameters *
4634 *****************************************************************************/
4635
4636 #if NIMBLE_BLE_CONNECT
ble_gap_update_entry_alloc(void)4637 static struct ble_gap_update_entry *ble_gap_update_entry_alloc(void)
4638 {
4639 struct ble_gap_update_entry *entry;
4640 entry = os_memblock_get(&ble_gap_update_entry_pool);
4641 if (entry != NULL) {
4642 memset_s(entry, sizeof(*entry), 0, sizeof(*entry));
4643 }
4644
4645 return entry;
4646 }
4647 #endif
4648
ble_gap_update_entry_free(struct ble_gap_update_entry * entry)4649 static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry)
4650 {
4651 if (entry != NULL) {
4652 #if MYNEWT_VAL(BLE_HS_DEBUG)
4653 memset_s(entry, sizeof(*entry), 0xff, sizeof(*entry));
4654 #endif
4655 int rc = os_memblock_put(&ble_gap_update_entry_pool, entry);
4656 BLE_HS_DBG_ASSERT_EVAL(rc == 0);
4657 }
4658 }
4659
ble_gap_update_entry_find(uint16_t conn_handle,struct ble_gap_update_entry ** out_prev)4660 static struct ble_gap_update_entry *ble_gap_update_entry_find(uint16_t conn_handle,
4661 struct ble_gap_update_entry **out_prev)
4662 {
4663 struct ble_gap_update_entry *entry;
4664 struct ble_gap_update_entry *prev;
4665 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
4666 prev = NULL;
4667 SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
4668 if (entry->conn_handle == conn_handle) {
4669 break;
4670 }
4671
4672 prev = entry;
4673 }
4674
4675 if (out_prev != NULL) {
4676 *out_prev = prev;
4677 }
4678
4679 return entry;
4680 }
4681
ble_gap_update_entry_remove(uint16_t conn_handle)4682 static struct ble_gap_update_entry *ble_gap_update_entry_remove(uint16_t conn_handle)
4683 {
4684 struct ble_gap_update_entry *entry;
4685 struct ble_gap_update_entry *prev;
4686 entry = ble_gap_update_entry_find(conn_handle, &prev);
4687 if (entry != NULL) {
4688 if (prev == NULL) {
4689 SLIST_REMOVE_HEAD(&ble_gap_update_entries, next);
4690 } else {
4691 SLIST_NEXT(prev, next) = SLIST_NEXT(entry, next);
4692 }
4693
4694 ble_hs_timer_resched();
4695 }
4696
4697 return entry;
4698 }
4699
4700 #if NIMBLE_BLE_CONNECT
ble_gap_update_l2cap_cb(uint16_t conn_handle,int status,void * arg)4701 static void ble_gap_update_l2cap_cb(uint16_t conn_handle, int status, void *arg)
4702 {
4703 struct ble_gap_update_entry *entry;
4704 /* Report failures and rejections. Success gets reported when the
4705 * controller sends the connection update complete event.
4706 */
4707 ble_hs_lock();
4708 entry = ble_gap_update_entry_remove(conn_handle);
4709 ble_hs_unlock();
4710
4711 if (entry != NULL) {
4712 ble_gap_update_entry_free(entry);
4713
4714 if (status != 0) {
4715 ble_gap_update_notify(conn_handle, status);
4716 }
4717
4718 /* On success let's wait for the controller to notify about update */
4719 }
4720 }
4721
ble_gap_tx_param_pos_reply(uint16_t conn_handle,struct ble_gap_upd_params * params)4722 static int ble_gap_tx_param_pos_reply(uint16_t conn_handle, struct ble_gap_upd_params *params)
4723 {
4724 struct ble_hci_le_rem_conn_param_rr_cp cmd;
4725 cmd.conn_handle = htole16(conn_handle);
4726 cmd.conn_itvl_min = htole16(params->itvl_min);
4727 cmd.conn_itvl_max = htole16(params->itvl_max);
4728 cmd.conn_latency = htole16(params->latency);
4729 cmd.supervision_timeout = htole16(params->supervision_timeout);
4730 cmd.min_ce = htole16(params->min_ce_len);
4731 cmd.max_ce = htole16(params->max_ce_len);
4732 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_REM_CONN_PARAM_RR), &cmd, sizeof(cmd), NULL, 0);
4733 }
4734
ble_gap_tx_param_neg_reply(uint16_t conn_handle,uint8_t reject_reason)4735 static int ble_gap_tx_param_neg_reply(uint16_t conn_handle, uint8_t reject_reason)
4736 {
4737 struct ble_hci_le_rem_conn_params_nrr_cp cmd;
4738 cmd.conn_handle = htole16(conn_handle);
4739 cmd.reason = reject_reason;
4740 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
4741 BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR), &cmd, sizeof(cmd), NULL, 0);
4742 }
4743 #endif
4744
ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req * ev)4745 void ble_gap_rx_param_req(const struct ble_hci_ev_le_subev_rem_conn_param_req *ev)
4746 {
4747 #if NIMBLE_BLE_CONNECT
4748 struct ble_gap_upd_params peer_params;
4749 struct ble_gap_upd_params self_params;
4750 struct ble_gap_event event;
4751 uint16_t conn_handle;
4752 int rc;
4753 memset_s(&event, sizeof(event), 0, sizeof(event));
4754 peer_params.itvl_min = le16toh(ev->min_interval);
4755 peer_params.itvl_max = le16toh(ev->max_interval);
4756 peer_params.latency = le16toh(ev->latency);
4757 peer_params.supervision_timeout = le16toh(ev->timeout);
4758 peer_params.min_ce_len = 0;
4759 peer_params.max_ce_len = 0;
4760 /* Copy the peer params into the self params to make it easy on the
4761 * application. The application callback will change only the fields which
4762 * it finds unsuitable.
4763 */
4764 self_params = peer_params;
4765 conn_handle = le16toh(ev->conn_handle);
4766 memset_s(&event, sizeof(event), 0, sizeof(event));
4767 event.type = BLE_GAP_EVENT_CONN_UPDATE_REQ;
4768 event.conn_update_req.conn_handle = conn_handle;
4769 event.conn_update_req.self_params = &self_params;
4770 event.conn_update_req.peer_params = &peer_params;
4771 rc = ble_gap_call_conn_event_cb(&event, conn_handle);
4772 if (rc == 0) {
4773 rc = ble_gap_tx_param_pos_reply(conn_handle, &self_params);
4774 if (rc != 0) {
4775 ble_gap_update_failed(conn_handle, rc);
4776 }
4777 } else {
4778 ble_gap_tx_param_neg_reply(conn_handle, rc);
4779 }
4780
4781 #endif
4782 }
4783
4784 #if NIMBLE_BLE_CONNECT
ble_gap_update_tx(uint16_t conn_handle,const struct ble_gap_upd_params * params)4785 static int ble_gap_update_tx(uint16_t conn_handle, const struct ble_gap_upd_params *params)
4786 {
4787 struct ble_hci_le_conn_update_cp cmd;
4788 cmd.conn_handle = htole16(conn_handle);
4789 cmd.conn_itvl_min = htole16(params->itvl_min);
4790 cmd.conn_itvl_max = htole16(params->itvl_max);
4791 cmd.conn_latency = htole16(params->latency);
4792 cmd.supervision_timeout = htole16(params->supervision_timeout);
4793 cmd.min_ce_len = htole16(params->min_ce_len);
4794 cmd.max_ce_len = htole16(params->max_ce_len);
4795 return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CONN_UPDATE), &cmd, sizeof(cmd), NULL, 0);
4796 }
4797
ble_gap_validate_conn_params(const struct ble_gap_upd_params * params)4798 static bool ble_gap_validate_conn_params(const struct ble_gap_upd_params *params)
4799 {
4800 /* Requirements from Bluetooth spec. v4.2 [Vol 2, Part E], 7.8.18 */
4801 if (params->itvl_min > params->itvl_max) {
4802 return false;
4803 }
4804
4805 if (params->itvl_min < 0x0006 || params->itvl_max > 0x0C80) {
4806 return false;
4807 }
4808
4809 if (params->latency > 0x01F3) {
4810 return false;
4811 }
4812
4813 /* According to specification mentioned above we should make sure that:
4814 * supervision_timeout_ms > (1 + latency) * 2 * max_interval_ms
4815 * =>
4816 * supervision_timeout * 10 ms > (1 + latency) * 2 * itvl_max * 1.25ms
4817 */
4818 if (params->supervision_timeout <=
4819 (((1 + params->latency) * params->itvl_max) / 4)) { // 4:byte alignment
4820 return false;
4821 }
4822
4823 return true;
4824 }
4825 #endif
4826
ble_gap_update_params(uint16_t conn_handle,const struct ble_gap_upd_params * params)4827 int ble_gap_update_params(uint16_t conn_handle, const struct ble_gap_upd_params *params)
4828 {
4829 #if NIMBLE_BLE_CONNECT
4830 struct ble_l2cap_sig_update_params l2cap_params;
4831 struct ble_gap_update_entry *entry;
4832 struct ble_gap_update_entry *dup;
4833 struct ble_hs_conn *conn;
4834 int l2cap_update;
4835 int rc;
4836 l2cap_update = 0;
4837
4838 /* Validate parameters with a spec */
4839 if (!ble_gap_validate_conn_params(params)) {
4840 return BLE_HS_EINVAL;
4841 }
4842
4843 STATS_INC(ble_gap_stats, update);
4844 memset_s(&l2cap_params, sizeof(l2cap_params), 0, sizeof(l2cap_params));
4845 entry = NULL;
4846 ble_hs_lock();
4847 conn = ble_hs_conn_find(conn_handle);
4848 if (conn == NULL) {
4849 rc = BLE_HS_ENOTCONN;
4850 goto done;
4851 }
4852
4853 /* Don't allow two concurrent updates to the same connection. */
4854 dup = ble_gap_update_entry_find(conn_handle, NULL);
4855 if (dup != NULL) {
4856 rc = BLE_HS_EALREADY;
4857 goto done;
4858 }
4859
4860 entry = ble_gap_update_entry_alloc();
4861 if (entry == NULL) {
4862 rc = BLE_HS_ENOMEM;
4863 goto done;
4864 }
4865
4866 entry->conn_handle = conn_handle;
4867 entry->params = *params;
4868 entry->exp_os_ticks = ble_npl_time_get() +
4869 ble_npl_time_ms_to_ticks32(BLE_GAP_UPDATE_TIMEOUT_MS);
4870 BLE_HS_LOG(INFO, "GAP procedure initiated: ");
4871 ble_gap_log_update(conn_handle, params);
4872 BLE_HS_LOG(INFO, "\r\n");
4873
4874 /*
4875 * If LL update procedure is not supported on this connection and we are
4876 * the slave, fail over to the L2CAP update procedure.
4877 */
4878 if ((conn->supported_feat & BLE_HS_HCI_LE_FEAT_CONN_PARAM_REQUEST) == 0 &&
4879 !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
4880 l2cap_update = 1;
4881 rc = 0;
4882 } else {
4883 rc = ble_gap_update_tx(conn_handle, params);
4884 }
4885
4886 done:
4887 ble_hs_unlock();
4888
4889 if (!l2cap_update) {
4890 ble_hs_timer_resched();
4891 } else {
4892 ble_gap_update_to_l2cap(params, &l2cap_params);
4893 rc = ble_l2cap_sig_update(conn_handle, &l2cap_params,
4894 ble_gap_update_l2cap_cb, NULL);
4895 }
4896
4897 ble_hs_lock();
4898
4899 if (rc == 0) {
4900 SLIST_INSERT_HEAD(&ble_gap_update_entries, entry, next);
4901 } else {
4902 ble_gap_update_entry_free(entry);
4903 STATS_INC(ble_gap_stats, update_fail);
4904 }
4905
4906 ble_hs_unlock();
4907 return rc;
4908 #else
4909 return BLE_HS_ENOTSUP;
4910 #endif
4911 }
4912
4913 /*****************************************************************************
4914 * $security *
4915 *****************************************************************************/
ble_gap_security_initiate(uint16_t conn_handle)4916 int ble_gap_security_initiate(uint16_t conn_handle)
4917 {
4918 #if NIMBLE_BLE_SM
4919 struct ble_store_value_sec value_sec;
4920 struct ble_store_key_sec key_sec;
4921 struct ble_hs_conn_addrs addrs;
4922 ble_hs_conn_flags_t conn_flags;
4923 struct ble_hs_conn *conn;
4924 int rc;
4925 STATS_INC(ble_gap_stats, security_initiate);
4926 ble_hs_lock();
4927 conn = ble_hs_conn_find(conn_handle);
4928 if (conn != NULL) {
4929 conn_flags = conn->bhc_flags;
4930 ble_hs_conn_addrs(conn, &addrs);
4931 memset_s(&key_sec, sizeof(key_sec), 0, sizeof(key_sec));
4932 key_sec.peer_addr = addrs.peer_id_addr;
4933 }
4934
4935 ble_hs_unlock();
4936
4937 if (conn == NULL) {
4938 rc = BLE_HS_ENOTCONN;
4939 goto done;
4940 }
4941
4942 if (conn_flags & BLE_HS_CONN_F_MASTER) {
4943 /* Search the security database for an LTK for this peer. If one
4944 * is found, perform the encryption procedure rather than the pairing
4945 * procedure.
4946 */
4947 rc = ble_store_read_peer_sec(&key_sec, &value_sec);
4948 if (rc == 0 && value_sec.ltk_present) {
4949 rc = ble_sm_enc_initiate(conn_handle, value_sec.key_size,
4950 value_sec.ltk, value_sec.ediv,
4951 value_sec.rand_num,
4952 value_sec.authenticated);
4953 if (rc != 0) {
4954 goto done;
4955 }
4956 } else {
4957 rc = ble_sm_pair_initiate(conn_handle);
4958 if (rc != 0) {
4959 goto done;
4960 }
4961 }
4962 } else {
4963 rc = ble_sm_slave_initiate(conn_handle);
4964 if (rc != 0) {
4965 goto done;
4966 }
4967 }
4968
4969 rc = 0;
4970 done:
4971
4972 if (rc != 0) {
4973 STATS_INC(ble_gap_stats, security_initiate_fail);
4974 }
4975
4976 return rc;
4977 #else
4978 return BLE_HS_ENOTSUP;
4979 #endif
4980 }
4981
ble_gap_pair_initiate(uint16_t conn_handle)4982 int ble_gap_pair_initiate(uint16_t conn_handle)
4983 {
4984 int rc;
4985 rc = ble_sm_pair_initiate(conn_handle);
4986 return rc;
4987 }
4988
ble_gap_encryption_initiate(uint16_t conn_handle,uint8_t key_size,const uint8_t * ltk,uint16_t ediv,uint64_t rand_val,int auth)4989 int ble_gap_encryption_initiate(uint16_t conn_handle,
4990 uint8_t key_size,
4991 const uint8_t *ltk,
4992 uint16_t ediv,
4993 uint64_t rand_val,
4994 int auth)
4995 {
4996 #if NIMBLE_BLE_SM
4997 ble_hs_conn_flags_t conn_flags;
4998 int rc;
4999 rc = ble_hs_atomic_conn_flags(conn_handle, &conn_flags);
5000 if (rc != 0) {
5001 return rc;
5002 }
5003
5004 if (!(conn_flags & BLE_HS_CONN_F_MASTER)) {
5005 return BLE_HS_EROLE;
5006 }
5007
5008 rc = ble_sm_enc_initiate(conn_handle, key_size, ltk,
5009 ediv, rand_val, auth);
5010 return rc;
5011 #else
5012 return BLE_HS_ENOTSUP;
5013 #endif
5014 }
5015
ble_gap_unpair(const ble_addr_t * peer_addr)5016 int ble_gap_unpair(const ble_addr_t *peer_addr)
5017 {
5018 struct ble_hs_conn *conn;
5019
5020 if (ble_addr_cmp(peer_addr, BLE_ADDR_ANY) == 0) {
5021 return BLE_HS_EINVAL;
5022 }
5023
5024 ble_hs_lock();
5025 conn = ble_hs_conn_find_by_addr(peer_addr);
5026 if (conn != NULL) {
5027 ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
5028 }
5029
5030 ble_hs_unlock();
5031 ble_hs_pvcy_remove_entry(peer_addr->type,
5032 peer_addr->val);
5033 return ble_store_util_delete_peer(peer_addr);
5034 }
5035
ble_gap_unpair_oldest_peer(void)5036 int ble_gap_unpair_oldest_peer(void)
5037 {
5038 ble_addr_t oldest_peer_id_addr;
5039 int num_peers;
5040 int rc;
5041 rc = ble_store_util_bonded_peers(&oldest_peer_id_addr, &num_peers, 1);
5042 if (num_peers == 0) {
5043 return 0;
5044 }
5045
5046 rc = ble_gap_unpair(&oldest_peer_id_addr);
5047 if (rc != 0) {
5048 return rc;
5049 }
5050
5051 return 0;
5052 }
5053
ble_gap_passkey_event(uint16_t conn_handle,struct ble_gap_passkey_params * passkey_params)5054 void ble_gap_passkey_event(uint16_t conn_handle,
5055 struct ble_gap_passkey_params *passkey_params)
5056 {
5057 #if NIMBLE_BLE_SM
5058 struct ble_gap_event event;
5059 BLE_HS_LOG(DEBUG, "send passkey action request %d\r\n",
5060 passkey_params->action);
5061 memset_s(&event, sizeof(event), 0, sizeof(event));
5062 event.type = BLE_GAP_EVENT_PASSKEY_ACTION;
5063 event.passkey.conn_handle = conn_handle;
5064 event.passkey.params = *passkey_params;
5065 ble_gap_call_conn_event_cb(&event, conn_handle);
5066 #endif
5067 }
5068
ble_gap_enc_event(uint16_t conn_handle,int status,int security_restored)5069 void ble_gap_enc_event(uint16_t conn_handle, int status, int security_restored)
5070 {
5071 #if NIMBLE_BLE_SM
5072 struct ble_gap_event event;
5073 memset_s(&event, sizeof(event), 0, sizeof(event));
5074 event.type = BLE_GAP_EVENT_ENC_CHANGE;
5075 event.enc_change.conn_handle = conn_handle;
5076 event.enc_change.status = status;
5077 ble_gap_event_listener_call(&event);
5078 ble_gap_call_conn_event_cb(&event, conn_handle);
5079
5080 if (status == 0) {
5081 if (security_restored) {
5082 ble_gatts_bonding_restored(conn_handle);
5083 } else {
5084 ble_gatts_bonding_established(conn_handle);
5085 }
5086 }
5087
5088 #endif
5089 }
5090
ble_gap_identity_event(uint16_t conn_handle)5091 void ble_gap_identity_event(uint16_t conn_handle)
5092 {
5093 #if NIMBLE_BLE_SM
5094 struct ble_gap_event event;
5095 BLE_HS_LOG(DEBUG, "send identity changed");
5096 memset_s(&event, sizeof(event), 0, sizeof(event));
5097 event.type = BLE_GAP_EVENT_IDENTITY_RESOLVED;
5098 event.identity_resolved.conn_handle = conn_handle;
5099 ble_gap_call_conn_event_cb(&event, conn_handle);
5100 #endif
5101 }
5102
ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing * rp)5103 int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp)
5104 {
5105 #if NIMBLE_BLE_SM
5106 struct ble_gap_event event;
5107 int rc;
5108 memset_s(&event, sizeof(event), 0, sizeof(event));
5109 event.type = BLE_GAP_EVENT_REPEAT_PAIRING;
5110 event.repeat_pairing = *rp;
5111 rc = ble_gap_call_conn_event_cb(&event, rp->conn_handle);
5112 return rc;
5113 #else
5114 return 0;
5115 #endif
5116 }
5117
5118 /*****************************************************************************
5119 * $rssi *
5120 *****************************************************************************/
5121
ble_gap_conn_rssi(uint16_t conn_handle,int8_t * out_rssi)5122 int ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi)
5123 {
5124 int rc;
5125 rc = ble_hs_hci_util_read_rssi(conn_handle, out_rssi);
5126 return rc;
5127 }
5128
5129 /*****************************************************************************
5130 * $notify *
5131 *****************************************************************************/
5132
ble_gap_notify_rx_event(uint16_t conn_handle,uint16_t attr_handle,struct os_mbuf * om,int is_indication)5133 void ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
5134 struct os_mbuf *om, int is_indication)
5135 {
5136 #if !MYNEWT_VAL(BLE_GATT_NOTIFY) && !MYNEWT_VAL(BLE_GATT_INDICATE)
5137 return;
5138 #endif
5139 struct ble_gap_event event;
5140 memset_s(&event, sizeof(event), 0, sizeof(event));
5141 event.type = BLE_GAP_EVENT_NOTIFY_RX;
5142 event.notify_rx.conn_handle = conn_handle;
5143 event.notify_rx.attr_handle = attr_handle;
5144 event.notify_rx.om = om;
5145 event.notify_rx.indication = is_indication;
5146 ble_gap_event_listener_call(&event);
5147 ble_gap_call_conn_event_cb(&event, conn_handle);
5148 os_mbuf_free_chain(event.notify_rx.om);
5149 }
5150
ble_gap_notify_tx_event(int status,uint16_t conn_handle,uint16_t attr_handle,int is_indication)5151 void ble_gap_notify_tx_event(int status, uint16_t conn_handle, uint16_t attr_handle, int is_indication)
5152 {
5153 #if MYNEWT_VAL(BLE_GATT_NOTIFY) || MYNEWT_VAL(BLE_GATT_INDICATE)
5154 struct ble_gap_event event;
5155 memset_s(&event, sizeof(event), 0, sizeof(event));
5156 event.type = BLE_GAP_EVENT_NOTIFY_TX;
5157 event.notify_tx.conn_handle = conn_handle;
5158 event.notify_tx.status = status;
5159 event.notify_tx.attr_handle = attr_handle;
5160 event.notify_tx.indication = is_indication;
5161 ble_gap_event_listener_call(&event);
5162 ble_gap_call_conn_event_cb(&event, conn_handle);
5163 #endif
5164 }
5165
5166 /*****************************************************************************
5167 * $subscribe *
5168 *****************************************************************************/
5169
ble_gap_subscribe_event(uint16_t conn_handle,uint16_t attr_handle,uint8_t reason,uint8_t prev_notify,uint8_t cur_notify,uint8_t prev_indicate,uint8_t cur_indicate)5170 void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
5171 uint8_t reason,
5172 uint8_t prev_notify, uint8_t cur_notify,
5173 uint8_t prev_indicate, uint8_t cur_indicate)
5174 {
5175 struct ble_gap_event event;
5176 BLE_HS_DBG_ASSERT(prev_notify != cur_notify ||
5177 prev_indicate != cur_indicate);
5178 BLE_HS_DBG_ASSERT(reason == BLE_GAP_SUBSCRIBE_REASON_WRITE ||
5179 reason == BLE_GAP_SUBSCRIBE_REASON_TERM ||
5180 reason == BLE_GAP_SUBSCRIBE_REASON_RESTORE);
5181 memset_s(&event, sizeof(event), 0, sizeof(event));
5182 event.type = BLE_GAP_EVENT_SUBSCRIBE;
5183 event.subscribe.conn_handle = conn_handle;
5184 event.subscribe.attr_handle = attr_handle;
5185 event.subscribe.reason = reason;
5186 event.subscribe.prev_notify = !!prev_notify;
5187 event.subscribe.cur_notify = !!cur_notify;
5188 event.subscribe.prev_indicate = !!prev_indicate;
5189 event.subscribe.cur_indicate = !!cur_indicate;
5190 ble_gap_event_listener_call(&event);
5191 ble_gap_call_conn_event_cb(&event, conn_handle);
5192 }
5193
5194 /*****************************************************************************
5195 * $mtu *
5196 *****************************************************************************/
5197
ble_gap_mtu_event(uint16_t conn_handle,uint16_t cid,uint16_t mtu)5198 void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu)
5199 {
5200 struct ble_gap_event event;
5201 memset_s(&event, sizeof(event), 0, sizeof(event));
5202 event.type = BLE_GAP_EVENT_MTU;
5203 event.mtu.conn_handle = conn_handle;
5204 event.mtu.channel_id = cid;
5205 event.mtu.value = mtu;
5206 ble_gap_event_listener_call(&event);
5207 ble_gap_call_conn_event_cb(&event, conn_handle);
5208 }
5209
5210 /*****************************************************************************
5211 * $preempt *
5212 *****************************************************************************/
5213
ble_gap_preempt_no_lock(void)5214 void ble_gap_preempt_no_lock(void)
5215 {
5216 #if NIMBLE_BLE_ADVERTISE
5217 #if MYNEWT_VAL(BLE_EXT_ADV)
5218 int rc;
5219 for (int i = 0; i < BLE_ADV_INSTANCES; i++) {
5220 rc = ble_gap_ext_adv_stop_no_lock(i);
5221 if (rc == 0) {
5222 ble_gap_slave[i].preempted = 1;
5223 }
5224 }
5225
5226 #else
5227 int rc = ble_gap_adv_stop_no_lock();
5228 if (rc == 0) {
5229 ble_gap_slave[0].preempted = 1;
5230 }
5231
5232 #endif
5233 #endif
5234 #if NIMBLE_BLE_CONNECT
5235 rc = ble_gap_conn_cancel_no_lock();
5236 if (rc == 0) {
5237 ble_gap_master.preempted_op = BLE_GAP_OP_M_CONN;
5238 }
5239
5240 #endif
5241 #if NIMBLE_BLE_SCAN
5242 rc = ble_gap_disc_cancel_no_lock();
5243 if (rc == 0) {
5244 ble_gap_master.preempted_op = BLE_GAP_OP_M_DISC;
5245 }
5246
5247 #endif
5248 }
5249
5250 /**
5251 * @brief Preempts the GAP if it is not already preempted.
5252 *
5253 * Aborts all active GAP procedures and prevents new ones from being started.
5254 * This function is used to ensure an idle GAP so that the controller's
5255 * resolving list can be modified. When done accessing the resolving list, the
5256 * caller must call `ble_gap_preempt_done()` to permit new GAP procedures.
5257 *
5258 * On preemption, all aborted GAP procedures are reported with a status or
5259 * reason code of BLE_HS_EPREEMPTED. An attempt to initiate a new GAP
5260 * procedure during preemption fails with a return code of BLE_HS_EPREEMPTED.
5261 */
ble_gap_preempt(void)5262 void ble_gap_preempt(void)
5263 {
5264 ble_hs_lock();
5265
5266 if (!ble_gap_is_preempted()) {
5267 ble_gap_preempt_no_lock();
5268 }
5269
5270 ble_hs_unlock();
5271 }
5272
5273 /**
5274 * Takes GAP out of the preempted state, allowing new GAP procedures to be
5275 * initiated. This function should only be called after a call to
5276 * `ble_gap_preempt()`.
5277 */
5278
5279 static struct ble_npl_mutex preempt_done_mutex;
5280
ble_gap_preempt_done(void)5281 void ble_gap_preempt_done(void)
5282 {
5283 struct ble_gap_event event;
5284 ble_gap_event_fn *master_cb;
5285 void *master_arg;
5286 int disc_preempted;
5287 int i;
5288 static struct {
5289 ble_gap_event_fn *cb;
5290 void *arg;
5291 } slaves[BLE_ADV_INSTANCES];
5292 disc_preempted = 0;
5293 /* Protects slaves from accessing by multiple threads */
5294 ble_npl_mutex_pend(&preempt_done_mutex, 0xFFFFFFFF);
5295 memset_s(slaves, sizeof(slaves), 0, sizeof(slaves));
5296 ble_hs_lock();
5297
5298 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
5299 if (ble_gap_slave[i].preempted) {
5300 ble_gap_slave[i].preempted = 0;
5301 slaves[i].cb = ble_gap_slave[i].cb;
5302 slaves[i].arg = ble_gap_slave[i].cb_arg;
5303 }
5304 }
5305
5306 if (ble_gap_master.preempted_op == BLE_GAP_OP_M_DISC) {
5307 ble_gap_master.preempted_op = BLE_GAP_OP_NULL;
5308 disc_preempted = 1;
5309 master_cb = ble_gap_master.cb;
5310 master_arg = ble_gap_master.cb_arg;
5311 }
5312
5313 ble_hs_unlock();
5314 event.type = BLE_GAP_EVENT_ADV_COMPLETE;
5315 event.adv_complete.reason = BLE_HS_EPREEMPTED;
5316
5317 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
5318 if (slaves[i].cb) {
5319 #if MYNEWT_VAL(BLE_EXT_ADV)
5320 event.adv_complete.instance = i;
5321 event.adv_complete.conn_handle = i;
5322 #endif
5323 ble_gap_call_event_cb(&event, slaves[i].cb, slaves[i].arg);
5324 }
5325 }
5326
5327 ble_npl_mutex_release(&preempt_done_mutex);
5328
5329 if (disc_preempted) {
5330 event.type = BLE_GAP_EVENT_DISC_COMPLETE;
5331 event.disc_complete.reason = BLE_HS_EPREEMPTED;
5332 ble_gap_call_event_cb(&event, master_cb, master_arg);
5333 }
5334 }
5335
ble_gap_event_listener_register(struct ble_gap_event_listener * listener,ble_gap_event_fn * fn,void * arg)5336 int ble_gap_event_listener_register(struct ble_gap_event_listener *listener,
5337 ble_gap_event_fn *fn, void *arg)
5338 {
5339 struct ble_gap_event_listener *evl = NULL;
5340 int rc;
5341 SLIST_FOREACH(evl, &ble_gap_event_listener_list, link) {
5342 if (evl == listener) {
5343 break;
5344 }
5345 }
5346
5347 if (!evl) {
5348 if (fn) {
5349 memset_s(listener, sizeof(*listener), 0, sizeof(*listener));
5350 listener->fn = fn;
5351 listener->arg = arg;
5352 SLIST_INSERT_HEAD(&ble_gap_event_listener_list, listener, link);
5353 rc = 0;
5354 } else {
5355 rc = BLE_HS_EINVAL;
5356 }
5357 } else {
5358 rc = BLE_HS_EALREADY;
5359 }
5360
5361 return rc;
5362 }
5363
ble_gap_event_listener_unregister(struct ble_gap_event_listener * listener)5364 int ble_gap_event_listener_unregister(struct ble_gap_event_listener *listener)
5365 {
5366 struct ble_gap_event_listener *evl = NULL;
5367 int rc;
5368 /*
5369 * We check if element exists on the list only for sanity to let caller
5370 * know whether it registered its listener before.
5371 */
5372 SLIST_FOREACH(evl, &ble_gap_event_listener_list, link) {
5373 if (evl == listener) {
5374 break;
5375 }
5376 }
5377
5378 if (!evl) {
5379 rc = BLE_HS_ENOENT;
5380 } else {
5381 SLIST_REMOVE(&ble_gap_event_listener_list, listener,
5382 ble_gap_event_listener, link);
5383 rc = 0;
5384 }
5385
5386 return rc;
5387 }
5388
ble_gap_event_listener_call(struct ble_gap_event * event)5389 static int ble_gap_event_listener_call(struct ble_gap_event *event)
5390 {
5391 struct ble_gap_event_listener *evl = NULL;
5392 SLIST_FOREACH(evl, &ble_gap_event_listener_list, link) {
5393 evl->fn(event, evl->arg);
5394 }
5395 return 0;
5396 }
5397
5398 /*****************************************************************************
5399 * $init *
5400 *****************************************************************************/
5401
ble_gap_init(void)5402 int ble_gap_init(void)
5403 {
5404 int rc;
5405 memset_s(&ble_gap_master, sizeof(ble_gap_master), 0, sizeof(ble_gap_master));
5406 memset_s(ble_gap_slave, sizeof(ble_gap_slave), 0, sizeof(ble_gap_slave));
5407 #if MYNEWT_VAL(BLE_PERIODIC_ADV)
5408 memset_s(&ble_gap_sync, sizeof(ble_gap_sync), 0, sizeof(ble_gap_sync));
5409 #endif
5410 ble_npl_mutex_init(&preempt_done_mutex);
5411 SLIST_INIT(&ble_gap_update_entries);
5412 SLIST_INIT(&ble_gap_event_listener_list);
5413 rc = os_mempool_init(&ble_gap_update_entry_pool,
5414 MYNEWT_VAL(BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE),
5415 sizeof(struct ble_gap_update_entry),
5416 ble_gap_update_entry_mem,
5417 "ble_gap_update");
5418 switch (rc) {
5419 case 0:
5420 break;
5421
5422 case OS_ENOMEM:
5423 rc = BLE_HS_ENOMEM;
5424 goto err;
5425
5426 default:
5427 rc = BLE_HS_EOS;
5428 goto err;
5429 }
5430
5431 rc = stats_init_and_reg(STATS_HDR(ble_gap_stats), STATS_SIZE_INIT_PARMS(ble_gap_stats, STATS_SIZE_32),
5432 STATS_NAME_INIT_PARMS(ble_gap_stats), "ble_gap");
5433 if (rc != 0) {
5434 goto err;
5435 }
5436
5437 return 0;
5438 err:
5439 return rc;
5440 }
ble_gap_deinit(void)5441 void ble_gap_deinit(void)
5442 {
5443 ble_npl_mutex_deinit(&preempt_done_mutex);
5444 }