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