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 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <assert.h>
23 #include "syscfg/syscfg.h"
24 #include "os/os.h"
25 #include "os/os_cputime.h"
26 #include "ble/xcvr.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_hci.h"
35 #include "controller/ble_ll_adv.h"
36 #include "controller/ble_ll_sched.h"
37 #include "controller/ble_ll_scan.h"
38 #include "controller/ble_ll_whitelist.h"
39 #include "controller/ble_ll_resolv.h"
40 #include "controller/ble_ll_trace.h"
41 #include "ble_ll_conn_priv.h"
42
43 /* XXX: TODO
44 * 1) Need to look at advertising and scan request PDUs. Do I allocate these
45 * once? Do I use a different pool for smaller ones? Do I statically declare
46 * them?
47 * 3) How do features get supported? What happens if device does not support
48 * advertising? (for example)
49 * 4) How to determine the advertising interval we will actually use. As of
50 * now, we set it to max.
51 * 5) How does the advertising channel tx power get set? I dont implement
52 * that currently.
53 */
54
55 /* Scheduling data for secondary channel */
56 struct ble_ll_adv_aux {
57 struct ble_ll_sched_item sch;
58 uint32_t start_time;
59 uint16_t aux_data_offset;
60 uint8_t ext_hdr;
61 uint8_t aux_data_len;
62 uint8_t payload_len;
63 };
64
65 /*
66 * Advertising state machine
67 *
68 * The advertising state machine data structure.
69 *
70 * adv_pdu_len
71 * The length of the advertising PDU that will be sent. This does not
72 * include the preamble, access address and CRC.
73 *
74 * initiator_addr:
75 * This is the address that we send in directed advertisements (the
76 * INITA field). If we are using Privacy this is a RPA that we need to
77 * generate. We reserve space in the advsm to save time when creating
78 * the ADV_DIRECT_IND. If own address type is not 2 or 3, this is simply
79 * the peer address from the set advertising parameters.
80 */
81 struct ble_ll_adv_sm
82 {
83 uint8_t adv_enabled;
84 uint8_t adv_instance;
85 uint8_t adv_chanmask;
86 uint8_t adv_filter_policy;
87 uint8_t own_addr_type;
88 uint8_t peer_addr_type;
89 uint8_t adv_chan;
90 uint8_t adv_pdu_len;
91 int8_t adv_rpa_index;
92 int8_t adv_txpwr;
93 uint16_t flags;
94 uint16_t props;
95 uint16_t adv_itvl_min;
96 uint16_t adv_itvl_max;
97 uint32_t adv_itvl_usecs;
98 uint32_t adv_event_start_time;
99 uint32_t adv_pdu_start_time;
100 uint32_t adv_end_time;
101 uint32_t adv_rpa_timer;
102 uint8_t adva[BLE_DEV_ADDR_LEN];
103 uint8_t adv_rpa[BLE_DEV_ADDR_LEN];
104 uint8_t peer_addr[BLE_DEV_ADDR_LEN];
105 uint8_t initiator_addr[BLE_DEV_ADDR_LEN];
106 struct os_mbuf *adv_data;
107 struct os_mbuf *scan_rsp_data;
108 uint8_t *conn_comp_ev;
109 struct ble_npl_event adv_txdone_ev;
110 struct ble_ll_sched_item adv_sch;
111 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
112 uint8_t aux_active : 1;
113 uint8_t aux_index : 1;
114 uint8_t aux_first_pdu : 1;
115 uint8_t aux_not_scanned : 1;
116 struct ble_mbuf_hdr *rx_ble_hdr;
117 struct os_mbuf **aux_data;
118 struct ble_ll_adv_aux aux[2];
119 struct ble_npl_event adv_sec_txdone_ev;
120 uint16_t duration;
121 uint16_t adi;
122 uint8_t adv_secondary_chan;
123 uint8_t adv_random_addr[BLE_DEV_ADDR_LEN];
124 uint8_t events_max;
125 uint8_t events;
126 uint8_t pri_phy;
127 uint8_t sec_phy;
128 #endif
129 };
130
131 #define BLE_LL_ADV_SM_FLAG_TX_ADD 0x0001
132 #define BLE_LL_ADV_SM_FLAG_RX_ADD 0x0002
133 #define BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF 0x0004
134 #define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD 0x0008
135 #define BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK 0x0030 /* use helpers! */
136 #define BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE 0x0040
137 #define BLE_LL_ADV_SM_FLAG_CONFIGURED 0x0080
138 #define BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO 0x0100
139
140 #define ADV_DATA_LEN(_advsm) \
141 ((_advsm->adv_data) ? OS_MBUF_PKTLEN(advsm->adv_data) : 0)
142 #define SCAN_RSP_DATA_LEN(_advsm) \
143 ((_advsm->scan_rsp_data) ? OS_MBUF_PKTLEN(advsm->scan_rsp_data) : 0)
144 #define AUX_DATA_LEN(_advsm) \
145 (*(_advsm->aux_data) ? OS_MBUF_PKTLEN(*advsm->aux_data) : 0)
146
147 #define AUX_CURRENT(_advsm) (&(_advsm->aux[_advsm->aux_index]))
148 #define AUX_NEXT(_advsm) (&(_advsm->aux[_advsm->aux_index ^ 1]))
149
150 static inline int
ble_ll_adv_active_chanset_is_pri(struct ble_ll_adv_sm * advsm)151 ble_ll_adv_active_chanset_is_pri(struct ble_ll_adv_sm *advsm)
152 {
153 return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x10;
154 }
155
156 static inline int
ble_ll_adv_active_chanset_is_sec(struct ble_ll_adv_sm * advsm)157 ble_ll_adv_active_chanset_is_sec(struct ble_ll_adv_sm *advsm)
158 {
159 return (advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0x20;
160 }
161
162 static inline void
ble_ll_adv_active_chanset_clear(struct ble_ll_adv_sm * advsm)163 ble_ll_adv_active_chanset_clear(struct ble_ll_adv_sm *advsm)
164 {
165 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK;
166 }
167
168 static inline void
ble_ll_adv_active_chanset_set_pri(struct ble_ll_adv_sm * advsm)169 ble_ll_adv_active_chanset_set_pri(struct ble_ll_adv_sm *advsm)
170 {
171 assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0);
172 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK;
173 advsm->flags |= 0x10;
174 }
175
176 static inline void
ble_ll_adv_active_chanset_set_sec(struct ble_ll_adv_sm * advsm)177 ble_ll_adv_active_chanset_set_sec(struct ble_ll_adv_sm *advsm)
178 {
179 assert((advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK) == 0);
180 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK;
181 advsm->flags |= 0x20;
182 }
183
184 /* The advertising state machine global object */
185 struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES];
186 struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm;
187
188 static void ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr);
189 static void ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm);
190 static void ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm);
191
192 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
193 static void
ble_ll_adv_rpa_update(struct ble_ll_adv_sm * advsm)194 ble_ll_adv_rpa_update(struct ble_ll_adv_sm *advsm)
195 {
196 if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type,
197 advsm->adva, 1)) {
198 advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD;
199 } else {
200 if (advsm->own_addr_type & 1) {
201 advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD;
202 } else {
203 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD;
204 }
205 }
206
207 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
208 if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type,
209 advsm->initiator_addr, 0)) {
210 advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD;
211 } else {
212 if (advsm->peer_addr_type & 1) {
213 advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD;
214 } else {
215 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD;
216 }
217 }
218 }
219 }
220
221 /**
222 * Called to change advertisers ADVA and INITA (for directed advertisements)
223 * as an advertiser needs to adhere to the resolvable private address generation
224 * timer.
225 *
226 * NOTE: the resolvable private address code uses its own timer to regenerate
227 * local resolvable private addresses. The advertising code uses its own
228 * timer to reset the INITA (for directed advertisements). This code also sets
229 * the appropriate txadd and rxadd bits that will go into the advertisement.
230 *
231 * Another thing to note: it is possible that an IRK is all zeroes in the
232 * resolving list. That is why we need to check if the generated address is
233 * in fact a RPA as a resolving list entry with all zeroes will use the
234 * identity address (which may be a private address or public).
235 *
236 * @param advsm
237 */
238 void
ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm * advsm)239 ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm)
240 {
241 if (advsm->own_addr_type < BLE_HCI_ADV_OWN_ADDR_PRIV_PUB) {
242 return;
243 }
244
245 if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO) {
246 ble_ll_adv_rpa_update(advsm);
247 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO;
248 }
249 }
250
251 void
ble_ll_adv_rpa_timeout(void)252 ble_ll_adv_rpa_timeout(void)
253 {
254 struct ble_ll_adv_sm *advsm;
255 int i;
256
257 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
258 advsm = &g_ble_ll_adv_sm[i];
259
260 if (advsm->adv_enabled &&
261 advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
262 /* Mark RPA as timed out so we get a new RPA */
263 advsm->flags |= BLE_LL_ADV_SM_FLAG_ADV_RPA_TMO;
264 }
265 }
266 }
267 #endif
268
269 /**
270 * Calculate the first channel that we should advertise upon when we start
271 * an advertising event.
272 *
273 * @param advsm
274 *
275 * @return uint8_t The number of the first channel usable for advertising.
276 */
277 static uint8_t
ble_ll_adv_first_chan(struct ble_ll_adv_sm * advsm)278 ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm)
279 {
280 uint8_t adv_chan;
281
282 /* Set first advertising channel */
283 if (advsm->adv_chanmask & 0x01) {
284 adv_chan = BLE_PHY_ADV_CHAN_START;
285 } else if (advsm->adv_chanmask & 0x02) {
286 adv_chan = BLE_PHY_ADV_CHAN_START + 1;
287 } else {
288 adv_chan = BLE_PHY_ADV_CHAN_START + 2;
289 }
290
291 return adv_chan;
292 }
293
294 /**
295 * Calculate the final channel that we should advertise upon when we start
296 * an advertising event.
297 *
298 * @param advsm
299 *
300 * @return uint8_t The number of the final channel usable for advertising.
301 */
302 static uint8_t
ble_ll_adv_final_chan(struct ble_ll_adv_sm * advsm)303 ble_ll_adv_final_chan(struct ble_ll_adv_sm *advsm)
304 {
305 uint8_t adv_chan;
306
307 if (advsm->adv_chanmask & 0x04) {
308 adv_chan = BLE_PHY_ADV_CHAN_START + 2;
309 } else if (advsm->adv_chanmask & 0x02) {
310 adv_chan = BLE_PHY_ADV_CHAN_START + 1;
311 } else {
312 adv_chan = BLE_PHY_ADV_CHAN_START;
313 }
314
315 return adv_chan;
316 }
317
318 /**
319 * Create the advertising legacy PDU
320 *
321 * @param advsm Pointer to advertisement state machine
322 */
323 static uint8_t
ble_ll_adv_legacy_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)324 ble_ll_adv_legacy_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
325 {
326 struct ble_ll_adv_sm *advsm;
327 uint8_t adv_data_len;
328 uint8_t pdulen;
329 uint8_t pdu_type;
330
331 advsm = pducb_arg;
332
333 /* assume this is not a direct ind */
334 adv_data_len = ADV_DATA_LEN(advsm);
335 pdulen = BLE_DEV_ADDR_LEN + adv_data_len;
336
337 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
338 pdu_type = BLE_ADV_PDU_TYPE_ADV_DIRECT_IND;
339
340 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
341 pdu_type |= BLE_ADV_PDU_HDR_CHSEL;
342 #endif
343
344 if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) {
345 pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND;
346 }
347
348 adv_data_len = 0;
349 pdulen = BLE_ADV_DIRECT_IND_LEN;
350 } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
351 pdu_type = BLE_ADV_PDU_TYPE_ADV_IND;
352
353 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
354 pdu_type |= BLE_ADV_PDU_HDR_CHSEL;
355 #endif
356 } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
357 pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND;
358 } else {
359 pdu_type = BLE_ADV_PDU_TYPE_ADV_NONCONN_IND;
360 }
361
362 /* An invalid advertising data length indicates a memory overwrite */
363 assert(adv_data_len <= BLE_ADV_LEGACY_DATA_MAX_LEN);
364
365 /* Set the PDU length in the state machine (includes header) */
366 advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN;
367
368 /* Set TxAdd to random if needed. */
369 if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
370 pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
371 }
372
373 *hdr_byte = pdu_type;
374
375 /* Construct advertisement */
376 memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN);
377 dptr += BLE_DEV_ADDR_LEN;
378
379 /* For ADV_DIRECT_IND add inita */
380 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
381 memcpy(dptr, advsm->initiator_addr, BLE_DEV_ADDR_LEN);
382 }
383
384 /* Copy in advertising data, if any */
385 if (adv_data_len != 0) {
386 os_mbuf_copydata(advsm->adv_data, 0, adv_data_len, dptr);
387 }
388
389 return pdulen;
390 }
391
392 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
393 static void
ble_ll_adv_put_aux_ptr(struct ble_ll_adv_sm * advsm,uint32_t offset,uint8_t * dptr)394 ble_ll_adv_put_aux_ptr(struct ble_ll_adv_sm *advsm, uint32_t offset,
395 uint8_t *dptr)
396 {
397 dptr[0] = advsm->adv_secondary_chan;
398
399 if (offset > 245700) {
400 dptr[0] |= 0x80;
401 offset = offset / 300;
402 } else {
403 offset = offset / 30;
404 }
405
406 dptr[1] = (offset & 0x000000ff);
407 dptr[2] = ((offset >> 8) & 0x0000001f) | (advsm->sec_phy - 1) << 5; //TODO;
408 }
409
410 /**
411 * Create the advertising PDU
412 */
413 static uint8_t
ble_ll_adv_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)414 ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
415 {
416 struct ble_ll_adv_sm *advsm;
417 uint8_t pdu_type;
418 uint8_t adv_mode;
419 uint8_t ext_hdr_len;
420 uint8_t ext_hdr_flags;
421 uint32_t offset;
422
423 advsm = pducb_arg;
424
425 assert(ble_ll_adv_active_chanset_is_pri(advsm));
426 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
427 return ble_ll_adv_legacy_pdu_make(dptr, advsm, hdr_byte);
428 }
429
430 /* only ADV_EXT_IND goes on primary advertising channels */
431 pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND;
432
433 /* Set TxAdd to random if needed. */
434 if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
435 pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
436 }
437
438 *hdr_byte = pdu_type;
439
440 adv_mode = 0;
441 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
442 adv_mode |= BLE_LL_EXT_ADV_MODE_CONN;
443 }
444 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
445 adv_mode |= BLE_LL_EXT_ADV_MODE_SCAN;
446 }
447
448 ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_DATA_INFO_SIZE +
449 BLE_LL_EXT_ADV_AUX_PTR_SIZE;
450 ext_hdr_flags = (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT) |
451 (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT);
452
453 /* ext hdr len and adv mode */
454 dptr[0] = ext_hdr_len | (adv_mode << 6);
455 dptr += 1;
456
457 /* ext hdr flags */
458 dptr[0] = ext_hdr_flags;
459 dptr += 1;
460
461 /* ADI */
462 dptr[0] = advsm->adi & 0x00ff;
463 dptr[1] = advsm->adi >> 8;
464 dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
465
466 /* AuxPtr */
467 if (AUX_CURRENT(advsm)->sch.enqueued) {
468 offset = os_cputime_ticks_to_usecs(AUX_CURRENT(advsm)->start_time - advsm->adv_pdu_start_time);
469 } else {
470 offset = 0;
471 }
472 ble_ll_adv_put_aux_ptr(advsm, offset, dptr);
473
474 return BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len;
475 }
476
477 /**
478 * Create the AUX PDU
479 */
480 static uint8_t
ble_ll_adv_aux_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)481 ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
482 {
483 struct ble_ll_adv_sm *advsm;
484 struct ble_ll_adv_aux *aux;
485 uint8_t adv_mode;
486 uint8_t pdu_type;
487 uint8_t ext_hdr_len;
488 uint32_t offset;
489
490 advsm = pducb_arg;
491 aux = AUX_CURRENT(advsm);
492
493 assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY));
494 assert(ble_ll_adv_active_chanset_is_sec(advsm));
495
496 /* It's the same for AUX_ADV_IND and AUX_CHAIN_IND */
497 pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND;
498
499 /* Set TxAdd to random if needed. */
500 if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
501 pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
502 }
503
504 /* We do not create scannable PDUs here - this is handled separately */
505 adv_mode = 0;
506 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
507 adv_mode |= BLE_LL_EXT_ADV_MODE_CONN;
508 }
509
510 ext_hdr_len = aux->payload_len - BLE_LL_EXT_ADV_HDR_LEN - aux->aux_data_len;
511 dptr[0] = (adv_mode << 6) | ext_hdr_len;
512 dptr += 1;
513
514 dptr[0] = aux->ext_hdr;
515 dptr += 1;
516
517 if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) {
518 memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE);
519 dptr += BLE_LL_EXT_ADV_ADVA_SIZE;
520 }
521
522 if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) {
523 memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE);
524 dptr += BLE_LL_EXT_ADV_TARGETA_SIZE;
525
526 /* Set RxAdd to random if needed. */
527 if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) {
528 pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND;
529 }
530 }
531
532 if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) {
533 dptr[0] = advsm->adi & 0x00ff;
534 dptr[1] = advsm->adi >> 8;
535 dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
536 }
537
538 if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) {
539 if (!AUX_NEXT(advsm)->sch.enqueued) {
540 /*
541 * Trim data here in case we do not have next aux scheduled. This
542 * can happen if next aux was outside advertising set period and
543 * was removed from scheduler.
544 */
545 offset = 0;
546 } else if (advsm->rx_ble_hdr) {
547 offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime);
548 offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + BLE_LL_IFS);
549 } else {
550 offset = os_cputime_ticks_to_usecs(AUX_NEXT(advsm)->start_time - aux->start_time);
551 }
552
553 ble_ll_adv_put_aux_ptr(advsm, offset, dptr);
554
555 dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE;
556 }
557
558 if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) {
559 dptr[0] = advsm->adv_txpwr;
560 dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE;
561 }
562
563 if (aux->aux_data_len) {
564 os_mbuf_copydata(*advsm->aux_data, aux->aux_data_offset,
565 aux->aux_data_len, dptr);
566 }
567
568 *hdr_byte = pdu_type;
569
570 return aux->payload_len;
571 }
572
573 static uint8_t
ble_ll_adv_aux_scannable_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)574 ble_ll_adv_aux_scannable_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
575 {
576 struct ble_ll_adv_sm *advsm;
577 uint8_t pdu_type;
578 uint8_t *ext_hdr_len;
579 uint8_t *ext_hdr;
580 uint8_t pdulen;
581
582 advsm = pducb_arg;
583
584 assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY));
585 assert(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE);
586 assert(advsm->aux_first_pdu);
587 assert(ble_ll_adv_active_chanset_is_sec(advsm));
588
589 pdu_type = BLE_ADV_PDU_TYPE_AUX_ADV_IND;
590
591 /* Set TxAdd to random if needed. */
592 if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
593 pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
594 }
595
596 ext_hdr_len = &dptr[0];
597 ext_hdr = &dptr[1];
598 dptr += 2;
599
600 /* Flags always */
601 *ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE;
602 *ext_hdr = 0;
603
604 /* AdvA always */
605 *ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE;
606 *ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT);
607 memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE);
608 dptr += BLE_LL_EXT_ADV_ADVA_SIZE;
609
610 /* TargetA only for directed */
611 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
612 *ext_hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE;
613 *ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT);
614 memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE);
615 dptr += BLE_LL_EXT_ADV_TARGETA_SIZE;
616
617 /* Set RxAdd to random if needed. */
618 if (advsm->flags & BLE_LL_ADV_SM_FLAG_RX_ADD) {
619 pdu_type |= BLE_ADV_PDU_HDR_RXADD_RAND;
620 }
621 }
622
623 /* ADI always */
624 *ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
625 *ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT);
626 dptr[0] = advsm->adi & 0x00ff;
627 dptr[1] = advsm->adi >> 8;
628 dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
629
630 /* TxPower if configured */
631 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) {
632 *ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE;
633 *ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT);
634 dptr[0] = advsm->adv_txpwr;
635 dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE;
636 }
637
638 pdulen = BLE_LL_EXT_ADV_HDR_LEN + *ext_hdr_len;
639
640 *hdr_byte = pdu_type;
641 *ext_hdr_len |= (BLE_LL_EXT_ADV_MODE_SCAN << 6);
642
643 return pdulen;
644 }
645 #endif
646
647 static uint8_t
ble_ll_adv_scan_rsp_legacy_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)648 ble_ll_adv_scan_rsp_legacy_pdu_make(uint8_t *dptr, void *pducb_arg,
649 uint8_t *hdr_byte)
650 {
651 struct ble_ll_adv_sm *advsm;
652 uint8_t scan_rsp_len;
653 uint8_t pdulen;
654 uint8_t hdr;
655
656 advsm = pducb_arg;
657
658 /* Make sure that the length is valid */
659 scan_rsp_len = SCAN_RSP_DATA_LEN(advsm);
660 assert(scan_rsp_len <= BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN);
661
662 /* Set BLE transmit header */
663 pdulen = BLE_DEV_ADDR_LEN + scan_rsp_len;
664 hdr = BLE_ADV_PDU_TYPE_SCAN_RSP;
665 if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
666 hdr |= BLE_ADV_PDU_HDR_TXADD_RAND;
667 }
668
669 *hdr_byte = hdr;
670
671 /*
672 * The adva in this packet will be the same one that was being advertised
673 * and is based on the peer identity address in the set advertising
674 * parameters. If a different peer sends us a scan request (for some reason)
675 * we will reply with an adva that was not generated based on the local irk
676 * of the peer sending the scan request.
677 */
678
679 /* Construct scan response */
680 memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN);
681 if (scan_rsp_len != 0) {
682 os_mbuf_copydata(advsm->scan_rsp_data, 0, scan_rsp_len,
683 dptr + BLE_DEV_ADDR_LEN);
684 }
685
686 return pdulen;
687 }
688
689 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
690 /**
691 * Create a scan response PDU
692 *
693 * @param advsm
694 */
695 static uint8_t
ble_ll_adv_scan_rsp_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)696 ble_ll_adv_scan_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
697 {
698 struct ble_ll_adv_sm *advsm;
699
700 advsm = pducb_arg;
701
702 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
703 return ble_ll_adv_scan_rsp_legacy_pdu_make(dptr, pducb_arg, hdr_byte);
704 }
705
706 return ble_ll_adv_aux_pdu_make(dptr, pducb_arg, hdr_byte);
707 }
708
709 struct aux_conn_rsp_data {
710 struct ble_ll_adv_sm *advsm;
711 uint8_t *peer;
712 uint8_t rxadd;
713 };
714
715 /**
716 * Create a AUX connect response PDU
717 *
718 * @param advsm
719 */
720 static uint8_t
ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)721 ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t *dptr, void *pducb_arg,
722 uint8_t *hdr_byte)
723 {
724 struct aux_conn_rsp_data *rsp_data;
725 uint8_t pdulen;
726 uint8_t ext_hdr_len;
727 uint8_t ext_hdr_flags;
728 uint8_t hdr;
729
730 rsp_data = pducb_arg;
731
732 /* flags,AdvA and TargetA */
733 ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_ADVA_SIZE +
734 BLE_LL_EXT_ADV_TARGETA_SIZE;
735 ext_hdr_flags = (1 << BLE_LL_EXT_ADV_ADVA_BIT);
736 ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT);
737
738 pdulen = BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len;
739
740 /* Set BLE transmit header */
741 hdr = BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP;
742 if (rsp_data->rxadd) {
743 hdr |= BLE_ADV_PDU_HDR_RXADD_MASK;
744 }
745 if (rsp_data->advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) {
746 hdr |= BLE_ADV_PDU_HDR_TXADD_MASK;
747 }
748
749 *hdr_byte = hdr;
750
751 /* ext hdr len and adv mode (00b) */
752 dptr[0] = ext_hdr_len;
753 dptr += 1;
754
755 /* ext hdr flags */
756 dptr[0] = ext_hdr_flags;
757 dptr += 1;
758
759 memcpy(dptr, rsp_data->advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE);
760 dptr += BLE_LL_EXT_ADV_ADVA_SIZE;
761
762 memcpy(dptr, rsp_data->peer, BLE_LL_EXT_ADV_TARGETA_SIZE);
763 dptr += BLE_LL_EXT_ADV_ADVA_SIZE;
764
765 return pdulen;
766 }
767 #endif
768
769 /**
770 * Called to indicate the advertising event is over.
771 *
772 * Context: Interrupt
773 *
774 * @param advsm
775 *
776 */
777 static void
ble_ll_adv_tx_done(void * arg)778 ble_ll_adv_tx_done(void *arg)
779 {
780 struct ble_ll_adv_sm *advsm;
781
782 /* XXX: for now, reset power to max after advertising */
783 ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
784
785 advsm = (struct ble_ll_adv_sm *)arg;
786
787 ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance,
788 advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK);
789
790 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
791 if (ble_ll_adv_active_chanset_is_pri(advsm)) {
792 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
793 } else if (ble_ll_adv_active_chanset_is_sec(advsm)) {
794 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
795 } else {
796 assert(0);
797 }
798 #else
799 assert(ble_ll_adv_active_chanset_is_pri(advsm));
800 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
801 #endif
802
803 ble_ll_state_set(BLE_LL_STATE_STANDBY);
804
805 ble_ll_adv_active_chanset_clear(advsm);
806
807 /* We no longer have a current state machine */
808 g_ble_ll_cur_adv_sm = NULL;
809 }
810
811 /*
812 * Called when an advertising event has been removed from the scheduler
813 * without being run.
814 */
815 void
ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm * advsm)816 ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm)
817 {
818 /*
819 * Need to set advertising channel to final chan so new event gets
820 * scheduled.
821 */
822 advsm->adv_chan = ble_ll_adv_final_chan(advsm);
823 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
824 }
825
826 /**
827 * This is the scheduler callback (called from interrupt context) which
828 * transmits an advertisement.
829 *
830 * Context: Interrupt (scheduler)
831 *
832 * @param sch
833 *
834 * @return int
835 */
836 static int
ble_ll_adv_tx_start_cb(struct ble_ll_sched_item * sch)837 ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
838 {
839 int rc;
840 uint8_t end_trans;
841 uint32_t txstart;
842 struct ble_ll_adv_sm *advsm;
843
844 /* Get the state machine for the event */
845 advsm = (struct ble_ll_adv_sm *)sch->cb_arg;
846
847 /* Set the current advertiser */
848 g_ble_ll_cur_adv_sm = advsm;
849
850 ble_ll_adv_active_chanset_set_pri(advsm);
851
852 /* Set the power */
853 ble_phy_txpwr_set(advsm->adv_txpwr);
854
855 /* Set channel */
856 rc = ble_phy_setchan(advsm->adv_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV);
857 assert(rc == 0);
858
859 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
860 /* Set phy mode */
861 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
862 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
863 ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M);
864 } else {
865 ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy);
866 }
867 #else
868 ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M);
869 #endif
870 #endif
871
872 /* Set transmit start time. */
873 txstart = sch->start_time + g_ble_ll_sched_offset_ticks;
874 rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
875 if (rc) {
876 STATS_INC(ble_ll_stats, adv_late_starts);
877 goto adv_tx_done;
878 }
879
880 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
881 /* XXX: automatically do this in the phy based on channel? */
882 ble_phy_encrypt_disable();
883 #endif
884
885 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
886 advsm->adv_rpa_index = -1;
887 if (ble_ll_resolv_enabled()) {
888 ble_phy_resolv_list_enable();
889 } else {
890 ble_phy_resolv_list_disable();
891 }
892 #endif
893
894 /* We switch to RX after connectable or scannable legacy packets. */
895 if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
896 ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) ||
897 (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE))) {
898 end_trans = BLE_PHY_TRANSITION_TX_RX;
899 ble_phy_set_txend_cb(NULL, NULL);
900 } else {
901 end_trans = BLE_PHY_TRANSITION_NONE;
902 ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
903 }
904
905 /* Transmit advertisement */
906 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
907 rc = ble_phy_tx(ble_ll_adv_pdu_make, advsm, end_trans);
908 #else
909 rc = ble_phy_tx(ble_ll_adv_legacy_pdu_make, advsm, end_trans);
910 #endif
911 if (rc) {
912 goto adv_tx_done;
913 }
914
915 /* Enable/disable whitelisting based on filter policy */
916 if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) {
917 ble_ll_whitelist_enable();
918 } else {
919 ble_ll_whitelist_disable();
920 }
921
922 /* Set link layer state to advertising */
923 ble_ll_state_set(BLE_LL_STATE_ADV);
924
925 /* Count # of adv. sent */
926 STATS_INC(ble_ll_stats, adv_txg);
927
928 return BLE_LL_SCHED_STATE_RUNNING;
929
930 adv_tx_done:
931 ble_ll_adv_tx_done(advsm);
932 return BLE_LL_SCHED_STATE_DONE;
933 }
934
935 static void
ble_ll_adv_set_sched(struct ble_ll_adv_sm * advsm)936 ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm)
937 {
938 uint32_t max_usecs;
939 struct ble_ll_sched_item *sch;
940
941 sch = &advsm->adv_sch;
942 sch->cb_arg = advsm;
943 sch->sched_cb = ble_ll_adv_tx_start_cb;
944 sch->sched_type = BLE_LL_SCHED_TYPE_ADV;
945
946 /* Set end time to maximum time this schedule item may take */
947 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
948 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
949 max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M);
950
951 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
952 max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS;
953 } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
954 max_usecs += BLE_LL_SCHED_ADV_MAX_USECS;
955 }
956 } else {
957 /*
958 * In ADV_EXT_IND we always set only ADI and AUX so the payload length
959 * is always 7 bytes.
960 */
961 max_usecs = ble_ll_pdu_tx_time_get(7, advsm->pri_phy);
962 }
963 #else
964 max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M);
965
966 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
967 max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS;
968 } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
969 max_usecs += BLE_LL_SCHED_ADV_MAX_USECS;
970 }
971 #endif
972
973 sch->start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
974 sch->remainder = 0;
975 sch->end_time = advsm->adv_pdu_start_time +
976 ble_ll_usecs_to_ticks_round_up(max_usecs);
977 }
978
979 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
980 static int
ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item * sch)981 ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
982 {
983 int rc;
984 uint8_t end_trans;
985 uint32_t txstart;
986 struct ble_ll_adv_sm *advsm;
987 ble_phy_tx_pducb_t pducb;
988
989 /* Get the state machine for the event */
990 advsm = (struct ble_ll_adv_sm *)sch->cb_arg;
991
992 /* Set the current advertiser */
993 g_ble_ll_cur_adv_sm = advsm;
994
995 ble_ll_adv_active_chanset_set_sec(advsm);
996
997 /* Set the power */
998 ble_phy_txpwr_set(advsm->adv_txpwr);
999
1000 /* Set channel */
1001 rc = ble_phy_setchan(advsm->adv_secondary_chan, BLE_ACCESS_ADDR_ADV,
1002 BLE_LL_CRCINIT_ADV);
1003 assert(rc == 0);
1004
1005 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1006 /* Set phy mode */
1007 ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy);
1008 #endif
1009
1010 /* Set transmit start time. */
1011 txstart = sch->start_time + g_ble_ll_sched_offset_ticks;
1012 rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
1013 if (rc) {
1014 STATS_INC(ble_ll_stats, adv_late_starts);
1015 goto adv_tx_done;
1016 }
1017
1018 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1019 ble_phy_encrypt_disable();
1020 #endif
1021
1022 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1023 advsm->adv_rpa_index = -1;
1024 if (ble_ll_resolv_enabled()) {
1025 ble_phy_resolv_list_enable();
1026 } else {
1027 ble_phy_resolv_list_disable();
1028 }
1029 #endif
1030
1031 /* Set phy mode based on type of advertisement */
1032 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
1033 end_trans = BLE_PHY_TRANSITION_TX_RX;
1034 ble_phy_set_txend_cb(NULL, NULL);
1035 pducb = ble_ll_adv_aux_pdu_make;
1036 } else if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) &&
1037 advsm->aux_first_pdu) {
1038 end_trans = BLE_PHY_TRANSITION_TX_RX;
1039 ble_phy_set_txend_cb(NULL, NULL);
1040 pducb = ble_ll_adv_aux_scannable_pdu_make;
1041 } else {
1042 end_trans = BLE_PHY_TRANSITION_NONE;
1043 ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
1044 pducb = ble_ll_adv_aux_pdu_make;
1045 }
1046
1047 /* Transmit advertisement */
1048 rc = ble_phy_tx(pducb, advsm, end_trans);
1049 if (rc) {
1050 goto adv_tx_done;
1051 }
1052
1053 /* Enable/disable whitelisting based on filter policy */
1054 if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) {
1055 ble_ll_whitelist_enable();
1056 } else {
1057 ble_ll_whitelist_disable();
1058 }
1059
1060 /* Set link layer state to advertising */
1061 ble_ll_state_set(BLE_LL_STATE_ADV);
1062
1063 /* Count # of adv. sent */
1064 STATS_INC(ble_ll_stats, adv_txg);
1065
1066 return BLE_LL_SCHED_STATE_RUNNING;
1067
1068 adv_tx_done:
1069 ble_ll_adv_tx_done(advsm);
1070 return BLE_LL_SCHED_STATE_DONE;
1071 }
1072
1073 static uint8_t
ble_ll_adv_aux_scannable_pdu_payload_len(struct ble_ll_adv_sm * advsm)1074 ble_ll_adv_aux_scannable_pdu_payload_len(struct ble_ll_adv_sm *advsm)
1075 {
1076 uint8_t len;
1077
1078 /* Flags, AdvA and ADI always */
1079 len = BLE_LL_EXT_ADV_HDR_LEN + BLE_LL_EXT_ADV_FLAGS_SIZE +
1080 BLE_LL_EXT_ADV_ADVA_SIZE + BLE_LL_EXT_ADV_DATA_INFO_SIZE;
1081
1082 /* TargetA only for directed */
1083 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
1084 len += BLE_LL_EXT_ADV_TARGETA_SIZE;
1085 }
1086
1087 /* TxPower if configured */
1088 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) {
1089 len += BLE_LL_EXT_ADV_TX_POWER_SIZE;
1090 }
1091
1092 return len;
1093 }
1094
1095 static void
ble_ll_adv_aux_calculate(struct ble_ll_adv_sm * advsm,struct ble_ll_adv_aux * aux,uint16_t aux_data_offset)1096 ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
1097 struct ble_ll_adv_aux *aux, uint16_t aux_data_offset)
1098 {
1099 uint16_t rem_aux_data_len;
1100 uint8_t hdr_len;
1101 bool chainable;
1102
1103 assert(!aux->sch.enqueued);
1104 assert((AUX_DATA_LEN(advsm) > aux_data_offset) ||
1105 (AUX_DATA_LEN(advsm) == 0 && aux_data_offset == 0));
1106
1107 aux->aux_data_offset = aux_data_offset;
1108 aux->aux_data_len = 0;
1109 aux->payload_len = 0;
1110 aux->ext_hdr = 0;
1111
1112 rem_aux_data_len = AUX_DATA_LEN(advsm) - aux_data_offset;
1113 chainable = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE);
1114
1115 hdr_len = BLE_LL_EXT_ADV_HDR_LEN + BLE_LL_EXT_ADV_FLAGS_SIZE;
1116
1117 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) {
1118 /* Flags and ADI */
1119 aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT);
1120 hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE;
1121 }
1122
1123 /* AdvA for 1st PDU in chain (i.e. AUX_ADV_IND or AUX_SCAN_RSP) */
1124 if (aux_data_offset == 0) {
1125 aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT);
1126 hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE;
1127 }
1128
1129 /* TargetA for directed connectable */
1130 if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) &&
1131 (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) {
1132 aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT);
1133 hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE;
1134 }
1135
1136 /* TxPower if configured */
1137 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) {
1138 aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT);
1139 hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE;
1140 }
1141
1142 /* AdvData always */
1143 aux->aux_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_aux_data_len);
1144
1145 /* AuxPtr if there are more AdvData remaining that we can fit here */
1146 if (chainable && (rem_aux_data_len > aux->aux_data_len)) {
1147 aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT);
1148 hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE;
1149 aux->aux_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE;
1150
1151 /* PDU payload should be full if chained */
1152 assert(hdr_len + aux->aux_data_len == BLE_LL_MAX_PAYLOAD_LEN);
1153 }
1154
1155 aux->payload_len = hdr_len + aux->aux_data_len;
1156 }
1157
1158 static void
ble_ll_adv_aux_scheduled(struct ble_ll_adv_sm * advsm,uint32_t sch_start,void * arg)1159 ble_ll_adv_aux_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start,
1160 void *arg)
1161 {
1162 struct ble_ll_adv_aux *aux = arg;
1163
1164 aux->start_time = sch_start + g_ble_ll_sched_offset_ticks;
1165 }
1166
1167 static void
ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm * advsm)1168 ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm)
1169 {
1170 struct ble_ll_adv_aux *aux;
1171 struct ble_ll_adv_aux *aux_next;
1172 struct ble_ll_sched_item *sch;
1173 uint16_t rem_aux_data_len;
1174 uint16_t next_aux_data_offset;
1175 uint32_t max_usecs;
1176
1177 assert(advsm->aux_active);
1178
1179 aux = AUX_CURRENT(advsm);
1180 aux_next = AUX_NEXT(advsm);
1181
1182 assert(!aux_next->sch.enqueued);
1183
1184 /*
1185 * Do not schedule next aux if current aux is no longer scheduled since we
1186 * do not have reference time for scheduling.
1187 */
1188 if (!aux->sch.enqueued) {
1189 return;
1190 }
1191
1192 /*
1193 * Do not schedule next aux if current aux does not have AuxPtr in extended
1194 * header as this means we do not need subsequent ADV_CHAIN_IND to be sent.
1195 */
1196 if (!(aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) {
1197 return;
1198 }
1199
1200 next_aux_data_offset = aux->aux_data_offset + aux->aux_data_len;
1201
1202 assert(AUX_DATA_LEN(advsm) >= next_aux_data_offset);
1203
1204 rem_aux_data_len = AUX_DATA_LEN(advsm) - next_aux_data_offset;
1205 assert(rem_aux_data_len > 0);
1206
1207 ble_ll_adv_aux_calculate(advsm, aux_next, next_aux_data_offset);
1208 max_usecs = ble_ll_pdu_tx_time_get(aux_next->payload_len, advsm->sec_phy);
1209
1210 aux_next->start_time = aux->sch.end_time +
1211 ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS);
1212
1213 sch = &aux_next->sch;
1214 sch->start_time = aux_next->start_time - g_ble_ll_sched_offset_ticks;
1215 sch->remainder = 0;
1216 sch->end_time = aux_next->start_time +
1217 ble_ll_usecs_to_ticks_round_up(max_usecs);
1218 ble_ll_sched_adv_new(&aux_next->sch, ble_ll_adv_aux_scheduled, aux_next);
1219
1220 /*
1221 * In case duration is set for advertising set we need to check if newly
1222 * scheduled aux will fit inside duration. If not, remove it from scheduler
1223 * so advertising will stop after current aux.
1224 */
1225 if (advsm->duration && (aux_next->sch.end_time > advsm->adv_end_time)) {
1226 ble_ll_sched_rmv_elem(&aux_next->sch);
1227 }
1228 }
1229
1230 static void
ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm * advsm)1231 ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
1232 {
1233 struct ble_ll_adv_aux *aux;
1234 struct ble_ll_sched_item *sch;
1235 uint32_t max_usecs;
1236
1237 assert(!advsm->aux_active);
1238 assert(!advsm->aux[0].sch.enqueued);
1239 assert(!advsm->aux[1].sch.enqueued);
1240
1241 advsm->aux_active = 1;
1242 advsm->aux_index = 0;
1243 advsm->aux_first_pdu = 1;
1244 advsm->aux_not_scanned = 0;
1245
1246 aux = AUX_CURRENT(advsm);
1247 ble_ll_adv_aux_calculate(advsm, aux, 0);
1248
1249 /* TODO we could use CSA2 for this
1250 * (will be needed for periodic advertising anyway)
1251 */
1252 advsm->adv_secondary_chan = rand() % BLE_PHY_NUM_DATA_CHANS;
1253
1254 /* Set end time to maximum time this schedule item may take */
1255 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
1256 max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy) +
1257 BLE_LL_IFS +
1258 /* AUX_CONN_REQ */
1259 ble_ll_pdu_tx_time_get(34 + 14, advsm->sec_phy) +
1260 BLE_LL_IFS +
1261 /* AUX_CONN_RSP */
1262 ble_ll_pdu_tx_time_get(14, advsm->sec_phy);
1263 } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
1264 /* Scheduled aux is calculated for AUX_SCAN_RSP, 1st aux is created separately */
1265 max_usecs = ble_ll_pdu_tx_time_get(ble_ll_adv_aux_scannable_pdu_payload_len(advsm),
1266 advsm->sec_phy) +
1267 BLE_LL_IFS +
1268 /* AUX_SCAN_REQ */
1269 ble_ll_pdu_tx_time_get(12, advsm->sec_phy) +
1270 BLE_LL_IFS +
1271 /* AUX_SCAN_RSP */
1272 ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy);
1273 } else {
1274 max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy);
1275 }
1276
1277 sch = &aux->sch;
1278 sch->start_time = aux->start_time - g_ble_ll_sched_offset_ticks;
1279 sch->remainder = 0;
1280 sch->end_time = aux->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs);
1281 ble_ll_sched_adv_new(sch, ble_ll_adv_aux_scheduled, aux);
1282
1283 }
1284
1285 static void
ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm * advsm)1286 ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm *advsm)
1287 {
1288 static const uint8_t bits[8] = {0, 1, 1, 2, 1, 2, 2, 3};
1289 struct ble_ll_sched_item *sched = &advsm->adv_sch;
1290 uint32_t adv_pdu_dur;
1291 uint32_t adv_event_dur;
1292 uint8_t chans;
1293
1294 assert(!advsm->aux_active);
1295 assert(!advsm->aux[0].sch.enqueued);
1296 assert(!advsm->aux[1].sch.enqueued);
1297
1298 assert(advsm->adv_chanmask > 0 &&
1299 advsm->adv_chanmask <= BLE_HCI_ADV_CHANMASK_DEF);
1300
1301 chans = bits[advsm->adv_chanmask];
1302
1303 /*
1304 * We want to schedule auxiliary packet as soon as possible after the end
1305 * of advertising event, but no sooner than T_MAFS. The interval between
1306 * advertising packets is 250 usecs (8.19 ticks) on LE Coded and a bit less
1307 * on 1M, but it can vary a bit due to scheduling which we can't really
1308 * control. Since we round ticks up for both interval and T_MAFS, we still
1309 * have some margin here. The worst thing that can happen is that we skip
1310 * last advertising packet which is not a bit problem so leave it as-is, no
1311 * need to make code more complicated.
1312 */
1313
1314 /*
1315 * XXX: this could be improved if phy has TX-TX transition with controlled
1316 * or predefined interval, but since it makes advertising code even
1317 * more complicated let's skip it for now...
1318 */
1319
1320 adv_pdu_dur = (int32_t)(sched->end_time - sched->start_time) -
1321 g_ble_ll_sched_offset_ticks;
1322
1323 /* 9 is 8.19 ticks rounded up - see comment above */
1324 adv_event_dur = (adv_pdu_dur * chans) + (9 * (chans - 1));
1325
1326 advsm->aux[0].start_time = advsm->adv_event_start_time + adv_event_dur +
1327 ble_ll_usecs_to_ticks_round_up(BLE_LL_MAFS);
1328 }
1329
1330 static void
ble_ll_adv_aux_schedule(struct ble_ll_adv_sm * advsm)1331 ble_ll_adv_aux_schedule(struct ble_ll_adv_sm *advsm)
1332 {
1333 /*
1334 * For secondary channel we always start by scheduling two consecutive
1335 * auxiliary packets at once. Then, after sending one packet we try to
1336 * schedule another one as long as there are some data left to send. This
1337 * is to make sure we can always calculate AuxPtr to subsequent packet
1338 * without need to scheduled it in an interrupt.
1339 */
1340
1341 ble_ll_adv_aux_set_start_time(advsm);
1342 ble_ll_adv_aux_schedule_first(advsm);
1343 ble_ll_adv_aux_schedule_next(advsm);
1344
1345 /*
1346 * In case duration is set for advertising set we need to check if at least
1347 * 1st aux will fit inside duration. If not, stop advertising now so we do
1348 * not start extended advertising event which we cannot finish in time.
1349 */
1350 if (advsm->duration &&
1351 (AUX_CURRENT(advsm)->sch.end_time > advsm->adv_end_time)) {
1352 ble_ll_adv_sm_stop_timeout(advsm);
1353 }
1354 }
1355 #endif
1356
1357 /**
1358 * Called when advertising need to be halted. This normally should not be called
1359 * and is only called when a scheduled item executes but advertising is still
1360 * running.
1361 *
1362 * Context: Interrupt
1363 */
1364 void
ble_ll_adv_halt(void)1365 ble_ll_adv_halt(void)
1366 {
1367 struct ble_ll_adv_sm *advsm;
1368
1369 if (g_ble_ll_cur_adv_sm != NULL) {
1370 advsm = g_ble_ll_cur_adv_sm;
1371
1372 ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance);
1373
1374 ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
1375
1376 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
1377 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1378 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) {
1379 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
1380 }
1381 #endif
1382
1383 ble_ll_state_set(BLE_LL_STATE_STANDBY);
1384 ble_ll_adv_active_chanset_clear(g_ble_ll_cur_adv_sm);
1385 g_ble_ll_cur_adv_sm = NULL;
1386 } else {
1387 ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, UINT32_MAX);
1388 }
1389 }
1390
1391 /**
1392 * Called by the HCI command parser when a set advertising parameters command
1393 * has been received.
1394 *
1395 * Context: Link Layer task (HCI command parser)
1396 *
1397 * @param cmd
1398 *
1399 * @return int
1400 */
1401 int
ble_ll_adv_set_adv_params(uint8_t * cmd)1402 ble_ll_adv_set_adv_params(uint8_t *cmd)
1403 {
1404 uint8_t adv_type;
1405 uint8_t adv_filter_policy;
1406 uint8_t adv_chanmask;
1407 uint8_t own_addr_type;
1408 uint8_t peer_addr_type;
1409 uint16_t adv_itvl_min;
1410 uint16_t adv_itvl_max;
1411 struct ble_ll_adv_sm *advsm;
1412 uint16_t props;
1413
1414 advsm = &g_ble_ll_adv_sm[0];
1415 if (advsm->adv_enabled) {
1416 return BLE_ERR_CMD_DISALLOWED;
1417 }
1418
1419 /* Make sure intervals are OK (along with advertising type */
1420 adv_itvl_min = get_le16(cmd);
1421 adv_itvl_max = get_le16(cmd + 2);
1422 adv_type = cmd[4];
1423
1424 /*
1425 * Get the filter policy now since we will ignore it if we are doing
1426 * directed advertising
1427 */
1428 adv_filter_policy = cmd[14];
1429
1430 switch (adv_type) {
1431 case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
1432 adv_filter_policy = BLE_HCI_ADV_FILT_NONE;
1433 memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
1434
1435 /* Ignore min/max interval */
1436 adv_itvl_min = 0;
1437 adv_itvl_max = 0;
1438
1439 props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR ;
1440 break;
1441 case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
1442 adv_filter_policy = BLE_HCI_ADV_FILT_NONE;
1443 memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
1444
1445 props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR ;
1446 break;
1447 case BLE_HCI_ADV_TYPE_ADV_IND:
1448 props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND;
1449 break;
1450 case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND:
1451 props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN;
1452 break;
1453 case BLE_HCI_ADV_TYPE_ADV_SCAN_IND:
1454 props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN;
1455 break;
1456 default:
1457 return BLE_ERR_INV_HCI_CMD_PARMS;
1458 }
1459
1460 /* Make sure intervals values are valid
1461 * (HD directed advertising ignores those parameters)
1462 */
1463 if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED)) {
1464 if ((adv_itvl_min > adv_itvl_max) ||
1465 (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) ||
1466 (adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) ||
1467 (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN) ||
1468 (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) {
1469 return BLE_ERR_INV_HCI_CMD_PARMS;
1470 }
1471 }
1472
1473 /* Check own and peer address type */
1474 own_addr_type = cmd[5];
1475 peer_addr_type = cmd[6];
1476
1477 if ((own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
1478 (peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
1479 return BLE_ERR_INV_HCI_CMD_PARMS;
1480 }
1481
1482 advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
1483
1484 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1485 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
1486 /* Copy peer address */
1487 memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
1488 }
1489 #else
1490 /* If we dont support privacy some address types wont work */
1491 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
1492 return BLE_ERR_UNSUPPORTED;
1493 }
1494 #endif
1495
1496 /* There are only three adv channels, so check for any outside the range */
1497 adv_chanmask = cmd[13];
1498 if (((adv_chanmask & 0xF8) != 0) || (adv_chanmask == 0)) {
1499 return BLE_ERR_INV_HCI_CMD_PARMS;
1500 }
1501
1502 /* Check for valid filter policy */
1503 if (adv_filter_policy > BLE_HCI_ADV_FILT_MAX) {
1504 return BLE_ERR_INV_HCI_CMD_PARMS;
1505 }
1506
1507 /* Fill out rest of advertising state machine */
1508 advsm->own_addr_type = own_addr_type;
1509 advsm->peer_addr_type = peer_addr_type;
1510 advsm->adv_filter_policy = adv_filter_policy;
1511 advsm->adv_chanmask = adv_chanmask;
1512 advsm->adv_itvl_min = adv_itvl_min;
1513 advsm->adv_itvl_max = adv_itvl_max;
1514 advsm->props = props;
1515
1516 return 0;
1517 }
1518
1519 /**
1520 * Stop advertising state machine
1521 *
1522 * Context: Link Layer task.
1523 *
1524 * @param advsm
1525 */
1526 static void
ble_ll_adv_sm_stop(struct ble_ll_adv_sm * advsm)1527 ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
1528 {
1529 os_sr_t sr;
1530
1531 if (advsm->adv_enabled) {
1532 /* Remove any scheduled advertising items */
1533 ble_ll_sched_rmv_elem(&advsm->adv_sch);
1534 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1535 advsm->aux_active = 0;
1536 ble_ll_sched_rmv_elem(&advsm->aux[0].sch);
1537 ble_ll_sched_rmv_elem(&advsm->aux[1].sch);
1538 #endif
1539
1540 /* Set to standby if we are no longer advertising */
1541 OS_ENTER_CRITICAL(sr);
1542 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1543 if (g_ble_ll_cur_adv_sm == advsm) {
1544 ble_phy_disable();
1545 ble_ll_wfr_disable();
1546 ble_ll_state_set(BLE_LL_STATE_STANDBY);
1547 g_ble_ll_cur_adv_sm = NULL;
1548 ble_ll_scan_chk_resume();
1549 }
1550 #else
1551 if (ble_ll_state_get() == BLE_LL_STATE_ADV) {
1552 ble_phy_disable();
1553 ble_ll_wfr_disable();
1554 ble_ll_state_set(BLE_LL_STATE_STANDBY);
1555 g_ble_ll_cur_adv_sm = NULL;
1556 ble_ll_scan_chk_resume();
1557 }
1558 #endif
1559 #ifdef BLE_XCVR_RFCLK
1560 ble_ll_sched_rfclk_chk_restart();
1561 #endif
1562 OS_EXIT_CRITICAL(sr);
1563
1564 ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
1565 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1566 ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
1567 #endif
1568
1569 /* If there is an event buf we need to free it */
1570 if (advsm->conn_comp_ev) {
1571 ble_hci_trans_buf_free(advsm->conn_comp_ev);
1572 advsm->conn_comp_ev = NULL;
1573 }
1574
1575 ble_ll_adv_active_chanset_clear(advsm);
1576
1577 /* Disable advertising */
1578 advsm->adv_enabled = 0;
1579 }
1580 }
1581
1582 static void
ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm * advsm)1583 ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm)
1584 {
1585 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1586 if (ble_ll_hci_adv_mode_ext()) {
1587 ble_ll_hci_ev_send_adv_set_terminated(BLE_ERR_DIR_ADV_TMO,
1588 advsm->adv_instance, 0,
1589 advsm->events);
1590 }
1591 #endif
1592
1593 /*
1594 * For high duty directed advertising we need to send connection
1595 * complete event with proper status
1596 */
1597 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
1598 ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO,
1599 advsm->conn_comp_ev, advsm);
1600 advsm->conn_comp_ev = NULL;
1601 }
1602
1603 /* Disable advertising */
1604 ble_ll_adv_sm_stop(advsm);
1605 }
1606
1607 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1608 static void
ble_ll_adv_sm_stop_limit_reached(struct ble_ll_adv_sm * advsm)1609 ble_ll_adv_sm_stop_limit_reached(struct ble_ll_adv_sm *advsm)
1610 {
1611 ble_ll_hci_ev_send_adv_set_terminated(BLE_RR_LIMIT_REACHED,
1612 advsm->adv_instance, 0,
1613 advsm->events);
1614
1615 /*
1616 * For high duty directed advertising we need to send connection
1617 * complete event with proper status
1618 *
1619 * Spec is a bit unambiguous here since it doesn't define what code should
1620 * be used if HD directed advertising was terminated before timeout due to
1621 * events count limit. For now just use same code as with duration timeout.
1622 */
1623 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
1624 ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO,
1625 advsm->conn_comp_ev, advsm);
1626 advsm->conn_comp_ev = NULL;
1627 }
1628
1629 /* Disable advertising */
1630 ble_ll_adv_sm_stop(advsm);
1631 }
1632 #endif
1633
1634 static void
ble_ll_adv_scheduled(struct ble_ll_adv_sm * advsm,uint32_t sch_start,void * arg)1635 ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start, void *arg)
1636 {
1637 /* The event start time is when we start transmission of the adv PDU */
1638 advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks;
1639 advsm->adv_pdu_start_time = advsm->adv_event_start_time;
1640
1641 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1642 /* this is validated for HD adv so no need to do additional checks here
1643 * duration is in 10ms units
1644 */
1645 if (advsm->duration) {
1646 advsm->adv_end_time = advsm->adv_event_start_time +
1647 os_cputime_usecs_to_ticks(advsm->duration * 10000);
1648 }
1649 #else
1650 /* Set the time at which we must end directed, high-duty cycle advertising.
1651 */
1652 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
1653 advsm->adv_end_time = advsm->adv_event_start_time +
1654 os_cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000);
1655 }
1656 #endif
1657 }
1658
1659 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1660 #endif
1661
1662 /**
1663 * Start the advertising state machine. This is called when the host sends
1664 * the "enable advertising" command and is not called again while in the
1665 * advertising state.
1666 *
1667 * Context: Link-layer task.
1668 *
1669 * @param advsm Pointer to advertising state machine
1670 *
1671 * @return int
1672 */
1673 static int
ble_ll_adv_sm_start(struct ble_ll_adv_sm * advsm)1674 ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
1675 {
1676 uint8_t adv_chan;
1677 uint8_t *addr;
1678 uint8_t *evbuf;
1679
1680 /* only clear flags that are not set from HCI */
1681 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_TX_ADD;
1682 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_RX_ADD;
1683 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD;
1684
1685 if (advsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
1686 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1687 if (!ble_ll_is_valid_random_addr(advsm->adv_random_addr)) {
1688 return BLE_ERR_INV_HCI_CMD_PARMS;
1689 }
1690 #else
1691 if (!ble_ll_is_valid_random_addr(g_random_addr)) {
1692 return BLE_ERR_CMD_DISALLOWED;
1693 }
1694 #endif
1695 }
1696
1697 /*
1698 * Get an event with which to send the connection complete event if
1699 * this is connectable
1700 */
1701 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
1702 /* We expect this to be NULL but if not we wont allocate one... */
1703 if (advsm->conn_comp_ev == NULL) {
1704 evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
1705 if (!evbuf) {
1706 return BLE_ERR_MEM_CAPACITY;
1707 }
1708 advsm->conn_comp_ev = evbuf;
1709 }
1710 }
1711
1712 /* Set advertising address */
1713 if ((advsm->own_addr_type & 1) == 0) {
1714 addr = g_dev_addr;
1715 } else {
1716 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1717 addr = advsm->adv_random_addr;
1718 #else
1719 addr = g_random_addr;
1720 #endif
1721 advsm->flags |= BLE_LL_ADV_SM_FLAG_TX_ADD;
1722 }
1723 memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN);
1724
1725 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
1726 memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN);
1727 if (advsm->peer_addr_type & 1) {
1728 advsm->flags |= BLE_LL_ADV_SM_FLAG_RX_ADD;
1729 }
1730 }
1731
1732 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1733 /* This will generate an RPA for both initiator addr and adva */
1734 if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
1735 ble_ll_adv_rpa_update(advsm);
1736 }
1737 #endif
1738
1739 /* Set flag telling us that advertising is enabled */
1740 advsm->adv_enabled = 1;
1741
1742 /* Determine the advertising interval we will use */
1743 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
1744 /* Set it to max. allowed for high duty cycle advertising */
1745 advsm->adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX;
1746 } else {
1747 advsm->adv_itvl_usecs = (uint32_t)advsm->adv_itvl_max;
1748 advsm->adv_itvl_usecs *= BLE_LL_ADV_ITVL;
1749 }
1750
1751 /* Set first advertising channel */
1752 adv_chan = ble_ll_adv_first_chan(advsm);
1753 advsm->adv_chan = adv_chan;
1754
1755 /*
1756 * XXX: while this may not be the most efficient, schedule the first
1757 * advertising event some time in the future (5 msecs). This will give
1758 * time to start up any clocks or anything and also avoid a bunch of code
1759 * to check if we are currently doing anything. Just makes this simple.
1760 *
1761 * Might also want to align this on a slot in the future.
1762 *
1763 * NOTE: adv_event_start_time gets set by the sched_adv_new
1764 */
1765 advsm->adv_pdu_start_time = os_cputime_get32() +
1766 os_cputime_usecs_to_ticks(5000);
1767
1768 /*
1769 * Schedule advertising. We set the initial schedule start and end
1770 * times to the earliest possible start/end.
1771 */
1772 ble_ll_adv_set_sched(advsm);
1773 ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled, NULL);
1774
1775 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1776 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) {
1777 ble_ll_adv_aux_schedule(advsm);
1778 }
1779 #endif
1780
1781 return BLE_ERR_SUCCESS;
1782 }
1783
1784 /**
1785 * Called when the LE HCI command read advertising channel tx power command
1786 * has been received. Returns the current advertising transmit power.
1787 *
1788 * Context: Link Layer task (HCI command parser)
1789 *
1790 * @return int
1791 */
1792 int
ble_ll_adv_read_txpwr(uint8_t * rspbuf,uint8_t * rsplen)1793 ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen)
1794 {
1795 rspbuf[0] = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
1796 *rsplen = 1;
1797 return BLE_ERR_SUCCESS;
1798 }
1799
1800 /**
1801 * Turn advertising on/off.
1802 *
1803 * Context: Link Layer task
1804 *
1805 * @param cmd
1806 *
1807 * @return int
1808 */
1809 int
ble_ll_adv_set_enable(uint8_t instance,uint8_t enable,int duration,uint8_t events)1810 ble_ll_adv_set_enable(uint8_t instance, uint8_t enable, int duration,
1811 uint8_t events)
1812 {
1813 int rc;
1814 struct ble_ll_adv_sm *advsm;
1815
1816 if (instance >= BLE_ADV_INSTANCES) {
1817 return BLE_ERR_INV_HCI_CMD_PARMS;
1818 }
1819
1820 advsm = &g_ble_ll_adv_sm[instance];
1821
1822 rc = BLE_ERR_SUCCESS;
1823 if (enable == 1) {
1824 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1825 if (advsm->flags & BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE) {
1826 return BLE_ERR_CMD_DISALLOWED;
1827 }
1828
1829 if (ble_ll_hci_adv_mode_ext() &&
1830 (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) &&
1831 !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
1832 SCAN_RSP_DATA_LEN(advsm) == 0) {
1833 return BLE_ERR_CMD_DISALLOWED;
1834 }
1835
1836 /* handle specifics of HD dir adv enabled in legacy way */
1837 if (duration < 0) {
1838 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
1839 duration = BLE_LL_ADV_STATE_HD_MAX / 10;
1840 } else {
1841 duration = 0;
1842 }
1843 }
1844 advsm->duration = duration;
1845 advsm->events_max = events;
1846 advsm->events = 0;
1847 #endif
1848
1849 /* If already enabled, do nothing */
1850 if (!advsm->adv_enabled) {
1851 /* Start the advertising state machine */
1852 rc = ble_ll_adv_sm_start(advsm);
1853 }
1854 } else if (enable == 0) {
1855 ble_ll_adv_sm_stop(advsm);
1856 } else {
1857 rc = BLE_ERR_INV_HCI_CMD_PARMS;
1858 }
1859
1860 return rc;
1861 }
1862
1863 static void
ble_ll_adv_update_data_mbuf(struct os_mbuf ** omp,bool new_data,uint16_t maxlen,const void * data,uint16_t datalen)1864 ble_ll_adv_update_data_mbuf(struct os_mbuf **omp, bool new_data, uint16_t maxlen,
1865 const void *data, uint16_t datalen)
1866 {
1867 struct os_mbuf *om;
1868 int ret;
1869
1870 om = *omp;
1871
1872 if (new_data) {
1873 if (om) {
1874 os_mbuf_free_chain(om);
1875 }
1876
1877 om = os_msys_get_pkthdr(datalen, 0);
1878 if (!om) {
1879 goto done;
1880 }
1881 }
1882
1883 assert(om);
1884
1885 if (OS_MBUF_PKTLEN(om) + datalen > maxlen) {
1886 os_mbuf_free_chain(om);
1887 om = NULL;
1888 goto done;
1889 }
1890
1891 ret = os_mbuf_append(om, data, datalen);
1892 if (ret) {
1893 os_mbuf_free_chain(om);
1894 om = NULL;
1895 }
1896
1897 done:
1898 *omp = om;
1899 }
1900
1901 static bool
instance_configured(struct ble_ll_adv_sm * advsm)1902 instance_configured(struct ble_ll_adv_sm *advsm)
1903 {
1904 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1905 if (ble_ll_hci_adv_mode_ext()) {
1906 return advsm->flags & BLE_LL_ADV_SM_FLAG_CONFIGURED;
1907 }
1908 #endif
1909
1910 /* legacy HCI instance is always configured */
1911 return true;
1912 }
1913
1914 /**
1915 * Set the scan response data that the controller will send.
1916 *
1917 * @param cmd
1918 * @param len
1919 *
1920 * @return int
1921 */
1922 int
ble_ll_adv_set_scan_rsp_data(uint8_t * cmd,uint8_t cmd_len,uint8_t instance,uint8_t operation)1923 ble_ll_adv_set_scan_rsp_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
1924 uint8_t operation)
1925 {
1926 uint8_t datalen;
1927 struct ble_ll_adv_sm *advsm;
1928 bool new_data;
1929
1930 if (instance >= BLE_ADV_INSTANCES) {
1931 return BLE_ERR_INV_HCI_CMD_PARMS;
1932 }
1933
1934 advsm = &g_ble_ll_adv_sm[instance];
1935 datalen = cmd[0];
1936
1937 if (datalen > 251 || datalen > cmd_len - 1) {
1938 return BLE_ERR_INV_HCI_CMD_PARMS;
1939 }
1940
1941 if (!instance_configured(advsm)) {
1942 return BLE_ERR_UNK_ADV_INDENT;
1943 }
1944
1945 /* check if type of advertising support scan rsp */
1946 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) {
1947 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) {
1948 return BLE_ERR_INV_HCI_CMD_PARMS;
1949 }
1950 }
1951
1952 switch (operation) {
1953 case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE:
1954 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
1955 if (datalen > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) {
1956 return BLE_ERR_INV_HCI_CMD_PARMS;
1957 }
1958 }
1959
1960 break;
1961 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1962 case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_LAST:
1963 /* TODO mark scan rsp as complete? */
1964 /* fall through */
1965 case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT:
1966 if (!advsm->scan_rsp_data) {
1967 return BLE_ERR_INV_HCI_CMD_PARMS;
1968 }
1969
1970 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
1971 return BLE_ERR_INV_HCI_CMD_PARMS;
1972 }
1973
1974 if (advsm->adv_enabled) {
1975 return BLE_ERR_CMD_DISALLOWED;
1976 }
1977
1978 if (!datalen) {
1979 return BLE_ERR_INV_HCI_CMD_PARMS;
1980 }
1981 break;
1982 case BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST:
1983 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
1984 return BLE_ERR_INV_HCI_CMD_PARMS;
1985 }
1986
1987 if (advsm->adv_enabled) {
1988 return BLE_ERR_CMD_DISALLOWED;
1989 }
1990
1991 if (!datalen) {
1992 return BLE_ERR_INV_HCI_CMD_PARMS;
1993 }
1994
1995 break;
1996 #endif
1997 default:
1998 return BLE_ERR_INV_HCI_CMD_PARMS;
1999 }
2000
2001 new_data = (operation == BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE) ||
2002 (operation == BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST);
2003
2004 ble_ll_adv_update_data_mbuf(&advsm->scan_rsp_data, new_data,
2005 BLE_SCAN_RSP_DATA_MAX_LEN, cmd + 1, datalen);
2006 if (!advsm->scan_rsp_data) {
2007 return BLE_ERR_MEM_CAPACITY;
2008 }
2009
2010 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2011 /* DID shall be updated when host provides new scan response data */
2012 advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
2013 #endif
2014
2015 return BLE_ERR_SUCCESS;
2016 }
2017
2018 /**
2019 * Called by the LL HCI command parser when a set advertising
2020 * data command has been sent from the host to the controller.
2021 *
2022 * @param cmd Pointer to command data
2023 * @param len Length of command data
2024 *
2025 * @return int 0: success; BLE_ERR_INV_HCI_CMD_PARMS otherwise.
2026 */
2027 int
ble_ll_adv_set_adv_data(uint8_t * cmd,uint8_t cmd_len,uint8_t instance,uint8_t operation)2028 ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t cmd_len, uint8_t instance,
2029 uint8_t operation)
2030 {
2031 uint8_t datalen;
2032 struct ble_ll_adv_sm *advsm;
2033 bool new_data;
2034
2035 if (instance >= BLE_ADV_INSTANCES) {
2036 return BLE_ERR_INV_HCI_CMD_PARMS;
2037 }
2038
2039 advsm = &g_ble_ll_adv_sm[instance];
2040 datalen = cmd[0];
2041
2042 if (datalen > 251 || datalen > cmd_len - 1) {
2043 return BLE_ERR_INV_HCI_CMD_PARMS;
2044 }
2045
2046 if (!instance_configured(advsm)) {
2047 return BLE_ERR_UNK_ADV_INDENT;
2048 }
2049
2050 /* check if type of advertising support adv data */
2051 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2052 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
2053 if (ble_ll_hci_adv_mode_ext()) {
2054 return BLE_ERR_INV_HCI_CMD_PARMS;
2055 }
2056 }
2057 } else {
2058 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
2059 return BLE_ERR_INV_HCI_CMD_PARMS;
2060 }
2061 }
2062
2063 switch (operation) {
2064 case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE:
2065 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2066 if (datalen > BLE_ADV_LEGACY_DATA_MAX_LEN) {
2067 return BLE_ERR_INV_HCI_CMD_PARMS;
2068 }
2069 }
2070
2071 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE;
2072 break;
2073 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2074 case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED:
2075 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2076 return BLE_ERR_INV_HCI_CMD_PARMS;
2077 }
2078
2079 if (!advsm->adv_enabled || !ADV_DATA_LEN(advsm) || datalen) {
2080 return BLE_ERR_INV_HCI_CMD_PARMS;
2081 }
2082
2083 /* update DID only */
2084 advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
2085 return BLE_ERR_SUCCESS;
2086 case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST:
2087 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE;
2088 /* fall through */
2089 case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT:
2090 if (!advsm->adv_data) {
2091 return BLE_ERR_INV_HCI_CMD_PARMS;
2092 }
2093
2094 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2095 return BLE_ERR_INV_HCI_CMD_PARMS;
2096 }
2097
2098 if (!datalen) {
2099 return BLE_ERR_INV_HCI_CMD_PARMS;
2100 }
2101
2102 if (advsm->adv_enabled) {
2103 return BLE_ERR_CMD_DISALLOWED;
2104 }
2105 break;
2106 case BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST:
2107 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2108 return BLE_ERR_INV_HCI_CMD_PARMS;
2109 }
2110
2111 if (advsm->adv_enabled) {
2112 return BLE_ERR_CMD_DISALLOWED;
2113 }
2114
2115 if (!datalen) {
2116 return BLE_ERR_INV_HCI_CMD_PARMS;
2117 }
2118
2119 advsm->flags |= BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE;
2120 break;
2121 #endif
2122 default:
2123 return BLE_ERR_INV_HCI_CMD_PARMS;
2124 }
2125
2126 new_data = (operation == BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE) ||
2127 (operation == BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST);
2128
2129 ble_ll_adv_update_data_mbuf(&advsm->adv_data, new_data, BLE_ADV_DATA_MAX_LEN,
2130 cmd + 1, datalen);
2131 if (!advsm->adv_data) {
2132 return BLE_ERR_MEM_CAPACITY;
2133 }
2134
2135 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2136 /* DID shall be updated when host provides new advertising data */
2137 advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
2138 #endif
2139
2140 return BLE_ERR_SUCCESS;
2141 }
2142
2143 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2144 int
ble_ll_adv_ext_set_param(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)2145 ble_ll_adv_ext_set_param(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
2146 {
2147 int rc;
2148 uint8_t adv_filter_policy;
2149 uint8_t adv_chanmask;
2150 uint8_t own_addr_type;
2151 uint8_t peer_addr_type;
2152 uint32_t adv_itvl_min;
2153 uint32_t adv_itvl_max;
2154 uint16_t props;
2155 struct ble_ll_adv_sm *advsm;
2156 uint8_t pri_phy;
2157 uint8_t sec_phy;
2158 uint8_t sid;
2159 uint8_t scan_req_notif;
2160 int8_t tx_power = 0;
2161
2162 if (cmdbuf[0] >= BLE_ADV_INSTANCES) {
2163 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2164 goto done;
2165 }
2166
2167 advsm = &g_ble_ll_adv_sm[cmdbuf[0]];
2168 if (advsm->adv_enabled) {
2169 rc = BLE_ERR_CMD_DISALLOWED;
2170 goto done;
2171 }
2172
2173 props = get_le16(&cmdbuf[1]);
2174
2175 adv_itvl_min = cmdbuf[5] << 16 | cmdbuf[4] << 8 | cmdbuf[3];
2176 adv_itvl_max = cmdbuf[8] << 16 | cmdbuf[7] << 8 | cmdbuf[6];
2177
2178 if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) {
2179 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2180 goto done;
2181 }
2182
2183 if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2184 if (ADV_DATA_LEN(advsm) > BLE_ADV_LEGACY_DATA_MAX_LEN ||
2185 SCAN_RSP_DATA_LEN(advsm) > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) {
2186 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2187 goto done;
2188 }
2189
2190 /* if legacy bit is set possible values are limited */
2191 switch (props) {
2192 case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND:
2193 case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR:
2194 case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR:
2195 case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN:
2196 case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN:
2197 break;
2198 default:
2199 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2200 goto done;
2201 }
2202 } else {
2203 /* HD directed advertising allowed only on legacy PDUs */
2204 if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
2205 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2206 goto done;
2207 }
2208
2209 /* if ext advertising PDUs are used then it shall not be both
2210 * connectable and scanable
2211 */
2212 if ((props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) &&
2213 (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) {
2214 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2215 goto done;
2216 }
2217 }
2218
2219 /* High Duty Directed advertising is special */
2220 if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
2221 if (ADV_DATA_LEN(advsm) || SCAN_RSP_DATA_LEN(advsm)) {
2222 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2223 goto done;
2224 }
2225
2226 /* Ignore min/max interval */
2227 adv_itvl_min = 0;
2228 adv_itvl_max = 0;
2229 } else {
2230 /* validate intervals for non HD-directed advertising */
2231 if ((adv_itvl_min > adv_itvl_max) ||
2232 (adv_itvl_min < BLE_HCI_ADV_ITVL_MIN) ||
2233 (adv_itvl_max < BLE_HCI_ADV_ITVL_MIN)) {
2234 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2235 goto done;
2236 }
2237
2238 /* TODO for now limit those to values from legacy advertising
2239 *
2240 * If the primary advertising interval range is outside the advertising
2241 * interval range supported by the Controller, then the Controller shall
2242 * return the error code Unsupported Feature or Parameter Value (0x11).
2243 */
2244 if ((adv_itvl_min > BLE_HCI_ADV_ITVL_MAX) ||
2245 (adv_itvl_max > BLE_HCI_ADV_ITVL_MAX)) {
2246 rc = BLE_ERR_UNSUPPORTED;
2247 goto done;
2248 }
2249 }
2250
2251 /* There are only three adv channels, so check for any outside the range */
2252 adv_chanmask = cmdbuf[9];
2253 if (((adv_chanmask & 0xF8) != 0) || (adv_chanmask == 0)) {
2254 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2255 goto done;
2256 }
2257
2258 /* Check own and peer address type */
2259 own_addr_type = cmdbuf[10];
2260 peer_addr_type = cmdbuf[11];
2261
2262 if ((own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) ||
2263 (peer_addr_type > BLE_HCI_ADV_PEER_ADDR_MAX)) {
2264 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2265 goto done;
2266 }
2267
2268 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 0)
2269 /* If we dont support privacy some address types wont work */
2270 if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
2271 rc = BLE_ERR_UNSUPPORTED;
2272 goto done;
2273 }
2274 #endif
2275
2276 adv_filter_policy = cmdbuf[18];
2277 /* Check filter policy (valid only for undirected */
2278 if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) &&
2279 adv_filter_policy > BLE_HCI_ADV_FILT_MAX) {
2280 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2281 goto done;
2282 }
2283
2284 pri_phy = cmdbuf[20];
2285 if (pri_phy != BLE_HCI_LE_PHY_1M && pri_phy != BLE_HCI_LE_PHY_CODED) {
2286 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2287 goto done;
2288 }
2289
2290 sec_phy = cmdbuf[22];
2291 if (sec_phy != BLE_HCI_LE_PHY_1M && sec_phy != BLE_HCI_LE_PHY_2M &&
2292 sec_phy != BLE_HCI_LE_PHY_CODED) {
2293 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2294 goto done;
2295 }
2296
2297 sid = cmdbuf[23];
2298 if (sid > 0x0f) {
2299 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2300 goto done;
2301 }
2302
2303 scan_req_notif = cmdbuf[24];
2304 if (scan_req_notif > 0x01) {
2305 rc = BLE_ERR_INV_HCI_CMD_PARMS;
2306 goto done;
2307 }
2308
2309 rc = BLE_ERR_SUCCESS;
2310
2311 if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
2312 memcpy(advsm->peer_addr, &cmdbuf[12], BLE_DEV_ADDR_LEN);
2313 }
2314
2315 tx_power = (int8_t) cmdbuf[19];
2316 if (tx_power == 127) {
2317 /* no preference */
2318 advsm->adv_txpwr = MYNEWT_VAL(BLE_LL_TX_PWR_DBM);
2319 } else {
2320 advsm->adv_txpwr = ble_phy_txpower_round(tx_power);
2321 }
2322
2323 advsm->own_addr_type = own_addr_type;
2324 advsm->peer_addr_type = peer_addr_type;
2325 advsm->adv_filter_policy = adv_filter_policy;
2326 advsm->adv_chanmask = adv_chanmask;
2327 advsm->adv_itvl_min = adv_itvl_min;
2328 advsm->adv_itvl_max = adv_itvl_max;
2329 advsm->pri_phy = pri_phy;
2330 advsm->sec_phy = sec_phy;
2331 /* Update SID only */
2332 advsm->adi = (advsm->adi & 0x0fff) | ((sid << 12));
2333
2334 advsm->props = props;
2335
2336 /* Set proper mbuf chain for aux data */
2337 if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2338 advsm->aux_data = NULL;
2339 } else if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
2340 advsm->aux_data = &advsm->scan_rsp_data;
2341 } else {
2342 advsm->aux_data = &advsm->adv_data;
2343 }
2344
2345 if (scan_req_notif) {
2346 advsm->flags |= BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF;
2347 } else {
2348 advsm->flags &= ~BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF;
2349 }
2350
2351 advsm->flags |= BLE_LL_ADV_SM_FLAG_CONFIGURED;
2352
2353 done:
2354 /* Update TX power */
2355 rspbuf[0] = ble_phy_txpower_round(tx_power);
2356 *rsplen = 1;
2357
2358 return rc;
2359 }
2360
2361 int
ble_ll_adv_ext_set_adv_data(uint8_t * cmdbuf,uint8_t cmdlen)2362 ble_ll_adv_ext_set_adv_data(uint8_t *cmdbuf, uint8_t cmdlen)
2363 {
2364 /* check if length is correct */
2365 if (cmdlen < 4) {
2366 return BLE_ERR_INV_HCI_CMD_PARMS;
2367 }
2368
2369 /* TODO fragment preference ignored for now */
2370
2371 return ble_ll_adv_set_adv_data(cmdbuf + 3, cmdlen - 3, cmdbuf[0],
2372 cmdbuf[1]);
2373 }
2374
2375 int
ble_ll_adv_ext_set_scan_rsp(uint8_t * cmdbuf,uint8_t cmdlen)2376 ble_ll_adv_ext_set_scan_rsp(uint8_t *cmdbuf, uint8_t cmdlen)
2377 {
2378 /* check if length is correct */
2379 if (cmdlen < 4) {
2380 return BLE_ERR_INV_HCI_CMD_PARMS;
2381 }
2382
2383 /* TODO fragment preference ignored for now */
2384
2385 return ble_ll_adv_set_scan_rsp_data(cmdbuf + 3, cmdlen - 3, cmdbuf[0],
2386 cmdbuf[1]);
2387 }
2388
2389 struct ext_adv_set {
2390 uint8_t handle;
2391 uint16_t duration;
2392 uint8_t events;
2393 } __attribute__((packed));
2394
2395 /**
2396 * HCI LE extended advertising enable command
2397 *
2398 * @param cmd Pointer to command data
2399 * @param len Command data length
2400 *
2401 * @return int BLE error code
2402 */
2403 int
ble_ll_adv_ext_set_enable(uint8_t * cmd,uint8_t len)2404 ble_ll_adv_ext_set_enable(uint8_t *cmd, uint8_t len)
2405 {
2406 struct ble_ll_adv_sm *advsm;
2407 struct ext_adv_set* set;
2408 uint8_t enable;
2409 uint8_t sets;
2410 int i, j, rc;
2411
2412 if (len < 2) {
2413 return BLE_ERR_INV_HCI_CMD_PARMS;
2414 }
2415
2416 enable = cmd[0];
2417 sets = cmd[1];
2418 cmd += 2;
2419
2420 /* check if length is correct */
2421 if (len != 2 + (sets * sizeof (*set))) {
2422 return BLE_ERR_INV_HCI_CMD_PARMS;
2423 }
2424
2425 if (sets > BLE_ADV_INSTANCES) {
2426 return BLE_ERR_INV_HCI_CMD_PARMS;
2427 }
2428
2429 if (sets == 0) {
2430 if (enable) {
2431 return BLE_ERR_INV_HCI_CMD_PARMS;
2432 }
2433
2434 /* disable all instances */
2435 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
2436 ble_ll_adv_set_enable(i, 0, 0, 0);
2437 }
2438
2439 return BLE_ERR_SUCCESS;
2440 }
2441
2442 set = (void *) cmd;
2443 /* validate instances */
2444 for (i = 0; i < sets; i++) {
2445 if (set->handle >= BLE_ADV_INSTANCES) {
2446 return BLE_ERR_INV_HCI_CMD_PARMS;
2447 }
2448
2449 /* validate duplicated sets */
2450 for (j = 1; j < sets - i; j++) {
2451 if (set->handle == set[j].handle) {
2452 return BLE_ERR_INV_HCI_CMD_PARMS;
2453 }
2454 }
2455
2456 advsm = &g_ble_ll_adv_sm[set->handle];
2457
2458 if (!instance_configured(advsm)) {
2459 return BLE_ERR_UNK_ADV_INDENT;
2460 }
2461
2462 if (enable) {
2463 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
2464 if (set->duration == 0 || le16toh(set->duration) > 128) {
2465 return BLE_ERR_INV_HCI_CMD_PARMS;
2466 }
2467 }
2468 }
2469
2470 set++;
2471 }
2472
2473 set = (void *) cmd;
2474 for (i = 0; i < sets; i++) {
2475 rc = ble_ll_adv_set_enable(set->handle, enable, le16toh(set->duration),
2476 set->events);
2477 if (rc) {
2478 return rc;
2479 }
2480
2481 set++;
2482 }
2483
2484 return BLE_ERR_SUCCESS;
2485 }
2486
2487 int
ble_ll_adv_set_random_addr(uint8_t * addr,uint8_t instance)2488 ble_ll_adv_set_random_addr(uint8_t *addr, uint8_t instance)
2489 {
2490 struct ble_ll_adv_sm *advsm;
2491
2492 if (instance >= BLE_ADV_INSTANCES) {
2493 return BLE_ERR_INV_HCI_CMD_PARMS;
2494 }
2495
2496 advsm = &g_ble_ll_adv_sm[instance];
2497
2498 /*
2499 * Reject if connectable advertising is on
2500 * Core Spec Vol. 2 Part E 7.8.52
2501 */
2502 if (advsm->adv_enabled &&
2503 (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE)) {
2504 return BLE_ERR_CMD_DISALLOWED;
2505 }
2506
2507 memcpy(advsm->adv_random_addr, addr, BLE_DEV_ADDR_LEN);
2508 return BLE_ERR_SUCCESS;
2509 }
2510
2511 /**
2512 * HCI LE extended advertising remove command
2513 *
2514 * @param instance Advertising instance to be removed
2515 *
2516 * @return int BLE error code
2517 */
2518 int
ble_ll_adv_remove(uint8_t instance)2519 ble_ll_adv_remove(uint8_t instance)
2520 {
2521 struct ble_ll_adv_sm *advsm;
2522
2523 /* TODO
2524 * Should we allow any value for instance ID?
2525 */
2526
2527 if (instance >= BLE_ADV_INSTANCES) {
2528 return BLE_ERR_INV_HCI_CMD_PARMS;
2529 }
2530
2531 advsm = &g_ble_ll_adv_sm[instance];
2532
2533 if (!instance_configured(advsm)) {
2534 return BLE_ERR_UNK_ADV_INDENT;
2535 }
2536
2537 if (advsm->adv_enabled) {
2538 return BLE_ERR_CMD_DISALLOWED;
2539 }
2540
2541 if (advsm->adv_data) {
2542 os_mbuf_free_chain(advsm->adv_data);
2543 }
2544 if (advsm->scan_rsp_data) {
2545 os_mbuf_free_chain(advsm->scan_rsp_data);
2546 }
2547
2548 ble_ll_adv_sm_init(advsm);
2549
2550 return BLE_ERR_SUCCESS;
2551 }
2552
2553 /**
2554 * HCI LE extended advertising clear command
2555 *
2556 * @return int BLE error code
2557 */
2558 int
ble_ll_adv_clear_all(void)2559 ble_ll_adv_clear_all(void)
2560 {
2561 int i;
2562
2563 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
2564 if (g_ble_ll_adv_sm[i].adv_enabled) {
2565 return BLE_ERR_CMD_DISALLOWED;
2566 }
2567 }
2568
2569 ble_ll_adv_reset();
2570
2571 return BLE_ERR_SUCCESS;
2572 }
2573 #endif
2574
2575 /**
2576 * Says whether the specified address is already connected or not.
2577 * @param [in] addr The peer address.
2578 * @param [in] addr_type Public address (0) or random address (1).
2579 * @return Return 1 if already connected, 0 otherwise.
2580 */
2581 static int
ble_ll_adv_already_connected(const uint8_t * addr,uint8_t addr_type)2582 ble_ll_adv_already_connected(const uint8_t* addr, uint8_t addr_type)
2583 {
2584 struct ble_ll_conn_sm *connsm;
2585
2586 /* extracted from ble_ll_conn_slave_start function */
2587 SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
2588 if (!memcmp(&connsm->peer_addr, addr, BLE_DEV_ADDR_LEN)) {
2589 if (addr_type == BLE_ADDR_RANDOM) {
2590 if (connsm->peer_addr_type & 1) {
2591 return 1;
2592 }
2593 } else {
2594 if ((connsm->peer_addr_type & 1) == 0) {
2595 return 1;
2596 }
2597 }
2598 }
2599 }
2600
2601 return 0;
2602 }
2603
2604 /**
2605 * Called when the LL receives a scan request or connection request
2606 *
2607 * Context: Called from interrupt context.
2608 *
2609 * @param rxbuf
2610 *
2611 * @return -1: request not for us or is a connect request.
2612 * 0: request (scan) is for us and we successfully went from rx to tx.
2613 * > 0: PHY error attempting to go from rx to tx.
2614 */
2615 static int
ble_ll_adv_rx_req(uint8_t pdu_type,struct os_mbuf * rxpdu)2616 ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
2617 {
2618 int rc;
2619 int resolved;
2620 uint8_t chk_wl;
2621 uint8_t txadd;
2622 uint8_t peer_addr_type;
2623 uint8_t *rxbuf;
2624 uint8_t *adva;
2625 uint8_t *peer;
2626 struct ble_mbuf_hdr *ble_hdr;
2627 struct ble_ll_adv_sm *advsm;
2628 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2629 struct aux_conn_rsp_data rsp_data;
2630 #endif
2631 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
2632 struct ble_ll_resolv_entry *rl;
2633 #endif
2634
2635 /* See if adva in the request (scan or connect) matches what we sent */
2636 advsm = g_ble_ll_cur_adv_sm;
2637 rxbuf = rxpdu->om_data;
2638 adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
2639 if (memcmp(advsm->adva, adva, BLE_DEV_ADDR_LEN)) {
2640 return -1;
2641 }
2642
2643 /* Set device match bit if we are whitelisting */
2644 if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
2645 chk_wl = advsm->adv_filter_policy & 1;
2646 } else {
2647 chk_wl = advsm->adv_filter_policy & 2;
2648 }
2649
2650 /* Get the peer address type */
2651 if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
2652 txadd = BLE_ADDR_RANDOM;
2653 } else {
2654 txadd = BLE_ADDR_PUBLIC;
2655 }
2656
2657 ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
2658 peer = rxbuf + BLE_LL_PDU_HDR_LEN;
2659 peer_addr_type = txadd;
2660 resolved = 0;
2661
2662 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
2663 rl = NULL;
2664 if (ble_ll_resolv_enabled()) {
2665 if (ble_ll_is_rpa(peer, txadd)) {
2666 advsm->adv_rpa_index = ble_hw_resolv_list_match();
2667 if (advsm->adv_rpa_index >= 0) {
2668 ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
2669 rl = &g_ble_ll_resolv_list[advsm->adv_rpa_index];
2670 if (chk_wl) {
2671 peer = rl->rl_identity_addr;
2672 peer_addr_type = rl->rl_addr_type;
2673 resolved = 1;
2674 }
2675 } else {
2676 if (chk_wl) {
2677 return -1;
2678 }
2679 }
2680 } else {
2681 /* Verify privacy mode */
2682 rl = ble_ll_resolv_list_find(peer, peer_addr_type);
2683 if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
2684 ble_ll_resolv_irk_nonzero(rl->rl_peer_irk)) {
2685 return -1;
2686 }
2687 }
2688 }
2689 #endif
2690
2691 /* Set device match bit if we are whitelisting */
2692 if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
2693 return -1;
2694 }
2695
2696 /*
2697 * We set the device match bit to tell the upper layer that we will
2698 * accept the request
2699 */
2700 ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
2701
2702 /* Setup to transmit the scan response if appropriate */
2703 rc = -1;
2704
2705 if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
2706 /* XXX TODO: assume we do not need to change phy mode */
2707 ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
2708
2709 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2710 if (advsm->flags & BLE_LL_ADV_SM_FLAG_SCAN_REQ_NOTIF) {
2711 ble_ll_hci_ev_send_scan_req_recv(advsm->adv_instance, peer,
2712 peer_addr_type);
2713 }
2714
2715 /*
2716 * We need to store current rxed packet header temporarily so AuxPtr
2717 * can be calculated (if necessary) relative to AUX_SCAN_RSP instead of
2718 * AUX_ADV_IND.
2719 */
2720
2721 advsm->rx_ble_hdr = ble_hdr;
2722 rc = ble_phy_tx(ble_ll_adv_scan_rsp_pdu_make, advsm,
2723 BLE_PHY_TRANSITION_NONE);
2724 advsm->rx_ble_hdr = NULL;
2725 #else
2726 rc = ble_phy_tx(ble_ll_adv_scan_rsp_legacy_pdu_make, advsm,
2727 BLE_PHY_TRANSITION_NONE);
2728 #endif
2729
2730 if (!rc) {
2731 ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD;
2732 STATS_INC(ble_ll_stats, scan_rsp_txg);
2733 }
2734 } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ) {
2735 /* See if the device is already connected */
2736 if (ble_ll_adv_already_connected(peer, peer_addr_type)) {
2737 return -1;
2738 }
2739
2740 /*
2741 * Only accept connect requests from the desired address if we
2742 * are doing directed advertising
2743 */
2744 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
2745 if (memcmp(advsm->peer_addr, peer, BLE_DEV_ADDR_LEN)) {
2746 return -1;
2747 }
2748 }
2749
2750 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2751 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
2752 return -1;
2753 }
2754
2755 /* use remote address used over the air */
2756 rsp_data.advsm = advsm;
2757 rsp_data.peer = rxbuf + BLE_LL_PDU_HDR_LEN;
2758 rsp_data.rxadd = rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK;
2759
2760 ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
2761 rc = ble_phy_tx(ble_ll_adv_aux_conn_rsp_pdu_make, &rsp_data,
2762 BLE_PHY_TRANSITION_NONE);
2763 if (!rc) {
2764 advsm->flags |= BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD;
2765 STATS_INC(ble_ll_stats, aux_conn_rsp_tx);
2766 }
2767 #endif
2768 }
2769
2770 return rc;
2771 }
2772
2773 /**
2774 * Called when a connect request has been received.
2775 *
2776 * Context: Link Layer
2777 *
2778 * @param rxbuf
2779 * @param flags
2780 *
2781 * @return 0: no connection started. 1: connection started
2782 */
2783 static int
ble_ll_adv_conn_req_rxd(uint8_t * rxbuf,struct ble_mbuf_hdr * hdr,struct ble_ll_adv_sm * advsm)2784 ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr,
2785 struct ble_ll_adv_sm *advsm)
2786 {
2787 int valid;
2788 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
2789 uint8_t resolved;
2790 #endif
2791 uint8_t addr_type;
2792 uint8_t *inita;
2793 uint8_t *ident_addr;
2794
2795 /* Don't create connection if AUX_CONNECT_RSP was not send */
2796 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) {
2797 if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) {
2798 return 0;
2799 }
2800 }
2801
2802 /* Check filter policy. */
2803 valid = 0;
2804 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
2805 resolved = BLE_MBUF_HDR_RESOLVED(hdr);
2806 #endif
2807 inita = rxbuf + BLE_LL_PDU_HDR_LEN;
2808 if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) {
2809
2810 valid = 1;
2811 if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
2812 addr_type = BLE_ADDR_RANDOM;
2813 } else {
2814 addr_type = BLE_ADDR_PUBLIC;
2815 }
2816
2817 /*
2818 * Only accept connect requests from the desired address if we
2819 * are doing directed advertising
2820 */
2821 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) {
2822 ident_addr = inita;
2823
2824 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
2825 if (resolved) {
2826 ident_addr = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr;
2827 addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
2828 }
2829 #endif
2830 if ((addr_type != advsm->peer_addr_type) ||
2831 memcmp(advsm->peer_addr, ident_addr, BLE_DEV_ADDR_LEN)) {
2832 valid = 0;
2833 }
2834 }
2835 }
2836
2837 if (valid) {
2838 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
2839 if (resolved) {
2840 /* Retain the resolvable private address that we received. */
2841 memcpy(advsm->adv_rpa, inita, BLE_DEV_ADDR_LEN);
2842
2843 /* Update resolving list with current peer RPA */
2844 ble_ll_resolv_set_peer_rpa(advsm->adv_rpa_index, inita);
2845
2846 /*
2847 * Overwrite received inita with identity address since that
2848 * is used from now on.
2849 */
2850 memcpy(inita,
2851 g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr,
2852 BLE_DEV_ADDR_LEN);
2853
2854 /* Peer address type is an identity address */
2855 addr_type = g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
2856 addr_type += 2;
2857 }
2858 #endif
2859
2860 /* Try to start slave connection. If successful, stop advertising */
2861 valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr,
2862 !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY));
2863 if (valid) {
2864 /* stop advertising only if not transmitting connection response */
2865 if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) {
2866 ble_ll_adv_sm_stop(advsm);
2867 }
2868 }
2869 }
2870
2871 return valid;
2872 }
2873
2874 /**
2875 * Called on phy rx pdu end when in advertising state.
2876 *
2877 * There are only two pdu types we care about in this state: scan requests
2878 * and connection requests. When we receive a scan request we must determine if
2879 * we need to send a scan response and that needs to be acted on within T_IFS.
2880 *
2881 * When we receive a connection request, we need to determine if we will allow
2882 * this device to start a connection with us. However, no immediate response is
2883 * sent so we handle this at the link layer task.
2884 *
2885 * Context: Interrupt
2886 *
2887 * @param pdu_type Type of pdu received.
2888 * @param rxpdu Pointer to received PDU
2889 *
2890 * @return int
2891 * < 0: Disable the phy after reception.
2892 * == 0: Do not disable the PHY
2893 * > 0: Do not disable PHY as that has already been done.
2894 */
2895 int
ble_ll_adv_rx_isr_end(uint8_t pdu_type,struct os_mbuf * rxpdu,int crcok)2896 ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok)
2897 {
2898 int rc;
2899 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2900 struct ble_mbuf_hdr *rxhdr;
2901 #endif
2902
2903 rc = -1;
2904 if (rxpdu == NULL) {
2905 ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm);
2906 } else {
2907 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2908 rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
2909 rxhdr->rxinfo.user_data = g_ble_ll_cur_adv_sm;
2910 if (ble_ll_adv_active_chanset_is_sec(g_ble_ll_cur_adv_sm)) {
2911 rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV_SEC;
2912 } else {
2913 assert(ble_ll_adv_active_chanset_is_pri(g_ble_ll_cur_adv_sm));
2914 }
2915 #endif
2916 if (crcok) {
2917 if ((pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) ||
2918 (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
2919 /* Process request */
2920 rc = ble_ll_adv_rx_req(pdu_type, rxpdu);
2921 }
2922 }
2923
2924 if (rc) {
2925 /* We no longer have a current state machine */
2926 g_ble_ll_cur_adv_sm = NULL;
2927 }
2928 }
2929
2930 if (rc) {
2931 ble_ll_state_set(BLE_LL_STATE_STANDBY);
2932 }
2933
2934 return rc;
2935 }
2936
2937 /**
2938 * Process a received packet at the link layer task when in the advertising
2939 * state
2940 *
2941 * Context: Link Layer
2942 *
2943 *
2944 * @param ptype
2945 * @param rxbuf
2946 * @param hdr
2947 *
2948 * @return int
2949 */
2950 void
ble_ll_adv_rx_pkt_in(uint8_t ptype,uint8_t * rxbuf,struct ble_mbuf_hdr * hdr)2951 ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
2952 {
2953 int adv_event_over;
2954 struct ble_ll_adv_sm *advsm;
2955
2956 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
2957 advsm = (struct ble_ll_adv_sm *)hdr->rxinfo.user_data;
2958 #else
2959 advsm = &g_ble_ll_adv_sm[0];
2960 #endif
2961
2962 /*
2963 * It is possible that advertising was stopped and a packet plcaed on the
2964 * LL receive packet queue. In this case, just ignore the received packet
2965 * as the advertising state machine is no longer "valid"
2966 */
2967 if (!advsm->adv_enabled) {
2968 return;
2969 }
2970
2971 /*
2972 * If we have received a scan request and we are transmitting a response
2973 * or we have received a valid connect request, dont "end" the advertising
2974 * event. In the case of a connect request we will stop advertising. In
2975 * the case of the scan response transmission we will get a transmit
2976 * end callback.
2977 */
2978 adv_event_over = 1;
2979 if (BLE_MBUF_HDR_CRC_OK(hdr)) {
2980 if (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ) {
2981 if (ble_ll_adv_conn_req_rxd(rxbuf, hdr, advsm)) {
2982 adv_event_over = 0;
2983 }
2984 } else {
2985 if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) &&
2986 (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) {
2987 adv_event_over = 0;
2988 }
2989 }
2990 }
2991
2992 if (adv_event_over) {
2993 ble_ll_adv_make_done(advsm, hdr);
2994 }
2995 }
2996
2997 /**
2998 * Called when a receive PDU has started and we are advertising.
2999 *
3000 * Context: interrupt
3001 *
3002 * @param pdu_type
3003 * @param rxpdu
3004 *
3005 * @return int
3006 * < 0: A frame we dont want to receive.
3007 * = 0: Continue to receive frame. Dont go from rx to tx
3008 * > 0: Continue to receive frame and go from rx to tx when done
3009 */
3010 int
ble_ll_adv_rx_isr_start(uint8_t pdu_type)3011 ble_ll_adv_rx_isr_start(uint8_t pdu_type)
3012 {
3013 int rc;
3014 struct ble_ll_adv_sm *advsm;
3015
3016 /* Assume we will abort the frame */
3017 rc = -1;
3018
3019 /* If we get a scan request we must tell the phy to go from rx to tx */
3020 advsm = g_ble_ll_cur_adv_sm;
3021 if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
3022 /* Only accept scan requests if we are indirect adv or scan adv */
3023 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) {
3024 rc = 1;
3025 }
3026 } else {
3027 /* Only accept connect requests if connectable advertising event */
3028 if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ) {
3029 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) {
3030 rc = 0;
3031 }
3032 }
3033 }
3034
3035 /*
3036 * If we abort the frame, we need to post the LL task to check if the
3037 * advertising event is over.
3038 */
3039 if (rc < 0) {
3040 ble_ll_adv_tx_done(advsm);
3041 }
3042
3043 return rc;
3044 }
3045
3046 static void
ble_ll_adv_drop_event(struct ble_ll_adv_sm * advsm)3047 ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm)
3048 {
3049 STATS_INC(ble_ll_stats, adv_drop_event);
3050
3051 ble_ll_sched_rmv_elem(&advsm->adv_sch);
3052 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3053 ble_ll_sched_rmv_elem(&advsm->aux[0].sch);
3054 ble_ll_sched_rmv_elem(&advsm->aux[1].sch);
3055
3056 ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
3057 advsm->aux_active = 0;
3058 #endif
3059
3060 advsm->adv_chan = ble_ll_adv_final_chan(advsm);
3061 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
3062 }
3063
3064 static void
ble_ll_adv_reschedule_event(struct ble_ll_adv_sm * advsm)3065 ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm)
3066 {
3067 int rc;
3068 uint32_t start_time;
3069 uint32_t max_delay_ticks;
3070
3071 assert(advsm->adv_enabled);
3072
3073 if (!advsm->adv_sch.enqueued) {
3074 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) {
3075 max_delay_ticks = 0;
3076 } else {
3077 max_delay_ticks =
3078 os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000);
3079 }
3080
3081 rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time,
3082 max_delay_ticks);
3083 if (rc) {
3084 ble_ll_adv_drop_event(advsm);
3085 return;
3086 }
3087
3088 start_time += g_ble_ll_sched_offset_ticks;
3089 advsm->adv_event_start_time = start_time;
3090 advsm->adv_pdu_start_time = start_time;
3091 }
3092
3093 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3094 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
3095 !advsm->aux_active) {
3096 ble_ll_adv_aux_schedule(advsm);
3097 }
3098 #endif
3099 }
3100
3101 /**
3102 * Called when an advertising event is over.
3103 *
3104 * Context: Link Layer task.
3105 *
3106 * @param arg Pointer to advertising state machine.
3107 */
3108 static void
ble_ll_adv_done(struct ble_ll_adv_sm * advsm)3109 ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
3110
3111 {
3112 int rc;
3113 int resched_pdu;
3114 uint8_t mask;
3115 uint8_t final_adv_chan;
3116 int32_t delta_t;
3117 uint32_t itvl;
3118 uint32_t tick_itvl;
3119 uint32_t start_time;
3120
3121 assert(advsm->adv_enabled);
3122
3123 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3124 if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) {
3125 /* stop advertising this was due to transmitting connection response */
3126 if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) {
3127 ble_ll_adv_sm_stop(advsm);
3128 return;
3129 }
3130 }
3131 #endif
3132
3133 /* Remove the element from the schedule if it is still there. */
3134 ble_ll_sched_rmv_elem(&advsm->adv_sch);
3135
3136 ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
3137
3138 /*
3139 * Check if we have ended our advertising event. If our last advertising
3140 * packet was sent on the last channel, it means we are done with this
3141 * event.
3142 */
3143 final_adv_chan = ble_ll_adv_final_chan(advsm);
3144
3145 if (advsm->adv_chan == final_adv_chan) {
3146 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3147 if (advsm->events_max) {
3148 advsm->events++;
3149 }
3150 #endif
3151
3152 /* Check if we need to resume scanning */
3153 ble_ll_scan_chk_resume();
3154
3155 /* Turn off the clock if not doing anything else */
3156 #ifdef BLE_XCVR_RFCLK
3157 ble_ll_sched_rfclk_chk_restart();
3158 #endif
3159
3160 /* This event is over. Set adv channel to first one */
3161 advsm->adv_chan = ble_ll_adv_first_chan(advsm);
3162
3163 /*
3164 * Calculate start time of next advertising event. NOTE: we do not
3165 * add the random advDelay as the scheduling code will do that.
3166 */
3167 itvl = advsm->adv_itvl_usecs;
3168 tick_itvl = os_cputime_usecs_to_ticks(itvl);
3169 advsm->adv_event_start_time += tick_itvl;
3170 advsm->adv_pdu_start_time = advsm->adv_event_start_time;
3171
3172 /*
3173 * The scheduled time better be in the future! If it is not, we will
3174 * just keep advancing until we the time is in the future
3175 */
3176 start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
3177
3178 delta_t = (int32_t)(start_time - os_cputime_get32());
3179 if (delta_t < 0) {
3180 /*
3181 * NOTE: we just the same interval that we calculated earlier.
3182 * No real need to keep recalculating a new interval.
3183 */
3184 while (delta_t < 0) {
3185 advsm->adv_event_start_time += tick_itvl;
3186 advsm->adv_pdu_start_time = advsm->adv_event_start_time;
3187 delta_t += (int32_t)tick_itvl;
3188 }
3189 }
3190 resched_pdu = 0;
3191 } else {
3192 /*
3193 * Move to next advertising channel. If not in the mask, just
3194 * increment by 1. We can do this because we already checked if we
3195 * just transmitted on the last advertising channel
3196 */
3197 ++advsm->adv_chan;
3198 mask = 1 << (advsm->adv_chan - BLE_PHY_ADV_CHAN_START);
3199 if ((mask & advsm->adv_chanmask) == 0) {
3200 ++advsm->adv_chan;
3201 }
3202
3203 /*
3204 * We will transmit right away. Set next pdu start time to now
3205 * plus a xcvr start delay just so we dont count late adv starts
3206 */
3207 advsm->adv_pdu_start_time = os_cputime_get32() +
3208 g_ble_ll_sched_offset_ticks;
3209
3210 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3211 /* If we're past aux (unlikely, but can happen), just drop an event */
3212 if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) &&
3213 advsm->aux_active &&
3214 advsm->adv_pdu_start_time > AUX_CURRENT(advsm)->start_time) {
3215 ble_ll_adv_drop_event(advsm);
3216 return;
3217 }
3218 #endif
3219
3220 resched_pdu = 1;
3221 }
3222
3223 /* check if advertising timed out */
3224 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3225 if (advsm->duration &&
3226 advsm->adv_pdu_start_time >= advsm->adv_end_time) {
3227 /* Legacy PDUs need to be stop here.
3228 * For ext adv it will be stopped when AUX is done (unless it was
3229 * dropped so check if AUX is active here as well).
3230 */
3231 if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) ||
3232 !advsm->aux_active) {
3233 ble_ll_adv_sm_stop_timeout(advsm);
3234 }
3235
3236 return;
3237 }
3238 #else
3239 if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) &&
3240 (advsm->adv_pdu_start_time >= advsm->adv_end_time)) {
3241 ble_ll_adv_sm_stop_timeout(advsm);
3242 return;
3243 }
3244 #endif
3245
3246 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3247 if (advsm->events_max && (advsm->events >= advsm->events_max)) {
3248 /* Legacy PDUs need to be stop here.
3249 * For ext adv it will be stopped when AUX is done (unless it was
3250 * dropped so check if AUX is active here as well).
3251 */
3252 if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) ||
3253 !advsm->aux_active) {
3254 ble_ll_adv_sm_stop_limit_reached(advsm);
3255 }
3256
3257 return;
3258 }
3259 #endif
3260
3261 /* We need to regenerate our RPA's if we have passed timeout */
3262 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
3263 ble_ll_adv_chk_rpa_timeout(advsm);
3264 #endif
3265
3266 /* Schedule advertising transmit */
3267 ble_ll_adv_set_sched(advsm);
3268
3269 if (!resched_pdu) {
3270 ble_ll_adv_reschedule_event(advsm);
3271 return;
3272 }
3273
3274 /*
3275 * In the unlikely event we cant reschedule this, just post a done
3276 * event and we will reschedule the next advertising event
3277 */
3278 rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch);
3279 if (rc) {
3280 STATS_INC(ble_ll_stats, adv_resched_pdu_fail);
3281 ble_ll_adv_drop_event(advsm);
3282 }
3283 }
3284
3285 static void
ble_ll_adv_event_done(struct ble_npl_event * ev)3286 ble_ll_adv_event_done(struct ble_npl_event *ev)
3287 {
3288 ble_ll_adv_done(ble_npl_event_get_arg(ev));
3289 }
3290
3291 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3292 /**
3293 * Called when auxiliary packet is txd on secondary channel
3294 *
3295 * Context: Link Layer task.
3296 *
3297 * @param ev
3298 */
3299 static void
ble_ll_adv_sec_done(struct ble_ll_adv_sm * advsm)3300 ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
3301 {
3302 struct ble_ll_adv_aux *aux;
3303 struct ble_ll_adv_aux *aux_next;
3304
3305 assert(advsm->adv_enabled);
3306 assert(advsm->aux_active);
3307
3308 aux = AUX_CURRENT(advsm);
3309 aux_next = AUX_NEXT(advsm);
3310
3311 if (advsm->aux_not_scanned) {
3312 ble_ll_sched_rmv_elem(&aux_next->sch);
3313 }
3314
3315 /* Remove anything else scheduled for secondary channel */
3316 ble_ll_sched_rmv_elem(&aux->sch);
3317 ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev);
3318
3319 /* Stop advertising due to transmitting connection response */
3320 if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) {
3321 ble_ll_adv_sm_stop(advsm);
3322 return;
3323 }
3324
3325 /* If we have next AUX scheduled, try to schedule another one */
3326 if (aux_next->sch.enqueued) {
3327 advsm->aux_index ^= 1;
3328 advsm->aux_first_pdu = 0;
3329 ble_ll_adv_aux_schedule_next(advsm);
3330 return;
3331 }
3332
3333 /* Check if we need to resume scanning */
3334 ble_ll_scan_chk_resume();
3335
3336 /* Check if advertising timed out */
3337 if (advsm->duration && (advsm->adv_pdu_start_time >= advsm->adv_end_time)) {
3338 ble_ll_adv_sm_stop_timeout(advsm);
3339 return;
3340 }
3341
3342 if (advsm->events_max && (advsm->events >= advsm->events_max)) {
3343 ble_ll_adv_sm_stop_limit_reached(advsm);
3344 return;
3345 }
3346
3347 advsm->aux_active = 0;
3348 ble_ll_adv_reschedule_event(advsm);
3349 }
3350
3351 static void
ble_ll_adv_sec_event_done(struct ble_npl_event * ev)3352 ble_ll_adv_sec_event_done(struct ble_npl_event *ev)
3353 {
3354 ble_ll_adv_sec_done(ble_npl_event_get_arg(ev));
3355 }
3356 #endif
3357
3358 static void
ble_ll_adv_make_done(struct ble_ll_adv_sm * advsm,struct ble_mbuf_hdr * hdr)3359 ble_ll_adv_make_done(struct ble_ll_adv_sm *advsm, struct ble_mbuf_hdr *hdr)
3360 {
3361 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3362 if (BLE_MBUF_HDR_EXT_ADV_SEC(hdr)) {
3363 assert(!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY));
3364 assert(ble_ll_adv_active_chanset_is_sec(advsm));
3365 ble_ll_adv_active_chanset_clear(advsm);
3366 ble_ll_adv_sec_done(advsm);
3367 } else {
3368 assert(ble_ll_adv_active_chanset_is_pri(advsm));
3369 ble_ll_adv_active_chanset_clear(advsm);
3370 ble_ll_adv_done(advsm);
3371 }
3372 #else
3373 assert(ble_ll_adv_active_chanset_is_pri(advsm));
3374 ble_ll_adv_active_chanset_clear(advsm);
3375 ble_ll_adv_done(advsm);
3376 #endif
3377 }
3378
3379 /**
3380 * Checks if the controller can change the whitelist. If advertising is enabled
3381 * and is using the whitelist the controller is not allowed to change the
3382 * whitelist.
3383 *
3384 * @return int 0: not allowed to change whitelist; 1: change allowed.
3385 */
3386 int
ble_ll_adv_can_chg_whitelist(void)3387 ble_ll_adv_can_chg_whitelist(void)
3388 {
3389 struct ble_ll_adv_sm *advsm;
3390 int rc;
3391 int i;
3392
3393 rc = 1;
3394 for (i = 0; i < BLE_ADV_INSTANCES; ++i) {
3395 advsm = &g_ble_ll_adv_sm[i];
3396 if (advsm->adv_enabled &&
3397 (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE)) {
3398 rc = 0;
3399 break;
3400 }
3401 }
3402
3403 return rc;
3404 }
3405
3406 /**
3407 * Sends the connection complete event when advertising a connection starts.
3408 *
3409 * @return uint8_t* Pointer to event buffer
3410 */
3411 void
ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm * connsm,struct ble_mbuf_hdr * rxhdr)3412 ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm,
3413 struct ble_mbuf_hdr *rxhdr)
3414 {
3415 uint8_t *evbuf;
3416 struct ble_ll_adv_sm *advsm;
3417
3418 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3419 advsm = (struct ble_ll_adv_sm *)rxhdr->rxinfo.user_data;
3420 #else
3421 advsm = &g_ble_ll_adv_sm[0];
3422 #endif
3423
3424 evbuf = advsm->conn_comp_ev;
3425 assert(evbuf != NULL);
3426 advsm->conn_comp_ev = NULL;
3427
3428 ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm);
3429
3430 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
3431 ble_ll_hci_ev_le_csa(connsm);
3432 #endif
3433
3434 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3435 if (ble_ll_hci_adv_mode_ext()) {
3436 ble_ll_hci_ev_send_adv_set_terminated(0, advsm->adv_instance,
3437 connsm->conn_handle, advsm->events);
3438 }
3439 #endif
3440 }
3441
3442 /**
3443 * Returns the local resolvable private address currently being using by
3444 * the advertiser
3445 *
3446 * @return uint8_t*
3447 */
3448 uint8_t *
ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm * advsm)3449 ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm)
3450 {
3451 uint8_t *rpa = NULL;
3452
3453 if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
3454 if ((advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) &&
3455 ble_ll_is_rpa(advsm->adva, 1)) {
3456 rpa = advsm->adva;
3457 }
3458 }
3459
3460 return rpa;
3461 }
3462
3463 /**
3464 * Returns the peer resolvable private address of last device connecting to us
3465 *
3466 * @return uint8_t*
3467 */
3468 uint8_t *
ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm * advsm)3469 ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm)
3470 {
3471 /* XXX: should this go into IRK list or connection? */
3472 return advsm->adv_rpa;
3473 }
3474
3475 /**
3476 * Called when the LL wait for response timer expires while in the advertising
3477 * state. Disables the phy and
3478 *
3479 */
3480 void
ble_ll_adv_wfr_timer_exp(void)3481 ble_ll_adv_wfr_timer_exp(void)
3482 {
3483 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3484 g_ble_ll_cur_adv_sm->aux_not_scanned = 1;
3485 #endif
3486
3487 ble_phy_disable();
3488 ble_ll_adv_tx_done(g_ble_ll_cur_adv_sm);
3489 }
3490
3491 /**
3492 * Reset the advertising state machine.
3493 *
3494 * Context: Link Layer task
3495 *
3496 */
3497 void
ble_ll_adv_reset(void)3498 ble_ll_adv_reset(void)
3499 {
3500 int i;
3501 struct ble_ll_adv_sm *advsm;
3502
3503 for (i = 0; i < BLE_ADV_INSTANCES; ++i) {
3504 advsm = &g_ble_ll_adv_sm[i];
3505
3506 /* Stop advertising state machine */
3507 ble_ll_adv_sm_stop(advsm);
3508
3509 /* clear any data present */
3510 os_mbuf_free_chain(advsm->adv_data);
3511 os_mbuf_free_chain(advsm->scan_rsp_data);
3512
3513 /* re-initialize the advertiser state machine */
3514 ble_ll_adv_sm_init(advsm);
3515 }
3516 }
3517
3518 /* Called to determine if advertising is enabled.
3519 */
3520 uint8_t
ble_ll_adv_enabled(void)3521 ble_ll_adv_enabled(void)
3522 {
3523 int i;
3524
3525 for (i = 0; i < BLE_ADV_INSTANCES; i++) {
3526 if (g_ble_ll_adv_sm[i].adv_enabled) {
3527 return 1;
3528 }
3529 }
3530
3531 return 0;
3532 }
3533
3534 static void
ble_ll_adv_sm_init(struct ble_ll_adv_sm * advsm)3535 ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm)
3536 {
3537 uint8_t i = advsm->adv_instance;
3538
3539 memset(advsm, 0, sizeof(struct ble_ll_adv_sm));
3540
3541 advsm->adv_instance = i;
3542 advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF;
3543 advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF;
3544 advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF;
3545
3546 /* Initialize advertising tx done event */
3547 ble_npl_event_init(&advsm->adv_txdone_ev, ble_ll_adv_event_done, advsm);
3548 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3549 ble_npl_event_init(&advsm->adv_sec_txdone_ev, ble_ll_adv_sec_event_done, advsm);
3550 #endif
3551
3552 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
3553 /* Initialize aux schedulers */
3554 advsm->aux_active = 0;
3555 advsm->aux[0].sch.cb_arg = advsm;
3556 advsm->aux[0].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb;
3557 advsm->aux[0].sch.sched_type = BLE_LL_SCHED_TYPE_ADV;
3558 advsm->aux[1].sch.cb_arg = advsm;
3559 advsm->aux[1].sch.sched_cb = ble_ll_adv_secondary_tx_start_cb;
3560 advsm->aux[1].sch.sched_type = BLE_LL_SCHED_TYPE_ADV;
3561 #endif
3562
3563 /*XXX Configure instances to be legacy on start */
3564 advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE;
3565 advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY;
3566 }
3567
3568 /**
3569 * Initialize the advertising functionality of a BLE device. This should
3570 * be called once on initialization
3571 */
3572 void
ble_ll_adv_init(void)3573 ble_ll_adv_init(void)
3574 {
3575 int i;
3576
3577 /* Set default advertising parameters */
3578 for (i = 0; i < BLE_ADV_INSTANCES; ++i) {
3579 g_ble_ll_adv_sm[i].adv_instance = i;
3580 ble_ll_adv_sm_init(&g_ble_ll_adv_sm[i]);
3581 }
3582 }
3583
3584