xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_adv.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 #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