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