xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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 <assert.h>
21*042d53a7SEvalZero #include <errno.h>
22*042d53a7SEvalZero #include <string.h>
23*042d53a7SEvalZero #include "sysinit/sysinit.h"
24*042d53a7SEvalZero #include "syscfg/syscfg.h"
25*042d53a7SEvalZero #include "stats/stats.h"
26*042d53a7SEvalZero #include "nimble/ble_hci_trans.h"
27*042d53a7SEvalZero #include "ble_hs_priv.h"
28*042d53a7SEvalZero #include "ble_monitor_priv.h"
29*042d53a7SEvalZero #include "nimble/nimble_npl.h"
30*042d53a7SEvalZero #ifndef MYNEWT
31*042d53a7SEvalZero #include "nimble/nimble_port.h"
32*042d53a7SEvalZero #endif
33*042d53a7SEvalZero 
34*042d53a7SEvalZero #define BLE_HS_HCI_EVT_COUNT                    \
35*042d53a7SEvalZero     (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) +     \
36*042d53a7SEvalZero      MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
37*042d53a7SEvalZero 
38*042d53a7SEvalZero static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev);
39*042d53a7SEvalZero static void ble_hs_event_tx_notify(struct ble_npl_event *ev);
40*042d53a7SEvalZero static void ble_hs_event_reset(struct ble_npl_event *ev);
41*042d53a7SEvalZero static void ble_hs_event_start_stage1(struct ble_npl_event *ev);
42*042d53a7SEvalZero static void ble_hs_event_start_stage2(struct ble_npl_event *ev);
43*042d53a7SEvalZero static void ble_hs_timer_sched(int32_t ticks_from_now);
44*042d53a7SEvalZero 
45*042d53a7SEvalZero struct os_mempool ble_hs_hci_ev_pool;
46*042d53a7SEvalZero static os_membuf_t ble_hs_hci_os_event_buf[
47*042d53a7SEvalZero     OS_MEMPOOL_SIZE(BLE_HS_HCI_EVT_COUNT, sizeof (struct ble_npl_event))
48*042d53a7SEvalZero ];
49*042d53a7SEvalZero 
50*042d53a7SEvalZero /** OS event - triggers tx of pending notifications and indications. */
51*042d53a7SEvalZero static struct ble_npl_event ble_hs_ev_tx_notifications;
52*042d53a7SEvalZero 
53*042d53a7SEvalZero /** OS event - triggers a full reset. */
54*042d53a7SEvalZero static struct ble_npl_event ble_hs_ev_reset;
55*042d53a7SEvalZero 
56*042d53a7SEvalZero static struct ble_npl_event ble_hs_ev_start_stage1;
57*042d53a7SEvalZero static struct ble_npl_event ble_hs_ev_start_stage2;
58*042d53a7SEvalZero 
59*042d53a7SEvalZero uint8_t ble_hs_sync_state;
60*042d53a7SEvalZero uint8_t ble_hs_enabled_state;
61*042d53a7SEvalZero static int ble_hs_reset_reason;
62*042d53a7SEvalZero 
63*042d53a7SEvalZero #define BLE_HS_SYNC_RETRY_TIMEOUT_MS    100 /* ms */
64*042d53a7SEvalZero 
65*042d53a7SEvalZero static void *ble_hs_parent_task;
66*042d53a7SEvalZero 
67*042d53a7SEvalZero /**
68*042d53a7SEvalZero  * Handles unresponsive timeouts and periodic retries in case of resource
69*042d53a7SEvalZero  * shortage.
70*042d53a7SEvalZero  */
71*042d53a7SEvalZero static struct ble_npl_callout ble_hs_timer;
72*042d53a7SEvalZero 
73*042d53a7SEvalZero /* Shared queue that the host uses for work items. */
74*042d53a7SEvalZero static struct ble_npl_eventq *ble_hs_evq;
75*042d53a7SEvalZero 
76*042d53a7SEvalZero static struct ble_mqueue ble_hs_rx_q;
77*042d53a7SEvalZero 
78*042d53a7SEvalZero static struct ble_npl_mutex ble_hs_mutex;
79*042d53a7SEvalZero 
80*042d53a7SEvalZero /** These values keep track of required ATT and GATT resources counts.  They
81*042d53a7SEvalZero  * increase as services are added, and are read when the ATT server and GATT
82*042d53a7SEvalZero  * server are started.
83*042d53a7SEvalZero  */
84*042d53a7SEvalZero uint16_t ble_hs_max_attrs;
85*042d53a7SEvalZero uint16_t ble_hs_max_services;
86*042d53a7SEvalZero uint16_t ble_hs_max_client_configs;
87*042d53a7SEvalZero 
88*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
89*042d53a7SEvalZero static uint8_t ble_hs_dbg_mutex_locked;
90*042d53a7SEvalZero #endif
91*042d53a7SEvalZero 
92*042d53a7SEvalZero STATS_SECT_DECL(ble_hs_stats) ble_hs_stats;
93*042d53a7SEvalZero STATS_NAME_START(ble_hs_stats)
STATS_NAME(ble_hs_stats,conn_create)94*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, conn_create)
95*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, conn_delete)
96*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, hci_cmd)
97*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, hci_event)
98*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, hci_invalid_ack)
99*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, hci_unknown_event)
100*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, hci_timeout)
101*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, reset)
102*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, sync)
103*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, pvcy_add_entry)
104*042d53a7SEvalZero     STATS_NAME(ble_hs_stats, pvcy_add_entry_fail)
105*042d53a7SEvalZero STATS_NAME_END(ble_hs_stats)
106*042d53a7SEvalZero 
107*042d53a7SEvalZero struct ble_npl_eventq *
108*042d53a7SEvalZero ble_hs_evq_get(void)
109*042d53a7SEvalZero {
110*042d53a7SEvalZero     return ble_hs_evq;
111*042d53a7SEvalZero }
112*042d53a7SEvalZero 
113*042d53a7SEvalZero void
ble_hs_evq_set(struct ble_npl_eventq * evq)114*042d53a7SEvalZero ble_hs_evq_set(struct ble_npl_eventq *evq)
115*042d53a7SEvalZero {
116*042d53a7SEvalZero     ble_hs_evq = evq;
117*042d53a7SEvalZero }
118*042d53a7SEvalZero 
119*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
120*042d53a7SEvalZero int
ble_hs_locked_by_cur_task(void)121*042d53a7SEvalZero ble_hs_locked_by_cur_task(void)
122*042d53a7SEvalZero {
123*042d53a7SEvalZero #if MYNEWT
124*042d53a7SEvalZero     struct os_task *owner;
125*042d53a7SEvalZero 
126*042d53a7SEvalZero     if (!ble_npl_os_started()) {
127*042d53a7SEvalZero         return ble_hs_dbg_mutex_locked;
128*042d53a7SEvalZero     }
129*042d53a7SEvalZero 
130*042d53a7SEvalZero     owner = ble_hs_mutex.mu.mu_owner;
131*042d53a7SEvalZero     return owner != NULL && owner == os_sched_get_current_task();
132*042d53a7SEvalZero #else
133*042d53a7SEvalZero     return 1;
134*042d53a7SEvalZero #endif
135*042d53a7SEvalZero }
136*042d53a7SEvalZero #endif
137*042d53a7SEvalZero 
138*042d53a7SEvalZero /**
139*042d53a7SEvalZero  * Indicates whether the host's parent task is currently running.
140*042d53a7SEvalZero  */
141*042d53a7SEvalZero int
ble_hs_is_parent_task(void)142*042d53a7SEvalZero ble_hs_is_parent_task(void)
143*042d53a7SEvalZero {
144*042d53a7SEvalZero     return !ble_npl_os_started() ||
145*042d53a7SEvalZero            ble_npl_get_current_task_id() == ble_hs_parent_task;
146*042d53a7SEvalZero }
147*042d53a7SEvalZero 
148*042d53a7SEvalZero /**
149*042d53a7SEvalZero  * Locks the BLE host mutex.  Nested locks allowed.
150*042d53a7SEvalZero  */
151*042d53a7SEvalZero void
ble_hs_lock_nested(void)152*042d53a7SEvalZero ble_hs_lock_nested(void)
153*042d53a7SEvalZero {
154*042d53a7SEvalZero     int rc;
155*042d53a7SEvalZero 
156*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
157*042d53a7SEvalZero     if (!ble_npl_os_started()) {
158*042d53a7SEvalZero         ble_hs_dbg_mutex_locked = 1;
159*042d53a7SEvalZero         return;
160*042d53a7SEvalZero     }
161*042d53a7SEvalZero #endif
162*042d53a7SEvalZero 
163*042d53a7SEvalZero     rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff);
164*042d53a7SEvalZero     BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
165*042d53a7SEvalZero }
166*042d53a7SEvalZero 
167*042d53a7SEvalZero /**
168*042d53a7SEvalZero  * Unlocks the BLE host mutex.  Nested locks allowed.
169*042d53a7SEvalZero  */
170*042d53a7SEvalZero void
ble_hs_unlock_nested(void)171*042d53a7SEvalZero ble_hs_unlock_nested(void)
172*042d53a7SEvalZero {
173*042d53a7SEvalZero     int rc;
174*042d53a7SEvalZero 
175*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
176*042d53a7SEvalZero     if (!ble_npl_os_started()) {
177*042d53a7SEvalZero         ble_hs_dbg_mutex_locked = 0;
178*042d53a7SEvalZero         return;
179*042d53a7SEvalZero     }
180*042d53a7SEvalZero #endif
181*042d53a7SEvalZero 
182*042d53a7SEvalZero     rc = ble_npl_mutex_release(&ble_hs_mutex);
183*042d53a7SEvalZero     BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED);
184*042d53a7SEvalZero }
185*042d53a7SEvalZero 
186*042d53a7SEvalZero /**
187*042d53a7SEvalZero  * Locks the BLE host mutex.  Nested locks not allowed.
188*042d53a7SEvalZero  */
189*042d53a7SEvalZero void
ble_hs_lock(void)190*042d53a7SEvalZero ble_hs_lock(void)
191*042d53a7SEvalZero {
192*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
193*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
194*042d53a7SEvalZero     if (!ble_npl_os_started()) {
195*042d53a7SEvalZero         BLE_HS_DBG_ASSERT(!ble_hs_dbg_mutex_locked);
196*042d53a7SEvalZero     }
197*042d53a7SEvalZero #endif
198*042d53a7SEvalZero 
199*042d53a7SEvalZero     ble_hs_lock_nested();
200*042d53a7SEvalZero }
201*042d53a7SEvalZero 
202*042d53a7SEvalZero /**
203*042d53a7SEvalZero  * Unlocks the BLE host mutex.  Nested locks not allowed.
204*042d53a7SEvalZero  */
205*042d53a7SEvalZero void
ble_hs_unlock(void)206*042d53a7SEvalZero ble_hs_unlock(void)
207*042d53a7SEvalZero {
208*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
209*042d53a7SEvalZero     if (!ble_npl_os_started()) {
210*042d53a7SEvalZero         BLE_HS_DBG_ASSERT(ble_hs_dbg_mutex_locked);
211*042d53a7SEvalZero     }
212*042d53a7SEvalZero #endif
213*042d53a7SEvalZero 
214*042d53a7SEvalZero     ble_hs_unlock_nested();
215*042d53a7SEvalZero }
216*042d53a7SEvalZero 
217*042d53a7SEvalZero void
ble_hs_process_rx_data_queue(void)218*042d53a7SEvalZero ble_hs_process_rx_data_queue(void)
219*042d53a7SEvalZero {
220*042d53a7SEvalZero     struct os_mbuf *om;
221*042d53a7SEvalZero 
222*042d53a7SEvalZero     while ((om = ble_mqueue_get(&ble_hs_rx_q)) != NULL) {
223*042d53a7SEvalZero #if BLE_MONITOR
224*042d53a7SEvalZero         ble_monitor_send_om(BLE_MONITOR_OPCODE_ACL_RX_PKT, om);
225*042d53a7SEvalZero #endif
226*042d53a7SEvalZero 
227*042d53a7SEvalZero         ble_hs_hci_evt_acl_process(om);
228*042d53a7SEvalZero     }
229*042d53a7SEvalZero }
230*042d53a7SEvalZero 
231*042d53a7SEvalZero static int
ble_hs_wakeup_tx_conn(struct ble_hs_conn * conn)232*042d53a7SEvalZero ble_hs_wakeup_tx_conn(struct ble_hs_conn *conn)
233*042d53a7SEvalZero {
234*042d53a7SEvalZero     struct os_mbuf_pkthdr *omp;
235*042d53a7SEvalZero     struct os_mbuf *om;
236*042d53a7SEvalZero     int rc;
237*042d53a7SEvalZero 
238*042d53a7SEvalZero     while ((omp = STAILQ_FIRST(&conn->bhc_tx_q)) != NULL) {
239*042d53a7SEvalZero         STAILQ_REMOVE_HEAD(&conn->bhc_tx_q, omp_next);
240*042d53a7SEvalZero 
241*042d53a7SEvalZero         om = OS_MBUF_PKTHDR_TO_MBUF(omp);
242*042d53a7SEvalZero         rc = ble_hs_hci_acl_tx_now(conn, &om);
243*042d53a7SEvalZero         if (rc == BLE_HS_EAGAIN) {
244*042d53a7SEvalZero             /* Controller is at capacity.  This packet will be the first to
245*042d53a7SEvalZero              * get transmitted next time around.
246*042d53a7SEvalZero              */
247*042d53a7SEvalZero             STAILQ_INSERT_HEAD(&conn->bhc_tx_q, OS_MBUF_PKTHDR(om), omp_next);
248*042d53a7SEvalZero             return BLE_HS_EAGAIN;
249*042d53a7SEvalZero         }
250*042d53a7SEvalZero     }
251*042d53a7SEvalZero 
252*042d53a7SEvalZero     return 0;
253*042d53a7SEvalZero }
254*042d53a7SEvalZero 
255*042d53a7SEvalZero /**
256*042d53a7SEvalZero  * Schedules the transmission of all queued ACL data packets to the controller.
257*042d53a7SEvalZero  */
258*042d53a7SEvalZero void
ble_hs_wakeup_tx(void)259*042d53a7SEvalZero ble_hs_wakeup_tx(void)
260*042d53a7SEvalZero {
261*042d53a7SEvalZero     struct ble_hs_conn *conn;
262*042d53a7SEvalZero     int rc;
263*042d53a7SEvalZero 
264*042d53a7SEvalZero     ble_hs_lock();
265*042d53a7SEvalZero 
266*042d53a7SEvalZero     /* If there is a connection with a partially transmitted packet, it has to
267*042d53a7SEvalZero      * be serviced first.  The controller is waiting for the remainder so it
268*042d53a7SEvalZero      * can reassemble it.
269*042d53a7SEvalZero      */
270*042d53a7SEvalZero     for (conn = ble_hs_conn_first();
271*042d53a7SEvalZero          conn != NULL;
272*042d53a7SEvalZero          conn = SLIST_NEXT(conn, bhc_next)) {
273*042d53a7SEvalZero 
274*042d53a7SEvalZero         if (conn->bhc_flags & BLE_HS_CONN_F_TX_FRAG) {
275*042d53a7SEvalZero             rc = ble_hs_wakeup_tx_conn(conn);
276*042d53a7SEvalZero             if (rc != 0) {
277*042d53a7SEvalZero                 goto done;
278*042d53a7SEvalZero             }
279*042d53a7SEvalZero             break;
280*042d53a7SEvalZero         }
281*042d53a7SEvalZero     }
282*042d53a7SEvalZero 
283*042d53a7SEvalZero     /* For each connection, transmit queued packets until there are no more
284*042d53a7SEvalZero      * packets to send or the controller's buffers are exhausted.
285*042d53a7SEvalZero      */
286*042d53a7SEvalZero     for (conn = ble_hs_conn_first();
287*042d53a7SEvalZero          conn != NULL;
288*042d53a7SEvalZero          conn = SLIST_NEXT(conn, bhc_next)) {
289*042d53a7SEvalZero 
290*042d53a7SEvalZero         rc = ble_hs_wakeup_tx_conn(conn);
291*042d53a7SEvalZero         if (rc != 0) {
292*042d53a7SEvalZero             goto done;
293*042d53a7SEvalZero         }
294*042d53a7SEvalZero     }
295*042d53a7SEvalZero 
296*042d53a7SEvalZero done:
297*042d53a7SEvalZero     ble_hs_unlock();
298*042d53a7SEvalZero }
299*042d53a7SEvalZero 
300*042d53a7SEvalZero static void
ble_hs_clear_rx_queue(void)301*042d53a7SEvalZero ble_hs_clear_rx_queue(void)
302*042d53a7SEvalZero {
303*042d53a7SEvalZero     struct os_mbuf *om;
304*042d53a7SEvalZero 
305*042d53a7SEvalZero     while ((om = ble_mqueue_get(&ble_hs_rx_q)) != NULL) {
306*042d53a7SEvalZero         os_mbuf_free_chain(om);
307*042d53a7SEvalZero     }
308*042d53a7SEvalZero }
309*042d53a7SEvalZero 
310*042d53a7SEvalZero int
ble_hs_is_enabled(void)311*042d53a7SEvalZero ble_hs_is_enabled(void)
312*042d53a7SEvalZero {
313*042d53a7SEvalZero     return ble_hs_enabled_state == BLE_HS_ENABLED_STATE_ON;
314*042d53a7SEvalZero }
315*042d53a7SEvalZero 
316*042d53a7SEvalZero int
ble_hs_synced(void)317*042d53a7SEvalZero ble_hs_synced(void)
318*042d53a7SEvalZero {
319*042d53a7SEvalZero     return ble_hs_sync_state == BLE_HS_SYNC_STATE_GOOD;
320*042d53a7SEvalZero }
321*042d53a7SEvalZero 
322*042d53a7SEvalZero static int
ble_hs_sync(void)323*042d53a7SEvalZero ble_hs_sync(void)
324*042d53a7SEvalZero {
325*042d53a7SEvalZero     ble_npl_time_t retry_tmo_ticks;
326*042d53a7SEvalZero     int rc;
327*042d53a7SEvalZero 
328*042d53a7SEvalZero     /* Set the sync state to "bringup."  This allows the parent task to send
329*042d53a7SEvalZero      * the startup sequence to the controller.  No other tasks are allowed to
330*042d53a7SEvalZero      * send any commands.
331*042d53a7SEvalZero      */
332*042d53a7SEvalZero     ble_hs_sync_state = BLE_HS_SYNC_STATE_BRINGUP;
333*042d53a7SEvalZero 
334*042d53a7SEvalZero     rc = ble_hs_startup_go();
335*042d53a7SEvalZero     if (rc == 0) {
336*042d53a7SEvalZero         ble_hs_sync_state = BLE_HS_SYNC_STATE_GOOD;
337*042d53a7SEvalZero     } else {
338*042d53a7SEvalZero         ble_hs_sync_state = BLE_HS_SYNC_STATE_BAD;
339*042d53a7SEvalZero     }
340*042d53a7SEvalZero 
341*042d53a7SEvalZero     retry_tmo_ticks = ble_npl_time_ms_to_ticks32(BLE_HS_SYNC_RETRY_TIMEOUT_MS);
342*042d53a7SEvalZero     ble_hs_timer_sched(retry_tmo_ticks);
343*042d53a7SEvalZero 
344*042d53a7SEvalZero     if (rc == 0) {
345*042d53a7SEvalZero         rc = ble_hs_misc_restore_irks();
346*042d53a7SEvalZero         if (rc != 0) {
347*042d53a7SEvalZero             BLE_HS_LOG(INFO, "Failed to restore IRKs from store; status=%d",
348*042d53a7SEvalZero                        rc);
349*042d53a7SEvalZero         }
350*042d53a7SEvalZero 
351*042d53a7SEvalZero         if (ble_hs_cfg.sync_cb != NULL) {
352*042d53a7SEvalZero             ble_hs_cfg.sync_cb();
353*042d53a7SEvalZero         }
354*042d53a7SEvalZero 
355*042d53a7SEvalZero         STATS_INC(ble_hs_stats, sync);
356*042d53a7SEvalZero     }
357*042d53a7SEvalZero 
358*042d53a7SEvalZero     return rc;
359*042d53a7SEvalZero }
360*042d53a7SEvalZero 
361*042d53a7SEvalZero static int
ble_hs_reset(void)362*042d53a7SEvalZero ble_hs_reset(void)
363*042d53a7SEvalZero {
364*042d53a7SEvalZero     uint16_t conn_handle;
365*042d53a7SEvalZero     int rc;
366*042d53a7SEvalZero 
367*042d53a7SEvalZero     STATS_INC(ble_hs_stats, reset);
368*042d53a7SEvalZero 
369*042d53a7SEvalZero     ble_hs_sync_state = 0;
370*042d53a7SEvalZero 
371*042d53a7SEvalZero     /* Reset transport.  Assume success; there is nothing we can do in case of
372*042d53a7SEvalZero      * failure.  If the transport failed to reset, the host will reset itself
373*042d53a7SEvalZero      * again when it fails to sync with the controller.
374*042d53a7SEvalZero      */
375*042d53a7SEvalZero     (void)ble_hci_trans_reset();
376*042d53a7SEvalZero 
377*042d53a7SEvalZero     ble_hs_clear_rx_queue();
378*042d53a7SEvalZero 
379*042d53a7SEvalZero     while (1) {
380*042d53a7SEvalZero         conn_handle = ble_hs_atomic_first_conn_handle();
381*042d53a7SEvalZero         if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
382*042d53a7SEvalZero             break;
383*042d53a7SEvalZero         }
384*042d53a7SEvalZero 
385*042d53a7SEvalZero         ble_gap_conn_broken(conn_handle, ble_hs_reset_reason);
386*042d53a7SEvalZero     }
387*042d53a7SEvalZero 
388*042d53a7SEvalZero     /* Clear configured addresses. */
389*042d53a7SEvalZero     ble_hs_id_reset();
390*042d53a7SEvalZero 
391*042d53a7SEvalZero     if (ble_hs_cfg.reset_cb != NULL && ble_hs_reset_reason != 0) {
392*042d53a7SEvalZero         ble_hs_cfg.reset_cb(ble_hs_reset_reason);
393*042d53a7SEvalZero     }
394*042d53a7SEvalZero     ble_hs_reset_reason = 0;
395*042d53a7SEvalZero 
396*042d53a7SEvalZero     rc = ble_hs_sync();
397*042d53a7SEvalZero     return rc;
398*042d53a7SEvalZero }
399*042d53a7SEvalZero 
400*042d53a7SEvalZero /**
401*042d53a7SEvalZero  * Called when the host timer expires.  Handles unresponsive timeouts and
402*042d53a7SEvalZero  * periodic retries in case of resource shortage.
403*042d53a7SEvalZero  */
404*042d53a7SEvalZero static void
ble_hs_timer_exp(struct ble_npl_event * ev)405*042d53a7SEvalZero ble_hs_timer_exp(struct ble_npl_event *ev)
406*042d53a7SEvalZero {
407*042d53a7SEvalZero     int32_t ticks_until_next;
408*042d53a7SEvalZero 
409*042d53a7SEvalZero     switch (ble_hs_sync_state) {
410*042d53a7SEvalZero     case BLE_HS_SYNC_STATE_GOOD:
411*042d53a7SEvalZero         ticks_until_next = ble_gattc_timer();
412*042d53a7SEvalZero         ble_hs_timer_sched(ticks_until_next);
413*042d53a7SEvalZero 
414*042d53a7SEvalZero         ticks_until_next = ble_gap_timer();
415*042d53a7SEvalZero         ble_hs_timer_sched(ticks_until_next);
416*042d53a7SEvalZero 
417*042d53a7SEvalZero         ticks_until_next = ble_l2cap_sig_timer();
418*042d53a7SEvalZero         ble_hs_timer_sched(ticks_until_next);
419*042d53a7SEvalZero 
420*042d53a7SEvalZero         ticks_until_next = ble_sm_timer();
421*042d53a7SEvalZero         ble_hs_timer_sched(ticks_until_next);
422*042d53a7SEvalZero 
423*042d53a7SEvalZero         ticks_until_next = ble_hs_conn_timer();
424*042d53a7SEvalZero         ble_hs_timer_sched(ticks_until_next);
425*042d53a7SEvalZero         break;
426*042d53a7SEvalZero 
427*042d53a7SEvalZero     case BLE_HS_SYNC_STATE_BAD:
428*042d53a7SEvalZero         ble_hs_reset();
429*042d53a7SEvalZero         break;
430*042d53a7SEvalZero 
431*042d53a7SEvalZero     case BLE_HS_SYNC_STATE_BRINGUP:
432*042d53a7SEvalZero     default:
433*042d53a7SEvalZero         /* The timer should not be set in this state. */
434*042d53a7SEvalZero         assert(0);
435*042d53a7SEvalZero         break;
436*042d53a7SEvalZero     }
437*042d53a7SEvalZero 
438*042d53a7SEvalZero }
439*042d53a7SEvalZero 
440*042d53a7SEvalZero static void
ble_hs_timer_reset(uint32_t ticks)441*042d53a7SEvalZero ble_hs_timer_reset(uint32_t ticks)
442*042d53a7SEvalZero {
443*042d53a7SEvalZero     int rc;
444*042d53a7SEvalZero 
445*042d53a7SEvalZero     if (!ble_hs_is_enabled()) {
446*042d53a7SEvalZero         ble_npl_callout_stop(&ble_hs_timer);
447*042d53a7SEvalZero     } else {
448*042d53a7SEvalZero         rc = ble_npl_callout_reset(&ble_hs_timer, ticks);
449*042d53a7SEvalZero         BLE_HS_DBG_ASSERT_EVAL(rc == 0);
450*042d53a7SEvalZero     }
451*042d53a7SEvalZero }
452*042d53a7SEvalZero 
453*042d53a7SEvalZero static void
ble_hs_timer_sched(int32_t ticks_from_now)454*042d53a7SEvalZero ble_hs_timer_sched(int32_t ticks_from_now)
455*042d53a7SEvalZero {
456*042d53a7SEvalZero     ble_npl_time_t abs_time;
457*042d53a7SEvalZero 
458*042d53a7SEvalZero     if (ticks_from_now == BLE_HS_FOREVER) {
459*042d53a7SEvalZero         return;
460*042d53a7SEvalZero     }
461*042d53a7SEvalZero 
462*042d53a7SEvalZero     /* Reset timer if it is not currently scheduled or if the specified time is
463*042d53a7SEvalZero      * sooner than the previous expiration time.
464*042d53a7SEvalZero      */
465*042d53a7SEvalZero     abs_time = ble_npl_time_get() + ticks_from_now;
466*042d53a7SEvalZero     if (!ble_npl_callout_is_active(&ble_hs_timer) ||
467*042d53a7SEvalZero             ((ble_npl_stime_t)(abs_time -
468*042d53a7SEvalZero                                ble_npl_callout_get_ticks(&ble_hs_timer))) < 0) {
469*042d53a7SEvalZero         ble_hs_timer_reset(ticks_from_now);
470*042d53a7SEvalZero     }
471*042d53a7SEvalZero }
472*042d53a7SEvalZero 
473*042d53a7SEvalZero void
ble_hs_timer_resched(void)474*042d53a7SEvalZero ble_hs_timer_resched(void)
475*042d53a7SEvalZero {
476*042d53a7SEvalZero     /* Reschedule the timer to run immediately.  The timer callback will query
477*042d53a7SEvalZero      * each module for an up-to-date expiration time.
478*042d53a7SEvalZero      */
479*042d53a7SEvalZero     ble_hs_timer_reset(0);
480*042d53a7SEvalZero }
481*042d53a7SEvalZero 
482*042d53a7SEvalZero static void
ble_hs_sched_start_stage2(void)483*042d53a7SEvalZero ble_hs_sched_start_stage2(void)
484*042d53a7SEvalZero {
485*042d53a7SEvalZero     ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(),
486*042d53a7SEvalZero                        &ble_hs_ev_start_stage2);
487*042d53a7SEvalZero }
488*042d53a7SEvalZero 
489*042d53a7SEvalZero void
ble_hs_sched_start(void)490*042d53a7SEvalZero ble_hs_sched_start(void)
491*042d53a7SEvalZero {
492*042d53a7SEvalZero #ifdef MYNEWT
493*042d53a7SEvalZero     ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(),
494*042d53a7SEvalZero                        &ble_hs_ev_start_stage1);
495*042d53a7SEvalZero #else
496*042d53a7SEvalZero     ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start_stage1);
497*042d53a7SEvalZero #endif
498*042d53a7SEvalZero }
499*042d53a7SEvalZero 
500*042d53a7SEvalZero static void
ble_hs_event_rx_hci_ev(struct ble_npl_event * ev)501*042d53a7SEvalZero ble_hs_event_rx_hci_ev(struct ble_npl_event *ev)
502*042d53a7SEvalZero {
503*042d53a7SEvalZero     uint8_t *hci_evt;
504*042d53a7SEvalZero     int rc;
505*042d53a7SEvalZero 
506*042d53a7SEvalZero     hci_evt = ble_npl_event_get_arg(ev);
507*042d53a7SEvalZero 
508*042d53a7SEvalZero     rc = os_memblock_put(&ble_hs_hci_ev_pool, ev);
509*042d53a7SEvalZero     BLE_HS_DBG_ASSERT_EVAL(rc == 0);
510*042d53a7SEvalZero 
511*042d53a7SEvalZero #if BLE_MONITOR
512*042d53a7SEvalZero     ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, hci_evt,
513*042d53a7SEvalZero                      hci_evt[1] + BLE_HCI_EVENT_HDR_LEN);
514*042d53a7SEvalZero #endif
515*042d53a7SEvalZero 
516*042d53a7SEvalZero     ble_hs_hci_evt_process(hci_evt);
517*042d53a7SEvalZero }
518*042d53a7SEvalZero 
519*042d53a7SEvalZero static void
ble_hs_event_tx_notify(struct ble_npl_event * ev)520*042d53a7SEvalZero ble_hs_event_tx_notify(struct ble_npl_event *ev)
521*042d53a7SEvalZero {
522*042d53a7SEvalZero     ble_gatts_tx_notifications();
523*042d53a7SEvalZero }
524*042d53a7SEvalZero 
525*042d53a7SEvalZero static void
ble_hs_event_rx_data(struct ble_npl_event * ev)526*042d53a7SEvalZero ble_hs_event_rx_data(struct ble_npl_event *ev)
527*042d53a7SEvalZero {
528*042d53a7SEvalZero     ble_hs_process_rx_data_queue();
529*042d53a7SEvalZero }
530*042d53a7SEvalZero 
531*042d53a7SEvalZero static void
ble_hs_event_reset(struct ble_npl_event * ev)532*042d53a7SEvalZero ble_hs_event_reset(struct ble_npl_event *ev)
533*042d53a7SEvalZero {
534*042d53a7SEvalZero     ble_hs_reset();
535*042d53a7SEvalZero }
536*042d53a7SEvalZero 
537*042d53a7SEvalZero /**
538*042d53a7SEvalZero  * Implements the first half of the start process.  This just enqueues another
539*042d53a7SEvalZero  * event on the host parent task's event queue.
540*042d53a7SEvalZero  *
541*042d53a7SEvalZero  * Starting is done in two stages to allow the application time to configure
542*042d53a7SEvalZero  * the event queue to use after system initialization but before the host
543*042d53a7SEvalZero  * starts.
544*042d53a7SEvalZero  */
545*042d53a7SEvalZero static void
ble_hs_event_start_stage1(struct ble_npl_event * ev)546*042d53a7SEvalZero ble_hs_event_start_stage1(struct ble_npl_event *ev)
547*042d53a7SEvalZero {
548*042d53a7SEvalZero     ble_hs_sched_start_stage2();
549*042d53a7SEvalZero }
550*042d53a7SEvalZero 
551*042d53a7SEvalZero /**
552*042d53a7SEvalZero  * Implements the second half of the start process.  This actually starts the
553*042d53a7SEvalZero  * host.
554*042d53a7SEvalZero  *
555*042d53a7SEvalZero  * Starting is done in two stages to allow the application time to configure
556*042d53a7SEvalZero  * the event queue to use after system initialization but before the host
557*042d53a7SEvalZero  * starts.
558*042d53a7SEvalZero  */
559*042d53a7SEvalZero static void
ble_hs_event_start_stage2(struct ble_npl_event * ev)560*042d53a7SEvalZero ble_hs_event_start_stage2(struct ble_npl_event *ev)
561*042d53a7SEvalZero {
562*042d53a7SEvalZero     int rc;
563*042d53a7SEvalZero 
564*042d53a7SEvalZero     rc = ble_hs_start();
565*042d53a7SEvalZero     assert(rc == 0);
566*042d53a7SEvalZero }
567*042d53a7SEvalZero 
568*042d53a7SEvalZero void
ble_hs_enqueue_hci_event(uint8_t * hci_evt)569*042d53a7SEvalZero ble_hs_enqueue_hci_event(uint8_t *hci_evt)
570*042d53a7SEvalZero {
571*042d53a7SEvalZero     struct ble_npl_event *ev;
572*042d53a7SEvalZero 
573*042d53a7SEvalZero     ev = os_memblock_get(&ble_hs_hci_ev_pool);
574*042d53a7SEvalZero     if (ev == NULL) {
575*042d53a7SEvalZero         ble_hci_trans_buf_free(hci_evt);
576*042d53a7SEvalZero     } else {
577*042d53a7SEvalZero         ble_npl_event_init(ev, ble_hs_event_rx_hci_ev, hci_evt);
578*042d53a7SEvalZero         ble_npl_eventq_put(ble_hs_evq, ev);
579*042d53a7SEvalZero     }
580*042d53a7SEvalZero }
581*042d53a7SEvalZero 
582*042d53a7SEvalZero /**
583*042d53a7SEvalZero  * Schedules for all pending notifications and indications to be sent in the
584*042d53a7SEvalZero  * host parent task.
585*042d53a7SEvalZero  */
586*042d53a7SEvalZero void
ble_hs_notifications_sched(void)587*042d53a7SEvalZero ble_hs_notifications_sched(void)
588*042d53a7SEvalZero {
589*042d53a7SEvalZero #if !MYNEWT_VAL(BLE_HS_REQUIRE_OS)
590*042d53a7SEvalZero     if (!ble_npl_os_started()) {
591*042d53a7SEvalZero         ble_gatts_tx_notifications();
592*042d53a7SEvalZero         return;
593*042d53a7SEvalZero     }
594*042d53a7SEvalZero #endif
595*042d53a7SEvalZero 
596*042d53a7SEvalZero     ble_npl_eventq_put(ble_hs_evq, &ble_hs_ev_tx_notifications);
597*042d53a7SEvalZero }
598*042d53a7SEvalZero 
599*042d53a7SEvalZero void
ble_hs_sched_reset(int reason)600*042d53a7SEvalZero ble_hs_sched_reset(int reason)
601*042d53a7SEvalZero {
602*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(ble_hs_reset_reason == 0);
603*042d53a7SEvalZero 
604*042d53a7SEvalZero     ble_hs_reset_reason = reason;
605*042d53a7SEvalZero     ble_npl_eventq_put(ble_hs_evq, &ble_hs_ev_reset);
606*042d53a7SEvalZero }
607*042d53a7SEvalZero 
608*042d53a7SEvalZero void
ble_hs_hw_error(uint8_t hw_code)609*042d53a7SEvalZero ble_hs_hw_error(uint8_t hw_code)
610*042d53a7SEvalZero {
611*042d53a7SEvalZero     ble_hs_sched_reset(BLE_HS_HW_ERR(hw_code));
612*042d53a7SEvalZero }
613*042d53a7SEvalZero 
614*042d53a7SEvalZero int
ble_hs_start(void)615*042d53a7SEvalZero ble_hs_start(void)
616*042d53a7SEvalZero {
617*042d53a7SEvalZero     int rc;
618*042d53a7SEvalZero 
619*042d53a7SEvalZero     ble_hs_lock();
620*042d53a7SEvalZero     switch (ble_hs_enabled_state) {
621*042d53a7SEvalZero     case BLE_HS_ENABLED_STATE_ON:
622*042d53a7SEvalZero         rc = BLE_HS_EALREADY;
623*042d53a7SEvalZero         break;
624*042d53a7SEvalZero 
625*042d53a7SEvalZero     case BLE_HS_ENABLED_STATE_STOPPING:
626*042d53a7SEvalZero         rc = BLE_HS_EBUSY;
627*042d53a7SEvalZero         break;
628*042d53a7SEvalZero 
629*042d53a7SEvalZero     case BLE_HS_ENABLED_STATE_OFF:
630*042d53a7SEvalZero         ble_hs_enabled_state = BLE_HS_ENABLED_STATE_ON;
631*042d53a7SEvalZero         rc = 0;
632*042d53a7SEvalZero         break;
633*042d53a7SEvalZero 
634*042d53a7SEvalZero     default:
635*042d53a7SEvalZero         assert(0);
636*042d53a7SEvalZero         rc = BLE_HS_EUNKNOWN;
637*042d53a7SEvalZero         break;
638*042d53a7SEvalZero     }
639*042d53a7SEvalZero     ble_hs_unlock();
640*042d53a7SEvalZero 
641*042d53a7SEvalZero     if (rc != 0) {
642*042d53a7SEvalZero         return rc;
643*042d53a7SEvalZero     }
644*042d53a7SEvalZero 
645*042d53a7SEvalZero     ble_hs_parent_task = ble_npl_get_current_task_id();
646*042d53a7SEvalZero 
647*042d53a7SEvalZero     /* Stop the timer just in case the host was already running (e.g., unit
648*042d53a7SEvalZero      * tests).
649*042d53a7SEvalZero      */
650*042d53a7SEvalZero     ble_npl_callout_stop(&ble_hs_timer);
651*042d53a7SEvalZero 
652*042d53a7SEvalZero     ble_npl_callout_init(&ble_hs_timer, ble_hs_evq, ble_hs_timer_exp, NULL);
653*042d53a7SEvalZero 
654*042d53a7SEvalZero     rc = ble_gatts_start();
655*042d53a7SEvalZero     if (rc != 0) {
656*042d53a7SEvalZero         return rc;
657*042d53a7SEvalZero     }
658*042d53a7SEvalZero 
659*042d53a7SEvalZero     ble_hs_sync();
660*042d53a7SEvalZero 
661*042d53a7SEvalZero     return 0;
662*042d53a7SEvalZero }
663*042d53a7SEvalZero 
664*042d53a7SEvalZero /**
665*042d53a7SEvalZero  * Called when a data packet is received from the controller.  This function
666*042d53a7SEvalZero  * consumes the supplied mbuf, regardless of the outcome.
667*042d53a7SEvalZero  *
668*042d53a7SEvalZero  * @param om                    The incoming data packet, beginning with the
669*042d53a7SEvalZero  *                                  HCI ACL data header.
670*042d53a7SEvalZero  *
671*042d53a7SEvalZero  * @return                      0 on success; nonzero on failure.
672*042d53a7SEvalZero  */
673*042d53a7SEvalZero static int
ble_hs_rx_data(struct os_mbuf * om,void * arg)674*042d53a7SEvalZero ble_hs_rx_data(struct os_mbuf *om, void *arg)
675*042d53a7SEvalZero {
676*042d53a7SEvalZero     int rc;
677*042d53a7SEvalZero 
678*042d53a7SEvalZero     /* If flow control is enabled, mark this packet with its corresponding
679*042d53a7SEvalZero      * connection handle.
680*042d53a7SEvalZero      */
681*042d53a7SEvalZero     ble_hs_flow_fill_acl_usrhdr(om);
682*042d53a7SEvalZero 
683*042d53a7SEvalZero     rc = ble_mqueue_put(&ble_hs_rx_q, ble_hs_evq, om);
684*042d53a7SEvalZero     if (rc != 0) {
685*042d53a7SEvalZero         os_mbuf_free_chain(om);
686*042d53a7SEvalZero         return BLE_HS_EOS;
687*042d53a7SEvalZero     }
688*042d53a7SEvalZero 
689*042d53a7SEvalZero     return 0;
690*042d53a7SEvalZero }
691*042d53a7SEvalZero 
692*042d53a7SEvalZero /**
693*042d53a7SEvalZero  * Enqueues an ACL data packet for transmission.  This function consumes the
694*042d53a7SEvalZero  * supplied mbuf, regardless of the outcome.
695*042d53a7SEvalZero  *
696*042d53a7SEvalZero  * @param om                    The outgoing data packet, beginning with the
697*042d53a7SEvalZero  *                                  HCI ACL data header.
698*042d53a7SEvalZero  *
699*042d53a7SEvalZero  * @return                      0 on success; nonzero on failure.
700*042d53a7SEvalZero  */
701*042d53a7SEvalZero int
ble_hs_tx_data(struct os_mbuf * om)702*042d53a7SEvalZero ble_hs_tx_data(struct os_mbuf *om)
703*042d53a7SEvalZero {
704*042d53a7SEvalZero #if BLE_MONITOR
705*042d53a7SEvalZero     ble_monitor_send_om(BLE_MONITOR_OPCODE_ACL_TX_PKT, om);
706*042d53a7SEvalZero #endif
707*042d53a7SEvalZero 
708*042d53a7SEvalZero     ble_hci_trans_hs_acl_tx(om);
709*042d53a7SEvalZero     return 0;
710*042d53a7SEvalZero }
711*042d53a7SEvalZero 
712*042d53a7SEvalZero void
ble_hs_init(void)713*042d53a7SEvalZero ble_hs_init(void)
714*042d53a7SEvalZero {
715*042d53a7SEvalZero     int rc;
716*042d53a7SEvalZero 
717*042d53a7SEvalZero     /* Ensure this function only gets called by sysinit. */
718*042d53a7SEvalZero     SYSINIT_ASSERT_ACTIVE();
719*042d53a7SEvalZero 
720*042d53a7SEvalZero     /* Create memory pool of OS events */
721*042d53a7SEvalZero     rc = os_mempool_init(&ble_hs_hci_ev_pool, BLE_HS_HCI_EVT_COUNT,
722*042d53a7SEvalZero                          sizeof (struct ble_npl_event), ble_hs_hci_os_event_buf,
723*042d53a7SEvalZero                          "ble_hs_hci_ev_pool");
724*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
725*042d53a7SEvalZero 
726*042d53a7SEvalZero     /* These get initialized here to allow unit tests to run without a zeroed
727*042d53a7SEvalZero      * bss.
728*042d53a7SEvalZero      */
729*042d53a7SEvalZero     ble_hs_reset_reason = 0;
730*042d53a7SEvalZero     ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF;
731*042d53a7SEvalZero 
732*042d53a7SEvalZero     ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify,
733*042d53a7SEvalZero                        NULL);
734*042d53a7SEvalZero     ble_npl_event_init(&ble_hs_ev_reset, ble_hs_event_reset, NULL);
735*042d53a7SEvalZero     ble_npl_event_init(&ble_hs_ev_start_stage1, ble_hs_event_start_stage1,
736*042d53a7SEvalZero                        NULL);
737*042d53a7SEvalZero     ble_npl_event_init(&ble_hs_ev_start_stage2, ble_hs_event_start_stage2,
738*042d53a7SEvalZero                        NULL);
739*042d53a7SEvalZero 
740*042d53a7SEvalZero     ble_hs_hci_init();
741*042d53a7SEvalZero 
742*042d53a7SEvalZero     rc = ble_hs_conn_init();
743*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
744*042d53a7SEvalZero 
745*042d53a7SEvalZero     rc = ble_l2cap_init();
746*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
747*042d53a7SEvalZero 
748*042d53a7SEvalZero     rc = ble_att_init();
749*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
750*042d53a7SEvalZero 
751*042d53a7SEvalZero     rc = ble_att_svr_init();
752*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
753*042d53a7SEvalZero 
754*042d53a7SEvalZero     rc = ble_gap_init();
755*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
756*042d53a7SEvalZero 
757*042d53a7SEvalZero     rc = ble_gattc_init();
758*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
759*042d53a7SEvalZero 
760*042d53a7SEvalZero     rc = ble_gatts_init();
761*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
762*042d53a7SEvalZero 
763*042d53a7SEvalZero     ble_hs_stop_init();
764*042d53a7SEvalZero 
765*042d53a7SEvalZero     ble_mqueue_init(&ble_hs_rx_q, ble_hs_event_rx_data, NULL);
766*042d53a7SEvalZero 
767*042d53a7SEvalZero     rc = stats_init_and_reg(
768*042d53a7SEvalZero         STATS_HDR(ble_hs_stats), STATS_SIZE_INIT_PARMS(ble_hs_stats,
769*042d53a7SEvalZero         STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_hs_stats), "ble_hs");
770*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
771*042d53a7SEvalZero 
772*042d53a7SEvalZero     rc = ble_npl_mutex_init(&ble_hs_mutex);
773*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
774*042d53a7SEvalZero 
775*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
776*042d53a7SEvalZero     ble_hs_dbg_mutex_locked = 0;
777*042d53a7SEvalZero #endif
778*042d53a7SEvalZero 
779*042d53a7SEvalZero     /* Configure the HCI transport to communicate with a host. */
780*042d53a7SEvalZero     ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
781*042d53a7SEvalZero 
782*042d53a7SEvalZero #ifdef MYNEWT
783*042d53a7SEvalZero     ble_hs_evq_set((struct ble_npl_eventq *)os_eventq_dflt_get());
784*042d53a7SEvalZero #else
785*042d53a7SEvalZero     ble_hs_evq_set(nimble_port_get_dflt_eventq());
786*042d53a7SEvalZero #endif
787*042d53a7SEvalZero 
788*042d53a7SEvalZero #if BLE_MONITOR
789*042d53a7SEvalZero     rc = ble_monitor_init();
790*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
791*042d53a7SEvalZero #endif
792*042d53a7SEvalZero 
793*042d53a7SEvalZero     /* Enqueue the start event to the default event queue.  Using the default
794*042d53a7SEvalZero      * queue ensures the event won't run until the end of main().  This allows
795*042d53a7SEvalZero      * the application to configure this package in the meantime.
796*042d53a7SEvalZero      */
797*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_AUTO_START)
798*042d53a7SEvalZero #ifdef MYNEWT
799*042d53a7SEvalZero     ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(),
800*042d53a7SEvalZero                        &ble_hs_ev_start_stage1);
801*042d53a7SEvalZero #else
802*042d53a7SEvalZero     ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start_stage1);
803*042d53a7SEvalZero #endif
804*042d53a7SEvalZero #endif
805*042d53a7SEvalZero 
806*042d53a7SEvalZero #if BLE_MONITOR
807*042d53a7SEvalZero     ble_monitor_new_index(0, (uint8_t[6]){ }, "nimble0");
808*042d53a7SEvalZero #endif
809*042d53a7SEvalZero }
810