xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_gap.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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(&param[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(&param[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(&params);
3312 
3313     rc = ble_gap_disc_validate(own_addr_type, &params);
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, &params);
3344     BLE_HS_LOG(INFO, "\n");
3345 
3346     rc = ble_gap_disc_tx_params(own_addr_type, &params);
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