summaryrefslogtreecommitdiff
path: root/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_scan.h
blob: 139ad5e1f74f72496b361d4dc3a0496b45cb5614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifndef H_BLE_LL_SCAN_
#define H_BLE_LL_SCAN_

#include "controller/ble_ll_sched.h"
#include "hal/hal_timer.h"
#include "syscfg/syscfg.h"
#include "nimble/nimble_npl.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * SCAN_REQ
 *      -> ScanA    (6 bytes)
 *      -> AdvA     (6 bytes)
 *
 *  ScanA is the scanners public (TxAdd=0) or random (TxAdd = 1) address
 *  AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address.
 *
 * Sent by the LL in the Scanning state; received by the LL in the advertising
 * state. The advertising address is the intended recipient of this frame.
 */
#define BLE_SCAN_REQ_LEN                (12)

/*
 * SCAN_RSP
 *      -> AdvA         (6 bytes)
 *      -> ScanRspData  (0 - 31 bytes)
 *
 *  AdvaA is the advertisers public (TxAdd=0) or random (TxAdd=1) address.
 *  ScanRspData may contain any data from the advertisers host.
 *
 * Sent by the LL in the advertising state; received by the LL in the
 * scanning state.
 */
#define BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN       (31)
#define BLE_SCAN_LEGACY_MAX_PKT_LEN            (37)

#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
#define BLE_SCAN_RSP_DATA_MAX_LEN       MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)

/* For Bluetooth 5.0 we need state machine for two PHYs*/
#define BLE_LL_SCAN_PHY_NUMBER          (2)
#else
#define BLE_LL_SCAN_PHY_NUMBER          (1)
#define BLE_SCAN_RSP_DATA_MAX_LEN       BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN
#endif

#define PHY_UNCODED                    (0)
#define PHY_CODED                      (1)

#define BLE_LL_EXT_ADV_MODE_NON_CONN    (0x00)
#define BLE_LL_EXT_ADV_MODE_CONN        (0x01)
#define BLE_LL_EXT_ADV_MODE_SCAN        (0x02)

/* All values are stored as ticks */
struct ble_ll_scan_timing {
    uint32_t interval;
    uint32_t window;
    uint32_t start_time;
};

struct ble_ll_scan_params
{
    uint8_t phy;
    uint8_t own_addr_type;
    uint8_t scan_filt_policy;
    uint8_t configured;
    uint8_t scan_type;
    uint8_t scan_chan;
    struct ble_ll_scan_timing timing;
};

#define BLE_LL_AUX_HAS_ADVA                     0x01
#define BLE_LL_AUX_HAS_TARGETA                  0x02
#define BLE_LL_AUX_HAS_ADI                      0x04
#define BLE_LL_AUX_IS_MATCHED                   0x08
#define BLE_LL_AUX_IS_TARGETA_RESOLVED          0x10

#define BLE_LL_AUX_FLAG_HCI_SENT_ANY            0x02
#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED      0x04
#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED      0x08
#define BLE_LL_AUX_FLAG_SCAN_COMPLETE           0x10
#define BLE_LL_AUX_FLAG_SCAN_ERROR              0x20
#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED        0x40
#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED      0x80

struct ble_ll_aux_data {
    uint8_t flags;

    /*
     * Since aux_data can be accessed from ISR and LL, we have separate copies
     * of flags to make sure that ISR does not modify flags while LL uses them.
     * ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then
     * uses for further processing allowing to update 'flags_isr' if another
     * scan for given 'aux_data' is scheduled. Note that flags must not be unset
     * while aux_data is valid.
     */
    uint8_t flags_isr;
    uint8_t flags_ll;

    uint8_t ref_cnt;
    uint8_t chan;
    uint8_t aux_phy;
    uint8_t aux_primary_phy;
    uint8_t mode;
    uint8_t scanning;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
    int8_t rpa_index;
#endif
    uint16_t adi;
    uint32_t offset;
    uint8_t offset_units;
    uint8_t adva[6];
    uint8_t adva_type;
    uint8_t targeta[6];
    uint8_t targeta_type;
    uint16_t evt_type;
    struct ble_ll_sched_item sch;
    struct ble_hci_ev *evt;
    struct ble_npl_event ev;
};

