xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_scan.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <assert.h>
24 #include "syscfg/syscfg.h"
25 #include "os/os.h"
26 #include "os/os_cputime.h"
27 #include "nimble/ble.h"
28 #include "nimble/nimble_opt.h"
29 #include "nimble/hci_common.h"
30 #include "nimble/ble_hci_trans.h"
31 #include "controller/ble_phy.h"
32 #include "controller/ble_hw.h"
33 #include "controller/ble_ll.h"
34 #include "controller/ble_ll_sched.h"
35 #include "controller/ble_ll_adv.h"
36 #include "controller/ble_ll_scan.h"
37 #include "controller/ble_ll_hci.h"
38 #include "controller/ble_ll_whitelist.h"
39 #include "controller/ble_ll_resolv.h"
40 #include "controller/ble_ll_xcvr.h"
41 #include "controller/ble_ll_trace.h"
42 #include "ble_ll_conn_priv.h"
43 
44 /*
45  * XXX:
46  * 1) I think I can guarantee that we dont process things out of order if
47  * I send an event when a scan request is sent. The scan_rsp_pending flag
48  * code might be made simpler.
49  *
50  * 2) Interleave sending scan requests to different advertisers? I guess I need
51  * a list of advertisers to which I sent a scan request and have yet to
52  * receive a scan response from? Implement this.
53  */
54 
55 /* Dont allow more than 255 of these entries */
56 #if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) > 255
57     #error "Cannot have more than 255 duplicate entries!"
58 #endif
59 #if MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS) > 255
60     #error "Cannot have more than 255 scan response entries!"
61 #endif
62 
63 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
64 static const uint8_t ble_ll_valid_scan_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
65 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
66                                 | BLE_HCI_LE_PHY_CODED_PREF_MASK
67 #endif
68                               );
69 #endif
70 
71 /* The scanning parameters set by host */
72 static struct ble_ll_scan_params g_ble_ll_scan_params[BLE_LL_SCAN_PHY_NUMBER];
73 
74 /* The scanning state machine global object */
75 static struct ble_ll_scan_sm g_ble_ll_scan_sm;
76 
77 #define BLE_LL_EXT_ADV_ADVA_BIT         (0)
78 #define BLE_LL_EXT_ADV_TARGETA_BIT      (1)
79 #define BLE_LL_EXT_ADV_RFU_BIT          (2)
80 #define BLE_LL_EXT_ADV_DATA_INFO_BIT    (3)
81 #define BLE_LL_EXT_ADV_AUX_PTR_BIT      (4)
82 #define BLE_LL_EXT_ADV_SYNC_INFO_BIT    (5)
83 #define BLE_LL_EXT_ADV_TX_POWER_BIT     (6)
84 
85 #define BLE_LL_EXT_ADV_ADVA_SIZE        (6)
86 #define BLE_LL_EXT_ADV_TARGETA_SIZE     (6)
87 #define BLE_LL_EXT_ADV_DATA_INFO_SIZE   (2)
88 #define BLE_LL_EXT_ADV_AUX_PTR_SIZE     (3)
89 #define BLE_LL_EXT_ADV_SYNC_INFO_SIZE   (18)
90 #define BLE_LL_EXT_ADV_TX_POWER_SIZE    (1)
91 
92 struct ble_ll_ext_adv_hdr
93 {
94     uint8_t mode;
95     uint8_t hdr_len;
96     uint8_t hdr[0];
97 };
98 
99 struct ble_ll_ext_adv_report {
100     /* We support one report per event for now */
101     uint8_t event_meta; /* BLE_HCI_EVCODE_LE_META */
102     uint8_t event_len;
103     uint8_t subevt;
104     uint8_t num_reports;
105 
106     uint16_t evt_type;
107     uint8_t addr_type;
108     uint8_t addr[6];
109     uint8_t prim_phy;
110     uint8_t sec_phy;
111     uint8_t sid;
112     uint8_t tx_power;
113     int8_t rssi;
114     uint16_t per_adv_itvl;
115     uint8_t dir_addr_type;
116     uint8_t dir_addr[6];
117     uint8_t adv_data_len;
118     uint8_t adv_data[0];
119 } __attribute__((packed));
120 
121 /*
122  * Structure used to store advertisers. This is used to limit sending scan
123  * requests to the same advertiser and also to filter duplicate events sent
124  * to the host.
125  */
126 struct ble_ll_scan_advertisers
127 {
128     uint16_t            sc_adv_flags;
129     uint16_t            adi;
130     struct ble_dev_addr adv_addr;
131 };
132 
133 #define BLE_LL_SC_ADV_F_RANDOM_ADDR     (0x01)
134 #define BLE_LL_SC_ADV_F_SCAN_RSP_RXD    (0x02)
135 #define BLE_LL_SC_ADV_F_DIRECT_RPT_SENT (0x04)
136 #define BLE_LL_SC_ADV_F_ADV_RPT_SENT    (0x08)
137 #define BLE_LL_SC_ADV_F_SCAN_RSP_SENT   (0x10)
138 
139 /* Contains list of advertisers that we have heard scan responses from */
140 static uint8_t g_ble_ll_scan_num_rsp_advs;
141 struct ble_ll_scan_advertisers
142 g_ble_ll_scan_rsp_advs[MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)];
143 
144 /* Used to filter duplicate advertising events to host */
145 static uint8_t g_ble_ll_scan_num_dup_advs;
146 struct ble_ll_scan_advertisers
147 g_ble_ll_scan_dup_advs[MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS)];
148 
149 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
150 static os_membuf_t ext_adv_mem[ OS_MEMPOOL_SIZE(
151                     MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT),
152                     sizeof (struct ble_ll_aux_data))
153 ];
154 
155 static struct os_mempool ext_adv_pool;
156 
157 static int ble_ll_scan_start(struct ble_ll_scan_sm *scansm,
158                              struct ble_ll_sched_item *sch);
159 
160 static int
ble_ll_aux_scan_cb(struct ble_ll_sched_item * sch)161 ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch)
162 {
163     struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
164     uint8_t lls = ble_ll_state_get();
165     uint32_t wfr_usec;
166 
167     STATS_INC(ble_ll_stats, aux_sched_cb);
168 
169     /* In case scan has been disabled or there is other aux ptr in progress
170      * just drop the scheduled item
171      */
172     if (!scansm->scan_enabled || scansm->cur_aux_data) {
173         ble_ll_scan_aux_data_unref(sch->cb_arg);
174         goto done;
175     }
176 
177     /* Check if there is no aux connect sent. If so drop the sched item */
178     if (lls == BLE_LL_STATE_INITIATING && ble_ll_conn_init_pending_aux_conn_rsp()) {
179         ble_ll_scan_aux_data_unref(sch->cb_arg);
180         goto done;
181     }
182 
183     /* This function is called only when scanner is running. This can happen
184      *  in 3 states:
185      * BLE_LL_STATE_SCANNING
186      * BLE_LL_STATE_INITIATING
187      * BLE_LL_STATE_STANDBY
188      */
189     if (lls != BLE_LL_STATE_STANDBY) {
190         ble_phy_disable();
191         ble_ll_wfr_disable();
192         ble_ll_state_set(BLE_LL_STATE_STANDBY);
193     }
194 
195     /* When doing RX for AUX pkt, cur_aux_data keeps valid aux data */
196     scansm->cur_aux_data = sch->cb_arg;
197     BLE_LL_ASSERT(scansm->cur_aux_data != NULL);
198     scansm->cur_aux_data->scanning = 1;
199 
200     if (ble_ll_scan_start(scansm, sch)) {
201         ble_ll_scan_aux_data_unref(scansm->cur_aux_data);
202         scansm->cur_aux_data = NULL;
203         ble_ll_scan_chk_resume();
204         goto done;
205     }
206 
207     STATS_INC(ble_ll_stats, aux_fired_for_read);
208 
209     wfr_usec = scansm->cur_aux_data->offset_units ? 300 : 30;
210     ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usec);
211 
212 done:
213 
214     return BLE_LL_SCHED_STATE_DONE;
215 }
216 
217 static int
ble_ll_scan_ext_adv_init(struct ble_ll_aux_data ** aux_data)218 ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data)
219 {
220     struct ble_ll_aux_data *e;
221 
222     e = os_memblock_get(&ext_adv_pool);
223     if (!e) {
224         return -1;
225     }
226 
227     memset(e, 0, sizeof(*e));
228     e->sch.sched_cb = ble_ll_aux_scan_cb;
229     e->sch.cb_arg = e;
230     e->sch.sched_type = BLE_LL_SCHED_TYPE_AUX_SCAN;
231     e->ref_cnt = 1;
232     ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t)e, e->ref_cnt);
233 
234     *aux_data = e;
235     STATS_INC(ble_ll_stats, aux_allocated);
236 
237     return 0;
238 }
239 #endif
240 
241 /* See Vol 6 Part B Section 4.4.3.2. Active scanning backoff */
242 static void
ble_ll_scan_req_backoff(struct ble_ll_scan_sm * scansm,int success)243 ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
244 {
245     scansm->scan_rsp_pending = 0;
246     if (success) {
247         scansm->scan_rsp_cons_fails = 0;
248         ++scansm->scan_rsp_cons_ok;
249         if (scansm->scan_rsp_cons_ok == 2) {
250             scansm->scan_rsp_cons_ok = 0;
251             if (scansm->upper_limit > 1) {
252                 scansm->upper_limit >>= 1;
253             }
254         }
255         STATS_INC(ble_ll_stats, scan_req_txg);
256     } else {
257         scansm->scan_rsp_cons_ok = 0;
258         ++scansm->scan_rsp_cons_fails;
259         if (scansm->scan_rsp_cons_fails == 2) {
260             scansm->scan_rsp_cons_fails = 0;
261             if (scansm->upper_limit < 256) {
262                 scansm->upper_limit <<= 1;
263             }
264         }
265         STATS_INC(ble_ll_stats, scan_req_txf);
266     }
267 
268     scansm->backoff_count = rand() & (scansm->upper_limit - 1);
269     ++scansm->backoff_count;
270     BLE_LL_ASSERT(scansm->backoff_count <= 256);
271 }
272 
273 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
274 static void
ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm * scansm)275 ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
276 {
277     ble_npl_time_t now;
278 
279     now = ble_npl_time_get();
280     if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
281         /* Generate new NRPA */
282         ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
283         scansm->scan_nrpa[5] &= ~0xc0;
284 
285         /* We'll use the same timeout as for RPA rotation */
286         scansm->scan_nrpa_timer = now + ble_ll_resolv_get_rpa_tmo();
287     }
288 }
289 #endif
290 
291 /**
292  * ble ll scan req pdu make
293  *
294  * Construct a SCAN_REQ PDU.
295  *
296  * @param scansm Pointer to scanning state machine
297  * @param adv_addr Pointer to device address of advertiser
298  * @param addr_type 0 if public; non-zero if random. This is the addr type of
299  *                  the advertiser; not our "own address type"
300  */
301 static void
ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm * scansm,uint8_t * adv_addr,uint8_t adv_addr_type)302 ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm *scansm, uint8_t *adv_addr,
303                          uint8_t adv_addr_type)
304 {
305     uint8_t     *dptr;
306     uint8_t     pdu_type;
307     uint8_t     *scana;
308     struct os_mbuf *m;
309 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
310     uint8_t rpa[BLE_DEV_ADDR_LEN];
311     struct ble_ll_resolv_entry *rl;
312 #endif
313 
314     /* Construct first PDU header byte */
315     pdu_type = BLE_ADV_PDU_TYPE_SCAN_REQ;
316     if (adv_addr_type) {
317         pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND;
318     }
319 
320     /* Get the advertising PDU */
321     m = scansm->scan_req_pdu;
322     BLE_LL_ASSERT(m != NULL);
323 
324     /* Get pointer to our device address */
325     if ((scansm->own_addr_type & 1) == 0) {
326         scana = g_dev_addr;
327     } else {
328         pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
329         scana = g_random_addr;
330     }
331 
332 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
333     if (scansm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
334         rl = NULL;
335         if (ble_ll_is_rpa(adv_addr, adv_addr_type)) {
336             if (scansm->scan_rpa_index >= 0) {
337                 /* Generate a RPA to use for scana */
338                 rl = &g_ble_ll_resolv_list[scansm->scan_rpa_index];
339             }
340         } else {
341             if (ble_ll_resolv_enabled()) {
342                 rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
343             }
344         }
345 
346         /*
347          * If advertising device is on our resolving list, we use RPA generated
348          * using Local IRK from resolving list entry as ScanA. In other case,
349          * we use NRPA as ScanA as allowed by spec to prevent our device from
350          * being tracked when doing an active scan (see Core 5.0, Vol 6, Part B,
351          * section 6.3).
352          */
353         if (rl) {
354             ble_ll_resolv_get_priv_addr(rl, 1, rpa);
355             scana = rpa;
356         } else {
357             ble_ll_scan_refresh_nrpa(scansm);
358             scana = scansm->scan_nrpa;
359         }
360 
361         pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
362     }
363 #endif
364 
365     ble_ll_mbuf_init(m, BLE_SCAN_REQ_LEN, pdu_type);
366 
367     /* Construct the scan request */
368     dptr = m->om_data;
369     memcpy(dptr, scana, BLE_DEV_ADDR_LEN);
370     memcpy(dptr + BLE_DEV_ADDR_LEN, adv_addr, BLE_DEV_ADDR_LEN);
371 }
372 
373 /**
374  * Checks to see if an advertiser is on the duplicate address list.
375  *
376  * @param addr Pointer to address
377  * @param txadd TxAdd bit. 0: public; random otherwise
378  *
379  * @return uint8_t 0: not on list; any other value is
380  */
381 static struct ble_ll_scan_advertisers *
ble_ll_scan_find_dup_adv(uint8_t * addr,uint8_t txadd)382 ble_ll_scan_find_dup_adv(uint8_t *addr, uint8_t txadd)
383 {
384     uint8_t num_advs;
385     struct ble_ll_scan_advertisers *adv;
386 
387     /* Do we have an address match? Must match address type */
388     adv = &g_ble_ll_scan_dup_advs[0];
389     num_advs = g_ble_ll_scan_num_dup_advs;
390     while (num_advs) {
391         if (!memcmp(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN)) {
392             /* Address type must match */
393             if (txadd) {
394                 if ((adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) == 0) {
395                     goto next_dup_adv;
396                 }
397             } else {
398                 if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) {
399                     goto next_dup_adv;
400                 }
401             }
402 
403             return adv;
404         }
405 
406 next_dup_adv:
407         ++adv;
408         --num_advs;
409     }
410 
411     return NULL;
412 }
413 
414 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
415 static struct ble_ll_ext_adv_report *
ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report * copy_from)416 ble_ll_scan_init_ext_adv_report(struct ble_ll_ext_adv_report *copy_from)
417 {
418     struct ble_ll_ext_adv_report *evt;
419 
420     evt = (struct ble_ll_ext_adv_report *) ble_hci_trans_buf_alloc(
421                                                     BLE_HCI_TRANS_BUF_EVT_LO);
422     if (!evt) {
423         return NULL;
424     }
425 
426     if (copy_from) {
427         memcpy(evt, copy_from, sizeof(*evt));
428     } else {
429         memset(evt, 0, sizeof(*evt));
430 
431         evt->event_meta = BLE_HCI_EVCODE_LE_META;
432         evt->subevt = BLE_HCI_LE_SUBEV_EXT_ADV_RPT;
433         /* We support only one report per event now */
434         evt->num_reports = 1;
435         /* Init TX Power with "Not available" which is 127 */
436         evt->tx_power = 127;
437         /* Init RSSI with "Not available" which is 127 */
438         evt->rssi = 127;
439         /* Init SID with "Not available" which is 0xFF */
440         evt->sid = 0xFF;
441         /* Init address type with "anonymous" which is 0xFF */
442         evt->addr_type = 0xFF;
443     }
444 
445     return evt;
446 }
447 
448 static void
ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data * aux_data)449 ble_ll_scan_send_truncated_if_chained(struct ble_ll_aux_data *aux_data)
450 {
451     struct ble_ll_ext_adv_report *evt;
452 
453     if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
454         goto done;
455     }
456 
457     BLE_LL_ASSERT(aux_data);
458 
459     if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) {
460         /* if not chained, there is nothing to do here */
461         goto done;
462     }
463 
464     if (aux_data->evt) {
465         evt = aux_data->evt;
466         aux_data->evt = NULL;
467     } else {
468         evt = ble_ll_scan_init_ext_adv_report(NULL);
469         if (!evt) {
470             goto done;
471         }
472     }
473 
474     evt->event_len = sizeof(*evt);
475     evt->evt_type = aux_data->evt_type;
476     evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
477     BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
478 
479     if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_ADDRA)) {
480         memcpy(evt->addr, aux_data->addr, 6);
481         evt->addr_type = aux_data->addr_type;
482     }
483 
484     if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_DIR_ADDRA)) {
485         memcpy(evt->dir_addr, aux_data->dir_addr, 6);
486         evt->dir_addr_type = aux_data->dir_addr_type;
487     }
488 
489     evt->sid = (aux_data->adi >> 12);
490     ble_ll_hci_event_send((uint8_t *)evt);
491 
492 done:
493     ble_ll_scan_aux_data_unref(aux_data);
494 }
495 #endif
496 
497 void
ble_ll_scan_end_adv_evt(struct ble_ll_aux_data * aux_data)498 ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data)
499 {
500 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
501     /*
502      * Check if tuncated has been sent
503      *
504      * Normally reference counter here should be 2. 1 for outstanding
505      * complete event and one for ongoing scanning. If there is only 1
506      * that means, advertising event is already completed
507      * (truncated was sent to the host) and we just need to drop last reference.
508      * Otherwise we should try to send truncated event to the host.
509      */
510     if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT)) {
511         ble_ll_scan_send_truncated_if_chained(aux_data);
512     }
513 
514     if (ble_ll_scan_aux_data_unref(aux_data) > 0) {
515         BLE_LL_ASSERT(0);
516     }
517 
518 #endif
519 }
520 /**
521  * Do scan machine clean up on PHY disabled
522  *
523  */
524 void
ble_ll_scan_clean_cur_aux_data(void)525 ble_ll_scan_clean_cur_aux_data(void)
526 {
527 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
528     struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
529 
530     /* If scanner was reading aux ptr, we need to clean it up */
531     if (scansm && scansm->cur_aux_data) {
532         ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
533         scansm->cur_aux_data = NULL;
534     }
535 #endif
536 }
537 
538 /**
539  * Check if a packet is a duplicate advertising packet.
540  *
541  * @param pdu_type
542  * @param rxbuf
543  *
544  * @return int 0: not a duplicate. 1:duplicate
545  */
546 int
ble_ll_scan_is_dup_adv(uint8_t pdu_type,uint8_t txadd,uint8_t * addr)547 ble_ll_scan_is_dup_adv(uint8_t pdu_type, uint8_t txadd, uint8_t *addr)
548 {
549     struct ble_ll_scan_advertisers *adv;
550 
551     adv = ble_ll_scan_find_dup_adv(addr, txadd);
552     if (adv) {
553         /* Check appropriate flag (based on type of PDU) */
554         if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) {
555             if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_DIRECT_RPT_SENT) {
556                 return 1;
557             }
558         } else if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) {
559             if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_SCAN_RSP_SENT) {
560                 return 1;
561             }
562         } else {
563             if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_ADV_RPT_SENT) {
564                 return 1;
565             }
566         }
567     }
568 
569     return 0;
570 }
571 
572 /**
573  * Add an advertiser the list of duplicate advertisers. An address gets added to
574  * the list of duplicate addresses when the controller sends an advertising
575  * report to the host.
576  *
577  * @param addr   Pointer to advertisers address or identity address
578  * @param Txadd. TxAdd bit (0 public, random otherwise)
579  * @param subev  Type of advertising report sent (direct or normal).
580  * @param evtype Advertising event type
581  */
582 void
ble_ll_scan_add_dup_adv(uint8_t * addr,uint8_t txadd,uint8_t subev,uint8_t evtype)583 ble_ll_scan_add_dup_adv(uint8_t *addr, uint8_t txadd, uint8_t subev,
584                         uint8_t evtype)
585 {
586     uint8_t num_advs;
587     struct ble_ll_scan_advertisers *adv;
588 
589     /* Check to see if on list. */
590     adv = ble_ll_scan_find_dup_adv(addr, txadd);
591     if (!adv) {
592         /* XXX: for now, if we dont have room, just leave */
593         num_advs = g_ble_ll_scan_num_dup_advs;
594         if (num_advs == MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS)) {
595             return;
596         }
597 
598         /* Add the advertiser to the array */
599         adv = &g_ble_ll_scan_dup_advs[num_advs];
600         memcpy(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN);
601         ++g_ble_ll_scan_num_dup_advs;
602 
603         adv->sc_adv_flags = 0;
604         if (txadd) {
605             adv->sc_adv_flags |= BLE_LL_SC_ADV_F_RANDOM_ADDR;
606         }
607     }
608 
609     if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) {
610         adv->sc_adv_flags |= BLE_LL_SC_ADV_F_DIRECT_RPT_SENT;
611     } else {
612         if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
613             adv->sc_adv_flags |= BLE_LL_SC_ADV_F_SCAN_RSP_SENT;
614         } else {
615             adv->sc_adv_flags |= BLE_LL_SC_ADV_F_ADV_RPT_SENT;
616         }
617     }
618 }
619 
620 /**
621  * Checks to see if we have received a scan response from this advertiser.
622  *
623  * @param adv_addr Address of advertiser
624  * @param txadd TxAdd bit (0: public; random otherwise)
625  *
626  * @return int 0: have not received a scan response; 1 otherwise.
627  */
628 static int
ble_ll_scan_have_rxd_scan_rsp(uint8_t * addr,uint8_t txadd,uint8_t ext_adv,uint16_t adi)629 ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd,
630                               uint8_t ext_adv, uint16_t adi)
631 {
632     uint8_t num_advs;
633     struct ble_ll_scan_advertisers *adv;
634 
635     /* Do we have an address match? Must match address type */
636     adv = &g_ble_ll_scan_rsp_advs[0];
637     num_advs = g_ble_ll_scan_num_rsp_advs;
638     while (num_advs) {
639         if (!memcmp(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN)) {
640             /* Address type must match */
641             if (txadd) {
642                 if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) {
643                     if (ext_adv) {
644                         if (adi == adv->adi) {
645                             return 1;
646                         }
647                         goto next;
648                     }
649                     return 1;
650                 }
651             } else {
652                 if ((adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) == 0) {
653                     if (ext_adv) {
654                         if (adi == adv->adi) {
655                             return 1;
656                         }
657                         goto next;
658                     }
659                     return 1;
660                 }
661             }
662         }
663 next:
664         ++adv;
665         --num_advs;
666     }
667 
668     return 0;
669 }
670 
671 static void
ble_ll_scan_add_scan_rsp_adv(uint8_t * addr,uint8_t txadd,uint8_t ext_adv,uint16_t adi)672 ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd,
673                              uint8_t ext_adv, uint16_t adi)
674 {
675     uint8_t num_advs;
676     struct ble_ll_scan_advertisers *adv;
677 
678     /* XXX: for now, if we dont have room, just leave */
679     num_advs = g_ble_ll_scan_num_rsp_advs;
680     if (num_advs == MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)) {
681         return;
682     }
683 
684     /* Check if address is already on the list */
685     if (ble_ll_scan_have_rxd_scan_rsp(addr, txadd, ext_adv, adi)) {
686         return;
687     }
688 
689     /* Add the advertiser to the array */
690     adv = &g_ble_ll_scan_rsp_advs[num_advs];
691     memcpy(&adv->adv_addr, addr, BLE_DEV_ADDR_LEN);
692     adv->sc_adv_flags = BLE_LL_SC_ADV_F_SCAN_RSP_RXD;
693     if (txadd) {
694         adv->sc_adv_flags |= BLE_LL_SC_ADV_F_RANDOM_ADDR;
695     }
696     adv->adi = adi;
697     ++g_ble_ll_scan_num_rsp_advs;
698 
699     return;
700 }
701 
702 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
703 static int
ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,uint8_t addr_type,uint8_t * addr,uint8_t rssi,uint8_t adv_data_len,struct os_mbuf * adv_data,uint8_t * inita,uint8_t inita_type)704 ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
705                                       uint8_t addr_type, uint8_t *addr,
706                                       uint8_t rssi,
707                                       uint8_t adv_data_len, struct os_mbuf *adv_data,
708                                       uint8_t *inita, uint8_t inita_type)
709 {
710     struct ble_ll_ext_adv_report *evt;
711 
712     if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
713         return -1;
714     }
715 
716     /* Drop packet if it does not fit into event buffer */
717     if ((sizeof(*evt) + adv_data_len) + 1 > MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) {
718         STATS_INC(ble_ll_stats, adv_evt_dropped);
719         return -1;
720     }
721 
722     evt = ble_ll_scan_init_ext_adv_report(NULL);
723     if (!evt) {
724         return 0;
725     }
726 
727     switch (evtype) {
728     case BLE_HCI_ADV_RPT_EVTYPE_ADV_IND:
729         evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND;
730         break;
731     case BLE_HCI_ADV_RPT_EVTYPE_DIR_IND:
732         evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND;
733         break;
734     case BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND:
735         evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND;
736         break;
737     case BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP:
738         evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND;
739          break;
740     case BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND:
741         evt->evt_type = BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND;
742         break;
743     default:
744         BLE_LL_ASSERT(0);
745         break;
746     }
747 
748     evt->addr_type = addr_type;
749     memcpy(evt->addr, addr, BLE_DEV_ADDR_LEN);
750 
751     evt->event_len = sizeof(*evt);
752 
753     if (inita) {
754         /* TODO Really ?? */
755         evt->dir_addr_type = inita_type;
756         memcpy(evt->dir_addr, inita, BLE_DEV_ADDR_LEN);
757         evt->event_len += BLE_DEV_ADDR_LEN  + 1;
758     } else if (adv_data_len <= (MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE) - sizeof(*evt))) {
759         evt->adv_data_len = adv_data_len;
760         os_mbuf_copydata(adv_data, 0, adv_data_len, evt->adv_data);
761         evt->event_len += adv_data_len;
762     }
763 
764     evt->rssi = rssi;
765     evt->prim_phy = BLE_PHY_1M;
766 
767     return ble_ll_hci_event_send((uint8_t *) evt);
768 }
769 #endif
770 
771 static int
ble_ll_hci_send_adv_report(uint8_t subev,uint8_t evtype,uint8_t event_len,uint8_t addr_type,uint8_t * addr,uint8_t rssi,uint8_t adv_data_len,struct os_mbuf * adv_data,uint8_t * inita,uint8_t inita_type)772 ble_ll_hci_send_adv_report(uint8_t subev, uint8_t evtype,uint8_t event_len,
773                            uint8_t addr_type, uint8_t *addr, uint8_t rssi,
774                            uint8_t adv_data_len, struct os_mbuf *adv_data,
775                            uint8_t *inita, uint8_t inita_type)
776 {
777     uint8_t *evbuf;
778     uint8_t *tmp;
779 
780     if (!ble_ll_hci_is_le_event_enabled(subev)) {
781         return -1;
782     }
783 
784     /* Drop packet if it does not fit into event buffer */
785     if (event_len + 1 > MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) {
786         STATS_INC(ble_ll_stats, adv_evt_dropped);
787         return -1;
788     }
789 
790     evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
791     if (!evbuf) {
792         return -1;
793     }
794 
795     evbuf[0] = BLE_HCI_EVCODE_LE_META;
796     evbuf[1] = event_len;
797     evbuf[2] = subev;
798     evbuf[3] = 1;       /* number of reports */
799     evbuf[4] = evtype;
800     evbuf[5] = addr_type;
801     memcpy(&evbuf[6], addr, BLE_DEV_ADDR_LEN);
802 
803     tmp = &evbuf[12];
804     if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) {
805         BLE_LL_ASSERT(inita);
806         tmp[0] = inita_type;
807         memcpy(tmp + 1, inita, BLE_DEV_ADDR_LEN);
808         tmp += BLE_DEV_ADDR_LEN + 1;
809     } else if (subev == BLE_HCI_LE_SUBEV_ADV_RPT) {
810         tmp[0] = adv_data_len;
811         os_mbuf_copydata(adv_data, 0, adv_data_len, tmp + 1);
812         tmp += adv_data_len + 1;
813     } else {
814         BLE_LL_ASSERT(0);
815         return -1;
816     }
817 
818     tmp[0] = rssi;
819 
820     return ble_ll_hci_event_send(evbuf);
821 }
822 /**
823  * Send an advertising report to the host.
824  *
825  * NOTE: while we are allowed to send multiple devices in one report, we
826  * will just send for one for now.
827  *
828  * @param pdu_type
829  * @param txadd
830  * @param rxbuf
831  * @param hdr
832  * @param scansm
833  */
834 static void
ble_ll_scan_send_adv_report(uint8_t pdu_type,uint8_t * adva,uint8_t adva_type,uint8_t * inita,uint8_t inita_type,struct os_mbuf * om,struct ble_mbuf_hdr * hdr,struct ble_ll_scan_sm * scansm)835 ble_ll_scan_send_adv_report(uint8_t pdu_type, uint8_t *adva, uint8_t adva_type,
836                             uint8_t *inita, uint8_t inita_type,
837                             struct os_mbuf *om,
838                             struct ble_mbuf_hdr *hdr,
839                             struct ble_ll_scan_sm *scansm)
840 {
841     int rc;
842     uint8_t *rxbuf = om->om_data;
843     uint8_t evtype;
844     uint8_t subev;
845     uint8_t adv_data_len;
846     uint8_t event_len;
847 
848     if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) {
849         if (ble_ll_is_rpa(inita, inita_type)) {
850             /* For resolvable we send separate event */
851             subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT;
852             event_len = BLE_HCI_LE_ADV_DIRECT_RPT_LEN;
853         } else {
854             subev = BLE_HCI_LE_SUBEV_ADV_RPT;
855             event_len = BLE_HCI_LE_ADV_RPT_MIN_LEN;
856         }
857         evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
858 
859         adv_data_len = 0;
860     } else {
861         subev = BLE_HCI_LE_SUBEV_ADV_RPT;
862         if (pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) {
863             evtype = BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
864         } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND) {
865             evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
866         } else if (pdu_type == BLE_ADV_PDU_TYPE_ADV_NONCONN_IND) {
867             evtype = BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
868         } else {
869             evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
870         }
871         adv_data_len = rxbuf[1];
872         adv_data_len -= BLE_DEV_ADDR_LEN;
873         event_len = BLE_HCI_LE_ADV_RPT_MIN_LEN + adv_data_len;
874         os_mbuf_adj(om, BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN);
875     }
876 
877 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
878     if (BLE_MBUF_HDR_RESOLVED(hdr)) {
879         /*
880          * NOTE: this looks a bit odd, but the resolved address types
881          * are 2 greater than the unresolved ones in the spec, so
882          * we just add 2 here.
883          */
884         adva_type += 2;
885     }
886 #endif
887 
888 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
889     if (scansm->ext_scanning) {
890         rc = ble_ll_hci_send_legacy_ext_adv_report(evtype,
891                                                    adva_type, adva,
892                                                    hdr->rxinfo.rssi,
893                                                    adv_data_len, om,
894                                                    inita, inita_type);
895     } else {
896         rc = ble_ll_hci_send_adv_report(subev, evtype, event_len,
897                                         adva_type, adva,
898                                         hdr->rxinfo.rssi,
899                                         adv_data_len, om,
900                                         inita, inita_type);
901     }
902 #else
903     rc = ble_ll_hci_send_adv_report(subev, evtype, event_len,
904                                     adva_type, adva,
905                                     hdr->rxinfo.rssi,
906                                     adv_data_len, om,
907                                     inita, inita_type);
908 #endif
909     if (!rc) {
910         /* If filtering, add it to list of duplicate addresses */
911         if (scansm->scan_filt_dups) {
912             ble_ll_scan_add_dup_adv(adva, adva_type, subev, evtype);
913         }
914     }
915 }
916 
917 /**
918  * Checks the scanner filter policy to determine if we should allow or discard
919  * the received PDU.
920  *
921  * NOTE: connect requests and scan requests are not passed here
922  *
923  * @param pdu_type
924  * @param adv_addr
925  * @param adv_addr_type
926  * @param init_addr
927  * @param init_addr_type
928  * @param flags
929  *
930  * @return int 0: pdu allowed by filter policy. 1: pdu not allowed
931  */
932 static int
ble_ll_scan_chk_filter_policy(uint8_t pdu_type,uint8_t * adv_addr,uint8_t adv_addr_type,uint8_t * init_addr,uint8_t init_addr_type,uint8_t devmatch)933 ble_ll_scan_chk_filter_policy(uint8_t pdu_type, uint8_t *adv_addr,
934                               uint8_t adv_addr_type, uint8_t *init_addr,
935                               uint8_t init_addr_type, uint8_t devmatch)
936 {
937     int use_whitelist;
938     int chk_inita;
939     struct ble_ll_scan_params *params =
940                         &g_ble_ll_scan_sm.phy_data[g_ble_ll_scan_sm.cur_phy];
941 
942     use_whitelist = 0;
943     chk_inita = 0;
944 
945 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
946     if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && adv_addr == NULL) {
947         /* Note: adv_addr can be NULL (but don't have to) for ext adv. If NULL
948          * that means it is beacon and skip filter policy for now */
949         return 0;
950     }
951 #endif
952 
953     switch (params->scan_filt_policy) {
954     case BLE_HCI_SCAN_FILT_NO_WL:
955         break;
956     case BLE_HCI_SCAN_FILT_USE_WL:
957         use_whitelist = 1;
958         break;
959     case BLE_HCI_SCAN_FILT_NO_WL_INITA:
960         chk_inita = 1;
961         break;
962     case BLE_HCI_SCAN_FILT_USE_WL_INITA:
963         chk_inita = 1;
964         use_whitelist = 1;
965         break;
966     default:
967         BLE_LL_ASSERT(0);
968         break;
969     }
970 
971     /* If we are using the whitelist, check that first */
972     if (use_whitelist && (pdu_type != BLE_ADV_PDU_TYPE_SCAN_RSP)) {
973         /* If device does not match let us skip this PDU.
974          * If device matches, lets check for InitA further in the code
975          */
976         if (!devmatch) {
977             return 1;
978         }
979     }
980 
981     /* If this is a directed advertisement, init_addr is not NULL.
982      * Check that it is for us */
983     if (init_addr) {
984         /* Is this for us? If not, is it resolvable */
985         if (!ble_ll_is_our_devaddr(init_addr, init_addr_type)) {
986             if (!chk_inita || !ble_ll_is_rpa(adv_addr, adv_addr_type)) {
987                 return 1;
988             }
989         }
990     }
991 
992     return 0;
993 }
994 
995 static void
ble_ll_get_chan_to_scan(struct ble_ll_scan_sm * scansm,uint8_t * chan,int * phy)996 ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan,
997                         int *phy)
998 {
999     struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
1000 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1001     struct ble_ll_aux_data *aux_data = scansm->cur_aux_data;
1002 
1003     if (!scansm->ext_scanning || !aux_data || !aux_data->scanning) {
1004         *chan = scanphy->scan_chan;
1005         *phy = scanphy->phy;
1006         return;
1007     }
1008 
1009     *chan = aux_data->chan;
1010     *phy = aux_data->aux_phy;
1011 #else
1012     *chan = scanphy->scan_chan;
1013     *phy = scanphy->phy;
1014 #endif
1015 }
1016 /**
1017  * Called to enable the receiver for scanning.
1018  *
1019  * Context: Link Layer task
1020  *
1021  * @param sch
1022  *
1023  * @return int
1024  */
1025 static int
ble_ll_scan_start(struct ble_ll_scan_sm * scansm,struct ble_ll_sched_item * sch)1026 ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch)
1027 {
1028     int rc;
1029     struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
1030     uint8_t scan_chan;
1031 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1032     uint8_t phy_mode;
1033 #endif
1034     int phy;
1035 
1036     ble_ll_get_chan_to_scan(scansm, &scan_chan, &phy);
1037 
1038     /* XXX: right now scheduled item is only present if we schedule for aux
1039      *      scan just make sanity check that we have proper combination of
1040      *      sch and resulting scan_chan
1041      */
1042     BLE_LL_ASSERT(!sch || scan_chan < BLE_PHY_ADV_CHAN_START);
1043     BLE_LL_ASSERT(sch || scan_chan >= BLE_PHY_ADV_CHAN_START);
1044 
1045     /* Set channel */
1046     rc = ble_phy_setchan(scan_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV);
1047     BLE_LL_ASSERT(rc == 0);
1048 
1049     /*
1050      * Set transmit end callback to NULL in case we transmit a scan request.
1051      * There is a callback for the connect request.
1052      */
1053     ble_phy_set_txend_cb(NULL, NULL);
1054 
1055 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1056     ble_phy_encrypt_disable();
1057 #endif
1058 
1059 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1060     if (ble_ll_resolv_enabled()) {
1061         ble_phy_resolv_list_enable();
1062     } else {
1063         ble_phy_resolv_list_disable();
1064     }
1065 #endif
1066 
1067 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1068     phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY);
1069     ble_phy_mode_set(phy_mode, phy_mode);
1070 #endif
1071 
1072     /* XXX: probably need to make sure hfxo is running too */
1073     /* XXX: can make this better; want to just start asap. */
1074     if (sch) {
1075         rc = ble_phy_rx_set_start_time(sch->start_time +
1076                                        g_ble_ll_sched_offset_ticks,
1077                                        sch->remainder);
1078     } else {
1079         rc = ble_phy_rx_set_start_time(os_cputime_get32() +
1080                                        g_ble_ll_sched_offset_ticks, 0);
1081     }
1082     if (!rc || rc == BLE_PHY_ERR_RX_LATE) {
1083         /* If we are late here, it is still OK because we keep scanning.
1084          * Clear error
1085          */
1086         rc = 0;
1087 
1088         /* Enable/disable whitelisting */
1089         if (scanphy->scan_filt_policy & 1) {
1090             ble_ll_whitelist_enable();
1091         } else {
1092             ble_ll_whitelist_disable();
1093         }
1094 
1095         /* Set link layer state to scanning */
1096         if (scanphy->scan_type == BLE_SCAN_TYPE_INITIATE) {
1097             ble_ll_state_set(BLE_LL_STATE_INITIATING);
1098         } else {
1099             ble_ll_state_set(BLE_LL_STATE_SCANNING);
1100         }
1101     }
1102 
1103     /* If there is a still a scan response pending, we have failed! */
1104     if (scansm->scan_rsp_pending) {
1105         ble_ll_scan_req_backoff(scansm, 0);
1106     }
1107 
1108     return rc;
1109 }
1110 
1111 #ifdef BLE_XCVR_RFCLK
1112 static void
ble_ll_scan_rfclk_chk_stop(void)1113 ble_ll_scan_rfclk_chk_stop(void)
1114 {
1115     int stop;
1116     int32_t time_till_next;
1117     os_sr_t sr;
1118     uint32_t next_time;
1119 
1120     stop = 0;
1121     OS_ENTER_CRITICAL(sr);
1122     if (ble_ll_sched_next_time(&next_time)) {
1123         /*
1124          * If the time until the next event is too close, dont bother to turn
1125          * off the clock
1126          */
1127         time_till_next = (int32_t)(next_time - os_cputime_get32());
1128         if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
1129             stop = 1;
1130         }
1131     } else {
1132         stop = 1;
1133     }
1134     if (stop) {
1135         ble_ll_xcvr_rfclk_disable();
1136     }
1137     OS_EXIT_CRITICAL(sr);
1138 }
1139 #endif
1140 
1141 static uint8_t
ble_ll_scan_get_next_adv_prim_chan(uint8_t chan)1142 ble_ll_scan_get_next_adv_prim_chan(uint8_t chan)
1143 {
1144     ++chan;
1145     if (chan == BLE_PHY_NUM_CHANS) {
1146         chan = BLE_PHY_ADV_CHAN_START;
1147     }
1148 
1149     return chan;
1150 }
1151 
1152 static uint32_t
ble_ll_scan_get_current_scan_win(struct ble_ll_scan_sm * scansm,uint32_t cputime)1153 ble_ll_scan_get_current_scan_win(struct ble_ll_scan_sm *scansm, uint32_t cputime)
1154 {
1155     uint32_t itvl;
1156     struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
1157 
1158     /* Well, in case we missed to schedule scan, lets move to next stan interval.
1159      */
1160     itvl = os_cputime_usecs_to_ticks(scanphy->scan_itvl * BLE_HCI_SCAN_ITVL);
1161     while ((int32_t)(cputime - scanphy->scan_win_start_time) >= itvl) {
1162         scanphy->scan_win_start_time += itvl;
1163 
1164         /* If we missed scan window, make sure we update scan channel */
1165         scanphy->scan_chan =
1166                 ble_ll_scan_get_next_adv_prim_chan(scanphy->scan_chan);
1167     }
1168 
1169     return scanphy->scan_win_start_time;
1170 }
1171 /**
1172  * Called to determine if we are inside or outside the scan window. If we
1173  * are inside the scan window it means that the device should be receiving
1174  * on the scan channel.
1175  *
1176  * Context: Link Layer
1177  *
1178  * @param scansm
1179  *
1180  * @return int 0: inside scan window 1: outside scan window
1181  */
1182 static int
ble_ll_scan_window_chk(struct ble_ll_scan_sm * scansm,uint32_t cputime)1183 ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
1184 {
1185     uint32_t win;
1186     uint32_t dt;
1187     uint32_t win_start;
1188     struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
1189 
1190     win_start = ble_ll_scan_get_current_scan_win(scansm, cputime);
1191 
1192     if (scanphy->scan_window != scanphy->scan_itvl) {
1193         win = os_cputime_usecs_to_ticks(scanphy->scan_window * BLE_HCI_SCAN_ITVL);
1194         dt = cputime - win_start;
1195         if (dt >= win) {
1196 #ifdef BLE_XCVR_RFCLK
1197             if (dt < (scanphy->scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
1198                 ble_ll_scan_rfclk_chk_stop();
1199             }
1200 #endif
1201             return 1;
1202         }
1203     }
1204 
1205     return 0;
1206 }
1207 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1208 static void
ble_ll_scan_aux_data_free(struct ble_ll_aux_data * aux_scan)1209 ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_scan)
1210 {
1211     if (aux_scan) {
1212         if (aux_scan->evt) {
1213             ble_hci_trans_buf_free((uint8_t *)aux_scan->evt);
1214             aux_scan->evt = NULL;
1215         }
1216         os_memblock_put(&ext_adv_pool, aux_scan);
1217         STATS_INC(ble_ll_stats, aux_freed);
1218     }
1219 }
1220 
1221 void
ble_ll_scan_aux_data_ref(struct ble_ll_aux_data * aux_data)1222 ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_data)
1223 {
1224     os_sr_t sr;
1225 
1226     if (!aux_data) {
1227         return;
1228     }
1229 
1230     OS_ENTER_CRITICAL(sr);
1231     aux_data->ref_cnt++;
1232     ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t) aux_data, aux_data->ref_cnt);
1233 
1234     OS_EXIT_CRITICAL(sr);
1235 }
1236 
1237 int
ble_ll_scan_aux_data_unref(struct ble_ll_aux_data * aux_data)1238 ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_data)
1239 {
1240     os_sr_t sr;
1241     int ret;
1242 
1243     if (!aux_data) {
1244         return 0;
1245     }
1246 
1247     OS_ENTER_CRITICAL(sr);
1248     aux_data->ref_cnt--;
1249     ret = aux_data->ref_cnt;
1250     ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_UNREF, (uint32_t) aux_data, aux_data->ref_cnt);
1251 
1252     if (aux_data->ref_cnt == 0) {
1253         ble_ll_scan_aux_data_free(aux_data);
1254     }
1255 
1256     OS_EXIT_CRITICAL(sr);
1257 
1258     return ret;
1259 }
1260 
1261 static void
ble_ll_scan_sched_remove(struct ble_ll_sched_item * sch)1262 ble_ll_scan_sched_remove(struct ble_ll_sched_item *sch)
1263 {
1264     ble_ll_scan_aux_data_free(sch->cb_arg);
1265 }
1266 #endif
1267 /**
1268  * Stop the scanning state machine
1269  */
1270 void
ble_ll_scan_sm_stop(int chk_disable)1271 ble_ll_scan_sm_stop(int chk_disable)
1272 {
1273     os_sr_t sr;
1274     uint8_t lls;
1275     struct ble_ll_scan_sm *scansm;
1276 
1277     /* Stop the scanning timer  */
1278     scansm = &g_ble_ll_scan_sm;
1279     os_cputime_timer_stop(&scansm->scan_timer);
1280 
1281     /* Disable scanning state machine */
1282     scansm->scan_enabled = 0;
1283     scansm->restart_timer_needed = 0;
1284 
1285 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1286     OS_ENTER_CRITICAL(sr);
1287     ble_ll_scan_clean_cur_aux_data();
1288     OS_EXIT_CRITICAL(sr);
1289 
1290     ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove);
1291 #endif
1292 
1293     /* Count # of times stopped */
1294     STATS_INC(ble_ll_stats, scan_stops);
1295 
1296     /* Only set state if we are currently in a scan window */
1297     if (chk_disable) {
1298         OS_ENTER_CRITICAL(sr);
1299         lls = ble_ll_state_get();
1300 
1301         if ((lls == BLE_LL_STATE_SCANNING) ||
1302                         (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
1303             /* Disable phy */
1304             ble_phy_disable();
1305 
1306             /* Set LL state to standby */
1307             ble_ll_state_set(BLE_LL_STATE_STANDBY);
1308 
1309             /* May need to stop the rfclk */
1310 #ifdef BLE_XCVR_RFCLK
1311             ble_ll_scan_rfclk_chk_stop();
1312 #endif
1313         }
1314         OS_EXIT_CRITICAL(sr);
1315     }
1316 }
1317 
1318 static int
ble_ll_scan_sm_start(struct ble_ll_scan_sm * scansm)1319 ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
1320 {
1321     /*
1322      * This is not in the specification. I will reject the command with a
1323      * command disallowed error if no random address has been sent by the
1324      * host. All the parameter errors refer to the command parameter
1325      * (which in this case is just enable or disable) so that is why I chose
1326      * command disallowed.
1327      */
1328     if (scansm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
1329         if (!ble_ll_is_valid_random_addr(g_random_addr)) {
1330             return BLE_ERR_CMD_DISALLOWED;
1331         }
1332     }
1333 
1334     /* Count # of times started */
1335     STATS_INC(ble_ll_stats, scan_starts);
1336 
1337     /* Set flag telling us that scanning is enabled */
1338     scansm->scan_enabled = 1;
1339 
1340     /* Set first advertising channel */
1341     BLE_LL_ASSERT(scansm->cur_phy != PHY_NOT_CONFIGURED);
1342     scansm->phy_data[scansm->cur_phy].scan_chan = BLE_PHY_ADV_CHAN_START;
1343 
1344     if (scansm->next_phy != PHY_NOT_CONFIGURED &&
1345             scansm->next_phy != scansm->cur_phy) {
1346         scansm->phy_data[scansm->next_phy].scan_chan = BLE_PHY_ADV_CHAN_START;
1347     }
1348 
1349     /* Reset scan request backoff parameters to default */
1350     scansm->upper_limit = 1;
1351     scansm->backoff_count = 1;
1352     scansm->scan_rsp_pending = 0;
1353 
1354     /* Forget filtered advertisers from previous scan. */
1355     g_ble_ll_scan_num_rsp_advs = 0;
1356     g_ble_ll_scan_num_dup_advs = 0;
1357 
1358     /* XXX: align to current or next slot???. */
1359     /* Schedule start time now */
1360     scansm->phy_data[scansm->cur_phy].scan_win_start_time = os_cputime_get32();
1361 
1362     /* Post scanning event to start off the scanning process */
1363     ble_ll_event_send(&scansm->scan_sched_ev);
1364 
1365     return BLE_ERR_SUCCESS;
1366 }
1367 
1368 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1369 static void
ble_ll_scan_switch_phy(struct ble_ll_scan_sm * scansm)1370 ble_ll_scan_switch_phy(struct ble_ll_scan_sm *scansm)
1371 {
1372     uint8_t tmp;
1373 
1374     if (scansm->next_phy == PHY_NOT_CONFIGURED) {
1375         return;
1376     }
1377 
1378     tmp = scansm->next_phy;
1379     scansm->next_phy = scansm->cur_phy;
1380     scansm->cur_phy = tmp;
1381 
1382     /* PHY is changing in ble_ll_scan_start() */
1383 }
1384 
1385 /**
1386  * Called to change PHY if needed and set new event time
1387  *
1388  * Context: Link Layer task.
1389  *
1390  * @param arg
1391  */
1392 static bool
ble_ll_scan_start_next_phy(struct ble_ll_scan_sm * scansm,uint32_t * next_event_time)1393 ble_ll_scan_start_next_phy(struct ble_ll_scan_sm *scansm,
1394                                  uint32_t *next_event_time)
1395 {
1396     struct ble_ll_scan_params *cur_phy;
1397     struct ble_ll_scan_params *next_phy;
1398     uint32_t now;
1399     uint32_t win;
1400 
1401     /* Lets check if we want to switch to other PHY */
1402     if (scansm->cur_phy == scansm->next_phy ||
1403             scansm->next_phy == PHY_NOT_CONFIGURED) {
1404         return false;
1405     }
1406 
1407     cur_phy = &scansm->phy_data[scansm->cur_phy];
1408     next_phy = &scansm->phy_data[scansm->next_phy];
1409 
1410     /* Store next event for current phy */
1411     cur_phy->next_event_start = *next_event_time;
1412 
1413     /* Other PHY already wanted to scan. Allow it */
1414     ble_ll_scan_switch_phy(scansm);
1415 
1416     now = os_cputime_get32();
1417 
1418     /* Start with new channel only if PHY was scanning already */
1419     if (next_phy->next_event_start != 0) {
1420         next_phy->scan_chan =
1421                 ble_ll_scan_get_next_adv_prim_chan(next_phy->scan_chan);
1422     }
1423     next_phy->scan_win_start_time = now;
1424     win = os_cputime_usecs_to_ticks(next_phy->scan_window *
1425                                     BLE_HCI_SCAN_ITVL);
1426 
1427     next_phy->next_event_start = now + win;
1428 
1429     *next_event_time = next_phy->next_event_start;
1430     return true;
1431 }
1432 
1433 static void
ble_ll_aux_scan_rsp_failed(void)1434 ble_ll_aux_scan_rsp_failed(void)
1435 {
1436     STATS_INC(ble_ll_stats, aux_scan_rsp_err);
1437     ble_ll_scan_clean_cur_aux_data();
1438 }
1439 #endif
1440 
1441 /**
1442  * Called to process the scanning OS event which was posted to the LL task
1443  *
1444  * Context: Link Layer task.
1445  *
1446  * @param arg
1447  */
1448 static void
ble_ll_scan_event_proc(struct ble_npl_event * ev)1449 ble_ll_scan_event_proc(struct ble_npl_event *ev)
1450 {
1451     os_sr_t sr;
1452     int inside_window;
1453     int start_scan;
1454     uint32_t now;
1455     uint32_t dt;
1456     uint32_t win;
1457     uint32_t win_start;
1458     uint32_t scan_itvl;
1459     uint32_t next_event_time;
1460 #ifdef BLE_XCVR_RFCLK
1461     uint32_t xtal_ticks;
1462     int xtal_state;
1463 #endif
1464     struct ble_ll_scan_sm *scansm;
1465     struct ble_ll_scan_params *scanphy;
1466 
1467     /*
1468      * Get the scanning state machine. If not enabled (this is possible), just
1469      * leave and do nothing (just make sure timer is stopped).
1470      */
1471     scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev);
1472     scanphy = &scansm->phy_data[scansm->cur_phy];
1473 
1474     OS_ENTER_CRITICAL(sr);
1475     if (!scansm->scan_enabled) {
1476         os_cputime_timer_stop(&scansm->scan_timer);
1477         OS_EXIT_CRITICAL(sr);
1478         return;
1479     }
1480 
1481     if (scansm->cur_aux_data) {
1482         /* Aux scan in progress. Wait */
1483         STATS_INC(ble_ll_stats, scan_timer_stopped);
1484         scansm->restart_timer_needed = 1;
1485         OS_EXIT_CRITICAL(sr);
1486         return;
1487     }
1488 
1489     /* Make sure the scan window start time and channel are up to date. */
1490     now = os_cputime_get32();
1491     win_start = ble_ll_scan_get_current_scan_win(scansm, now);
1492 
1493     /* Check if we are in scan window */
1494     dt = now - win_start;
1495 
1496     if (scanphy->scan_window != scanphy->scan_itvl) {
1497         win = os_cputime_usecs_to_ticks(scanphy->scan_window * BLE_HCI_SCAN_ITVL);
1498         inside_window = dt < win ? 1 : 0;
1499     } else {
1500         win = 0;
1501         /* In case continous scan lets assume we area always in the window*/
1502         inside_window = 1;
1503     }
1504 
1505     /* Determine on/off state based on scan window */
1506     scan_itvl = os_cputime_usecs_to_ticks(scanphy->scan_itvl *
1507                                                     BLE_HCI_SCAN_ITVL);
1508 
1509     if (win != 0 && inside_window) {
1510         next_event_time = win_start + win;
1511     } else {
1512         next_event_time = win_start + scan_itvl;
1513     }
1514 
1515 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1516     if (inside_window == 0  &&
1517                         ble_ll_scan_start_next_phy(scansm, &next_event_time)) {
1518         /* Check if we should start next phy. If so let's say we are inside
1519          * the window
1520          */
1521         inside_window = 1;
1522     }
1523 #endif
1524 
1525     /*
1526      * If we are not in the standby state it means that the scheduled
1527      * scanning event was overlapped in the schedule. In this case all we do
1528      * is post the scan schedule end event.
1529      */
1530     start_scan = 1;
1531     switch (ble_ll_state_get()) {
1532     case BLE_LL_STATE_ADV:
1533     case BLE_LL_STATE_CONNECTION:
1534          start_scan = 0;
1535          break;
1536     case BLE_LL_STATE_INITIATING:
1537         /* Must disable PHY since we will move to a new channel */
1538         ble_phy_disable();
1539         if (!inside_window) {
1540             ble_ll_state_set(BLE_LL_STATE_STANDBY);
1541         }
1542         /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */
1543         ble_ll_conn_reset_pending_aux_conn_rsp();
1544         break;
1545     case BLE_LL_STATE_SCANNING:
1546         /* Must disable PHY since we will move to a new channel */
1547         ble_phy_disable();
1548         if (!inside_window) {
1549             ble_ll_state_set(BLE_LL_STATE_STANDBY);
1550         }
1551         break;
1552     case BLE_LL_STATE_STANDBY:
1553         break;
1554     default:
1555         BLE_LL_ASSERT(0);
1556         break;
1557     }
1558 
1559     if (start_scan && inside_window) {
1560 #ifdef BLE_XCVR_RFCLK
1561             xtal_state = ble_ll_xcvr_rfclk_state();
1562         if (xtal_state != BLE_RFCLK_STATE_SETTLED) {
1563             if (xtal_state == BLE_RFCLK_STATE_OFF) {
1564                 xtal_ticks = g_ble_ll_data.ll_xtal_ticks;
1565             } else {
1566                 xtal_ticks = ble_ll_xcvr_rfclk_time_till_settled();
1567             }
1568 
1569             /*
1570              * Only bother if we have enough time to receive anything
1571              * here. The next event time will turn off the clock.
1572              */
1573             if (win != 0) {
1574                 if ((win - dt) <= xtal_ticks)  {
1575                     goto done;
1576                 }
1577             }
1578 
1579             /*
1580              * If clock off, start clock. Set next event time to now plus
1581              * the clock setting time.
1582              */
1583             if (xtal_state == BLE_RFCLK_STATE_OFF) {
1584                 ble_ll_xcvr_rfclk_start_now(now);
1585             }
1586             next_event_time = now + xtal_ticks;
1587             goto done;
1588         }
1589 #endif
1590         ble_ll_scan_start(scansm, NULL);
1591         goto done;
1592     }
1593 
1594 #ifdef BLE_XCVR_RFCLK
1595     if (inside_window == 0) {
1596         /*
1597          * We need to wake up before we need to start scanning in order
1598          * to make sure the rfclock is on. If we are close to being on,
1599          * enable the rfclock. If not, set wakeup time.
1600          */
1601         if (dt >= (scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
1602             /* Start the clock if necessary */
1603             if (start_scan) {
1604                 if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
1605                     ble_ll_xcvr_rfclk_start_now(now);
1606                     next_event_time = now + g_ble_ll_data.ll_xtal_ticks;
1607                 }
1608             }
1609         } else {
1610             next_event_time -= g_ble_ll_data.ll_xtal_ticks;
1611             if (start_scan) {
1612                 ble_ll_scan_rfclk_chk_stop();
1613             }
1614         }
1615     }
1616 #endif
1617 
1618 done:
1619     OS_EXIT_CRITICAL(sr);
1620     os_cputime_timer_start(&scansm->scan_timer, next_event_time);
1621 }
1622 
1623 /**
1624  * ble ll scan rx pdu start
1625  *
1626  * Called when a PDU reception has started and the Link Layer is in the
1627  * scanning state.
1628  *
1629  * Context: Interrupt
1630  *
1631  * @param pdu_type
1632  * @param rxflags
1633  *
1634  * @return int
1635  *  0: we will not attempt to reply to this frame
1636  *  1: we may send a response to this frame.
1637  */
1638 int
ble_ll_scan_rx_isr_start(uint8_t pdu_type,uint16_t * rxflags)1639 ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags)
1640 {
1641     int rc;
1642     struct ble_ll_scan_sm *scansm;
1643     struct ble_ll_scan_params *scanphy;
1644 
1645     rc = 0;
1646     scansm = &g_ble_ll_scan_sm;
1647     scanphy = &scansm->phy_data[scansm->cur_phy];
1648 
1649     switch (scanphy->scan_type) {
1650     case BLE_SCAN_TYPE_ACTIVE:
1651         /* If adv ind or scan ind, we may send scan request */
1652         if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
1653             (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)) {
1654             rc = 1;
1655         }
1656 
1657 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1658         if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) {
1659             *rxflags |= BLE_MBUF_HDR_F_EXT_ADV;
1660             rc = 1;
1661         }
1662 #endif
1663 
1664         /*
1665          * If this is the first PDU after we sent the scan response (as
1666          * denoted by the scan rsp pending flag), we set a bit in the ble
1667          * header so the link layer can check to see if the scan request
1668          * was successful. We do it this way to let the Link Layer do the
1669          * work for successful scan requests. If failed, we do the work here.
1670          */
1671         if (scansm->scan_rsp_pending) {
1672             if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) {
1673                 *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_CHK;
1674             } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_SCAN_RSP) {
1675                 *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_CHK;
1676             } else {
1677                 ble_ll_scan_req_backoff(scansm, 0);
1678 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1679                 ble_ll_aux_scan_rsp_failed();
1680 #endif
1681             }
1682         }
1683 
1684         if (scansm->cur_aux_data && !scansm->scan_rsp_pending ) {
1685             STATS_INC(ble_ll_stats, aux_received);
1686         }
1687 
1688         /* Disable wfr if running */
1689         ble_ll_wfr_disable();
1690         break;
1691     case BLE_SCAN_TYPE_PASSIVE:
1692     default:
1693         break;
1694     }
1695 
1696     return rc;
1697 }
1698 
1699 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1700 static uint8_t
ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode)1701 ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode)
1702 {
1703     switch (adv_phy_mode) {
1704     case 0x00:
1705         return BLE_PHY_1M;
1706     case 0x01:
1707         return BLE_PHY_2M;
1708     case 0x02:
1709         return BLE_PHY_CODED;
1710     }
1711 
1712     return 0;
1713 }
1714 
1715 static int
ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data * aux_data,uint8_t * buf)1716 ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf)
1717 {
1718     uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF;
1719 
1720     aux_data->chan = (aux_ptr_field) & 0x3F;
1721     if (aux_data->chan >= BLE_PHY_NUM_DATA_CHANS) {
1722         return -1;
1723     }
1724 
1725     /* TODO use CA aux_ptr_field >> 6 */
1726 
1727     aux_data->offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF);
1728 
1729     if ((aux_ptr_field >> 7) & 0x01) {
1730             aux_data->offset *= 10;
1731             aux_data->offset_units = 1;
1732     }
1733 
1734     if (aux_data->offset < BLE_LL_MAFS) {
1735         return -1;
1736     }
1737 
1738     aux_data->aux_phy =
1739             ble_ll_ext_adv_phy_mode_to_local_phy((aux_ptr_field >> 21) & 0x07);
1740     if (aux_data->aux_phy == 0) {
1741         return -1;
1742     }
1743 
1744     return 0;
1745 }
1746 
1747 static void
ble_ll_ext_scan_parse_adv_info(struct ble_ll_scan_sm * scansm,struct ble_ll_ext_adv_report * evt,uint8_t * buf)1748 ble_ll_ext_scan_parse_adv_info(struct ble_ll_scan_sm *scansm,
1749                                struct ble_ll_ext_adv_report *evt, uint8_t *buf)
1750 {
1751     uint16_t adv_info = get_le16(buf);
1752 
1753     /* TODO Use DID */
1754 
1755     evt->sid = (adv_info >> 12);
1756 }
1757 
1758 /**
1759  * ble_ll_scan_get_aux_data
1760  *
1761  * Get aux data pointer. It is new allocated data for beacon or currently
1762  * processing aux data pointer. Aux data pointer will be attached to ble_hdr.rxinfo.user_data
1763  *
1764  * Context: Interrupt
1765  *
1766  * @param scansm
1767  * @param ble_hdr
1768  * @param rxbuf
1769  * @param aux_data
1770  *
1771  * @return int
1772  *  0: new allocated aux data
1773  *  1: current processing aux data
1774  * -1: error
1775  */
1776 int
ble_ll_scan_get_aux_data(struct ble_mbuf_hdr * ble_hdr,uint8_t * rxbuf)1777 ble_ll_scan_get_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf)
1778 {
1779     uint8_t ext_hdr_len;
1780     uint8_t pdu_len;
1781     uint8_t ext_hdr_flags;
1782     uint8_t *ext_hdr;
1783     uint8_t has_addr = 0;
1784     uint8_t has_dir_addr = 0;
1785     uint8_t has_adi = 0;
1786     int i;
1787     struct ble_ll_aux_data *current_aux = ble_hdr->rxinfo.user_data;
1788     struct ble_ll_aux_data *new_aux = NULL;
1789     struct ble_ll_aux_data tmp_aux_data = { 0 };
1790     int rc;
1791 
1792     pdu_len = rxbuf[1];
1793     if (pdu_len == 0) {
1794         return -1;
1795     }
1796 
1797     tmp_aux_data.mode = rxbuf[2] >> 6;
1798 
1799     ext_hdr_len = rxbuf[2] & 0x3F;
1800     if (ext_hdr_len < BLE_LL_EXT_ADV_AUX_PTR_SIZE && !ble_hdr->rxinfo.user_data) {
1801         return -1;
1802     }
1803 
1804     ext_hdr_flags = rxbuf[3];
1805     ext_hdr = &rxbuf[4];
1806 
1807     i = 0;
1808     /* Just all until AUX PTR it for now*/
1809     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) {
1810         memcpy(tmp_aux_data.addr, ext_hdr + i, 6);
1811         tmp_aux_data.addr_type =
1812                 ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK);
1813         i += BLE_LL_EXT_ADV_ADVA_SIZE;
1814         has_addr = 1;
1815     }
1816 
1817     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) {
1818         memcpy(tmp_aux_data.dir_addr, ext_hdr + i, 6);
1819                tmp_aux_data.dir_addr_type =
1820                         ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK);
1821                has_dir_addr = 1;
1822         i += BLE_LL_EXT_ADV_TARGETA_SIZE;
1823     }
1824 
1825     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_RFU_BIT)) {
1826         i += 1;
1827     }
1828 
1829     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) {
1830         tmp_aux_data.adi = get_le16(ext_hdr + i);
1831         i += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
1832         has_adi = 1;
1833     }
1834 
1835     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) {
1836 
1837         if (ble_ll_ext_scan_parse_aux_ptr(&tmp_aux_data, ext_hdr + i) < 0) {
1838             return -1;
1839         }
1840 
1841         if (current_aux) {
1842             /* If we are here that means there is chain advertising. */
1843 
1844             /* Lets reuse old aux_data */
1845             new_aux = current_aux;
1846 
1847             /* TODO Collision; Do smth smart when did does not match */
1848             if (!(new_aux->evt_type & (BLE_HCI_ADV_SCAN_MASK))
1849                             && (tmp_aux_data.adi != new_aux->adi)) {
1850                 STATS_INC(ble_ll_stats, aux_chain_err);
1851                 new_aux->flags |= BLE_LL_AUX_INCOMPLETE_ERR_BIT;
1852             }
1853 
1854             new_aux->flags |= BLE_LL_AUX_CHAIN_BIT;
1855             new_aux->flags |= BLE_LL_AUX_INCOMPLETE_BIT;
1856         } else {
1857             if (ble_ll_scan_ext_adv_init(&new_aux) < 0) {
1858             /* Out of memory */
1859             return -1;
1860             }
1861         }
1862 
1863         new_aux->aux_phy = tmp_aux_data.aux_phy;
1864 
1865         if (!current_aux) {
1866             /* Only for first ext adv we want to keep primary phy.*/
1867             new_aux->aux_primary_phy = ble_hdr->rxinfo.phy;
1868         }
1869 
1870         new_aux->chan = tmp_aux_data.chan;
1871         new_aux->offset = tmp_aux_data.offset;
1872         new_aux->mode = tmp_aux_data.mode;
1873 
1874         /* New aux_data or chaining */
1875         rc = 0;
1876     } else {
1877 
1878         /* So ext packet does not have aux ptr. It can be because
1879          * a) it is empty beacon (no aux ptr at all)
1880          * b) there is no chaining or chaining has just stopped. In this case we do hava aux_data */
1881 
1882         if (!current_aux) {
1883             new_aux = NULL;
1884             return 1;
1885         }
1886 
1887         /*If there is no new aux ptr, just get current one */
1888         new_aux = ble_hdr->rxinfo.user_data;
1889 
1890         /* Clear incomplete flag */
1891         new_aux->flags &= ~BLE_LL_AUX_INCOMPLETE_BIT;
1892 
1893         /* Current processing aux_ptr */
1894         rc = 1;
1895     }
1896 
1897     if (has_adi) {
1898         new_aux->adi = tmp_aux_data.adi;
1899         BLE_LL_SET_AUX_FLAG(new_aux, BLE_LL_AUX_HAS_ADI);
1900     }
1901 
1902     if (has_addr) {
1903         memcpy(new_aux->addr, tmp_aux_data.addr, 6);
1904         new_aux->addr_type = tmp_aux_data.addr_type;
1905         new_aux->flags |= BLE_LL_AUX_HAS_ADDRA;
1906     }
1907 
1908     if (has_dir_addr) {
1909         memcpy(new_aux->dir_addr, tmp_aux_data.dir_addr, 6);
1910         new_aux->dir_addr_type = tmp_aux_data.dir_addr_type;
1911         new_aux->flags |= BLE_LL_AUX_HAS_DIR_ADDRA;
1912     }
1913 
1914     ble_hdr->rxinfo.user_data = new_aux;
1915 
1916     return rc;
1917 }
1918 /**
1919  * Called when a receive ADV_EXT PDU has ended.
1920  *
1921  * Context: Interrupt
1922  *
1923  * @return int
1924  *       < 0  Error
1925  *      >= 0: Success (number of bytes left in PDU)
1926  *
1927  */
1928 int
ble_ll_scan_parse_ext_hdr(struct os_mbuf * om,uint8_t * adva,uint8_t adva_type,uint8_t * inita,uint8_t inita_type,struct ble_mbuf_hdr * ble_hdr,struct ble_ll_ext_adv_report * out_evt)1929 ble_ll_scan_parse_ext_hdr(struct os_mbuf *om,
1930                           uint8_t *adva, uint8_t adva_type,
1931                           uint8_t *inita, uint8_t inita_type,
1932                           struct ble_mbuf_hdr *ble_hdr,
1933                           struct ble_ll_ext_adv_report *out_evt)
1934 {
1935     uint8_t pdu_len;
1936     uint8_t ext_hdr_len;
1937     uint8_t ext_hdr_flags;
1938     uint8_t *ext_hdr;
1939     uint8_t *rxbuf = om->om_data;
1940     int i = 1;
1941     struct ble_ll_scan_sm *scansm;
1942     struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data;
1943 
1944     if (!out_evt) {
1945         return -1;
1946     }
1947 
1948     scansm = &g_ble_ll_scan_sm;
1949 
1950     if (!scansm->ext_scanning) {
1951        /* Ignore ext adv if host does not want it*/
1952        return -1;
1953     }
1954 
1955     pdu_len = rxbuf[1];
1956     if (pdu_len == 0) {
1957         return -1;
1958     }
1959 
1960     out_evt->evt_type = rxbuf[2] >> 6;
1961     if (out_evt->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) {
1962         return -1;
1963     }
1964 
1965     if (BLE_MBUF_HDR_SCAN_RSP_RCV(ble_hdr)) {
1966         out_evt->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK;
1967     }
1968 
1969     ext_hdr_len = rxbuf[2] & 0x3F;
1970     os_mbuf_adj(om, 3);
1971 
1972     ext_hdr_flags = rxbuf[3];
1973     ext_hdr = &rxbuf[4];
1974 
1975     i = 0;
1976     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) {
1977         i += BLE_LL_EXT_ADV_ADVA_SIZE;
1978     }
1979 
1980     if (adva) {
1981         memcpy(out_evt->addr, adva, 6);
1982         out_evt->addr_type = adva_type;
1983     }
1984 
1985     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) {
1986         i += BLE_LL_EXT_ADV_TARGETA_SIZE;
1987     }
1988 
1989     if (inita) {
1990        memcpy(out_evt->dir_addr, inita, 6);
1991        out_evt->dir_addr_type = inita_type;
1992        out_evt->evt_type |= BLE_HCI_ADV_DIRECT_MASK;
1993     }
1994 
1995     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_RFU_BIT)) {
1996         /* Just skip it for now*/
1997         i += 1;
1998     }
1999 
2000     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) {
2001         ble_ll_ext_scan_parse_adv_info(scansm, out_evt, (ext_hdr + i));
2002         i += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
2003     } else if (out_evt->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) {
2004         out_evt->sid = (aux_data->adi >> 12);
2005     }
2006 
2007     /* In this point of time we don't want to care about aux ptr */
2008     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) {
2009         i += BLE_LL_EXT_ADV_AUX_PTR_SIZE;
2010     }
2011 
2012     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) {
2013         /* TODO Handle periodic adv */
2014         i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE;
2015     }
2016 
2017     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) {
2018         out_evt->tx_power = *(ext_hdr + i);
2019         i += BLE_LL_EXT_ADV_TX_POWER_SIZE;
2020     }
2021 
2022     /* Skip ADAC if it is there */
2023     i = ext_hdr_len;
2024 
2025     /* In the event we need information on primary and secondary PHY used during
2026      * advertising.
2027      */
2028     if (!aux_data) {
2029         out_evt->prim_phy = ble_hdr->rxinfo.phy;
2030         goto done;
2031     }
2032 
2033     out_evt->sec_phy = aux_data->aux_phy;
2034     out_evt->prim_phy = aux_data->aux_primary_phy;
2035 
2036     /* Adjust mbuf to contain advertising data only */
2037     os_mbuf_adj(om, i);
2038 
2039     /* Let us first keep update event type in aux data.
2040      * Note that in aux chain and aux scan response packets
2041      * we do miss original event type, which we need for advertising report.
2042      */
2043     aux_data->evt_type |= out_evt->evt_type;
2044     out_evt->evt_type = aux_data->evt_type;
2045 
2046 done:
2047     return pdu_len - i - 1;
2048 }
2049 
2050 static int
ble_ll_scan_get_addr_from_ext_adv(uint8_t * rxbuf,struct ble_mbuf_hdr * ble_hdr,uint8_t ** addr,uint8_t * addr_type,uint8_t ** inita,uint8_t * inita_type,int * ext_mode)2051 ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr,
2052                                   uint8_t **addr, uint8_t *addr_type,
2053                                   uint8_t **inita, uint8_t *inita_type,
2054                                   int *ext_mode)
2055 {
2056     uint8_t pdu_len;
2057     uint8_t ext_hdr_len;
2058     uint8_t ext_hdr_flags;
2059     uint8_t *ext_hdr;
2060     int i;
2061     struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data;
2062 
2063     pdu_len = rxbuf[1];
2064     if (pdu_len == 0) {
2065         return -1;
2066     }
2067 
2068     *ext_mode = rxbuf[2] >> 6;
2069     if (*ext_mode > BLE_LL_EXT_ADV_MODE_SCAN) {
2070         return -1;
2071     }
2072 
2073     if (aux_data) {
2074         /* If address has been provided, we do have it already in aux_data.*/
2075         if (aux_data->flags & BLE_LL_AUX_HAS_ADDRA) {
2076             *addr = aux_data->addr;
2077             *addr_type = aux_data->addr_type;
2078         }
2079 
2080         if (!inita) {
2081             return 0;
2082         }
2083 
2084         if (aux_data->flags & BLE_LL_AUX_HAS_DIR_ADDRA) {
2085             *inita = aux_data->dir_addr;
2086             *inita_type = aux_data->dir_addr_type;
2087         }
2088 
2089         return 0;
2090     }
2091 
2092     /* If this is just becon with no aux data, lets get address from the packet */
2093 
2094     ext_hdr_len = rxbuf[2] & 0x3F;
2095 
2096     ext_hdr_flags = rxbuf[3];
2097     ext_hdr = &rxbuf[4];
2098 
2099     i = 0;
2100     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) {
2101         if (ext_hdr_len < BLE_LL_EXT_ADV_ADVA_SIZE) {
2102             return -1;
2103         }
2104 
2105         *addr = ext_hdr + i;
2106         *addr_type =
2107                 ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK);
2108         i += BLE_LL_EXT_ADV_ADVA_SIZE;
2109     }
2110 
2111     if (!inita) {
2112         return 0;
2113     }
2114 
2115     if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) {
2116         *inita = ext_hdr + i;
2117         *inita_type =
2118                 ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK);
2119         i += BLE_LL_EXT_ADV_TARGETA_SIZE;
2120     }
2121 
2122     return 0;
2123 }
2124 
2125 static int
ble_ll_scan_get_adi(struct ble_ll_aux_data * aux_data,uint16_t * adi)2126 ble_ll_scan_get_adi(struct ble_ll_aux_data *aux_data, uint16_t *adi)
2127 {
2128     if (!aux_data) {
2129         return -1;
2130     }
2131 
2132     if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_HAS_ADI)) {
2133         return -1;
2134     }
2135 
2136     *adi = aux_data->adi;
2137 
2138     return 0;
2139 }
2140 #endif
2141 
2142 int
ble_ll_scan_adv_decode_addr(uint8_t pdu_type,uint8_t * rxbuf,struct ble_mbuf_hdr * ble_hdr,uint8_t ** addr,uint8_t * addr_type,uint8_t ** inita,uint8_t * inita_type,int * ext_mode)2143 ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf,
2144                             struct ble_mbuf_hdr *ble_hdr,
2145                             uint8_t **addr, uint8_t *addr_type,
2146                             uint8_t **inita, uint8_t *inita_type,
2147                             int *ext_mode)
2148 {
2149     if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND &&
2150         pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) {
2151         /* Legacy advertising */
2152         *addr_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK);
2153         *addr = rxbuf + BLE_LL_PDU_HDR_LEN;
2154 
2155         if (!inita) {
2156             return 0;
2157         }
2158 
2159         if (pdu_type != BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) {
2160             *inita = NULL;
2161             *inita_type = 0;
2162             return 0;
2163         }
2164 
2165         *inita = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
2166         *inita_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK);
2167 
2168         return 0;
2169     }
2170 
2171     /* Extended advertising */
2172 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2173     if (ble_ll_scan_get_addr_from_ext_adv(rxbuf, ble_hdr, addr, addr_type,
2174                                           inita, inita_type, ext_mode)) {
2175         return -1;
2176     }
2177 #else
2178     return -1;
2179 #endif
2180 
2181     return 0;
2182 }
2183 
2184 /**
2185  * Called when a receive PDU has ended.
2186  *
2187  * Context: Interrupt
2188  *
2189  * @param rxpdu
2190  *
2191  * @return int
2192  *       < 0: Disable the phy after reception.
2193  *      == 0: Success. Do not disable the PHY.
2194  *       > 0: Do not disable PHY as that has already been done.
2195  */
2196 int
ble_ll_scan_rx_isr_end(struct os_mbuf * rxpdu,uint8_t crcok)2197 ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
2198 {
2199     int rc;
2200     int chk_send_req;
2201     int chk_wl;
2202     int index;
2203     int resolved;
2204     uint8_t pdu_type;
2205     uint8_t addr_type;
2206     uint8_t peer_addr_type = 0;
2207     uint8_t *adv_addr = NULL;
2208     uint8_t *peer = NULL;
2209     uint8_t *rxbuf;
2210     struct ble_mbuf_hdr *ble_hdr;
2211     struct ble_ll_scan_sm *scansm;
2212     struct ble_ll_scan_params *scanphy;
2213     int ext_adv_mode = -1;
2214 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2215     uint8_t phy_mode;
2216     uint16_t adi;
2217 #endif
2218 
2219     /* Get scanning state machine */
2220     scansm = &g_ble_ll_scan_sm;
2221     scanphy = &scansm->phy_data[scansm->cur_phy];
2222 
2223     /*
2224      * The reason we do something different here (as opposed to failed CRC) is
2225      * that the received PDU will not be handed up in this case. So we have
2226      * to restart scanning and handle a failed scan request. Note that we
2227      * return 0 in this case because we dont want the phy disabled.
2228      */
2229     if (rxpdu == NULL) {
2230         if (scansm->scan_rsp_pending) {
2231             ble_ll_scan_req_backoff(scansm, 0);
2232 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2233             ble_ll_aux_scan_rsp_failed();
2234 #endif
2235         }
2236         ble_phy_restart_rx();
2237         return 0;
2238     }
2239 
2240     rc = -1;
2241 
2242     ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
2243 
2244 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2245     if (scansm->cur_aux_data) {
2246         ble_hdr->rxinfo.user_data = scansm->cur_aux_data;
2247         scansm->cur_aux_data = NULL;
2248         if (ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data) == 0) {
2249             ble_hdr->rxinfo.user_data = NULL;
2250             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
2251             goto scan_rx_isr_exit;
2252         }
2253     }
2254 #endif
2255 
2256     /* Just leave if the CRC is not OK. */
2257     if (!crcok) {
2258 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2259         ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
2260 #endif
2261         goto scan_rx_isr_exit;
2262     }
2263 
2264     /* Get pdu type, pointer to address and address "type"  */
2265     rxbuf = rxpdu->om_data;
2266     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
2267 
2268 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2269     if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
2270         if (!scansm->ext_scanning) {
2271             goto scan_rx_isr_exit;
2272         }
2273         /* Create new aux data for beacon or get current processing aux ptr */
2274         rc = ble_ll_scan_get_aux_data(ble_hdr, rxbuf);
2275         if (rc < 0) {
2276             /* No memory or broken packet */
2277             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID;
2278 
2279             goto scan_rx_isr_exit;
2280         }
2281         if (rc == 0) {
2282             /* Let's tell LL to schedule aux */
2283             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT;
2284         }
2285 
2286         rc = -1;
2287     }
2288 #endif
2289 
2290     /* Lets get addresses from advertising report*/
2291     if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr,
2292                                     &peer, &peer_addr_type,
2293                                     NULL, NULL, &ext_adv_mode)) {
2294         goto scan_rx_isr_exit;
2295     }
2296 
2297     /* Determine if request may be sent and if whitelist needs to be checked */
2298     chk_send_req = 0;
2299     switch (pdu_type) {
2300 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2301     case BLE_ADV_PDU_TYPE_ADV_EXT_IND:
2302         if (!peer) {
2303             /*Wait for AUX ptr */
2304             goto scan_rx_isr_exit;
2305         }
2306 
2307         if ((ext_adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) &&
2308                 (scanphy->scan_type == BLE_SCAN_TYPE_ACTIVE)) {
2309             chk_send_req = 1;
2310         }
2311         chk_wl = 1;
2312     break;
2313 #endif
2314     case BLE_ADV_PDU_TYPE_ADV_IND:
2315     case BLE_ADV_PDU_TYPE_ADV_SCAN_IND:
2316         if (scanphy->scan_type == BLE_SCAN_TYPE_ACTIVE) {
2317             chk_send_req = 1;
2318         }
2319         chk_wl = 1;
2320         break;
2321     case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND:
2322     case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
2323         chk_wl = 1;
2324         break;
2325     default:
2326         chk_wl = 0;
2327         break;
2328     }
2329 
2330     /* Since peer might point to different address e.g. resolved one
2331      * lets do a copy of pointers for scan request
2332      */
2333     adv_addr = peer;
2334     addr_type = peer_addr_type;
2335 
2336     if ((scanphy->scan_filt_policy & 1) == 0) {
2337         chk_wl = 0;
2338     }
2339     resolved = 0;
2340 
2341     index = -1;
2342 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
2343     if (ble_ll_is_rpa(peer, peer_addr_type) && ble_ll_resolv_enabled()) {
2344         index = ble_hw_resolv_list_match();
2345         if (index >= 0) {
2346             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
2347             peer = g_ble_ll_resolv_list[index].rl_identity_addr;
2348             peer_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
2349             resolved = 1;
2350         } else {
2351             if (chk_wl) {
2352                 goto scan_rx_isr_exit;
2353             }
2354         }
2355     }
2356 #endif
2357     scansm->scan_rpa_index = index;
2358 
2359     /* If whitelist enabled, check to see if device is in the white list */
2360     if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
2361         goto scan_rx_isr_exit;
2362     }
2363     ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
2364 
2365     /* Should we send a scan request? */
2366     if (chk_send_req) {
2367 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2368         if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
2369             if (ble_ll_scan_get_adi(ble_hdr->rxinfo.user_data, &adi) < 0) {
2370                 /* There is not ADI in scannable packet? This must be some trash,
2371                  * ignore it
2372                  */
2373                 goto scan_rx_isr_exit;
2374             }
2375             if (ble_ll_scan_have_rxd_scan_rsp(peer, peer_addr_type, 1, adi)) {
2376                 goto scan_rx_isr_exit;
2377             }
2378         } else {
2379             /* Dont send scan request if we have sent one to this advertiser */
2380             if (ble_ll_scan_have_rxd_scan_rsp(peer, peer_addr_type, 0, 0)) {
2381                 goto scan_rx_isr_exit;
2382             }
2383         }
2384 #else
2385         /* Dont send scan request if we have sent one to this advertiser */
2386         if (ble_ll_scan_have_rxd_scan_rsp(peer, peer_addr_type, 0, 0)) {
2387             goto scan_rx_isr_exit;
2388         }
2389 #endif
2390         /* Better not be a scan response pending */
2391         BLE_LL_ASSERT(scansm->scan_rsp_pending == 0);
2392 
2393         /* We want to send a request. See if backoff allows us */
2394         --scansm->backoff_count;
2395         if (scansm->backoff_count == 0) {
2396 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2397             phy_mode = ble_ll_phy_to_phy_mode(ble_hdr->rxinfo.phy,
2398                                               BLE_HCI_LE_PHY_CODED_ANY);
2399             if (ble_ll_sched_scan_req_over_aux_ptr(ble_hdr->rxinfo.channel,
2400                                                    phy_mode)) {
2401                 goto scan_rx_isr_exit;
2402             }
2403 #endif
2404             /* XXX: TODO assume we are on correct phy */
2405             ble_ll_scan_req_pdu_make(scansm, adv_addr, addr_type);
2406             rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, scansm->scan_req_pdu,
2407                             BLE_PHY_TRANSITION_TX_RX);
2408 
2409             if (rc == 0) {
2410                 /* Set "waiting for scan response" flag */
2411                 scansm->scan_rsp_pending = 1;
2412 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2413                 if (ble_hdr->rxinfo.channel <  BLE_PHY_NUM_DATA_CHANS) {
2414                     /* Let's keep the aux ptr as a reference to scan rsp */
2415                     scansm->cur_aux_data = ble_hdr->rxinfo.user_data;
2416                     ble_ll_scan_aux_data_ref(scansm->cur_aux_data);
2417                     STATS_INC(ble_ll_stats, aux_scan_req_tx);
2418                 }
2419 #endif
2420             }
2421         }
2422     }
2423 
2424 scan_rx_isr_exit:
2425     if (rc) {
2426         ble_ll_state_set(BLE_LL_STATE_STANDBY);
2427     }
2428 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2429     /* On handover lets increase ref count */
2430     if (ble_hdr->rxinfo.user_data) {
2431         ble_ll_scan_aux_data_ref(ble_hdr->rxinfo.user_data);
2432     }
2433 #endif
2434     return rc;
2435 }
2436 
2437 /**
2438  * Called to resume scanning. This is called after an advertising event or
2439  * connection event has ended. It is also called if we receive a packet while
2440  * in the initiating or scanning state.
2441  *
2442  * Context: Link Layer task
2443  */
2444 void
ble_ll_scan_chk_resume(void)2445 ble_ll_scan_chk_resume(void)
2446 {
2447     os_sr_t sr;
2448     struct ble_ll_scan_sm *scansm;
2449 
2450     scansm = &g_ble_ll_scan_sm;
2451     if (scansm->scan_enabled) {
2452         OS_ENTER_CRITICAL(sr);
2453         if (scansm->restart_timer_needed) {
2454             scansm->restart_timer_needed = 0;
2455             ble_ll_event_send(&scansm->scan_sched_ev);
2456             STATS_INC(ble_ll_stats, scan_timer_restarted);
2457             OS_EXIT_CRITICAL(sr);
2458             return;
2459         }
2460 
2461         if (ble_ll_state_get() == BLE_LL_STATE_STANDBY &&
2462                     ble_ll_scan_window_chk(scansm, os_cputime_get32()) == 0) {
2463             /* Turn on the receiver and set state */
2464             ble_ll_scan_start(scansm, NULL);
2465         }
2466         OS_EXIT_CRITICAL(sr);
2467     }
2468 }
2469 
2470 /**
2471  * Scan timer callback; means that the scan window timeout has been reached
2472  * and we should perform the appropriate actions.
2473  *
2474  * Context: Interrupt (cputimer)
2475  *
2476  * @param arg Pointer to scan state machine.
2477  */
2478 void
ble_ll_scan_timer_cb(void * arg)2479 ble_ll_scan_timer_cb(void *arg)
2480 {
2481     struct ble_ll_scan_sm *scansm;
2482 
2483     scansm = (struct ble_ll_scan_sm *)arg;
2484     ble_ll_event_send(&scansm->scan_sched_ev);
2485 }
2486 
2487 /**
2488  * Called when the wait for response timer expires while in the scanning
2489  * state.
2490  *
2491  * Context: Interrupt.
2492  */
2493 void
ble_ll_scan_wfr_timer_exp(void)2494 ble_ll_scan_wfr_timer_exp(void)
2495 {
2496     struct ble_ll_scan_sm *scansm;
2497 
2498     /*
2499      * If we timed out waiting for a response, the scan response pending
2500      * flag should be set. Deal with scan backoff. Put device back into rx.
2501      */
2502     scansm = &g_ble_ll_scan_sm;
2503     if (scansm->scan_rsp_pending) {
2504         ble_ll_scan_req_backoff(scansm, 0);
2505 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2506         ble_ll_aux_scan_rsp_failed();
2507         ble_ll_scan_chk_resume();
2508 #endif
2509     }
2510 
2511 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2512     if (scansm->cur_aux_data) {
2513         ble_ll_scan_end_adv_evt(scansm->cur_aux_data);
2514         scansm->cur_aux_data = NULL;
2515         STATS_INC(ble_ll_stats, aux_missed_adv);
2516         ble_ll_scan_chk_resume();
2517     }
2518 #endif
2519 
2520     ble_phy_restart_rx();
2521 }
2522 
2523 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2524 /*
2525  * Send extended advertising report
2526  *
2527  * @return -1 on error (data truncated or other error)
2528  *          0 on success (data status is "completed")
2529  *          1 on success (data status is not "completed")
2530  */
2531 static int
ble_ll_hci_send_ext_adv_report(uint8_t ptype,uint8_t * adva,uint8_t adva_type,uint8_t * inita,uint8_t inita_type,struct os_mbuf * om,struct ble_mbuf_hdr * hdr)2532 ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
2533                                uint8_t *inita, uint8_t inita_type,
2534                                struct os_mbuf *om,
2535                                struct ble_mbuf_hdr *hdr)
2536 {
2537     struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
2538     struct ble_ll_ext_adv_report *evt;
2539     struct ble_ll_ext_adv_report *next_evt;
2540     int offset;
2541     int datalen;
2542     int rc;
2543     bool need_event;
2544     uint8_t max_event_len;
2545 
2546     if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
2547         rc = -1;
2548         goto done;
2549     }
2550 
2551     /*
2552      * We keep one allocated event in aux_data to be able to truncate chain
2553      * properly in case of error. If there is no event in aux_data it means this
2554      * is the first event for this chain.
2555      */
2556     if (aux_data && aux_data->evt) {
2557         evt = aux_data->evt;
2558         aux_data->evt = NULL;
2559     } else {
2560         evt = ble_ll_scan_init_ext_adv_report(NULL);
2561         if (!evt) {
2562             rc = -1;
2563             goto done;
2564         }
2565     }
2566 
2567     datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, hdr, evt);
2568     if (datalen < 0) {
2569         /* XXX what should we do here? send some trimmed event? */
2570         ble_hci_trans_buf_free((uint8_t *)evt);
2571         rc = -1;
2572         goto done;
2573     }
2574 
2575     offset = 0;
2576     max_event_len = min(UINT8_MAX, BLE_LL_MAX_EVT_LEN);
2577 
2578     do {
2579         need_event = false;
2580         next_evt = NULL;
2581 
2582         evt->adv_data_len = min(max_event_len - sizeof(*evt),
2583                                 datalen - offset);
2584         /* Event len, should not contain event meta code and let itself */
2585         evt->event_len = (sizeof(*evt) - BLE_HCI_EVENT_HDR_LEN) + evt->adv_data_len;
2586         evt->rssi = hdr->rxinfo.rssi;
2587 
2588         os_mbuf_copydata(om, offset, evt->adv_data_len, evt->adv_data);
2589         offset += evt->adv_data_len;
2590 
2591 
2592         if (offset < datalen) {
2593             /* Need another event for next fragment of this PDU */
2594             need_event = true;
2595         } else if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
2596             need_event = false;
2597         } else if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) {
2598             /* Need another event for next PDU in chain */
2599             need_event = true;
2600         }
2601 
2602         /* Assume data status is not "completed" */
2603         rc = 1;
2604 
2605         if (need_event) {
2606             /*
2607              * We will need another event so let's try to allocate one now. If
2608              * we cannot do this, need to mark event as truncated.
2609              */
2610             next_evt = ble_ll_scan_init_ext_adv_report(evt);
2611 
2612             if (next_evt) {
2613                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE);
2614             } else {
2615                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
2616                 BLE_LL_SET_AUX_FLAG(aux_data, BLE_LL_AUX_TRUNCATED_SENT);
2617                 rc = -1;
2618             }
2619         } else if (aux_data ) {
2620             if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
2621                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_TRUNCATED);
2622                 rc = -1;
2623             } else if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_BIT)) {
2624                 evt->evt_type |= (BLE_HCI_ADV_DATA_STATUS_INCOMPLETE);
2625             } else {
2626                 rc = 0;
2627             }
2628         } else {
2629             rc = 0;
2630         }
2631 
2632         ble_ll_hci_event_send((uint8_t *)evt);
2633 
2634         evt = next_evt;
2635     } while ((offset < datalen) && evt);
2636 
2637     BLE_LL_ASSERT(offset <= datalen);
2638 
2639     if (aux_data){
2640         /* Store any event left for later use */
2641         aux_data->evt = evt;
2642     } else {
2643         /* If it is empty beacon, evt shall be NULL */
2644         BLE_LL_ASSERT(!evt);
2645     }
2646 
2647 done:
2648     /* If advertising event is completed or failed, we can drop the reference */
2649     if (rc <= 0) {
2650         if (aux_data){
2651             if ((rc == 0) && (aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK)) {
2652                 /* Scan response completed successfully */
2653                 ble_ll_scan_add_scan_rsp_adv(aux_data->addr, aux_data->addr_type,
2654                                              1, aux_data->adi);
2655             }
2656             ble_ll_scan_aux_data_unref(aux_data);
2657         }
2658     }
2659 
2660     return rc;
2661 }
2662 #endif
2663 /**
2664  * Process a received PDU while in the scanning state.
2665  *
2666  * Context: Link Layer task.
2667  *
2668  * @param pdu_type
2669  * @param rxbuf
2670  */
2671 void
ble_ll_scan_rx_pkt_in(uint8_t ptype,struct os_mbuf * om,struct ble_mbuf_hdr * hdr)2672 ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr)
2673 {
2674 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
2675     int index;
2676     struct ble_ll_resolv_entry *rl;
2677 #endif
2678     uint8_t *rxbuf = om->om_data;
2679     uint8_t *adv_addr = NULL;
2680     uint8_t *adva;
2681     uint8_t *ident_addr;
2682     uint8_t ident_addr_type;
2683     uint8_t *init_addr = NULL;
2684     uint8_t init_addr_type = 0;
2685     uint8_t txadd = 0;
2686     uint8_t rxadd;
2687     uint8_t scan_rsp_chk;
2688     struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
2689     struct ble_mbuf_hdr *ble_hdr;
2690     int ext_adv_mode = -1;
2691 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2692     struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
2693     int rc;
2694     uint8_t evt_possibly_truncated = 0;
2695 #endif
2696 
2697     /* Set scan response check flag */
2698     scan_rsp_chk = BLE_MBUF_HDR_SCAN_RSP_RCV(hdr);
2699 
2700     /* We dont care about scan requests or connect requests */
2701     if (!BLE_MBUF_HDR_CRC_OK(hdr)) {
2702 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2703         if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
2704             evt_possibly_truncated = 1;
2705         }
2706 #endif
2707         goto scan_continue;
2708     }
2709 
2710     if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) || (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
2711         goto scan_continue;
2712     }
2713 
2714     if (ble_ll_scan_adv_decode_addr(ptype, rxbuf, hdr,
2715                                     &adv_addr, &txadd,
2716                                     &init_addr, &init_addr_type,
2717                                     &ext_adv_mode)) {
2718 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2719         evt_possibly_truncated = 1;
2720 #endif
2721         goto scan_continue;
2722     }
2723 
2724     ident_addr = adv_addr;
2725     ident_addr_type = txadd;
2726 
2727 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
2728     index = scansm->scan_rpa_index;
2729     if (index >= 0) {
2730         ident_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
2731         ident_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
2732 
2733         if (ble_ll_is_rpa(init_addr, init_addr_type)) {
2734            /* Let's try resolve InitA. */
2735            if (ble_ll_resolv_rpa(init_addr, g_ble_ll_resolv_list[index].rl_local_irk)) {
2736                init_addr = ble_ll_get_our_devaddr(scansm->own_addr_type & 1);
2737                init_addr_type = scansm->own_addr_type;
2738            }
2739        }
2740     } else if (init_addr && ble_ll_resolv_enabled() && ble_ll_is_rpa(init_addr, init_addr_type)) {
2741         /* If we are here it means AdvA is identity. Check if initA is RPA */
2742         rl = ble_ll_resolv_list_find(ident_addr, ident_addr_type);
2743         if (rl && ble_ll_resolv_rpa(init_addr, rl->rl_local_irk)) {
2744             init_addr = ble_ll_get_our_devaddr(scansm->own_addr_type & 1);
2745             init_addr_type = scansm->own_addr_type;
2746         }
2747     }
2748 #endif
2749 
2750     /* Check the scanner filter policy */
2751     if (ble_ll_scan_chk_filter_policy(ptype, adv_addr, txadd, init_addr,
2752                                       init_addr_type,
2753                                       BLE_MBUF_HDR_DEVMATCH(hdr))) {
2754 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2755         ble_ll_scan_aux_data_unref(aux_data);
2756 #endif
2757         goto scan_continue;
2758     }
2759 
2760     /*
2761      * XXX: The BLE spec is a bit unclear here. What if we get a scan
2762      * response from an advertiser that we did not send a request to?
2763      * Do we send an advertising report? Do we add it to list of devices
2764      * that we have heard a scan response from?
2765      */
2766     if (ptype == BLE_ADV_PDU_TYPE_SCAN_RSP) {
2767         /*
2768          * If this is a scan response in reply to a request we sent we need
2769          * to store this advertiser's address so we dont send a request to it.
2770          */
2771         if (scansm->scan_rsp_pending && scan_rsp_chk) {
2772             /*
2773              * We could also check the timing of the scan reponse; make sure
2774              * that it is relatively close to the end of the scan request but
2775              * we wont for now.
2776              */
2777             ble_hdr = BLE_MBUF_HDR_PTR(scansm->scan_req_pdu);
2778             rxadd = ble_hdr->txinfo.hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK;
2779             adva = scansm->scan_req_pdu->om_data + BLE_DEV_ADDR_LEN;
2780             if (((txadd && rxadd) || ((txadd + rxadd) == 0)) &&
2781                 !memcmp(adv_addr, adva, BLE_DEV_ADDR_LEN)) {
2782                 /* We have received a scan response. Add to list */
2783                 ble_ll_scan_add_scan_rsp_adv(ident_addr, ident_addr_type, 0, 0);
2784 
2785                 /* Perform scan request backoff procedure */
2786                 ble_ll_scan_req_backoff(scansm, 1);
2787             }
2788         } else {
2789             /* Ignore if this is not ours */
2790             goto scan_continue;
2791         }
2792     }
2793 
2794     /* Filter duplicates */
2795     if (scansm->scan_filt_dups) {
2796         if (ble_ll_scan_is_dup_adv(ptype, ident_addr_type, ident_addr)) {
2797 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2798             if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
2799                 ble_ll_scan_aux_data_unref(aux_data);
2800             }
2801 #endif
2802             goto scan_continue;
2803         }
2804     }
2805 
2806 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2807     if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) {
2808         if (!scansm->ext_scanning) {
2809             ble_ll_scan_aux_data_unref(aux_data);
2810             goto scan_continue;
2811         }
2812 
2813         if (BLE_MBUF_HDR_AUX_INVALID(hdr)) {
2814             evt_possibly_truncated = 1;
2815             goto scan_continue;
2816         }
2817 
2818         /* If it is ignore it means event is already truncated, just unref aux */
2819         if (aux_data && BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_IGNORE_BIT)) {
2820             ble_ll_scan_aux_data_unref(aux_data);
2821             goto scan_continue;
2822         }
2823 
2824         /* Let's see if that packet contains aux ptr*/
2825         if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
2826            BLE_LL_ASSERT(aux_data);
2827             if (ble_ll_sched_aux_scan(hdr, scansm, hdr->rxinfo.user_data)) {
2828                 /* We are here when could not schedule the aux ptr */
2829                 hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT;
2830                 /* Mark that chain is trimmed */
2831                 aux_data->flags |= BLE_LL_AUX_INCOMPLETE_ERR_BIT;
2832                 /* Note: aux_data unref will be done when truncated is sent to the host or
2833                  * below if we failed to schedule for the very first aux packet.
2834                  */
2835             } else {
2836                 /* We are here because successfully scheduled for next aux */
2837                 ble_ll_scan_aux_data_ref(aux_data);
2838             }
2839 
2840             /*
2841              * If this is ext adv, there is nothing to do here but just leave and wait
2842              * for aux packet. However, if we was not able to schedule for first aux packet,
2843              * make sure to unref aux_data here
2844              */
2845             if (!BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_CHAIN_BIT)) {
2846                 if (BLE_LL_CHECK_AUX_FLAG(aux_data, BLE_LL_AUX_INCOMPLETE_ERR_BIT)) {
2847                     ble_ll_scan_aux_data_unref(aux_data);
2848                 }
2849                 goto scan_continue;
2850             }
2851 
2852             STATS_INC(ble_ll_stats, aux_chain_cnt);
2853         }
2854 
2855         /* For the time when sending events up, lets increase ref count */
2856         ble_ll_scan_aux_data_ref(aux_data);
2857         rc = ble_ll_hci_send_ext_adv_report(ptype, ident_addr, ident_addr_type,
2858                                             init_addr, init_addr_type, om, hdr);
2859         if (rc < 0) {
2860             /*
2861              * Data were trimmed so no need to scan this chain anymore. Also
2862              * make sure we do not send any more events for this chain, just in
2863              * case we managed to scan something before events were processed.
2864              */
2865             if (BLE_MBUF_HDR_WAIT_AUX(hdr)) {
2866                 hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT;
2867                 if (ble_ll_sched_rmv_elem(&aux_data->sch) == 0) {
2868                     ble_ll_scan_aux_data_unref(aux_data);
2869                 }
2870             }
2871             aux_data->flags |= BLE_LL_AUX_IGNORE_BIT;
2872         }
2873         ble_ll_scan_aux_data_unref(aux_data);
2874 
2875         ble_ll_scan_switch_phy(scansm);
2876 
2877         if (scansm->scan_rsp_pending) {
2878             if (!scan_rsp_chk) {
2879                 /* We are here because we sent SCAN_REQ and wait for SCAN_RSP.
2880                  * We do not drop reference here by purpose, because
2881                  * it was already dropped in ble_ll_hci_send_ext_adv_report() as
2882                  * very first advertising report for scannable report is "completed"
2883                  */
2884                 return;
2885             }
2886 
2887             /* XXX: For now let us consider scan response as succeed in the backoff context,
2888              * after first scan response packet is received.
2889              * I guess we should marked it succeed after complete scan response is received,
2890              * and failed when truncated, but then we need to analyze reason of truncation as it
2891              * also might be issue of the resources on our side
2892              */
2893             ble_ll_scan_req_backoff(scansm, 1);
2894         }
2895 
2896         goto scan_continue;
2897     }
2898 #endif
2899 
2900     /* Send the advertising report */
2901     ble_ll_scan_send_adv_report(ptype, ident_addr, ident_addr_type,
2902                                 init_addr, init_addr_type, om, hdr, scansm);
2903 
2904 scan_continue:
2905 
2906 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2907     if (aux_data) {
2908         if (evt_possibly_truncated) {
2909             ble_ll_scan_end_adv_evt(aux_data);
2910         } else {
2911             /* This is ref for handover to LL */
2912             ble_ll_scan_aux_data_unref(aux_data);
2913         }
2914     }
2915 #endif
2916     /*
2917      * If the scan response check bit is set and we are pending a response,
2918      * we have failed the scan request (as we would have reset the scan rsp
2919      * pending flag if we received a valid response
2920      */
2921     if (scansm->scan_rsp_pending && scan_rsp_chk) {
2922         ble_ll_scan_req_backoff(scansm, 0);
2923     }
2924 
2925     ble_ll_scan_chk_resume();
2926 }
2927 
2928 int
ble_ll_scan_set_scan_params(uint8_t * cmd)2929 ble_ll_scan_set_scan_params(uint8_t *cmd)
2930 {
2931     uint8_t scan_type;
2932     uint8_t own_addr_type;
2933     uint8_t filter_policy;
2934     uint16_t scan_itvl;
2935     uint16_t scan_window;
2936     struct ble_ll_scan_sm *scansm;
2937     struct ble_ll_scan_params *scanp;
2938 
2939     /* If already enabled, we return an error */
2940     scansm = &g_ble_ll_scan_sm;
2941     if (scansm->scan_enabled) {
2942         return BLE_ERR_CMD_DISALLOWED;
2943     }
2944 
2945     /* Get the scan interval and window */
2946     scan_type = cmd[0];
2947     scan_itvl  = get_le16(cmd + 1);
2948     scan_window = get_le16(cmd + 3);
2949     own_addr_type = cmd[5];
2950     filter_policy = cmd[6];
2951 
2952     /* Check scan type */
2953     if ((scan_type != BLE_HCI_SCAN_TYPE_PASSIVE) &&
2954         (scan_type != BLE_HCI_SCAN_TYPE_ACTIVE)) {
2955         return BLE_ERR_INV_HCI_CMD_PARMS;
2956     }
2957 
2958     /* Check interval and window */
2959     if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) ||
2960         (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) ||
2961         (scan_window < BLE_HCI_SCAN_WINDOW_MIN) ||
2962         (scan_window > BLE_HCI_SCAN_WINDOW_MAX) ||
2963         (scan_itvl < scan_window)) {
2964         return BLE_ERR_INV_HCI_CMD_PARMS;
2965     }
2966 
2967     /* Check own addr type */
2968     if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
2969         return BLE_ERR_INV_HCI_CMD_PARMS;
2970     }
2971 
2972     /* Check scanner filter policy */
2973     if (filter_policy > BLE_HCI_SCAN_FILT_MAX) {
2974         return BLE_ERR_INV_HCI_CMD_PARMS;
2975     }
2976 
2977     /* Store scan parameters */
2978     scanp = &g_ble_ll_scan_params[PHY_UNCODED];
2979     scanp->configured = 1;
2980     scanp->scan_type = scan_type;
2981     scanp->scan_itvl = scan_itvl;
2982     scanp->scan_window = scan_window;
2983     scanp->scan_filt_policy = filter_policy;
2984     scanp->own_addr_type = own_addr_type;
2985 
2986 #if (BLE_LL_SCAN_PHY_NUMBER == 2)
2987     g_ble_ll_scan_params[PHY_CODED].configured = 0;
2988 #endif
2989 
2990     return 0;
2991 }
2992 
2993 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2994 static int
ble_ll_check_scan_params(uint8_t type,uint16_t itvl,uint16_t window)2995 ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window)
2996 {
2997     /* Check scan type */
2998     if ((type != BLE_HCI_SCAN_TYPE_PASSIVE) &&
2999         (type != BLE_HCI_SCAN_TYPE_ACTIVE)) {
3000         return BLE_ERR_INV_HCI_CMD_PARMS;
3001     }
3002 
3003     /* Check interval and window */
3004     if ((itvl < BLE_HCI_SCAN_ITVL_MIN) ||
3005         (itvl > BLE_HCI_SCAN_ITVL_MAX) ||
3006         (window < BLE_HCI_SCAN_WINDOW_MIN) ||
3007         (window > BLE_HCI_SCAN_WINDOW_MAX) ||
3008         (itvl < window)) {
3009         return BLE_ERR_INV_HCI_CMD_PARMS;
3010     }
3011 
3012     return 0;
3013 }
3014 
3015 int
ble_ll_set_ext_scan_params(uint8_t * cmd,uint8_t cmdlen)3016 ble_ll_set_ext_scan_params(uint8_t *cmd, uint8_t cmdlen)
3017 {
3018     struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { };
3019     struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED];
3020     struct ble_ll_scan_params *coded = &new_params[PHY_CODED];
3021     uint8_t idx;
3022     int rc;
3023 
3024     if (cmdlen < 3) {
3025         return BLE_ERR_INV_HCI_CMD_PARMS;
3026     }
3027 
3028     /* If already enabled, we return an error */
3029     if (g_ble_ll_scan_sm.scan_enabled) {
3030         return BLE_ERR_CMD_DISALLOWED;
3031     }
3032 
3033     /* Check own addr type */
3034     if (cmd[0] > BLE_HCI_ADV_OWN_ADDR_MAX) {
3035         return BLE_ERR_INV_HCI_CMD_PARMS;
3036     }
3037 
3038     coded->own_addr_type = cmd[0];
3039     uncoded->own_addr_type = cmd[0];
3040 
3041     /* Check scanner filter policy */
3042     if (cmd[1] > BLE_HCI_SCAN_FILT_MAX) {
3043         return BLE_ERR_INV_HCI_CMD_PARMS;
3044     }
3045 
3046     coded->scan_filt_policy = cmd[1];
3047     uncoded->scan_filt_policy = cmd[1];
3048 
3049     /* Check if no reserved bits in PHYS are set and that at least one valid PHY
3050      * is set.
3051      */
3052     if (!(cmd[2] & ble_ll_valid_scan_phy_mask) ||
3053                                     (cmd[2] & ~ble_ll_valid_scan_phy_mask)) {
3054          return BLE_ERR_INV_HCI_CMD_PARMS;
3055      }
3056 
3057     idx = 3;
3058     if (cmd[2] & BLE_HCI_LE_PHY_1M_PREF_MASK) {
3059         if (cmdlen < idx + 5) {
3060             return BLE_ERR_INV_HCI_CMD_PARMS;
3061         }
3062 
3063         uncoded->scan_type = cmd[idx];
3064         idx++;
3065         uncoded->scan_itvl = get_le16(cmd + idx);
3066         idx += 2;
3067         uncoded->scan_window = get_le16(cmd + idx);
3068         idx += 2;
3069 
3070         rc = ble_ll_check_scan_params(uncoded->scan_type,
3071                                       uncoded->scan_itvl,
3072                                       uncoded->scan_window);
3073         if (rc) {
3074             return rc;
3075         }
3076 
3077         /* That means user whats to use this PHY for scanning */
3078         uncoded->configured = 1;
3079     }
3080 
3081 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
3082     if (cmd[2] & BLE_HCI_LE_PHY_CODED_PREF_MASK) {
3083         if (cmdlen < idx + 5) {
3084             return BLE_ERR_INV_HCI_CMD_PARMS;
3085         }
3086 
3087         coded->scan_type = cmd[idx];
3088         idx++;
3089         coded->scan_itvl = get_le16(cmd + idx);
3090         idx += 2;
3091         coded->scan_window = get_le16(cmd + idx);
3092         idx += 2;
3093 
3094         rc = ble_ll_check_scan_params(coded->scan_type,
3095                                       coded->scan_itvl,
3096                                       coded->scan_window);
3097         if (rc) {
3098             return rc;
3099         }
3100 
3101         /* That means user whats to use this PHY for scanning */
3102         coded->configured = 1;
3103     }
3104 #endif
3105 
3106     /* If host requests continuous scan for 2 PHYs, we double scan interval
3107      * and split it for two equal scan windows between 2 PHYs
3108      */
3109     if ((coded->configured && uncoded->configured) &&
3110                 ((uncoded->scan_itvl == uncoded->scan_window) ||
3111                 (coded->scan_itvl == coded-> scan_window))) {
3112 
3113                 uncoded->scan_itvl *= 2;
3114                 coded-> scan_itvl = uncoded->scan_itvl;
3115                 coded->scan_window = uncoded->scan_window;
3116     }
3117 
3118     memcpy(g_ble_ll_scan_params, new_params, sizeof(new_params));
3119 
3120     return 0;
3121 }
3122 
3123 #endif
3124 
3125 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3126 static void
ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm * scansm)3127 ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm)
3128 {
3129     uint32_t now;
3130 
3131     now = os_cputime_get32();
3132 
3133     os_cputime_timer_stop(&scansm->duration_timer);
3134     os_cputime_timer_stop(&scansm->period_timer);
3135 
3136     if (scansm->duration_ticks) {
3137         os_cputime_timer_start(&scansm->duration_timer,
3138                                                 now + scansm->duration_ticks);
3139 
3140         if (scansm->period_ticks) {
3141             os_cputime_timer_start(&scansm->period_timer,
3142                                                     now + scansm->period_ticks);
3143         }
3144     }
3145 }
3146 
3147 static void
ble_ll_scan_duration_timer_cb(void * arg)3148 ble_ll_scan_duration_timer_cb(void *arg)
3149 {
3150     struct ble_ll_scan_sm *scansm;
3151 
3152     scansm = (struct ble_ll_scan_sm *)arg;
3153 
3154     ble_ll_scan_sm_stop(2);
3155 
3156     /* if period is set both timers get started from period cb */
3157     if (!scansm->period_ticks) {
3158         ble_ll_hci_ev_send_scan_timeout();
3159     }
3160 }
3161 
3162 static void
ble_ll_scan_period_timer_cb(void * arg)3163 ble_ll_scan_period_timer_cb(void *arg)
3164 {
3165     struct ble_ll_scan_sm *scansm = arg;
3166 
3167     ble_ll_scan_sm_start(scansm);
3168 
3169     /* always start timer regardless of ble_ll_scan_sm_start result
3170      * if it failed will restart in next period
3171      */
3172     ble_ll_scan_duration_period_timers_restart(scansm);
3173 }
3174 #endif
3175 
3176 /**
3177  * ble ll scan set enable
3178  *
3179  *  HCI scan set enable command processing function
3180  *
3181  *  Context: Link Layer task (HCI Command parser).
3182  *
3183  * @param cmd Pointer to command buffer
3184  *
3185  * @return int BLE error code.
3186  */
3187 int
ble_ll_scan_set_enable(uint8_t * cmd,uint8_t ext)3188 ble_ll_scan_set_enable(uint8_t *cmd, uint8_t ext)
3189 {
3190     int rc;
3191     uint8_t filter_dups;
3192     uint8_t enable;
3193     struct ble_ll_scan_sm *scansm;
3194     struct ble_ll_scan_params *scanp;
3195     struct ble_ll_scan_params *scanphy;
3196     int i;
3197 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3198     uint32_t period_ticks = 0;
3199     uint32_t dur_ticks = 0;
3200     uint16_t period;
3201     uint16_t dur;
3202 #endif
3203 
3204     /* Check for valid parameters */
3205     enable = cmd[0];
3206     filter_dups = cmd[1];
3207     if ((filter_dups > 1) || (enable > 1)) {
3208         return BLE_ERR_INV_HCI_CMD_PARMS;
3209     }
3210 
3211     scansm = &g_ble_ll_scan_sm;
3212 
3213 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3214     /* we can do that here since value will never change until reset */
3215     scansm->ext_scanning = ext;
3216 
3217     if (ext) {
3218         dur = get_le16(cmd + 2);
3219 
3220         /* Period parameter is ignored when the Duration parameter is zero */
3221         if (dur) {
3222             period = get_le16(cmd + 4);
3223         } else {
3224             period = 0;
3225         }
3226 
3227         /* period is in 1.28 sec units
3228          * TODO support full range, would require os_cputime milliseconds API
3229          */
3230         if (period > 3355) {
3231             return BLE_ERR_INV_HCI_CMD_PARMS;
3232         }
3233         period_ticks = os_cputime_usecs_to_ticks(period * 1280000);
3234 
3235         /* duration is in 10ms units */
3236         dur_ticks = os_cputime_usecs_to_ticks(dur * 10000);
3237 
3238         if (dur_ticks && period_ticks && (dur_ticks >= period_ticks)) {
3239             return BLE_ERR_INV_HCI_CMD_PARMS;
3240         }
3241     }
3242 #endif
3243 
3244     /* disable*/
3245     if (!enable) {
3246         if (scansm->scan_enabled) {
3247             ble_ll_scan_sm_stop(1);
3248         }
3249 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3250         os_cputime_timer_stop(&scansm->duration_timer);
3251         os_cputime_timer_stop(&scansm->period_timer);
3252 #endif
3253 
3254         return BLE_ERR_SUCCESS;
3255     }
3256 
3257     /* if already enable we just need to update parameters */
3258     if (scansm->scan_enabled) {
3259         /* Controller does not allow initiating and scanning.*/
3260         for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
3261             scanphy = &scansm->phy_data[i];
3262             if (scanphy->configured &&
3263                                 scanphy->scan_type == BLE_SCAN_TYPE_INITIATE) {
3264                 return BLE_ERR_CMD_DISALLOWED;
3265             }
3266         }
3267 
3268         /* update filter policy */
3269         scansm->scan_filt_dups = filter_dups;
3270 
3271 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3272         /* restart timers according to new settings */
3273         scansm->duration_ticks = dur_ticks;
3274         scansm->period_ticks = period_ticks;
3275         ble_ll_scan_duration_period_timers_restart(scansm);
3276 #endif
3277 
3278         return BLE_ERR_SUCCESS;
3279     }
3280 
3281     /* we can store those upfront regardless of start scan result since scan is
3282      * disabled now
3283      */
3284 
3285     scansm->scan_filt_dups = filter_dups;
3286     scansm->cur_phy = PHY_NOT_CONFIGURED;
3287     scansm->next_phy = PHY_NOT_CONFIGURED;
3288 
3289     for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
3290         scanphy = &scansm->phy_data[i];
3291         scanp = &g_ble_ll_scan_params[i];
3292 
3293         if (!scanp->configured) {
3294             continue;
3295         }
3296 
3297         scanphy->configured = scanp->configured;
3298         scanphy->scan_type = scanp->scan_type;
3299         scanphy->scan_itvl = scanp->scan_itvl;
3300         scanphy->scan_window = scanp->scan_window;
3301         scanphy->scan_filt_policy = scanp->scan_filt_policy;
3302         scanphy->own_addr_type = scanp->own_addr_type;
3303 
3304         if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
3305             scansm->cur_phy = i;
3306             /* Take own_addr_type from the first configured PHY.
3307              * Note: All configured PHYs shall have the same own_addr_type
3308              */
3309             scansm->own_addr_type = scanphy->own_addr_type;
3310         } else {
3311             scansm->next_phy = i;
3312         }
3313     }
3314 
3315     rc = ble_ll_scan_sm_start(scansm);
3316 
3317 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3318     if (rc == BLE_ERR_SUCCESS) {
3319         scansm->duration_ticks = dur_ticks;
3320         scansm->period_ticks = period_ticks;
3321         ble_ll_scan_duration_period_timers_restart(scansm);
3322     }
3323 #endif
3324 
3325     return rc;
3326 }
3327 
3328 /**
3329  * Checks if controller can change the whitelist. If scanning is enabled and
3330  * using the whitelist the controller is not allowed to change the whitelist.
3331  *
3332  * @return int 0: not allowed to change whitelist; 1: change allowed.
3333  */
3334 int
ble_ll_scan_can_chg_whitelist(void)3335 ble_ll_scan_can_chg_whitelist(void)
3336 {
3337     int rc;
3338     struct ble_ll_scan_sm *scansm;
3339     struct ble_ll_scan_params *params;
3340 
3341     scansm = &g_ble_ll_scan_sm;
3342     params = &scansm->phy_data[scansm->cur_phy];
3343     if (scansm->scan_enabled && (params->scan_filt_policy & 1)) {
3344         rc = 0;
3345     } else {
3346         rc = 1;
3347     }
3348 
3349     return rc;
3350 }
3351 
3352 int
ble_ll_scan_initiator_start(struct hci_create_conn * hcc,struct ble_ll_scan_sm ** sm)3353 ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
3354                             struct ble_ll_scan_sm **sm)
3355 {
3356     struct ble_ll_scan_sm *scansm;
3357     struct ble_ll_scan_params *scanphy;
3358     int rc;
3359 
3360     scansm = &g_ble_ll_scan_sm;
3361     scansm->own_addr_type = hcc->own_addr_type;
3362 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3363     scansm->ext_scanning = 0;
3364 #endif
3365     scansm->cur_phy = PHY_UNCODED;
3366     scansm->next_phy = PHY_NOT_CONFIGURED;
3367 
3368     scanphy = &scansm->phy_data[scansm->cur_phy];
3369     scanphy->scan_filt_policy = hcc->filter_policy;
3370     scanphy->scan_itvl = hcc->scan_itvl;
3371     scanphy->scan_window = hcc->scan_window;
3372     scanphy->scan_type = BLE_SCAN_TYPE_INITIATE;
3373 
3374     rc = ble_ll_scan_sm_start(scansm);
3375     if (sm == NULL) {
3376         return rc;
3377     }
3378 
3379     if (rc == BLE_ERR_SUCCESS) {
3380         *sm = scansm;
3381     } else {
3382         *sm = NULL;
3383     }
3384 
3385     return rc;
3386 }
3387 
3388 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3389 int
ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn * hcc,struct ble_ll_scan_sm ** sm)3390 ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
3391                                 struct ble_ll_scan_sm **sm)
3392 {
3393     struct ble_ll_scan_sm *scansm;
3394     struct ble_ll_scan_params *uncoded;
3395     struct ble_ll_scan_params *coded;
3396     struct hci_ext_conn_params *params;
3397     int rc;
3398 
3399     scansm = &g_ble_ll_scan_sm;
3400     scansm->own_addr_type = hcc->own_addr_type;
3401     scansm->cur_phy = PHY_NOT_CONFIGURED;
3402     scansm->next_phy = PHY_NOT_CONFIGURED;
3403     scansm->ext_scanning = 1;
3404 
3405     if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
3406         params = &hcc->params[0];
3407         uncoded = &scansm->phy_data[PHY_UNCODED];
3408 
3409         uncoded->scan_itvl = params->scan_itvl;
3410         uncoded->scan_window = params->scan_window;
3411         uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
3412         uncoded->scan_filt_policy = hcc->filter_policy;
3413         scansm->cur_phy = PHY_UNCODED;
3414     }
3415 
3416     if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
3417         params = &hcc->params[2];
3418         coded = &scansm->phy_data[PHY_CODED];
3419 
3420         coded->scan_itvl = params->scan_itvl;
3421         coded->scan_window = params->scan_window;
3422         coded->scan_type = BLE_SCAN_TYPE_INITIATE;
3423         coded->scan_filt_policy = hcc->filter_policy;
3424         if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
3425             scansm->cur_phy = PHY_CODED;
3426         } else {
3427             scansm->next_phy = PHY_CODED;
3428         }
3429     }
3430 
3431     /* If host request for continuous scan if 2 PHYs are requested, we split
3432      * time on two
3433      */
3434     if ((scansm->next_phy != PHY_NOT_CONFIGURED) &&
3435                 ((uncoded->scan_itvl == uncoded->scan_window) ||
3436                 (coded->scan_itvl == coded-> scan_window))) {
3437 
3438         uncoded->scan_itvl *= 2;
3439         coded-> scan_itvl = uncoded->scan_itvl;
3440         coded->scan_window = uncoded->scan_window;
3441     }
3442 
3443     rc = ble_ll_scan_sm_start(scansm);
3444     if (sm == NULL) {
3445         return rc;
3446     }
3447 
3448     if (rc == BLE_ERR_SUCCESS) {
3449         *sm = scansm;
3450     } else {
3451         *sm = NULL;
3452     }
3453 
3454     return rc;
3455 }
3456 #endif
3457 
3458 /**
3459  * Checks to see if the scanner is enabled.
3460  *
3461  * @return int 0: not enabled; enabled otherwise
3462  */
3463 int
ble_ll_scan_enabled(void)3464 ble_ll_scan_enabled(void)
3465 {
3466     return (int)g_ble_ll_scan_sm.scan_enabled;
3467 }
3468 
3469 /**
3470  * Returns the peer resolvable private address of last device connecting to us
3471  *
3472  * @return uint8_t*
3473  */
3474 uint8_t *
ble_ll_scan_get_peer_rpa(void)3475 ble_ll_scan_get_peer_rpa(void)
3476 {
3477     struct ble_ll_scan_sm *scansm;
3478 
3479     /* XXX: should this go into IRK list or connection? */
3480     scansm = &g_ble_ll_scan_sm;
3481     return scansm->scan_peer_rpa;
3482 }
3483 
3484 /**
3485  * Returns the local resolvable private address currently being using by
3486  * the scanner/initiator
3487  *
3488  * @return uint8_t*
3489  */
3490 uint8_t *
ble_ll_scan_get_local_rpa(void)3491 ble_ll_scan_get_local_rpa(void)
3492 {
3493     uint8_t *rpa;
3494     struct ble_ll_scan_sm *scansm;
3495 
3496     scansm = &g_ble_ll_scan_sm;
3497 
3498     /*
3499      * The RPA we used is in connect request or scan request and is the
3500      * first address in the packet
3501      */
3502     rpa = scansm->scan_req_pdu->om_data;
3503 
3504     return rpa;
3505 }
3506 
3507 /**
3508  * Set the Resolvable Private Address in the scanning (or initiating) state
3509  * machine.
3510  *
3511  * XXX: should this go into IRK list or connection?
3512  *
3513  * @param rpa
3514  */
3515 void
ble_ll_scan_set_peer_rpa(uint8_t * rpa)3516 ble_ll_scan_set_peer_rpa(uint8_t *rpa)
3517 {
3518     struct ble_ll_scan_sm *scansm;
3519 
3520     scansm = &g_ble_ll_scan_sm;
3521     memcpy(scansm->scan_peer_rpa, rpa, BLE_DEV_ADDR_LEN);
3522 }
3523 
3524 /* Returns the PDU allocated by the scanner */
3525 struct os_mbuf *
ble_ll_scan_get_pdu(void)3526 ble_ll_scan_get_pdu(void)
3527 {
3528     return g_ble_ll_scan_sm.scan_req_pdu;
3529 }
3530 
3531 /* Returns true if whitelist is enabled for scanning */
3532 int
ble_ll_scan_whitelist_enabled(void)3533 ble_ll_scan_whitelist_enabled(void)
3534 {
3535     struct ble_ll_scan_params *params;
3536 
3537     params = &g_ble_ll_scan_sm.phy_data[g_ble_ll_scan_sm.cur_phy];
3538     return params->scan_filt_policy & 1;
3539 }
3540 
3541 static void
ble_ll_scan_common_init(void)3542 ble_ll_scan_common_init(void)
3543 {
3544     struct ble_ll_scan_sm *scansm;
3545     struct ble_ll_scan_params *scanp;
3546     int i;
3547 
3548     /* Clear state machine in case re-initialized */
3549     scansm = &g_ble_ll_scan_sm;
3550     memset(scansm, 0, sizeof(struct ble_ll_scan_sm));
3551 
3552     /* Clear scan parameters in case re-initialized */
3553     memset(g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params));
3554 
3555     /* Initialize scanning window end event */
3556     ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm);
3557 
3558     for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
3559         /* Set all non-zero default parameters */
3560         scanp = &g_ble_ll_scan_params[i];
3561         scanp->scan_itvl = BLE_HCI_SCAN_ITVL_DEF;
3562         scanp->scan_window = BLE_HCI_SCAN_WINDOW_DEF;
3563     }
3564 
3565     scansm->phy_data[PHY_UNCODED].phy = BLE_PHY_1M;
3566 #if (BLE_LL_SCAN_PHY_NUMBER == 2)
3567     scansm->phy_data[PHY_CODED].phy = BLE_PHY_CODED;
3568 #endif
3569 
3570 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
3571     /* Make sure we'll generate new NRPA if necessary */
3572     scansm->scan_nrpa_timer = ble_npl_time_get();
3573 #endif
3574 
3575     /* Initialize scanning timer */
3576     os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm);
3577 
3578     /* Initialize extended scan timers */
3579 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3580     os_cputime_timer_init(&scansm->duration_timer,
3581                                         ble_ll_scan_duration_timer_cb, scansm);
3582     os_cputime_timer_init(&scansm->period_timer, ble_ll_scan_period_timer_cb,
3583                                                                         scansm);
3584 #endif
3585 
3586     /* Get a scan request mbuf (packet header) and attach to state machine */
3587     scansm->scan_req_pdu = os_msys_get_pkthdr(BLE_SCAN_LEGACY_MAX_PKT_LEN,
3588                                               sizeof(struct ble_mbuf_hdr));
3589     BLE_LL_ASSERT(scansm->scan_req_pdu != NULL);
3590 }
3591 
3592 /**
3593  * Called when the controller receives the reset command. Resets the
3594  * scanning state machine to its initial state.
3595  *
3596  * @return int
3597  */
3598 void
ble_ll_scan_reset(void)3599 ble_ll_scan_reset(void)
3600 {
3601     struct ble_ll_scan_sm *scansm;
3602 
3603     scansm = &g_ble_ll_scan_sm;
3604 
3605     /* If enabled, stop it. */
3606     if (scansm->scan_enabled) {
3607         ble_ll_scan_sm_stop(0);
3608     }
3609 
3610     /* stop extended scan timers */
3611 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3612     os_cputime_timer_stop(&scansm->duration_timer);
3613     os_cputime_timer_stop(&scansm->period_timer);
3614 #endif
3615 
3616     /* Free the scan request pdu */
3617     os_mbuf_free_chain(scansm->scan_req_pdu);
3618 
3619     /* Reset duplicate advertisers and those from which we rxd a response */
3620     g_ble_ll_scan_num_rsp_advs = 0;
3621     memset(&g_ble_ll_scan_rsp_advs[0], 0, sizeof(g_ble_ll_scan_rsp_advs));
3622 
3623     g_ble_ll_scan_num_dup_advs = 0;
3624     memset(&g_ble_ll_scan_dup_advs[0], 0, sizeof(g_ble_ll_scan_dup_advs));
3625 
3626 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3627     /* clear memory pool for AUX scan results */
3628     os_mempool_clear(&ext_adv_pool);
3629 #endif
3630 
3631     /* Call the common init function again */
3632     ble_ll_scan_common_init();
3633 }
3634 
3635 /**
3636  * ble ll scan init
3637  *
3638  * Initialize a scanner. Must be called before scanning can be started.
3639  * Expected to be called with a un-initialized scanning state machine.
3640  */
3641 void
ble_ll_scan_init(void)3642 ble_ll_scan_init(void)
3643 {
3644 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3645     os_error_t err;
3646 
3647     err = os_mempool_init(&ext_adv_pool,
3648                           MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT),
3649                           sizeof (struct ble_ll_aux_data),
3650                           ext_adv_mem,
3651                           "ble_ll_aux_scan_pool");
3652     BLE_LL_ASSERT(err == 0);
3653 #endif
3654 
3655     ble_ll_scan_common_init();
3656 }
3657