1*042d53a7SEvalZero /*
2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file
4*042d53a7SEvalZero * distributed with this work for additional information
5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file
6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at
9*042d53a7SEvalZero *
10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero * software distributed under the License is distributed on an
14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero * KIND, either express or implied. See the License for the
16*042d53a7SEvalZero * specific language governing permissions and limitations
17*042d53a7SEvalZero * under the License.
18*042d53a7SEvalZero */
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include <stdint.h>
21*042d53a7SEvalZero #include <stdlib.h>
22*042d53a7SEvalZero #include <assert.h>
23*042d53a7SEvalZero #include <string.h>
24*042d53a7SEvalZero #include "sysinit/sysinit.h"
25*042d53a7SEvalZero #include "syscfg/syscfg.h"
26*042d53a7SEvalZero #include "os/os.h"
27*042d53a7SEvalZero #include "os/os_cputime.h"
28*042d53a7SEvalZero #include "stats/stats.h"
29*042d53a7SEvalZero #include "nimble/ble.h"
30*042d53a7SEvalZero #include "nimble/nimble_opt.h"
31*042d53a7SEvalZero #include "nimble/hci_common.h"
32*042d53a7SEvalZero #include "nimble/ble_hci_trans.h"
33*042d53a7SEvalZero #include "controller/ble_hw.h"
34*042d53a7SEvalZero #include "controller/ble_phy.h"
35*042d53a7SEvalZero #include "controller/ble_phy_trace.h"
36*042d53a7SEvalZero #include "controller/ble_ll.h"
37*042d53a7SEvalZero #include "controller/ble_ll_adv.h"
38*042d53a7SEvalZero #include "controller/ble_ll_sched.h"
39*042d53a7SEvalZero #include "controller/ble_ll_scan.h"
40*042d53a7SEvalZero #include "controller/ble_ll_hci.h"
41*042d53a7SEvalZero #include "controller/ble_ll_whitelist.h"
42*042d53a7SEvalZero #include "controller/ble_ll_resolv.h"
43*042d53a7SEvalZero #include "controller/ble_ll_xcvr.h"
44*042d53a7SEvalZero #include "controller/ble_ll_trace.h"
45*042d53a7SEvalZero #include "ble_ll_conn_priv.h"
46*042d53a7SEvalZero
47*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
48*042d53a7SEvalZero #include "ble_ll_dtm_priv.h"
49*042d53a7SEvalZero #endif
50*042d53a7SEvalZero
51*042d53a7SEvalZero /* XXX:
52*042d53a7SEvalZero *
53*042d53a7SEvalZero * 1) use the sanity task!
54*042d53a7SEvalZero * 2) Need to figure out what to do with packets that we hand up that did
55*042d53a7SEvalZero * not pass the filter policy for the given state. Currently I count all
56*042d53a7SEvalZero * packets I think. Need to figure out what to do with this.
57*042d53a7SEvalZero * 3) For the features defined, we need to conditionally compile code.
58*042d53a7SEvalZero * 4) Should look into always disabled the wfr interrupt if we receive the
59*042d53a7SEvalZero * start of a frame. Need to look at the various states to see if this is the
60*042d53a7SEvalZero * right thing to do.
61*042d53a7SEvalZero */
62*042d53a7SEvalZero
63*042d53a7SEvalZero /* Supported states */
64*042d53a7SEvalZero #define BLE_LL_S_NCA (0x00000000001)
65*042d53a7SEvalZero #define BLE_LL_S_SA (0x00000000002)
66*042d53a7SEvalZero #define BLE_LL_S_CA (0x00000000004)
67*042d53a7SEvalZero #define BLE_LL_S_HDCA (0x00000000008)
68*042d53a7SEvalZero #define BLE_LL_S_PS (0x00000000010)
69*042d53a7SEvalZero #define BLE_LL_S_AS (0x00000000020)
70*042d53a7SEvalZero #define BLE_LL_S_INIT (0x00000000040)
71*042d53a7SEvalZero #define BLE_LL_S_SLAVE (0x00000000080)
72*042d53a7SEvalZero #define BLE_LL_S_NCA_PS (0x00000000100)
73*042d53a7SEvalZero #define BLE_LL_S_SA_PS (0x00000000200)
74*042d53a7SEvalZero #define BLE_LL_S_CA_PS (0x00000000400)
75*042d53a7SEvalZero #define BLE_LL_S_HDCA_PS (0x00000000800)
76*042d53a7SEvalZero #define BLE_LL_S_NCA_AS (0x00000001000)
77*042d53a7SEvalZero #define BLE_LL_S_SA_AS (0x00000002000)
78*042d53a7SEvalZero #define BLE_LL_S_CA_AS (0x00000004000)
79*042d53a7SEvalZero #define BLE_LL_S_HDCA_AS (0x00000008000)
80*042d53a7SEvalZero #define BLE_LL_S_NCA_INIT (0x00000010000)
81*042d53a7SEvalZero #define BLE_LL_S_SA_INIT (0x00000020000)
82*042d53a7SEvalZero #define BLE_LL_S_NCA_MASTER (0x00000040000)
83*042d53a7SEvalZero #define BLE_LL_S_SA_MASTER (0x00000080000)
84*042d53a7SEvalZero #define BLE_LL_S_NCA_SLAVE (0x00000100000)
85*042d53a7SEvalZero #define BLE_LL_S_SA_SLAVE (0x00000200000)
86*042d53a7SEvalZero #define BLE_LL_S_PS_INIT (0x00000400000)
87*042d53a7SEvalZero #define BLE_LL_S_AS_INIT (0x00000800000)
88*042d53a7SEvalZero #define BLE_LL_S_PS_MASTER (0x00001000000)
89*042d53a7SEvalZero #define BLE_LL_S_AS_MASTER (0x00002000000)
90*042d53a7SEvalZero #define BLE_LL_S_PS_SLAVE (0x00004000000)
91*042d53a7SEvalZero #define BLE_LL_S_AS_SLAVE (0x00008000000)
92*042d53a7SEvalZero #define BLE_LL_S_INIT_MASTER (0x00010000000)
93*042d53a7SEvalZero #define BLE_LL_S_LDCA (0x00020000000)
94*042d53a7SEvalZero #define BLE_LL_S_LDCA_PS (0x00040000000)
95*042d53a7SEvalZero #define BLE_LL_S_LDCA_AS (0x00080000000)
96*042d53a7SEvalZero #define BLE_LL_S_CA_INIT (0x00100000000)
97*042d53a7SEvalZero #define BLE_LL_S_HDCA_INIT (0x00200000000)
98*042d53a7SEvalZero #define BLE_LL_S_LDCA_INIT (0x00400000000)
99*042d53a7SEvalZero #define BLE_LL_S_CA_MASTER (0x00800000000)
100*042d53a7SEvalZero #define BLE_LL_S_HDCA_MASTER (0x01000000000)
101*042d53a7SEvalZero #define BLE_LL_S_LDCA_MASTER (0x02000000000)
102*042d53a7SEvalZero #define BLE_LL_S_CA_SLAVE (0x04000000000)
103*042d53a7SEvalZero #define BLE_LL_S_HDCA_SLAVE (0x08000000000)
104*042d53a7SEvalZero #define BLE_LL_S_LDCA_SLAVE (0x10000000000)
105*042d53a7SEvalZero #define BLE_LL_S_INIT_SLAVE (0x20000000000)
106*042d53a7SEvalZero
107*042d53a7SEvalZero #define BLE_LL_SUPPORTED_STATES \
108*042d53a7SEvalZero ( \
109*042d53a7SEvalZero BLE_LL_S_NCA | \
110*042d53a7SEvalZero BLE_LL_S_SA | \
111*042d53a7SEvalZero BLE_LL_S_CA | \
112*042d53a7SEvalZero BLE_LL_S_HDCA | \
113*042d53a7SEvalZero BLE_LL_S_PS | \
114*042d53a7SEvalZero BLE_LL_S_AS | \
115*042d53a7SEvalZero BLE_LL_S_INIT | \
116*042d53a7SEvalZero BLE_LL_S_SLAVE | \
117*042d53a7SEvalZero BLE_LL_S_NCA_PS | \
118*042d53a7SEvalZero BLE_LL_S_SA_PS | \
119*042d53a7SEvalZero BLE_LL_S_CA_PS | \
120*042d53a7SEvalZero BLE_LL_S_HDCA_PS | \
121*042d53a7SEvalZero BLE_LL_S_NCA_AS | \
122*042d53a7SEvalZero BLE_LL_S_SA_AS | \
123*042d53a7SEvalZero BLE_LL_S_CA_AS | \
124*042d53a7SEvalZero BLE_LL_S_HDCA_AS | \
125*042d53a7SEvalZero BLE_LL_S_NCA_INIT | \
126*042d53a7SEvalZero BLE_LL_S_SA_INIT | \
127*042d53a7SEvalZero BLE_LL_S_NCA_MASTER | \
128*042d53a7SEvalZero BLE_LL_S_SA_MASTER | \
129*042d53a7SEvalZero BLE_LL_S_NCA_SLAVE | \
130*042d53a7SEvalZero BLE_LL_S_SA_SLAVE | \
131*042d53a7SEvalZero BLE_LL_S_PS_INIT | \
132*042d53a7SEvalZero BLE_LL_S_AS_INIT | \
133*042d53a7SEvalZero BLE_LL_S_PS_MASTER | \
134*042d53a7SEvalZero BLE_LL_S_AS_MASTER | \
135*042d53a7SEvalZero BLE_LL_S_PS_SLAVE | \
136*042d53a7SEvalZero BLE_LL_S_AS_SLAVE | \
137*042d53a7SEvalZero BLE_LL_S_INIT_MASTER | \
138*042d53a7SEvalZero BLE_LL_S_LDCA | \
139*042d53a7SEvalZero BLE_LL_S_LDCA_PS | \
140*042d53a7SEvalZero BLE_LL_S_LDCA_AS | \
141*042d53a7SEvalZero BLE_LL_S_CA_INIT | \
142*042d53a7SEvalZero BLE_LL_S_HDCA_INIT | \
143*042d53a7SEvalZero BLE_LL_S_LDCA_INIT | \
144*042d53a7SEvalZero BLE_LL_S_CA_MASTER | \
145*042d53a7SEvalZero BLE_LL_S_HDCA_MASTER | \
146*042d53a7SEvalZero BLE_LL_S_LDCA_MASTER | \
147*042d53a7SEvalZero BLE_LL_S_CA_SLAVE | \
148*042d53a7SEvalZero BLE_LL_S_HDCA_SLAVE | \
149*042d53a7SEvalZero BLE_LL_S_LDCA_SLAVE | \
150*042d53a7SEvalZero BLE_LL_S_INIT_SLAVE)
151*042d53a7SEvalZero
152*042d53a7SEvalZero /* The global BLE LL data object */
153*042d53a7SEvalZero struct ble_ll_obj g_ble_ll_data;
154*042d53a7SEvalZero
155*042d53a7SEvalZero /* Global link layer statistics */
156*042d53a7SEvalZero STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
157*042d53a7SEvalZero STATS_NAME_START(ble_ll_stats)
158*042d53a7SEvalZero STATS_NAME(ble_ll_stats, hci_cmds)
159*042d53a7SEvalZero STATS_NAME(ble_ll_stats, hci_cmd_errs)
160*042d53a7SEvalZero STATS_NAME(ble_ll_stats, hci_events_sent)
161*042d53a7SEvalZero STATS_NAME(ble_ll_stats, bad_ll_state)
162*042d53a7SEvalZero STATS_NAME(ble_ll_stats, bad_acl_hdr)
163*042d53a7SEvalZero STATS_NAME(ble_ll_stats, no_bufs)
164*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_ok)
165*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_pdu_crc_err)
166*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_ok)
167*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_bytes_crc_err)
168*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_data_pdu_crc_ok)
169*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_data_pdu_crc_err)
170*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_data_bytes_crc_ok)
171*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_data_bytes_crc_err)
172*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_malformed_pkts)
173*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_ind)
174*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_direct_ind)
175*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_nonconn_ind)
176*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_adv_ext_ind)
177*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_scan_reqs)
178*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_scan_rsps)
179*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_connect_reqs)
180*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_scan_ind)
181*042d53a7SEvalZero STATS_NAME(ble_ll_stats, rx_aux_connect_rsp)
182*042d53a7SEvalZero STATS_NAME(ble_ll_stats, adv_txg)
183*042d53a7SEvalZero STATS_NAME(ble_ll_stats, adv_late_starts)
184*042d53a7SEvalZero STATS_NAME(ble_ll_stats, adv_resched_pdu_fail)
185*042d53a7SEvalZero STATS_NAME(ble_ll_stats, adv_drop_event)
186*042d53a7SEvalZero STATS_NAME(ble_ll_stats, sched_state_conn_errs)
187*042d53a7SEvalZero STATS_NAME(ble_ll_stats, sched_state_adv_errs)
188*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_starts)
189*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_stops)
190*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_req_txf)
191*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_req_txg)
192*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_rsp_txg)
193*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_missed_adv)
194*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_scheduled)
195*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_received)
196*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_fired_for_read)
197*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_allocated)
198*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_freed)
199*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_sched_cb)
200*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_conn_req_tx)
201*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_conn_rsp_tx)
202*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_conn_rsp_err)
203*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_scan_req_tx)
204*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_scan_rsp_err)
205*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_chain_cnt)
206*042d53a7SEvalZero STATS_NAME(ble_ll_stats, aux_chain_err)
207*042d53a7SEvalZero STATS_NAME(ble_ll_stats, adv_evt_dropped)
208*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_timer_stopped)
209*042d53a7SEvalZero STATS_NAME(ble_ll_stats, scan_timer_restarted)
210*042d53a7SEvalZero STATS_NAME_END(ble_ll_stats)
211*042d53a7SEvalZero
212*042d53a7SEvalZero static void ble_ll_event_rx_pkt(struct ble_npl_event *ev);
213*042d53a7SEvalZero static void ble_ll_event_tx_pkt(struct ble_npl_event *ev);
214*042d53a7SEvalZero static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev);
215*042d53a7SEvalZero
216*042d53a7SEvalZero #if MYNEWT
217*042d53a7SEvalZero
218*042d53a7SEvalZero /* The BLE LL task data structure */
219*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
220*042d53a7SEvalZero /* TODO: This is for testing. Check it we really need it */
221*042d53a7SEvalZero #define BLE_LL_STACK_SIZE (128)
222*042d53a7SEvalZero #else
223*042d53a7SEvalZero #define BLE_LL_STACK_SIZE (90)
224*042d53a7SEvalZero #endif
225*042d53a7SEvalZero
226*042d53a7SEvalZero struct os_task g_ble_ll_task;
227*042d53a7SEvalZero
228*042d53a7SEvalZero OS_TASK_STACK_DEFINE(g_ble_ll_stack, BLE_LL_STACK_SIZE);
229*042d53a7SEvalZero
230*042d53a7SEvalZero #endif /* MYNEWT */
231*042d53a7SEvalZero
232*042d53a7SEvalZero /** Our global device address (public) */
233*042d53a7SEvalZero uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
234*042d53a7SEvalZero
235*042d53a7SEvalZero /** Our random address */
236*042d53a7SEvalZero uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
237*042d53a7SEvalZero
238*042d53a7SEvalZero static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] =
239*042d53a7SEvalZero {
240*042d53a7SEvalZero [BLE_PHY_MODE_1M] =
241*042d53a7SEvalZero (BLE_LL_PREAMBLE_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN +
242*042d53a7SEvalZero BLE_LL_PDU_HDR_LEN) << 3,
243*042d53a7SEvalZero [BLE_PHY_MODE_2M] =
244*042d53a7SEvalZero (BLE_LL_PREAMBLE_LEN * 2 + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN +
245*042d53a7SEvalZero BLE_LL_PDU_HDR_LEN) << 2,
246*042d53a7SEvalZero /* For Coded PHY we have exact TX times provided by specification:
247*042d53a7SEvalZero * - Preamble, Access Address, CI, TERM1 (always coded as S=8)
248*042d53a7SEvalZero * - PDU, CRC, TERM2 (coded as S=2 or S=8)
249*042d53a7SEvalZero * (Vol 6, Part B, 2.2).
250*042d53a7SEvalZero */
251*042d53a7SEvalZero [BLE_PHY_MODE_CODED_125KBPS] =
252*042d53a7SEvalZero (80 + 256 + 16 + 24 + 8 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)),
253*042d53a7SEvalZero [BLE_PHY_MODE_CODED_500KBPS] =
254*042d53a7SEvalZero (80 + 256 + 16 + 24 + 2 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)),
255*042d53a7SEvalZero };
256*042d53a7SEvalZero
257*042d53a7SEvalZero /**
258*042d53a7SEvalZero * Counts the number of advertising PDU's received, by type. For advertising
259*042d53a7SEvalZero * PDU's that contain a destination address, we still count these packets even
260*042d53a7SEvalZero * if they are not for us.
261*042d53a7SEvalZero *
262*042d53a7SEvalZero * @param pdu_type
263*042d53a7SEvalZero */
264*042d53a7SEvalZero static void
ble_ll_count_rx_adv_pdus(uint8_t pdu_type)265*042d53a7SEvalZero ble_ll_count_rx_adv_pdus(uint8_t pdu_type)
266*042d53a7SEvalZero {
267*042d53a7SEvalZero /* Count received packet types */
268*042d53a7SEvalZero switch (pdu_type) {
269*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_EXT_IND:
270*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_ext_ind);
271*042d53a7SEvalZero break;
272*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_IND:
273*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_ind);
274*042d53a7SEvalZero break;
275*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
276*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_direct_ind);
277*042d53a7SEvalZero break;
278*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND:
279*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_nonconn_ind);
280*042d53a7SEvalZero break;
281*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_SCAN_REQ:
282*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_scan_reqs);
283*042d53a7SEvalZero break;
284*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_SCAN_RSP:
285*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_scan_rsps);
286*042d53a7SEvalZero break;
287*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_CONNECT_REQ:
288*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_connect_reqs);
289*042d53a7SEvalZero break;
290*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP:
291*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_aux_connect_rsp);
292*042d53a7SEvalZero break;
293*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_SCAN_IND:
294*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_scan_ind);
295*042d53a7SEvalZero break;
296*042d53a7SEvalZero default:
297*042d53a7SEvalZero break;
298*042d53a7SEvalZero }
299*042d53a7SEvalZero }
300*042d53a7SEvalZero
301*042d53a7SEvalZero /**
302*042d53a7SEvalZero * Allocate a pdu (chain) for reception.
303*042d53a7SEvalZero *
304*042d53a7SEvalZero * @param len
305*042d53a7SEvalZero *
306*042d53a7SEvalZero * @return struct os_mbuf*
307*042d53a7SEvalZero */
308*042d53a7SEvalZero struct os_mbuf *
ble_ll_rxpdu_alloc(uint16_t len)309*042d53a7SEvalZero ble_ll_rxpdu_alloc(uint16_t len)
310*042d53a7SEvalZero {
311*042d53a7SEvalZero uint16_t mb_bytes;
312*042d53a7SEvalZero struct os_mbuf *m;
313*042d53a7SEvalZero struct os_mbuf *n;
314*042d53a7SEvalZero struct os_mbuf *p;
315*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
316*042d53a7SEvalZero
317*042d53a7SEvalZero p = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
318*042d53a7SEvalZero if (!p) {
319*042d53a7SEvalZero goto rxpdu_alloc_exit;
320*042d53a7SEvalZero }
321*042d53a7SEvalZero
322*042d53a7SEvalZero /* Set packet length */
323*042d53a7SEvalZero pkthdr = OS_MBUF_PKTHDR(p);
324*042d53a7SEvalZero pkthdr->omp_len = len;
325*042d53a7SEvalZero
326*042d53a7SEvalZero /*
327*042d53a7SEvalZero * NOTE: first mbuf in chain will have data pre-pended to it so we adjust
328*042d53a7SEvalZero * m_data by a word.
329*042d53a7SEvalZero */
330*042d53a7SEvalZero p->om_data += 4;
331*042d53a7SEvalZero mb_bytes = (p->om_omp->omp_databuf_len - p->om_pkthdr_len - 4);
332*042d53a7SEvalZero
333*042d53a7SEvalZero if (mb_bytes < len) {
334*042d53a7SEvalZero n = p;
335*042d53a7SEvalZero len -= mb_bytes;
336*042d53a7SEvalZero while (len) {
337*042d53a7SEvalZero m = os_msys_get(len, 0);
338*042d53a7SEvalZero if (!m) {
339*042d53a7SEvalZero os_mbuf_free_chain(p);
340*042d53a7SEvalZero p = NULL;
341*042d53a7SEvalZero goto rxpdu_alloc_exit;
342*042d53a7SEvalZero }
343*042d53a7SEvalZero /* Chain new mbuf to existing chain */
344*042d53a7SEvalZero SLIST_NEXT(n, om_next) = m;
345*042d53a7SEvalZero n = m;
346*042d53a7SEvalZero mb_bytes = m->om_omp->omp_databuf_len;
347*042d53a7SEvalZero if (mb_bytes >= len) {
348*042d53a7SEvalZero len = 0;
349*042d53a7SEvalZero } else {
350*042d53a7SEvalZero len -= mb_bytes;
351*042d53a7SEvalZero }
352*042d53a7SEvalZero }
353*042d53a7SEvalZero }
354*042d53a7SEvalZero
355*042d53a7SEvalZero
356*042d53a7SEvalZero rxpdu_alloc_exit:
357*042d53a7SEvalZero if (!p) {
358*042d53a7SEvalZero STATS_INC(ble_ll_stats, no_bufs);
359*042d53a7SEvalZero }
360*042d53a7SEvalZero return p;
361*042d53a7SEvalZero }
362*042d53a7SEvalZero
363*042d53a7SEvalZero int
ble_ll_chk_txrx_octets(uint16_t octets)364*042d53a7SEvalZero ble_ll_chk_txrx_octets(uint16_t octets)
365*042d53a7SEvalZero {
366*042d53a7SEvalZero int rc;
367*042d53a7SEvalZero
368*042d53a7SEvalZero if ((octets < BLE_LL_CONN_SUPP_BYTES_MIN) ||
369*042d53a7SEvalZero (octets > BLE_LL_CONN_SUPP_BYTES_MAX)) {
370*042d53a7SEvalZero rc = 0;
371*042d53a7SEvalZero } else {
372*042d53a7SEvalZero rc = 1;
373*042d53a7SEvalZero }
374*042d53a7SEvalZero
375*042d53a7SEvalZero return rc;
376*042d53a7SEvalZero }
377*042d53a7SEvalZero
378*042d53a7SEvalZero int
ble_ll_chk_txrx_time(uint16_t time)379*042d53a7SEvalZero ble_ll_chk_txrx_time(uint16_t time)
380*042d53a7SEvalZero {
381*042d53a7SEvalZero int rc;
382*042d53a7SEvalZero
383*042d53a7SEvalZero if ((time < BLE_LL_CONN_SUPP_TIME_MIN) ||
384*042d53a7SEvalZero (time > BLE_LL_CONN_SUPP_TIME_MAX)) {
385*042d53a7SEvalZero rc = 0;
386*042d53a7SEvalZero } else {
387*042d53a7SEvalZero rc = 1;
388*042d53a7SEvalZero }
389*042d53a7SEvalZero
390*042d53a7SEvalZero return rc;
391*042d53a7SEvalZero }
392*042d53a7SEvalZero
393*042d53a7SEvalZero /**
394*042d53a7SEvalZero * Checks to see if the address is a resolvable private address.
395*042d53a7SEvalZero *
396*042d53a7SEvalZero * NOTE: the addr_type parameter will be 0 if the address is public;
397*042d53a7SEvalZero * any other value is random (all non-zero values).
398*042d53a7SEvalZero *
399*042d53a7SEvalZero * @param addr
400*042d53a7SEvalZero * @param addr_type Public (zero) or Random (non-zero) address
401*042d53a7SEvalZero *
402*042d53a7SEvalZero * @return int
403*042d53a7SEvalZero */
404*042d53a7SEvalZero int
ble_ll_is_rpa(uint8_t * addr,uint8_t addr_type)405*042d53a7SEvalZero ble_ll_is_rpa(uint8_t *addr, uint8_t addr_type)
406*042d53a7SEvalZero {
407*042d53a7SEvalZero int rc;
408*042d53a7SEvalZero
409*042d53a7SEvalZero if (addr_type && ((addr[5] & 0xc0) == 0x40)) {
410*042d53a7SEvalZero rc = 1;
411*042d53a7SEvalZero } else {
412*042d53a7SEvalZero rc = 0;
413*042d53a7SEvalZero }
414*042d53a7SEvalZero return rc;
415*042d53a7SEvalZero }
416*042d53a7SEvalZero
417*042d53a7SEvalZero /* Checks to see that the device is a valid random address */
418*042d53a7SEvalZero int
ble_ll_is_valid_random_addr(uint8_t * addr)419*042d53a7SEvalZero ble_ll_is_valid_random_addr(uint8_t *addr)
420*042d53a7SEvalZero {
421*042d53a7SEvalZero int i;
422*042d53a7SEvalZero int rc;
423*042d53a7SEvalZero uint16_t sum;
424*042d53a7SEvalZero uint8_t addr_type;
425*042d53a7SEvalZero
426*042d53a7SEvalZero /* Make sure all bits are neither one nor zero */
427*042d53a7SEvalZero sum = 0;
428*042d53a7SEvalZero for (i = 0; i < (BLE_DEV_ADDR_LEN -1); ++i) {
429*042d53a7SEvalZero sum += addr[i];
430*042d53a7SEvalZero }
431*042d53a7SEvalZero sum += addr[5] & 0x3f;
432*042d53a7SEvalZero
433*042d53a7SEvalZero if ((sum == 0) || (sum == ((5*255) + 0x3f))) {
434*042d53a7SEvalZero return 0;
435*042d53a7SEvalZero }
436*042d53a7SEvalZero
437*042d53a7SEvalZero /* Get the upper two bits of the address */
438*042d53a7SEvalZero rc = 1;
439*042d53a7SEvalZero addr_type = addr[5] & 0xc0;
440*042d53a7SEvalZero if (addr_type == 0xc0) {
441*042d53a7SEvalZero /* Static random address. No other checks needed */
442*042d53a7SEvalZero } else if (addr_type == 0x40) {
443*042d53a7SEvalZero /* Resolvable */
444*042d53a7SEvalZero sum = addr[3] + addr[4] + (addr[5] & 0x3f);
445*042d53a7SEvalZero if ((sum == 0) || (sum == (255 + 255 + 0x3f))) {
446*042d53a7SEvalZero rc = 0;
447*042d53a7SEvalZero }
448*042d53a7SEvalZero } else if (addr_type == 0) {
449*042d53a7SEvalZero /* non-resolvable. Cant be equal to public */
450*042d53a7SEvalZero if (!memcmp(g_dev_addr, addr, BLE_DEV_ADDR_LEN)) {
451*042d53a7SEvalZero rc = 0;
452*042d53a7SEvalZero }
453*042d53a7SEvalZero } else {
454*042d53a7SEvalZero /* Invalid upper two bits */
455*042d53a7SEvalZero rc = 0;
456*042d53a7SEvalZero }
457*042d53a7SEvalZero
458*042d53a7SEvalZero return rc;
459*042d53a7SEvalZero }
460*042d53a7SEvalZero
461*042d53a7SEvalZero /**
462*042d53a7SEvalZero * Called from the HCI command parser when the set random address command
463*042d53a7SEvalZero * is received.
464*042d53a7SEvalZero *
465*042d53a7SEvalZero * Context: Link Layer task (HCI command parser)
466*042d53a7SEvalZero *
467*042d53a7SEvalZero * @param addr Pointer to address
468*042d53a7SEvalZero *
469*042d53a7SEvalZero * @return int 0: success
470*042d53a7SEvalZero */
471*042d53a7SEvalZero int
ble_ll_set_random_addr(uint8_t * addr,bool hci_adv_ext)472*042d53a7SEvalZero ble_ll_set_random_addr(uint8_t *addr, bool hci_adv_ext)
473*042d53a7SEvalZero {
474*042d53a7SEvalZero /* If the Host issues this command when scanning or legacy advertising is
475*042d53a7SEvalZero * enabled, the Controller shall return the error code Command Disallowed.
476*042d53a7SEvalZero *
477*042d53a7SEvalZero * Test specification extends this also to initiating.
478*042d53a7SEvalZero */
479*042d53a7SEvalZero
480*042d53a7SEvalZero if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() ||
481*042d53a7SEvalZero (!hci_adv_ext && ble_ll_adv_enabled())) {
482*042d53a7SEvalZero return BLE_ERR_CMD_DISALLOWED;
483*042d53a7SEvalZero }
484*042d53a7SEvalZero
485*042d53a7SEvalZero if (!ble_ll_is_valid_random_addr(addr)) {
486*042d53a7SEvalZero return BLE_ERR_INV_HCI_CMD_PARMS;
487*042d53a7SEvalZero }
488*042d53a7SEvalZero
489*042d53a7SEvalZero memcpy(g_random_addr, addr, BLE_DEV_ADDR_LEN);
490*042d53a7SEvalZero
491*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
492*042d53a7SEvalZero /* For instance 0 we need same address if legacy advertising might be
493*042d53a7SEvalZero * used. If extended advertising is in use than this command doesn't
494*042d53a7SEvalZero * affect instance 0.
495*042d53a7SEvalZero */
496*042d53a7SEvalZero if (!hci_adv_ext)
497*042d53a7SEvalZero ble_ll_adv_set_random_addr(addr, 0);
498*042d53a7SEvalZero #endif
499*042d53a7SEvalZero
500*042d53a7SEvalZero return BLE_ERR_SUCCESS;
501*042d53a7SEvalZero }
502*042d53a7SEvalZero
503*042d53a7SEvalZero /**
504*042d53a7SEvalZero * Checks to see if an address is our device address (either public or
505*042d53a7SEvalZero * random)
506*042d53a7SEvalZero *
507*042d53a7SEvalZero * @param addr
508*042d53a7SEvalZero * @param addr_type
509*042d53a7SEvalZero *
510*042d53a7SEvalZero * @return int 0: not our device address. 1: is our device address
511*042d53a7SEvalZero */
512*042d53a7SEvalZero int
ble_ll_is_our_devaddr(uint8_t * addr,int addr_type)513*042d53a7SEvalZero ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
514*042d53a7SEvalZero {
515*042d53a7SEvalZero int rc;
516*042d53a7SEvalZero uint8_t *our_addr;
517*042d53a7SEvalZero
518*042d53a7SEvalZero if (addr_type) {
519*042d53a7SEvalZero our_addr = g_random_addr;
520*042d53a7SEvalZero } else {
521*042d53a7SEvalZero our_addr = g_dev_addr;
522*042d53a7SEvalZero }
523*042d53a7SEvalZero
524*042d53a7SEvalZero rc = 0;
525*042d53a7SEvalZero if (!memcmp(our_addr, addr, BLE_DEV_ADDR_LEN)) {
526*042d53a7SEvalZero rc = 1;
527*042d53a7SEvalZero }
528*042d53a7SEvalZero
529*042d53a7SEvalZero return rc;
530*042d53a7SEvalZero }
531*042d53a7SEvalZero
532*042d53a7SEvalZero /**
533*042d53a7SEvalZero * Get identity address
534*042d53a7SEvalZero *
535*042d53a7SEvalZero * @param addr_type Random (1). Public(0)
536*042d53a7SEvalZero *
537*042d53a7SEvalZero * @return pointer to identity address of given type.
538*042d53a7SEvalZero */
539*042d53a7SEvalZero uint8_t*
ble_ll_get_our_devaddr(uint8_t addr_type)540*042d53a7SEvalZero ble_ll_get_our_devaddr(uint8_t addr_type)
541*042d53a7SEvalZero {
542*042d53a7SEvalZero if (addr_type) {
543*042d53a7SEvalZero return g_random_addr;
544*042d53a7SEvalZero }
545*042d53a7SEvalZero
546*042d53a7SEvalZero return g_dev_addr;
547*042d53a7SEvalZero }
548*042d53a7SEvalZero
549*042d53a7SEvalZero /**
550*042d53a7SEvalZero * Wait for response timeout function
551*042d53a7SEvalZero *
552*042d53a7SEvalZero * Context: interrupt (ble scheduler)
553*042d53a7SEvalZero *
554*042d53a7SEvalZero * @param arg
555*042d53a7SEvalZero */
556*042d53a7SEvalZero void
ble_ll_wfr_timer_exp(void * arg)557*042d53a7SEvalZero ble_ll_wfr_timer_exp(void *arg)
558*042d53a7SEvalZero {
559*042d53a7SEvalZero int rx_start;
560*042d53a7SEvalZero uint8_t lls;
561*042d53a7SEvalZero
562*042d53a7SEvalZero rx_start = ble_phy_rx_started();
563*042d53a7SEvalZero lls = g_ble_ll_data.ll_state;
564*042d53a7SEvalZero
565*042d53a7SEvalZero ble_ll_trace_u32x3(BLE_LL_TRACE_ID_WFR_EXP, lls, ble_phy_xcvr_state_get(),
566*042d53a7SEvalZero (uint32_t)rx_start);
567*042d53a7SEvalZero
568*042d53a7SEvalZero /* If we have started a reception, there is nothing to do here */
569*042d53a7SEvalZero if (!rx_start) {
570*042d53a7SEvalZero switch (lls) {
571*042d53a7SEvalZero case BLE_LL_STATE_ADV:
572*042d53a7SEvalZero ble_ll_adv_wfr_timer_exp();
573*042d53a7SEvalZero break;
574*042d53a7SEvalZero case BLE_LL_STATE_CONNECTION:
575*042d53a7SEvalZero ble_ll_conn_wfr_timer_exp();
576*042d53a7SEvalZero break;
577*042d53a7SEvalZero case BLE_LL_STATE_SCANNING:
578*042d53a7SEvalZero ble_ll_scan_wfr_timer_exp();
579*042d53a7SEvalZero break;
580*042d53a7SEvalZero case BLE_LL_STATE_INITIATING:
581*042d53a7SEvalZero ble_ll_conn_init_wfr_timer_exp();
582*042d53a7SEvalZero break;
583*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
584*042d53a7SEvalZero case BLE_LL_STATE_DTM:
585*042d53a7SEvalZero ble_ll_dtm_wfr_timer_exp();
586*042d53a7SEvalZero break;
587*042d53a7SEvalZero #endif
588*042d53a7SEvalZero default:
589*042d53a7SEvalZero break;
590*042d53a7SEvalZero }
591*042d53a7SEvalZero }
592*042d53a7SEvalZero }
593*042d53a7SEvalZero
594*042d53a7SEvalZero /**
595*042d53a7SEvalZero * Enable the wait for response timer.
596*042d53a7SEvalZero *
597*042d53a7SEvalZero * Context: Interrupt.
598*042d53a7SEvalZero *
599*042d53a7SEvalZero * @param cputime
600*042d53a7SEvalZero * @param wfr_cb
601*042d53a7SEvalZero * @param arg
602*042d53a7SEvalZero */
603*042d53a7SEvalZero void
ble_ll_wfr_enable(uint32_t cputime)604*042d53a7SEvalZero ble_ll_wfr_enable(uint32_t cputime)
605*042d53a7SEvalZero {
606*042d53a7SEvalZero }
607*042d53a7SEvalZero
608*042d53a7SEvalZero /**
609*042d53a7SEvalZero * Disable the wait for response timer
610*042d53a7SEvalZero */
611*042d53a7SEvalZero void
ble_ll_wfr_disable(void)612*042d53a7SEvalZero ble_ll_wfr_disable(void)
613*042d53a7SEvalZero {
614*042d53a7SEvalZero }
615*042d53a7SEvalZero
616*042d53a7SEvalZero /**
617*042d53a7SEvalZero * ll tx pkt in proc
618*042d53a7SEvalZero *
619*042d53a7SEvalZero * Process ACL data packet input from host
620*042d53a7SEvalZero *
621*042d53a7SEvalZero * Context: Link layer task
622*042d53a7SEvalZero *
623*042d53a7SEvalZero */
624*042d53a7SEvalZero static void
ble_ll_tx_pkt_in(void)625*042d53a7SEvalZero ble_ll_tx_pkt_in(void)
626*042d53a7SEvalZero {
627*042d53a7SEvalZero uint16_t handle;
628*042d53a7SEvalZero uint16_t length;
629*042d53a7SEvalZero uint16_t pb;
630*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
631*042d53a7SEvalZero struct os_mbuf *om;
632*042d53a7SEvalZero
633*042d53a7SEvalZero /* Drain all packets off the queue */
634*042d53a7SEvalZero while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) {
635*042d53a7SEvalZero /* Get mbuf pointer from packet header pointer */
636*042d53a7SEvalZero pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q);
637*042d53a7SEvalZero om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
638*042d53a7SEvalZero
639*042d53a7SEvalZero /* Remove from queue */
640*042d53a7SEvalZero STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next);
641*042d53a7SEvalZero
642*042d53a7SEvalZero /* Strip HCI ACL header to get handle and length */
643*042d53a7SEvalZero handle = get_le16(om->om_data);
644*042d53a7SEvalZero length = get_le16(om->om_data + 2);
645*042d53a7SEvalZero os_mbuf_adj(om, sizeof(struct hci_data_hdr));
646*042d53a7SEvalZero
647*042d53a7SEvalZero /* Do some basic error checking */
648*042d53a7SEvalZero pb = handle & 0x3000;
649*042d53a7SEvalZero if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) {
650*042d53a7SEvalZero /* This is a bad ACL packet. Count a stat and free it */
651*042d53a7SEvalZero STATS_INC(ble_ll_stats, bad_acl_hdr);
652*042d53a7SEvalZero os_mbuf_free_chain(om);
653*042d53a7SEvalZero continue;
654*042d53a7SEvalZero }
655*042d53a7SEvalZero
656*042d53a7SEvalZero /* Hand to connection state machine */
657*042d53a7SEvalZero ble_ll_conn_tx_pkt_in(om, handle, length);
658*042d53a7SEvalZero }
659*042d53a7SEvalZero }
660*042d53a7SEvalZero
661*042d53a7SEvalZero /**
662*042d53a7SEvalZero * Count Link Layer statistics for received PDUs
663*042d53a7SEvalZero *
664*042d53a7SEvalZero * Context: Link layer task
665*042d53a7SEvalZero *
666*042d53a7SEvalZero * @param hdr
667*042d53a7SEvalZero * @param len
668*042d53a7SEvalZero */
669*042d53a7SEvalZero static void
ble_ll_count_rx_stats(struct ble_mbuf_hdr * hdr,uint16_t len,uint8_t pdu_type)670*042d53a7SEvalZero ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type)
671*042d53a7SEvalZero {
672*042d53a7SEvalZero uint8_t crcok;
673*042d53a7SEvalZero bool connection_data;
674*042d53a7SEvalZero
675*042d53a7SEvalZero crcok = BLE_MBUF_HDR_CRC_OK(hdr);
676*042d53a7SEvalZero connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_CONNECTION);
677*042d53a7SEvalZero
678*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
679*042d53a7SEvalZero /* Reuse connection stats for DTM */
680*042d53a7SEvalZero connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_DTM);
681*042d53a7SEvalZero #endif
682*042d53a7SEvalZero
683*042d53a7SEvalZero if (crcok) {
684*042d53a7SEvalZero if (connection_data) {
685*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok);
686*042d53a7SEvalZero STATS_INCN(ble_ll_stats, rx_data_bytes_crc_ok, len);
687*042d53a7SEvalZero } else {
688*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_pdu_crc_ok);
689*042d53a7SEvalZero STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_ok, len);
690*042d53a7SEvalZero ble_ll_count_rx_adv_pdus(pdu_type);
691*042d53a7SEvalZero }
692*042d53a7SEvalZero } else {
693*042d53a7SEvalZero if (connection_data) {
694*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_data_pdu_crc_err);
695*042d53a7SEvalZero STATS_INCN(ble_ll_stats, rx_data_bytes_crc_err, len);
696*042d53a7SEvalZero } else {
697*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_pdu_crc_err);
698*042d53a7SEvalZero STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_err, len);
699*042d53a7SEvalZero }
700*042d53a7SEvalZero }
701*042d53a7SEvalZero }
702*042d53a7SEvalZero
703*042d53a7SEvalZero /**
704*042d53a7SEvalZero * ll rx pkt in
705*042d53a7SEvalZero *
706*042d53a7SEvalZero * Process received packet from PHY.
707*042d53a7SEvalZero *
708*042d53a7SEvalZero * Context: Link layer task
709*042d53a7SEvalZero *
710*042d53a7SEvalZero */
711*042d53a7SEvalZero static void
ble_ll_rx_pkt_in(void)712*042d53a7SEvalZero ble_ll_rx_pkt_in(void)
713*042d53a7SEvalZero {
714*042d53a7SEvalZero os_sr_t sr;
715*042d53a7SEvalZero uint8_t pdu_type;
716*042d53a7SEvalZero uint8_t *rxbuf;
717*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
718*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
719*042d53a7SEvalZero struct os_mbuf *m;
720*042d53a7SEvalZero
721*042d53a7SEvalZero /* Drain all packets off the queue */
722*042d53a7SEvalZero while (STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q)) {
723*042d53a7SEvalZero /* Get mbuf pointer from packet header pointer */
724*042d53a7SEvalZero pkthdr = STAILQ_FIRST(&g_ble_ll_data.ll_rx_pkt_q);
725*042d53a7SEvalZero m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
726*042d53a7SEvalZero
727*042d53a7SEvalZero /* Remove from queue */
728*042d53a7SEvalZero OS_ENTER_CRITICAL(sr);
729*042d53a7SEvalZero STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_rx_pkt_q, omp_next);
730*042d53a7SEvalZero OS_EXIT_CRITICAL(sr);
731*042d53a7SEvalZero
732*042d53a7SEvalZero /* Note: pdu type wont get used unless this is an advertising pdu */
733*042d53a7SEvalZero ble_hdr = BLE_MBUF_HDR_PTR(m);
734*042d53a7SEvalZero rxbuf = m->om_data;
735*042d53a7SEvalZero pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
736*042d53a7SEvalZero ble_ll_count_rx_stats(ble_hdr, pkthdr->omp_len, pdu_type);
737*042d53a7SEvalZero
738*042d53a7SEvalZero /* Process the data or advertising pdu */
739*042d53a7SEvalZero /* Process the PDU */
740*042d53a7SEvalZero switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) {
741*042d53a7SEvalZero case BLE_LL_STATE_CONNECTION:
742*042d53a7SEvalZero ble_ll_conn_rx_data_pdu(m, ble_hdr);
743*042d53a7SEvalZero /* m is going to be free by function above */
744*042d53a7SEvalZero m = NULL;
745*042d53a7SEvalZero break;
746*042d53a7SEvalZero case BLE_LL_STATE_ADV:
747*042d53a7SEvalZero ble_ll_adv_rx_pkt_in(pdu_type, rxbuf, ble_hdr);
748*042d53a7SEvalZero break;
749*042d53a7SEvalZero case BLE_LL_STATE_SCANNING:
750*042d53a7SEvalZero ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr);
751*042d53a7SEvalZero break;
752*042d53a7SEvalZero case BLE_LL_STATE_INITIATING:
753*042d53a7SEvalZero ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr);
754*042d53a7SEvalZero break;
755*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
756*042d53a7SEvalZero case BLE_LL_STATE_DTM:
757*042d53a7SEvalZero ble_ll_dtm_rx_pkt_in(m, ble_hdr);
758*042d53a7SEvalZero break;
759*042d53a7SEvalZero #endif
760*042d53a7SEvalZero default:
761*042d53a7SEvalZero /* Any other state should never occur */
762*042d53a7SEvalZero STATS_INC(ble_ll_stats, bad_ll_state);
763*042d53a7SEvalZero break;
764*042d53a7SEvalZero }
765*042d53a7SEvalZero if (m) {
766*042d53a7SEvalZero /* Free the packet buffer */
767*042d53a7SEvalZero os_mbuf_free_chain(m);
768*042d53a7SEvalZero }
769*042d53a7SEvalZero }
770*042d53a7SEvalZero }
771*042d53a7SEvalZero
772*042d53a7SEvalZero /**
773*042d53a7SEvalZero * Called to put a packet on the Link Layer receive packet queue.
774*042d53a7SEvalZero *
775*042d53a7SEvalZero * @param rxpdu Pointer to received PDU
776*042d53a7SEvalZero */
777*042d53a7SEvalZero void
ble_ll_rx_pdu_in(struct os_mbuf * rxpdu)778*042d53a7SEvalZero ble_ll_rx_pdu_in(struct os_mbuf *rxpdu)
779*042d53a7SEvalZero {
780*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
781*042d53a7SEvalZero
782*042d53a7SEvalZero pkthdr = OS_MBUF_PKTHDR(rxpdu);
783*042d53a7SEvalZero STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next);
784*042d53a7SEvalZero ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev);
785*042d53a7SEvalZero }
786*042d53a7SEvalZero
787*042d53a7SEvalZero /**
788*042d53a7SEvalZero * Called to put a packet on the Link Layer transmit packet queue.
789*042d53a7SEvalZero *
790*042d53a7SEvalZero * @param txpdu Pointer to transmit packet
791*042d53a7SEvalZero */
792*042d53a7SEvalZero void
ble_ll_acl_data_in(struct os_mbuf * txpkt)793*042d53a7SEvalZero ble_ll_acl_data_in(struct os_mbuf *txpkt)
794*042d53a7SEvalZero {
795*042d53a7SEvalZero os_sr_t sr;
796*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
797*042d53a7SEvalZero
798*042d53a7SEvalZero pkthdr = OS_MBUF_PKTHDR(txpkt);
799*042d53a7SEvalZero OS_ENTER_CRITICAL(sr);
800*042d53a7SEvalZero STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next);
801*042d53a7SEvalZero OS_EXIT_CRITICAL(sr);
802*042d53a7SEvalZero ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev);
803*042d53a7SEvalZero }
804*042d53a7SEvalZero
805*042d53a7SEvalZero /**
806*042d53a7SEvalZero * Called to post event to Link Layer when a data buffer overflow has
807*042d53a7SEvalZero * occurred.
808*042d53a7SEvalZero *
809*042d53a7SEvalZero * Context: Interrupt
810*042d53a7SEvalZero *
811*042d53a7SEvalZero */
812*042d53a7SEvalZero void
ble_ll_data_buffer_overflow(void)813*042d53a7SEvalZero ble_ll_data_buffer_overflow(void)
814*042d53a7SEvalZero {
815*042d53a7SEvalZero ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev);
816*042d53a7SEvalZero }
817*042d53a7SEvalZero
818*042d53a7SEvalZero /**
819*042d53a7SEvalZero * Called when a HW error occurs.
820*042d53a7SEvalZero *
821*042d53a7SEvalZero * Context: Interrupt
822*042d53a7SEvalZero */
823*042d53a7SEvalZero void
ble_ll_hw_error(void)824*042d53a7SEvalZero ble_ll_hw_error(void)
825*042d53a7SEvalZero {
826*042d53a7SEvalZero ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer, 0);
827*042d53a7SEvalZero }
828*042d53a7SEvalZero
829*042d53a7SEvalZero /**
830*042d53a7SEvalZero * Called when the HW error timer expires.
831*042d53a7SEvalZero *
832*042d53a7SEvalZero * @param arg
833*042d53a7SEvalZero */
834*042d53a7SEvalZero static void
ble_ll_hw_err_timer_cb(struct ble_npl_event * ev)835*042d53a7SEvalZero ble_ll_hw_err_timer_cb(struct ble_npl_event *ev)
836*042d53a7SEvalZero {
837*042d53a7SEvalZero if (ble_ll_hci_ev_hw_err(BLE_HW_ERR_HCI_SYNC_LOSS)) {
838*042d53a7SEvalZero /*
839*042d53a7SEvalZero * Restart callout if failed to allocate event. Try to allocate an
840*042d53a7SEvalZero * event every 50 milliseconds (or each OS tick if a tick is longer
841*042d53a7SEvalZero * than 100 msecs).
842*042d53a7SEvalZero */
843*042d53a7SEvalZero ble_npl_callout_reset(&g_ble_ll_data.ll_hw_err_timer,
844*042d53a7SEvalZero ble_npl_time_ms_to_ticks32(50));
845*042d53a7SEvalZero }
846*042d53a7SEvalZero }
847*042d53a7SEvalZero
848*042d53a7SEvalZero /**
849*042d53a7SEvalZero * Called upon start of received PDU
850*042d53a7SEvalZero *
851*042d53a7SEvalZero * Context: Interrupt
852*042d53a7SEvalZero *
853*042d53a7SEvalZero * @param rxpdu
854*042d53a7SEvalZero * chan
855*042d53a7SEvalZero *
856*042d53a7SEvalZero * @return int
857*042d53a7SEvalZero * < 0: A frame we dont want to receive.
858*042d53a7SEvalZero * = 0: Continue to receive frame. Dont go from rx to tx
859*042d53a7SEvalZero * > 0: Continue to receive frame and go from rx to tx when done
860*042d53a7SEvalZero */
861*042d53a7SEvalZero int
ble_ll_rx_start(uint8_t * rxbuf,uint8_t chan,struct ble_mbuf_hdr * rxhdr)862*042d53a7SEvalZero ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr)
863*042d53a7SEvalZero {
864*042d53a7SEvalZero int rc;
865*042d53a7SEvalZero uint8_t pdu_type;
866*042d53a7SEvalZero
867*042d53a7SEvalZero /* Advertising channel PDU */
868*042d53a7SEvalZero pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
869*042d53a7SEvalZero
870*042d53a7SEvalZero ble_ll_trace_u32x2(BLE_LL_TRACE_ID_RX_START, g_ble_ll_data.ll_state,
871*042d53a7SEvalZero pdu_type);
872*042d53a7SEvalZero
873*042d53a7SEvalZero switch (g_ble_ll_data.ll_state) {
874*042d53a7SEvalZero case BLE_LL_STATE_CONNECTION:
875*042d53a7SEvalZero rc = ble_ll_conn_rx_isr_start(rxhdr, ble_phy_access_addr_get());
876*042d53a7SEvalZero break;
877*042d53a7SEvalZero case BLE_LL_STATE_ADV:
878*042d53a7SEvalZero rc = ble_ll_adv_rx_isr_start(pdu_type);
879*042d53a7SEvalZero break;
880*042d53a7SEvalZero case BLE_LL_STATE_INITIATING:
881*042d53a7SEvalZero rc = ble_ll_init_rx_isr_start(pdu_type, rxhdr);
882*042d53a7SEvalZero break;
883*042d53a7SEvalZero case BLE_LL_STATE_SCANNING:
884*042d53a7SEvalZero rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags);
885*042d53a7SEvalZero break;
886*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
887*042d53a7SEvalZero case BLE_LL_STATE_DTM:
888*042d53a7SEvalZero rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get());
889*042d53a7SEvalZero break;
890*042d53a7SEvalZero #endif
891*042d53a7SEvalZero default:
892*042d53a7SEvalZero /* Should not be in this state! */
893*042d53a7SEvalZero rc = -1;
894*042d53a7SEvalZero STATS_INC(ble_ll_stats, bad_ll_state);
895*042d53a7SEvalZero break;
896*042d53a7SEvalZero }
897*042d53a7SEvalZero
898*042d53a7SEvalZero return rc;
899*042d53a7SEvalZero }
900*042d53a7SEvalZero
901*042d53a7SEvalZero /**
902*042d53a7SEvalZero * Called by the PHY when a receive packet has ended.
903*042d53a7SEvalZero *
904*042d53a7SEvalZero * NOTE: Called from interrupt context!
905*042d53a7SEvalZero *
906*042d53a7SEvalZero * @param rxbuf Pointer to received PDU data
907*042d53a7SEvalZero * rxhdr Pointer to BLE header of received mbuf
908*042d53a7SEvalZero *
909*042d53a7SEvalZero * @return int
910*042d53a7SEvalZero * < 0: Disable the phy after reception.
911*042d53a7SEvalZero * == 0: Success. Do not disable the PHY.
912*042d53a7SEvalZero * > 0: Do not disable PHY as that has already been done.
913*042d53a7SEvalZero */
914*042d53a7SEvalZero int
ble_ll_rx_end(uint8_t * rxbuf,struct ble_mbuf_hdr * rxhdr)915*042d53a7SEvalZero ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
916*042d53a7SEvalZero {
917*042d53a7SEvalZero int rc;
918*042d53a7SEvalZero int badpkt;
919*042d53a7SEvalZero uint8_t pdu_type;
920*042d53a7SEvalZero uint8_t len;
921*042d53a7SEvalZero uint8_t crcok;
922*042d53a7SEvalZero struct os_mbuf *rxpdu;
923*042d53a7SEvalZero
924*042d53a7SEvalZero /* Get CRC status from BLE header */
925*042d53a7SEvalZero crcok = BLE_MBUF_HDR_CRC_OK(rxhdr);
926*042d53a7SEvalZero
927*042d53a7SEvalZero /* Get advertising PDU type and length */
928*042d53a7SEvalZero pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
929*042d53a7SEvalZero len = rxbuf[1];
930*042d53a7SEvalZero
931*042d53a7SEvalZero ble_ll_trace_u32x3(BLE_LL_TRACE_ID_RX_END, pdu_type, len,
932*042d53a7SEvalZero rxhdr->rxinfo.flags);
933*042d53a7SEvalZero
934*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
935*042d53a7SEvalZero if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) {
936*042d53a7SEvalZero rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr);
937*042d53a7SEvalZero return rc;
938*042d53a7SEvalZero }
939*042d53a7SEvalZero #endif
940*042d53a7SEvalZero
941*042d53a7SEvalZero if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_CONNECTION) {
942*042d53a7SEvalZero rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr);
943*042d53a7SEvalZero return rc;
944*042d53a7SEvalZero }
945*042d53a7SEvalZero
946*042d53a7SEvalZero /* If the CRC checks, make sure lengths check! */
947*042d53a7SEvalZero badpkt = 0;
948*042d53a7SEvalZero if (crcok) {
949*042d53a7SEvalZero switch (pdu_type) {
950*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_SCAN_REQ:
951*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
952*042d53a7SEvalZero if (len != BLE_SCAN_REQ_LEN) {
953*042d53a7SEvalZero badpkt = 1;
954*042d53a7SEvalZero }
955*042d53a7SEvalZero break;
956*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_SCAN_RSP:
957*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_IND:
958*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_SCAN_IND:
959*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND:
960*042d53a7SEvalZero if ((len < BLE_DEV_ADDR_LEN) || (len > BLE_ADV_SCAN_IND_MAX_LEN)) {
961*042d53a7SEvalZero badpkt = 1;
962*042d53a7SEvalZero }
963*042d53a7SEvalZero break;
964*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP:
965*042d53a7SEvalZero break;
966*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_ADV_EXT_IND:
967*042d53a7SEvalZero break;
968*042d53a7SEvalZero case BLE_ADV_PDU_TYPE_CONNECT_REQ:
969*042d53a7SEvalZero if (len != BLE_CONNECT_REQ_LEN) {
970*042d53a7SEvalZero badpkt = 1;
971*042d53a7SEvalZero }
972*042d53a7SEvalZero break;
973*042d53a7SEvalZero default:
974*042d53a7SEvalZero badpkt = 1;
975*042d53a7SEvalZero break;
976*042d53a7SEvalZero }
977*042d53a7SEvalZero
978*042d53a7SEvalZero /* If this is a malformed packet, just kill it here */
979*042d53a7SEvalZero if (badpkt) {
980*042d53a7SEvalZero STATS_INC(ble_ll_stats, rx_adv_malformed_pkts);
981*042d53a7SEvalZero }
982*042d53a7SEvalZero }
983*042d53a7SEvalZero
984*042d53a7SEvalZero /* Hand packet to the appropriate state machine (if crc ok) */
985*042d53a7SEvalZero rxpdu = NULL;
986*042d53a7SEvalZero switch (BLE_MBUF_HDR_RX_STATE(rxhdr)) {
987*042d53a7SEvalZero case BLE_LL_STATE_ADV:
988*042d53a7SEvalZero if (!badpkt) {
989*042d53a7SEvalZero rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN);
990*042d53a7SEvalZero if (rxpdu) {
991*042d53a7SEvalZero ble_phy_rxpdu_copy(rxbuf, rxpdu);
992*042d53a7SEvalZero }
993*042d53a7SEvalZero }
994*042d53a7SEvalZero rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok);
995*042d53a7SEvalZero break;
996*042d53a7SEvalZero case BLE_LL_STATE_SCANNING:
997*042d53a7SEvalZero if (!badpkt) {
998*042d53a7SEvalZero rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN);
999*042d53a7SEvalZero if (rxpdu) {
1000*042d53a7SEvalZero ble_phy_rxpdu_copy(rxbuf, rxpdu);
1001*042d53a7SEvalZero }
1002*042d53a7SEvalZero }
1003*042d53a7SEvalZero rc = ble_ll_scan_rx_isr_end(rxpdu, crcok);
1004*042d53a7SEvalZero break;
1005*042d53a7SEvalZero case BLE_LL_STATE_INITIATING:
1006*042d53a7SEvalZero rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr);
1007*042d53a7SEvalZero break;
1008*042d53a7SEvalZero default:
1009*042d53a7SEvalZero rc = -1;
1010*042d53a7SEvalZero STATS_INC(ble_ll_stats, bad_ll_state);
1011*042d53a7SEvalZero break;
1012*042d53a7SEvalZero }
1013*042d53a7SEvalZero
1014*042d53a7SEvalZero /* Hand packet up to higher layer (regardless of CRC failure) */
1015*042d53a7SEvalZero if (rxpdu) {
1016*042d53a7SEvalZero ble_ll_rx_pdu_in(rxpdu);
1017*042d53a7SEvalZero }
1018*042d53a7SEvalZero
1019*042d53a7SEvalZero return rc;
1020*042d53a7SEvalZero }
1021*042d53a7SEvalZero
1022*042d53a7SEvalZero uint8_t
ble_ll_tx_mbuf_pducb(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)1023*042d53a7SEvalZero ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
1024*042d53a7SEvalZero {
1025*042d53a7SEvalZero struct os_mbuf *txpdu;
1026*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
1027*042d53a7SEvalZero
1028*042d53a7SEvalZero txpdu = pducb_arg;
1029*042d53a7SEvalZero BLE_LL_ASSERT(txpdu);
1030*042d53a7SEvalZero ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
1031*042d53a7SEvalZero
1032*042d53a7SEvalZero os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, ble_hdr->txinfo.pyld_len,
1033*042d53a7SEvalZero dptr);
1034*042d53a7SEvalZero
1035*042d53a7SEvalZero *hdr_byte = ble_hdr->txinfo.hdr_byte;
1036*042d53a7SEvalZero
1037*042d53a7SEvalZero return ble_hdr->txinfo.pyld_len;
1038*042d53a7SEvalZero }
1039*042d53a7SEvalZero
1040*042d53a7SEvalZero uint8_t
ble_ll_tx_flat_mbuf_pducb(uint8_t * dptr,void * pducb_arg,uint8_t * hdr_byte)1041*042d53a7SEvalZero ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
1042*042d53a7SEvalZero {
1043*042d53a7SEvalZero struct os_mbuf *txpdu;
1044*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
1045*042d53a7SEvalZero
1046*042d53a7SEvalZero txpdu = pducb_arg;
1047*042d53a7SEvalZero BLE_LL_ASSERT(txpdu);
1048*042d53a7SEvalZero ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
1049*042d53a7SEvalZero
1050*042d53a7SEvalZero memcpy(dptr, txpdu->om_data, ble_hdr->txinfo.pyld_len);
1051*042d53a7SEvalZero
1052*042d53a7SEvalZero *hdr_byte = ble_hdr->txinfo.hdr_byte;
1053*042d53a7SEvalZero
1054*042d53a7SEvalZero return ble_hdr->txinfo.pyld_len;
1055*042d53a7SEvalZero }
1056*042d53a7SEvalZero
1057*042d53a7SEvalZero static void
ble_ll_event_rx_pkt(struct ble_npl_event * ev)1058*042d53a7SEvalZero ble_ll_event_rx_pkt(struct ble_npl_event *ev)
1059*042d53a7SEvalZero {
1060*042d53a7SEvalZero ble_ll_rx_pkt_in();
1061*042d53a7SEvalZero }
1062*042d53a7SEvalZero
1063*042d53a7SEvalZero static void
ble_ll_event_tx_pkt(struct ble_npl_event * ev)1064*042d53a7SEvalZero ble_ll_event_tx_pkt(struct ble_npl_event *ev)
1065*042d53a7SEvalZero {
1066*042d53a7SEvalZero ble_ll_tx_pkt_in();
1067*042d53a7SEvalZero }
1068*042d53a7SEvalZero
1069*042d53a7SEvalZero static void
ble_ll_event_dbuf_overflow(struct ble_npl_event * ev)1070*042d53a7SEvalZero ble_ll_event_dbuf_overflow(struct ble_npl_event *ev)
1071*042d53a7SEvalZero {
1072*042d53a7SEvalZero ble_ll_hci_ev_databuf_overflow();
1073*042d53a7SEvalZero }
1074*042d53a7SEvalZero
1075*042d53a7SEvalZero static void
ble_ll_event_comp_pkts(struct ble_npl_event * ev)1076*042d53a7SEvalZero ble_ll_event_comp_pkts(struct ble_npl_event *ev)
1077*042d53a7SEvalZero {
1078*042d53a7SEvalZero ble_ll_conn_num_comp_pkts_event_send(NULL);
1079*042d53a7SEvalZero }
1080*042d53a7SEvalZero
1081*042d53a7SEvalZero /**
1082*042d53a7SEvalZero * Link Layer task.
1083*042d53a7SEvalZero *
1084*042d53a7SEvalZero * This is the task that runs the Link Layer.
1085*042d53a7SEvalZero *
1086*042d53a7SEvalZero * @param arg
1087*042d53a7SEvalZero */
1088*042d53a7SEvalZero void
ble_ll_task(void * arg)1089*042d53a7SEvalZero ble_ll_task(void *arg)
1090*042d53a7SEvalZero {
1091*042d53a7SEvalZero struct ble_npl_event *ev;
1092*042d53a7SEvalZero
1093*042d53a7SEvalZero /*
1094*042d53a7SEvalZero * XXX RIOT ties event queue to a thread which initialized it so we need to
1095*042d53a7SEvalZero * create event queue in LL task, not in general init function. This can
1096*042d53a7SEvalZero * lead to some races between host and LL so for now let us have it as a
1097*042d53a7SEvalZero * hack for RIOT where races can be avoided by proper initialization inside
1098*042d53a7SEvalZero * package.
1099*042d53a7SEvalZero */
1100*042d53a7SEvalZero #ifdef RIOT_VERSION
1101*042d53a7SEvalZero ble_npl_eventq_init(&g_ble_ll_data.ll_evq);
1102*042d53a7SEvalZero #endif
1103*042d53a7SEvalZero
1104*042d53a7SEvalZero /* Init ble phy */
1105*042d53a7SEvalZero ble_phy_init();
1106*042d53a7SEvalZero
1107*042d53a7SEvalZero /* Set output power to 1mW (0 dBm) */
1108*042d53a7SEvalZero ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM));
1109*042d53a7SEvalZero
1110*042d53a7SEvalZero /* Tell the host that we are ready to receive packets */
1111*042d53a7SEvalZero ble_ll_hci_send_noop();
1112*042d53a7SEvalZero
1113*042d53a7SEvalZero ble_ll_rand_start();
1114*042d53a7SEvalZero
1115*042d53a7SEvalZero while (1) {
1116*042d53a7SEvalZero ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER);
1117*042d53a7SEvalZero assert(ev);
1118*042d53a7SEvalZero ble_npl_event_run(ev);
1119*042d53a7SEvalZero }
1120*042d53a7SEvalZero }
1121*042d53a7SEvalZero
1122*042d53a7SEvalZero /**
1123*042d53a7SEvalZero * ble ll state set
1124*042d53a7SEvalZero *
1125*042d53a7SEvalZero * Called to set the current link layer state.
1126*042d53a7SEvalZero *
1127*042d53a7SEvalZero * Context: Interrupt and Link Layer task
1128*042d53a7SEvalZero *
1129*042d53a7SEvalZero * @param ll_state
1130*042d53a7SEvalZero */
1131*042d53a7SEvalZero void
ble_ll_state_set(uint8_t ll_state)1132*042d53a7SEvalZero ble_ll_state_set(uint8_t ll_state)
1133*042d53a7SEvalZero {
1134*042d53a7SEvalZero g_ble_ll_data.ll_state = ll_state;
1135*042d53a7SEvalZero }
1136*042d53a7SEvalZero
1137*042d53a7SEvalZero /**
1138*042d53a7SEvalZero * ble ll state get
1139*042d53a7SEvalZero *
1140*042d53a7SEvalZero * Called to get the current link layer state.
1141*042d53a7SEvalZero *
1142*042d53a7SEvalZero * Context: Link Layer task (can be called from interrupt context though).
1143*042d53a7SEvalZero *
1144*042d53a7SEvalZero * @return ll_state
1145*042d53a7SEvalZero */
1146*042d53a7SEvalZero uint8_t
ble_ll_state_get(void)1147*042d53a7SEvalZero ble_ll_state_get(void)
1148*042d53a7SEvalZero {
1149*042d53a7SEvalZero return g_ble_ll_data.ll_state;
1150*042d53a7SEvalZero }
1151*042d53a7SEvalZero
1152*042d53a7SEvalZero /**
1153*042d53a7SEvalZero * ble ll event send
1154*042d53a7SEvalZero *
1155*042d53a7SEvalZero * Send an event to the Link Layer task
1156*042d53a7SEvalZero *
1157*042d53a7SEvalZero * @param ev Event to add to the Link Layer event queue.
1158*042d53a7SEvalZero */
1159*042d53a7SEvalZero void
ble_ll_event_send(struct ble_npl_event * ev)1160*042d53a7SEvalZero ble_ll_event_send(struct ble_npl_event *ev)
1161*042d53a7SEvalZero {
1162*042d53a7SEvalZero ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
1163*042d53a7SEvalZero }
1164*042d53a7SEvalZero
1165*042d53a7SEvalZero /**
1166*042d53a7SEvalZero * Returns the features supported by the link layer
1167*042d53a7SEvalZero *
1168*042d53a7SEvalZero * @return uint8_t bitmask of supported features.
1169*042d53a7SEvalZero */
1170*042d53a7SEvalZero uint64_t
ble_ll_read_supp_states(void)1171*042d53a7SEvalZero ble_ll_read_supp_states(void)
1172*042d53a7SEvalZero {
1173*042d53a7SEvalZero return BLE_LL_SUPPORTED_STATES;
1174*042d53a7SEvalZero }
1175*042d53a7SEvalZero
1176*042d53a7SEvalZero /**
1177*042d53a7SEvalZero * Returns the features supported by the link layer
1178*042d53a7SEvalZero *
1179*042d53a7SEvalZero * @return uint32_t bitmask of supported features.
1180*042d53a7SEvalZero */
1181*042d53a7SEvalZero uint32_t
ble_ll_read_supp_features(void)1182*042d53a7SEvalZero ble_ll_read_supp_features(void)
1183*042d53a7SEvalZero {
1184*042d53a7SEvalZero return g_ble_ll_data.ll_supp_features;
1185*042d53a7SEvalZero }
1186*042d53a7SEvalZero
1187*042d53a7SEvalZero /**
1188*042d53a7SEvalZero * Flush a link layer packet queue.
1189*042d53a7SEvalZero *
1190*042d53a7SEvalZero * @param pktq
1191*042d53a7SEvalZero */
1192*042d53a7SEvalZero static void
ble_ll_flush_pkt_queue(struct ble_ll_pkt_q * pktq)1193*042d53a7SEvalZero ble_ll_flush_pkt_queue(struct ble_ll_pkt_q *pktq)
1194*042d53a7SEvalZero {
1195*042d53a7SEvalZero struct os_mbuf_pkthdr *pkthdr;
1196*042d53a7SEvalZero struct os_mbuf *om;
1197*042d53a7SEvalZero
1198*042d53a7SEvalZero /* FLush all packets from Link layer queues */
1199*042d53a7SEvalZero while (STAILQ_FIRST(pktq)) {
1200*042d53a7SEvalZero /* Get mbuf pointer from packet header pointer */
1201*042d53a7SEvalZero pkthdr = STAILQ_FIRST(pktq);
1202*042d53a7SEvalZero om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
1203*042d53a7SEvalZero
1204*042d53a7SEvalZero /* Remove from queue and free the mbuf */
1205*042d53a7SEvalZero STAILQ_REMOVE_HEAD(pktq, omp_next);
1206*042d53a7SEvalZero os_mbuf_free_chain(om);
1207*042d53a7SEvalZero }
1208*042d53a7SEvalZero }
1209*042d53a7SEvalZero
1210*042d53a7SEvalZero /**
1211*042d53a7SEvalZero * Called to initialize a mbuf used by the controller
1212*042d53a7SEvalZero *
1213*042d53a7SEvalZero * NOTE: this is only used when the mbuf is created by the controller;
1214*042d53a7SEvalZero * it should not be used for data packets (ACL data packets) that come from
1215*042d53a7SEvalZero * the host. This routine assumes that the entire pdu length can fit in
1216*042d53a7SEvalZero * one mbuf contiguously.
1217*042d53a7SEvalZero *
1218*042d53a7SEvalZero * @param m
1219*042d53a7SEvalZero * @param pdulen
1220*042d53a7SEvalZero * @param hdr
1221*042d53a7SEvalZero */
1222*042d53a7SEvalZero void
ble_ll_mbuf_init(struct os_mbuf * m,uint8_t pdulen,uint8_t hdr)1223*042d53a7SEvalZero ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
1224*042d53a7SEvalZero {
1225*042d53a7SEvalZero struct ble_mbuf_hdr *ble_hdr;
1226*042d53a7SEvalZero
1227*042d53a7SEvalZero /* Set mbuf length and packet length */
1228*042d53a7SEvalZero m->om_len = pdulen;
1229*042d53a7SEvalZero OS_MBUF_PKTHDR(m)->omp_len = pdulen;
1230*042d53a7SEvalZero
1231*042d53a7SEvalZero /* Set BLE transmit header */
1232*042d53a7SEvalZero ble_hdr = BLE_MBUF_HDR_PTR(m);
1233*042d53a7SEvalZero ble_hdr->txinfo.flags = 0;
1234*042d53a7SEvalZero ble_hdr->txinfo.offset = 0;
1235*042d53a7SEvalZero ble_hdr->txinfo.pyld_len = pdulen;
1236*042d53a7SEvalZero ble_hdr->txinfo.hdr_byte = hdr;
1237*042d53a7SEvalZero }
1238*042d53a7SEvalZero
1239*042d53a7SEvalZero /**
1240*042d53a7SEvalZero * Called to reset the controller. This performs a "software reset" of the link
1241*042d53a7SEvalZero * layer; it does not perform a HW reset of the controller nor does it reset
1242*042d53a7SEvalZero * the HCI interface.
1243*042d53a7SEvalZero *
1244*042d53a7SEvalZero * Context: Link Layer task (HCI command)
1245*042d53a7SEvalZero *
1246*042d53a7SEvalZero * @return int The ble error code to place in the command complete event that
1247*042d53a7SEvalZero * is returned when this command is issued.
1248*042d53a7SEvalZero */
1249*042d53a7SEvalZero int
ble_ll_reset(void)1250*042d53a7SEvalZero ble_ll_reset(void)
1251*042d53a7SEvalZero {
1252*042d53a7SEvalZero int rc;
1253*042d53a7SEvalZero os_sr_t sr;
1254*042d53a7SEvalZero
1255*042d53a7SEvalZero /* Stop the phy */
1256*042d53a7SEvalZero ble_phy_disable();
1257*042d53a7SEvalZero
1258*042d53a7SEvalZero /* Stop any wait for response timer */
1259*042d53a7SEvalZero OS_ENTER_CRITICAL(sr);
1260*042d53a7SEvalZero ble_ll_wfr_disable();
1261*042d53a7SEvalZero ble_ll_sched_stop();
1262*042d53a7SEvalZero OS_EXIT_CRITICAL(sr);
1263*042d53a7SEvalZero
1264*042d53a7SEvalZero /* Stop any scanning */
1265*042d53a7SEvalZero ble_ll_scan_reset();
1266*042d53a7SEvalZero
1267*042d53a7SEvalZero /* Stop any advertising */
1268*042d53a7SEvalZero ble_ll_adv_reset();
1269*042d53a7SEvalZero
1270*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE)
1271*042d53a7SEvalZero ble_ll_dtm_reset();
1272*042d53a7SEvalZero #endif
1273*042d53a7SEvalZero
1274*042d53a7SEvalZero /* FLush all packets from Link layer queues */
1275*042d53a7SEvalZero ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q);
1276*042d53a7SEvalZero ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q);
1277*042d53a7SEvalZero
1278*042d53a7SEvalZero /* Reset LL stats */
1279*042d53a7SEvalZero STATS_RESET(ble_ll_stats);
1280*042d53a7SEvalZero
1281*042d53a7SEvalZero /* Reset any preferred PHYs */
1282*042d53a7SEvalZero g_ble_ll_data.ll_pref_tx_phys = 0;
1283*042d53a7SEvalZero g_ble_ll_data.ll_pref_rx_phys = 0;
1284*042d53a7SEvalZero
1285*042d53a7SEvalZero /* Reset connection module */
1286*042d53a7SEvalZero ble_ll_conn_module_reset();
1287*042d53a7SEvalZero
1288*042d53a7SEvalZero /* All this does is re-initialize the event masks so call the hci init */
1289*042d53a7SEvalZero ble_ll_hci_init();
1290*042d53a7SEvalZero
1291*042d53a7SEvalZero /* Reset scheduler */
1292*042d53a7SEvalZero ble_ll_sched_init();
1293*042d53a7SEvalZero
1294*042d53a7SEvalZero /* Set state to standby */
1295*042d53a7SEvalZero ble_ll_state_set(BLE_LL_STATE_STANDBY);
1296*042d53a7SEvalZero
1297*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
1298*042d53a7SEvalZero /* Stops rf clock and rfclock timer */
1299*042d53a7SEvalZero ble_ll_xcvr_rfclk_stop();
1300*042d53a7SEvalZero #endif
1301*042d53a7SEvalZero
1302*042d53a7SEvalZero /* Reset our random address */
1303*042d53a7SEvalZero memset(g_random_addr, 0, BLE_DEV_ADDR_LEN);
1304*042d53a7SEvalZero
1305*042d53a7SEvalZero /* Clear the whitelist */
1306*042d53a7SEvalZero ble_ll_whitelist_clear();
1307*042d53a7SEvalZero
1308*042d53a7SEvalZero /* Reset resolving list */
1309*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1310*042d53a7SEvalZero ble_ll_resolv_list_reset();
1311*042d53a7SEvalZero #endif
1312*042d53a7SEvalZero
1313*042d53a7SEvalZero /* Re-initialize the PHY */
1314*042d53a7SEvalZero rc = ble_phy_init();
1315*042d53a7SEvalZero
1316*042d53a7SEvalZero return rc;
1317*042d53a7SEvalZero }
1318*042d53a7SEvalZero
1319*042d53a7SEvalZero static void
ble_ll_seed_prng(void)1320*042d53a7SEvalZero ble_ll_seed_prng(void)
1321*042d53a7SEvalZero {
1322*042d53a7SEvalZero uint32_t seed;
1323*042d53a7SEvalZero int i;
1324*042d53a7SEvalZero
1325*042d53a7SEvalZero /* Seed random number generator with least significant bytes of device
1326*042d53a7SEvalZero * address.
1327*042d53a7SEvalZero */
1328*042d53a7SEvalZero seed = 0;
1329*042d53a7SEvalZero for (i = 0; i < 4; ++i) {
1330*042d53a7SEvalZero seed |= g_dev_addr[i];
1331*042d53a7SEvalZero seed <<= 8;
1332*042d53a7SEvalZero }
1333*042d53a7SEvalZero srand(seed);
1334*042d53a7SEvalZero }
1335*042d53a7SEvalZero
1336*042d53a7SEvalZero uint32_t
ble_ll_pdu_tx_time_get(uint16_t payload_len,int phy_mode)1337*042d53a7SEvalZero ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode)
1338*042d53a7SEvalZero {
1339*042d53a7SEvalZero uint32_t usecs;
1340*042d53a7SEvalZero
1341*042d53a7SEvalZero #if (BLE_LL_BT5_PHY_SUPPORTED)
1342*042d53a7SEvalZero if (phy_mode == BLE_PHY_MODE_1M) {
1343*042d53a7SEvalZero /* 8 usecs per byte */
1344*042d53a7SEvalZero usecs = payload_len << 3;
1345*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_2M) {
1346*042d53a7SEvalZero /* 4 usecs per byte */
1347*042d53a7SEvalZero usecs = payload_len << 2;
1348*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) {
1349*042d53a7SEvalZero /* S=8 => 8 * 8 = 64 usecs per byte */
1350*042d53a7SEvalZero usecs = payload_len << 6;
1351*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) {
1352*042d53a7SEvalZero /* S=2 => 2 * 8 = 16 usecs per byte */
1353*042d53a7SEvalZero usecs = payload_len << 4;
1354*042d53a7SEvalZero } else {
1355*042d53a7SEvalZero BLE_LL_ASSERT(0);
1356*042d53a7SEvalZero }
1357*042d53a7SEvalZero
1358*042d53a7SEvalZero usecs += g_ble_ll_pdu_header_tx_time[phy_mode];
1359*042d53a7SEvalZero #else
1360*042d53a7SEvalZero usecs = (((payload_len) + BLE_LL_PDU_HDR_LEN + BLE_LL_ACC_ADDR_LEN
1361*042d53a7SEvalZero + BLE_LL_PREAMBLE_LEN + BLE_LL_CRC_LEN) << 3);
1362*042d53a7SEvalZero #endif
1363*042d53a7SEvalZero
1364*042d53a7SEvalZero return usecs;
1365*042d53a7SEvalZero }
1366*042d53a7SEvalZero
1367*042d53a7SEvalZero uint16_t
ble_ll_pdu_max_tx_octets_get(uint32_t usecs,int phy_mode)1368*042d53a7SEvalZero ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode)
1369*042d53a7SEvalZero {
1370*042d53a7SEvalZero uint32_t header_tx_time;
1371*042d53a7SEvalZero uint16_t octets;
1372*042d53a7SEvalZero
1373*042d53a7SEvalZero BLE_LL_ASSERT(phy_mode < BLE_PHY_NUM_MODE);
1374*042d53a7SEvalZero
1375*042d53a7SEvalZero header_tx_time = g_ble_ll_pdu_header_tx_time[phy_mode];
1376*042d53a7SEvalZero
1377*042d53a7SEvalZero /*
1378*042d53a7SEvalZero * Current conn max tx time can be too short to even send a packet header
1379*042d53a7SEvalZero * and this can happen if we changed connection form uncoded to coded phy.
1380*042d53a7SEvalZero * However, the lower bound for conn max tx time (all of them) depends on
1381*042d53a7SEvalZero * current phy (uncoded/coded) but it always allows to send at least 27
1382*042d53a7SEvalZero * bytes of payload thus we alwyas return at least 27 from here.
1383*042d53a7SEvalZero *
1384*042d53a7SEvalZero * Reference:
1385*042d53a7SEvalZero * Core v5.0, Vol 6, Part B, section 4.5.10
1386*042d53a7SEvalZero * see connEffectiveMaxTxTime and connEffectiveMaxRxTime definitions
1387*042d53a7SEvalZero */
1388*042d53a7SEvalZero
1389*042d53a7SEvalZero if (usecs < header_tx_time) {
1390*042d53a7SEvalZero return 27;
1391*042d53a7SEvalZero }
1392*042d53a7SEvalZero
1393*042d53a7SEvalZero usecs -= header_tx_time;
1394*042d53a7SEvalZero
1395*042d53a7SEvalZero if (phy_mode == BLE_PHY_MODE_1M) {
1396*042d53a7SEvalZero /* 8 usecs per byte */
1397*042d53a7SEvalZero octets = usecs >> 3;
1398*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_2M) {
1399*042d53a7SEvalZero /* 4 usecs per byte */
1400*042d53a7SEvalZero octets = usecs >> 2;
1401*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) {
1402*042d53a7SEvalZero /* S=8 => 8 * 8 = 64 usecs per byte */
1403*042d53a7SEvalZero octets = usecs >> 6;
1404*042d53a7SEvalZero } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) {
1405*042d53a7SEvalZero /* S=2 => 2 * 8 = 16 usecs per byte */
1406*042d53a7SEvalZero octets = usecs >> 4;
1407*042d53a7SEvalZero } else {
1408*042d53a7SEvalZero BLE_LL_ASSERT(0);
1409*042d53a7SEvalZero }
1410*042d53a7SEvalZero
1411*042d53a7SEvalZero /* see comment at the beginning */
1412*042d53a7SEvalZero return max(27, octets);
1413*042d53a7SEvalZero }
1414*042d53a7SEvalZero
1415*042d53a7SEvalZero /**
1416*042d53a7SEvalZero * Initialize the Link Layer. Should be called only once
1417*042d53a7SEvalZero *
1418*042d53a7SEvalZero * @return int
1419*042d53a7SEvalZero */
1420*042d53a7SEvalZero void
ble_ll_init(void)1421*042d53a7SEvalZero ble_ll_init(void)
1422*042d53a7SEvalZero {
1423*042d53a7SEvalZero int rc;
1424*042d53a7SEvalZero uint32_t features;
1425*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
1426*042d53a7SEvalZero uint32_t xtal_ticks;
1427*042d53a7SEvalZero #endif
1428*042d53a7SEvalZero ble_addr_t addr;
1429*042d53a7SEvalZero struct ble_ll_obj *lldata;
1430*042d53a7SEvalZero
1431*042d53a7SEvalZero /* Ensure this function only gets called by sysinit. */
1432*042d53a7SEvalZero SYSINIT_ASSERT_ACTIVE();
1433*042d53a7SEvalZero
1434*042d53a7SEvalZero ble_ll_trace_init();
1435*042d53a7SEvalZero ble_phy_trace_init();
1436*042d53a7SEvalZero
1437*042d53a7SEvalZero /* Retrieve the public device address if not set by syscfg */
1438*042d53a7SEvalZero memcpy(&addr.val[0], MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR, BLE_DEV_ADDR_LEN);
1439*042d53a7SEvalZero if (!memcmp(&addr.val[0], ((ble_addr_t *)BLE_ADDR_ANY)->val,
1440*042d53a7SEvalZero BLE_DEV_ADDR_LEN)) {
1441*042d53a7SEvalZero rc = ble_hw_get_public_addr(&addr);
1442*042d53a7SEvalZero if (!rc) {
1443*042d53a7SEvalZero memcpy(g_dev_addr, &addr.val[0], BLE_DEV_ADDR_LEN);
1444*042d53a7SEvalZero }
1445*042d53a7SEvalZero } else {
1446*042d53a7SEvalZero memcpy(g_dev_addr, &addr.val[0], BLE_DEV_ADDR_LEN);
1447*042d53a7SEvalZero }
1448*042d53a7SEvalZero
1449*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
1450*042d53a7SEvalZero /* Settling time of crystal, in ticks */
1451*042d53a7SEvalZero xtal_ticks = MYNEWT_VAL(BLE_XTAL_SETTLE_TIME);
1452*042d53a7SEvalZero BLE_LL_ASSERT(xtal_ticks != 0);
1453*042d53a7SEvalZero g_ble_ll_data.ll_xtal_ticks = os_cputime_usecs_to_ticks(xtal_ticks);
1454*042d53a7SEvalZero
1455*042d53a7SEvalZero /* Initialize rf clock timer */
1456*042d53a7SEvalZero os_cputime_timer_init(&g_ble_ll_data.ll_rfclk_timer,
1457*042d53a7SEvalZero ble_ll_xcvr_rfclk_timer_exp, NULL);
1458*042d53a7SEvalZero
1459*042d53a7SEvalZero #endif
1460*042d53a7SEvalZero
1461*042d53a7SEvalZero /* Get pointer to global data object */
1462*042d53a7SEvalZero lldata = &g_ble_ll_data;
1463*042d53a7SEvalZero
1464*042d53a7SEvalZero /* Set acl pkt size and number */
1465*042d53a7SEvalZero lldata->ll_num_acl_pkts = MYNEWT_VAL(BLE_ACL_BUF_COUNT);
1466*042d53a7SEvalZero lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_ACL_BUF_SIZE);
1467*042d53a7SEvalZero
1468*042d53a7SEvalZero /*
1469*042d53a7SEvalZero * XXX RIOT ties event queue to a thread which initialized it so we need to
1470*042d53a7SEvalZero * create event queue in LL task, not in general init function. This can
1471*042d53a7SEvalZero * lead to some races between host and LL so for now let us have it as a
1472*042d53a7SEvalZero * hack for RIOT where races can be avoided by proper initialization inside
1473*042d53a7SEvalZero * package.
1474*042d53a7SEvalZero */
1475*042d53a7SEvalZero #ifndef RIOT_VERSION
1476*042d53a7SEvalZero /* Initialize eventq */
1477*042d53a7SEvalZero ble_npl_eventq_init(&lldata->ll_evq);
1478*042d53a7SEvalZero #endif
1479*042d53a7SEvalZero
1480*042d53a7SEvalZero /* Initialize the transmit (from host) and receive (from phy) queues */
1481*042d53a7SEvalZero STAILQ_INIT(&lldata->ll_tx_pkt_q);
1482*042d53a7SEvalZero STAILQ_INIT(&lldata->ll_rx_pkt_q);
1483*042d53a7SEvalZero
1484*042d53a7SEvalZero /* Initialize transmit (from host) and receive packet (from phy) event */
1485*042d53a7SEvalZero ble_npl_event_init(&lldata->ll_rx_pkt_ev, ble_ll_event_rx_pkt, NULL);
1486*042d53a7SEvalZero ble_npl_event_init(&lldata->ll_tx_pkt_ev, ble_ll_event_tx_pkt, NULL);
1487*042d53a7SEvalZero
1488*042d53a7SEvalZero /* Initialize data buffer overflow event and completed packets */
1489*042d53a7SEvalZero ble_npl_event_init(&lldata->ll_dbuf_overflow_ev, ble_ll_event_dbuf_overflow, NULL);
1490*042d53a7SEvalZero ble_npl_event_init(&lldata->ll_comp_pkt_ev, ble_ll_event_comp_pkts, NULL);
1491*042d53a7SEvalZero
1492*042d53a7SEvalZero /* Initialize the HW error timer */
1493*042d53a7SEvalZero ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer,
1494*042d53a7SEvalZero &g_ble_ll_data.ll_evq,
1495*042d53a7SEvalZero ble_ll_hw_err_timer_cb,
1496*042d53a7SEvalZero NULL);
1497*042d53a7SEvalZero
1498*042d53a7SEvalZero /* Initialize LL HCI */
1499*042d53a7SEvalZero ble_ll_hci_init();
1500*042d53a7SEvalZero
1501*042d53a7SEvalZero /* Init the scheduler */
1502*042d53a7SEvalZero ble_ll_sched_init();
1503*042d53a7SEvalZero
1504*042d53a7SEvalZero /* Initialize advertiser */
1505*042d53a7SEvalZero ble_ll_adv_init();
1506*042d53a7SEvalZero
1507*042d53a7SEvalZero /* Initialize a scanner */
1508*042d53a7SEvalZero ble_ll_scan_init();
1509*042d53a7SEvalZero
1510*042d53a7SEvalZero /* Initialize the connection module */
1511*042d53a7SEvalZero ble_ll_conn_module_init();
1512*042d53a7SEvalZero
1513*042d53a7SEvalZero /* Set the supported features. NOTE: we always support extended reject. */
1514*042d53a7SEvalZero features = BLE_LL_FEAT_EXTENDED_REJ;
1515*042d53a7SEvalZero
1516*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
1517*042d53a7SEvalZero features |= BLE_LL_FEAT_DATA_LEN_EXT;
1518*042d53a7SEvalZero #endif
1519*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_CONN_PARAM_REQ) == 1)
1520*042d53a7SEvalZero features |= BLE_LL_FEAT_CONN_PARM_REQ;
1521*042d53a7SEvalZero #endif
1522*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG) == 1)
1523*042d53a7SEvalZero features |= BLE_LL_FEAT_SLAVE_INIT;
1524*042d53a7SEvalZero #endif
1525*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1526*042d53a7SEvalZero features |= BLE_LL_FEAT_LE_ENCRYPTION;
1527*042d53a7SEvalZero #endif
1528*042d53a7SEvalZero
1529*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1530*042d53a7SEvalZero features |= (BLE_LL_FEAT_LL_PRIVACY | BLE_LL_FEAT_EXT_SCAN_FILT);
1531*042d53a7SEvalZero ble_ll_resolv_init();
1532*042d53a7SEvalZero #endif
1533*042d53a7SEvalZero
1534*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1535*042d53a7SEvalZero features |= BLE_LL_FEAT_LE_PING;
1536*042d53a7SEvalZero #endif
1537*042d53a7SEvalZero
1538*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
1539*042d53a7SEvalZero features |= BLE_LL_FEAT_EXT_ADV;
1540*042d53a7SEvalZero #endif
1541*042d53a7SEvalZero
1542*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) == 1)
1543*042d53a7SEvalZero /* CSA2 */
1544*042d53a7SEvalZero features |= BLE_LL_FEAT_CSA2;
1545*042d53a7SEvalZero #endif
1546*042d53a7SEvalZero
1547*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) == 1)
1548*042d53a7SEvalZero features |= BLE_LL_FEAT_LE_2M_PHY;
1549*042d53a7SEvalZero #endif
1550*042d53a7SEvalZero
1551*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) == 1)
1552*042d53a7SEvalZero features |= BLE_LL_FEAT_LE_CODED_PHY;
1553*042d53a7SEvalZero #endif
1554*042d53a7SEvalZero
1555*042d53a7SEvalZero /* Initialize random number generation */
1556*042d53a7SEvalZero ble_ll_rand_init();
1557*042d53a7SEvalZero
1558*042d53a7SEvalZero /* XXX: This really doesn't belong here, as the address probably has not
1559*042d53a7SEvalZero * been set yet.
1560*042d53a7SEvalZero */
1561*042d53a7SEvalZero ble_ll_seed_prng();
1562*042d53a7SEvalZero
1563*042d53a7SEvalZero lldata->ll_supp_features = features;
1564*042d53a7SEvalZero
1565*042d53a7SEvalZero #if MYNEWT
1566*042d53a7SEvalZero /* Initialize the LL task */
1567*042d53a7SEvalZero os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL,
1568*042d53a7SEvalZero MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack,
1569*042d53a7SEvalZero BLE_LL_STACK_SIZE);
1570*042d53a7SEvalZero #else
1571*042d53a7SEvalZero
1572*042d53a7SEvalZero /*
1573*042d53a7SEvalZero * For non-Mynewt OS it is required that OS creates task for LL and run LL
1574*042d53a7SEvalZero * routine which is wrapped by nimble_port_ll_task_func().
1575*042d53a7SEvalZero */
1576*042d53a7SEvalZero
1577*042d53a7SEvalZero #endif
1578*042d53a7SEvalZero
1579*042d53a7SEvalZero rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
1580*042d53a7SEvalZero STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
1581*042d53a7SEvalZero STATS_NAME_INIT_PARMS(ble_ll_stats),
1582*042d53a7SEvalZero "ble_ll");
1583*042d53a7SEvalZero SYSINIT_PANIC_ASSERT(rc == 0);
1584*042d53a7SEvalZero
1585*042d53a7SEvalZero ble_hci_trans_cfg_ll(ble_ll_hci_cmd_rx, NULL, ble_ll_hci_acl_rx, NULL);
1586*042d53a7SEvalZero
1587*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE)
1588*042d53a7SEvalZero ble_ll_dtm_init();
1589*042d53a7SEvalZero #endif
1590*042d53a7SEvalZero }
1591