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