struct ble_ll_scan_pdu_data {
    uint8_t hdr_byte;
    /* ScanA for SCAN_REQ and InitA for CONNECT_IND */
    union {
        uint8_t scana[BLE_DEV_ADDR_LEN];
        uint8_t inita[BLE_DEV_ADDR_LEN];
    };
    uint8_t adva[BLE_DEV_ADDR_LEN];
};

struct ble_ll_scan_sm
{
    uint8_t scan_enabled;
    uint8_t own_addr_type;
    uint8_t scan_filt_dups;
    uint8_t scan_rsp_pending;
    uint8_t scan_rsp_cons_fails;
    uint8_t scan_rsp_cons_ok;
    uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN];
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
    ble_npl_time_t scan_nrpa_timer;
    uint8_t scan_nrpa[BLE_DEV_ADDR_LEN];
#endif
    struct ble_ll_scan_pdu_data pdu_data;

    /* XXX: Shall we count backoff per phy? */
    uint16_t upper_limit;
    uint16_t backoff_count;
    uint32_t scan_win_start_time;
    struct ble_npl_event scan_sched_ev;
    struct hal_timer scan_timer;
    struct ble_npl_event scan_interrupted_ev;

#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
    struct hal_timer duration_timer;
    struct hal_timer period_timer;
    uint32_t duration_ticks;
    uint32_t period_ticks;
    uint8_t ext_scanning;
#endif

    uint8_t restart_timer_needed;
    struct ble_ll_aux_data *cur_aux_data;

    struct ble_ll_scan_params *scanp;
    struct ble_ll_scan_params *scanp_next;
    struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER];
};

/* Scan types */
#define BLE_SCAN_TYPE_PASSIVE   (BLE_HCI_SCAN_TYPE_PASSIVE)
#define BLE_SCAN_TYPE_ACTIVE    (BLE_HCI_SCAN_TYPE_ACTIVE)
#define BLE_SCAN_TYPE_INITIATE  (2)

/*---- HCI ----*/
/* Set scanning parameters */
int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len);

/* Turn scanning on/off */
int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);

#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len);
#endif

/*--- Controller Internal API ---*/
/* Initialize the scanner */
void ble_ll_scan_init(void);

/* Reset the scanner */
void ble_ll_scan_reset(void);

/* Called when Link Layer starts to receive a PDU and is in scanning state */
int ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags);

/* Called when Link Layer has finished receiving a PDU while scanning */
int ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);

/* Process a scan response PDU */
void ble_ll_scan_rx_pkt_in(uint8_t pdu_type, struct os_mbuf *om,
                           struct ble_mbuf_hdr *hdr);

/* Boolean function denoting whether or not the whitelist can be changed */
int ble_ll_scan_can_chg_whitelist(void);

/* Boolean function returning true if scanning enabled */
int ble_ll_scan_enabled(void);

/* Boolean function returns true if whitelist is enabled for scanning */
int ble_ll_scan_whitelist_enabled(void);

/* Initialize the scanner when we start initiating */
struct hci_create_conn;
int ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
                                struct ble_ll_scan_sm **sm);

/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */
struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void);

/* Called to set the resolvable private address of the last connected peer */
void ble_ll_scan_set_peer_rpa(uint8_t *rpa);

/* Returns peer RPA of last connection made */
uint8_t *ble_ll_scan_get_peer_rpa(void);

/* Returns the local RPA used by the scanner/initiator */
uint8_t *ble_ll_scan_get_local_rpa(void);

/* Stop the scanning state machine */
void ble_ll_scan_sm_stop(int chk_disable);

/* Resume scanning */
void ble_ll_scan_chk_resume(void);

/* Called when wait for response timer expires in scanning mode */
void ble_ll_scan_wfr_timer_exp(void);

/* Called when scan could be interrupted  */
void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm);

int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf,
                                struct ble_mbuf_hdr *ble_hdr,
                                uint8_t **addr, uint8_t *addr_type,
                                uint8_t **inita, uint8_t *init_addr_type,
                                int *ext_mode);

#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf,
                                bool *adva_present);

/* Initialize the extended scanner when we start initiating */
struct hci_ext_create_conn;
int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
                                    struct ble_ll_scan_sm **sm);

/* Called to parse extended advertising*/
struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
#endif

/* Called to halt currently running scan */
void ble_ll_scan_halt(void);

#ifdef __cplusplus
}
#endif

#endif /* H_BLE_LL_SCAN_ */