esp_radio/ble/
npl.rs

1use alloc::boxed::Box;
2use core::{
3    mem::transmute,
4    ptr::{addr_of, addr_of_mut},
5};
6
7use esp_hal::time::Instant;
8use esp_phy::{PhyController, PhyInitGuard};
9
10use super::*;
11use crate::{
12    binary::{c_types::*, include::*},
13    compat::{self, OSI_FUNCS_TIME_BLOCKING, common::str_from_c, queue},
14    time::{blob_ticks_to_micros, blob_ticks_to_millis, millis_to_blob_ticks},
15};
16
17#[cfg_attr(esp32c2, path = "os_adapter_esp32c2.rs")]
18#[cfg_attr(esp32c6, path = "os_adapter_esp32c6.rs")]
19#[cfg_attr(esp32h2, path = "os_adapter_esp32h2.rs")]
20pub(crate) mod ble_os_adapter_chip_specific;
21
22const EVENT_QUEUE_SIZE: usize = 16;
23
24const TIME_FOREVER: u32 = crate::compat::OSI_FUNCS_TIME_BLOCKING;
25
26#[cfg(esp32c2)]
27const OS_MSYS_1_BLOCK_COUNT: i32 = 24;
28#[cfg(esp32c2)]
29const SYSINIT_MSYS_1_MEMPOOL_SIZE: usize = 768;
30#[cfg(esp32c2)]
31const SYSINIT_MSYS_1_MEMBLOCK_SIZE: i32 = 128;
32#[cfg(esp32c2)]
33const OS_MSYS_2_BLOCK_COUNT: i32 = 24;
34#[cfg(esp32c2)]
35const SYSINIT_MSYS_2_MEMPOOL_SIZE: usize = 1920;
36#[cfg(esp32c2)]
37const SYSINIT_MSYS_2_MEMBLOCK_SIZE: i32 = 320;
38
39const BLE_HCI_TRANS_BUF_CMD: i32 = 3;
40
41// ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data
42const ACL_DATA_MBUF_LEADINGSPACE: usize = 4;
43
44#[repr(C)]
45#[derive(Copy, Clone)]
46struct Callout {
47    eventq: *const ble_npl_eventq,
48    timer_handle: ets_timer,
49    events: ble_npl_event,
50}
51
52#[repr(C)]
53#[derive(Copy, Clone)]
54struct Event {
55    event_fn_ptr: *const ble_npl_event_fn,
56    ev_arg_ptr: *const c_void,
57    queued: bool,
58}
59
60#[cfg(esp32c2)]
61type OsMembufT = u32;
62
63/// Memory pool
64#[repr(C)]
65pub(crate) struct OsMempool {
66    /// Size of the memory blocks, in bytes.
67    mp_block_size: u32,
68    /// The number of memory blocks.
69    mp_num_blocks: u16,
70    /// The number of free blocks left
71    mp_num_free: u16,
72    /// The lowest number of free blocks seen
73    mp_min_free: u16,
74    /// Bitmap of OS_MEMPOOL_F_[...] values.
75    mp_flags: u8,
76    /// Address of memory buffer used by pool
77    mp_membuf_addr: u32,
78
79    // STAILQ_ENTRY(os_mempool) mp_list;
80    next: *const OsMempool,
81
82    // SLIST_HEAD(,os_memblock);
83    first: *const c_void,
84
85    /// Name for memory block
86    name: *const u8,
87}
88
89#[cfg(esp32c2)]
90impl OsMempool {
91    const fn zeroed() -> Self {
92        Self {
93            mp_block_size: 0,
94            mp_num_blocks: 0,
95            mp_num_free: 0,
96            mp_min_free: 0,
97            mp_flags: 0,
98            mp_membuf_addr: 0,
99            next: core::ptr::null(),
100            first: core::ptr::null(),
101            name: core::ptr::null(),
102        }
103    }
104}
105
106/// A mbuf pool from which to allocate mbufs. This contains a pointer to the os
107/// mempool to allocate mbufs out of, the total number of elements in the pool,
108/// and the amount of "user" data in a non-packet header mbuf. The total pool
109/// size, in bytes, should be:
110///  os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
111#[repr(C)]
112pub(crate) struct OsMbufPool {
113    /// Total length of the databuf in each mbuf.  This is the size of the
114    /// mempool block, minus the mbuf header
115    omp_databuf_len: u16,
116    /// The memory pool which to allocate mbufs out of
117    omp_pool: *const OsMempool,
118
119    // STAILQ_ENTRY(os_mbuf_pool) omp_next;
120    next: *const OsMbufPool,
121}
122
123#[cfg(esp32c2)]
124impl OsMbufPool {
125    const fn zeroed() -> Self {
126        Self {
127            omp_databuf_len: 0,
128            omp_pool: core::ptr::null(),
129            next: core::ptr::null(),
130        }
131    }
132}
133
134/// Chained memory buffer.
135#[repr(C)]
136pub(crate) struct OsMbuf {
137    /// Current pointer to data in the structure
138    om_data: *const u8,
139    /// Flags associated with this buffer, see OS_MBUF_F_* defintions
140    om_flags: u8,
141    /// Length of packet header
142    om_pkthdr_len: u8,
143    /// Length of data in this buffer
144    om_len: u16,
145
146    /// The mbuf pool this mbuf was allocated out of
147    om_omp: *const OsMbufPool,
148
149    // SLIST_ENTRY(os_mbuf) om_next;
150    next: *const OsMbuf,
151
152    /// Pointer to the beginning of the data, after this buffer
153    om_databuf: u32,
154}
155
156#[cfg(esp32c2)]
157pub(crate) static mut OS_MSYS_INIT_1_DATA: *mut OsMembufT = core::ptr::null_mut();
158#[cfg(esp32c2)]
159pub(crate) static mut OS_MSYS_INIT_1_MBUF_POOL: OsMbufPool = OsMbufPool::zeroed();
160#[cfg(esp32c2)]
161pub(crate) static mut OS_MSYS_INIT_1_MEMPOOL: OsMempool = OsMempool::zeroed();
162
163#[cfg(esp32c2)]
164pub(crate) static mut OS_MSYS_INIT_2_DATA: *mut OsMembufT = core::ptr::null_mut();
165#[cfg(esp32c2)]
166pub(crate) static mut OS_MSYS_INIT_2_MBUF_POOL: OsMbufPool = OsMbufPool::zeroed();
167#[cfg(esp32c2)]
168pub(crate) static mut OS_MSYS_INIT_2_MEMPOOL: OsMempool = OsMempool::zeroed();
169
170unsafe extern "C" {
171    // Sends ACL data from host to controller.
172    //
173    // om                    The ACL data packet to send.
174    //
175    // 0 on success;
176    // A BLE_ERR_[...] error code on failure.
177    pub(crate) fn r_ble_hci_trans_hs_acl_tx(om: *const OsMbuf) -> i32;
178
179    // Sends an HCI command from the host to the controller.
180    //
181    // cmd                   The HCI command to send.  This buffer must be
182    //                                  allocated via ble_hci_trans_buf_alloc().
183    //
184    // 0 on success;
185    // A BLE_ERR_[...] error code on failure.
186    pub(crate) fn r_ble_hci_trans_hs_cmd_tx(cmd: *const u8) -> i32;
187
188    #[cfg(esp32c2)]
189    pub(crate) fn ble_controller_init(cfg: *const esp_bt_controller_config_t) -> i32;
190
191    #[cfg(not(esp32c2))]
192    pub(crate) fn r_ble_controller_disable() -> i32;
193
194    #[cfg(not(esp32c2))]
195    pub(crate) fn r_ble_controller_deinit() -> i32;
196
197    #[cfg(esp32c2)]
198    pub(crate) fn ble_controller_deinit() -> i32;
199
200    #[cfg(not(esp32c2))]
201    pub(crate) fn r_ble_controller_init(cfg: *const esp_bt_controller_config_t) -> i32;
202
203    #[cfg(esp32c2)]
204    pub(crate) fn ble_controller_enable(mode: u8) -> i32;
205
206    #[cfg(not(esp32c2))]
207    pub(crate) fn r_ble_controller_enable(mode: u8) -> i32;
208
209    pub(crate) fn esp_unregister_ext_funcs();
210
211    pub(crate) fn esp_register_ext_funcs(funcs: *const ExtFuncsT) -> i32;
212
213    pub(crate) fn esp_register_npl_funcs(funcs: *const npl_funcs_t) -> i32;
214
215    pub(crate) fn esp_unregister_npl_funcs();
216
217    #[cfg(esp32c2)]
218    pub(crate) fn ble_get_npl_element_info(
219        cfg: *const esp_bt_controller_config_t,
220        npl_info: *const BleNplCountInfoT,
221    ) -> i32;
222
223    #[cfg(not(esp32c2))]
224    pub(crate) fn r_ble_get_npl_element_info(
225        cfg: *const esp_bt_controller_config_t,
226        npl_info: *const BleNplCountInfoT,
227    ) -> i32;
228
229    pub(crate) fn bt_bb_v2_init_cmplx(value: u8);
230
231    pub(crate) fn r_ble_hci_trans_cfg_hs(
232        // ble_hci_trans_rx_cmd_fn
233        evt: Option<unsafe extern "C" fn(cmd: *const u8, arg: *const c_void) -> i32>,
234        evt_arg: *const c_void,
235        // ble_hci_trans_rx_acl_fn
236        acl_cb: Option<unsafe extern "C" fn(om: *const OsMbuf, arg: *const c_void) -> i32>,
237        acl_arg: *const c_void,
238    );
239
240    #[cfg(esp32c2)]
241    pub(crate) fn esp_ble_ll_set_public_addr(addr: *const u8);
242
243    #[cfg(not(esp32c2))]
244    pub(crate) fn r_esp_ble_ll_set_public_addr(addr: *const u8);
245
246    #[cfg(esp32c2)]
247    pub(crate) fn r_mem_init_mbuf_pool(
248        mem: *const c_void,
249        mempool: *const OsMempool,
250        mbuf_pool: *const OsMbufPool,
251        num_blocks: i32,
252        block_size: i32,
253        name: *const u8,
254    ) -> i32;
255
256    #[cfg(esp32c2)]
257    pub(crate) fn r_os_msys_reset();
258
259    #[cfg(esp32c2)]
260    pub(crate) fn r_os_msys_register(mbuf_pool: *const OsMbufPool) -> i32;
261
262    #[allow(unused)]
263    pub(crate) fn ble_osi_coex_funcs_register(coex_funcs: *const OsiCoexFuncsT) -> i32;
264
265    pub(crate) fn r_os_msys_get_pkthdr(dsize: u16, user_hdr_len: u16) -> *mut OsMbuf;
266
267    pub(crate) fn r_os_mbuf_append(om: *mut OsMbuf, src: *const u8, len: u16) -> i32;
268
269    pub(crate) fn r_os_mbuf_free_chain(om: *mut OsMbuf) -> i32;
270
271    pub(crate) fn r_ble_hci_trans_buf_alloc(typ: i32) -> *const u8;
272
273    pub(crate) fn r_ble_hci_trans_buf_free(buf: *const u8);
274
275    pub(crate) fn coex_pti_v2();
276}
277
278#[repr(C)]
279/// Contains pointers to external functions used by the BLE stack.
280pub(crate) struct ExtFuncsT {
281    ext_version: u32,
282    esp_intr_alloc: Option<
283        unsafe extern "C" fn(
284            source: u32,
285            flags: u32,
286            handler: *mut c_void,
287            arg: *mut c_void,
288            ret_handle: *mut *mut c_void,
289        ) -> i32,
290    >,
291    esp_intr_free: Option<unsafe extern "C" fn(ret_handle: *mut *mut c_void) -> i32>,
292    malloc: Option<unsafe extern "C" fn(size: u32) -> *mut c_void>,
293    free: Option<unsafe extern "C" fn(*mut c_void)>,
294    #[cfg(esp32c2)]
295    hal_uart_start_tx: Option<unsafe extern "C" fn(i32)>,
296    #[cfg(esp32c2)]
297    hal_uart_init_cbs: Option<
298        unsafe extern "C" fn(i32, *const c_void, *const c_void, *const c_void, c_void) -> i32,
299    >,
300    #[cfg(esp32c2)]
301    hal_uart_config: Option<unsafe extern "C" fn(i32, i32, u8, u8, u8, u8) -> i32>,
302    #[cfg(esp32c2)]
303    hal_uart_close: Option<unsafe extern "C" fn(i32) -> i32>,
304    #[cfg(esp32c2)]
305    hal_uart_blocking_tx: Option<unsafe extern "C" fn(i32, u8)>,
306    #[cfg(esp32c2)]
307    hal_uart_init: Option<unsafe extern "C" fn(i32, *const c_void) -> i32>,
308    task_create: Option<
309        unsafe extern "C" fn(
310            *mut c_void,
311            *const c_char,
312            u32,
313            *mut c_void,
314            u32,
315            *const c_void,
316            u32,
317        ) -> i32,
318    >,
319    task_delete: Option<unsafe extern "C" fn(*mut c_void)>,
320    osi_assert: Option<unsafe extern "C" fn(u32, *const c_void, u32, u32)>,
321    os_random: Option<unsafe extern "C" fn() -> u32>,
322    ecc_gen_key_pair: Option<unsafe extern "C" fn(*const u8, *const u8) -> i32>,
323    ecc_gen_dh_key: Option<unsafe extern "C" fn(*const u8, *const u8, *const u8, *const u8) -> i32>,
324    #[cfg(not(esp32h2))]
325    esp_reset_rpa_moudle: Option<unsafe extern "C" fn()>,
326    #[cfg(esp32c2)]
327    esp_bt_track_pll_cap: Option<unsafe extern "C" fn()>,
328    magic: u32,
329}
330
331static G_OSI_FUNCS: ExtFuncsT = ExtFuncsT {
332    #[cfg(not(esp32c2))]
333    ext_version: 0x20250415,
334    #[cfg(esp32c2)]
335    ext_version: 0x20221122,
336
337    esp_intr_alloc: Some(self::ble_os_adapter_chip_specific::esp_intr_alloc),
338    esp_intr_free: Some(esp_intr_free),
339    malloc: Some(crate::ble::malloc),
340    free: Some(crate::ble::free),
341    #[cfg(esp32c2)]
342    hal_uart_start_tx: None,
343    #[cfg(esp32c2)]
344    hal_uart_init_cbs: None,
345    #[cfg(esp32c2)]
346    hal_uart_config: None,
347    #[cfg(esp32c2)]
348    hal_uart_close: None,
349    #[cfg(esp32c2)]
350    hal_uart_blocking_tx: None,
351    #[cfg(esp32c2)]
352    hal_uart_init: None,
353    task_create: Some(task_create),
354    task_delete: Some(task_delete),
355    osi_assert: Some(osi_assert),
356    os_random: Some(os_random),
357    ecc_gen_key_pair: Some(ecc_gen_key_pair),
358    ecc_gen_dh_key: Some(ecc_gen_dh_key),
359    #[cfg(not(esp32h2))]
360    esp_reset_rpa_moudle: Some(self::ble_os_adapter_chip_specific::esp_reset_rpa_moudle),
361    #[cfg(esp32c2)]
362    esp_bt_track_pll_cap: None,
363    magic: 0xA5A5A5A5,
364};
365
366unsafe extern "C" fn ecc_gen_dh_key(_: *const u8, _: *const u8, _: *const u8, _: *const u8) -> i32 {
367    todo!()
368}
369
370unsafe extern "C" fn ecc_gen_key_pair(_: *const u8, _: *const u8) -> i32 {
371    todo!()
372}
373
374unsafe extern "C" fn os_random() -> u32 {
375    trace!("os_random");
376    unsafe { (crate::common_adapter::random() & u32::MAX) as u32 }
377}
378
379unsafe extern "C" fn task_create(
380    task_func: *mut c_void,
381    name: *const c_char,
382    stack_depth: u32,
383    param: *mut c_void,
384    prio: u32,
385    task_handle: *const c_void,
386    core_id: u32,
387) -> i32 {
388    let name_str = unsafe { str_from_c(name) };
389    trace!(
390        "task_create {:?} {} {} {:?} {} {:?} {}",
391        task_func, name_str, stack_depth, param, prio, task_handle, core_id,
392    );
393
394    unsafe {
395        *(task_handle as *mut usize) = 0;
396    } // we will run it in task 0
397
398    unsafe {
399        let task_func = transmute::<*mut c_void, extern "C" fn(*mut c_void)>(task_func);
400
401        let task = crate::preempt::task_create(
402            name_str,
403            task_func,
404            param,
405            prio,
406            if core_id < 2 { Some(core_id) } else { None },
407            stack_depth as usize,
408        );
409        *(task_handle as *mut usize) = task as usize;
410    }
411
412    1
413}
414
415unsafe extern "C" fn task_delete(task: *mut c_void) {
416    trace!("task delete called for {:?}", task);
417
418    unsafe {
419        crate::preempt::schedule_task_deletion(task);
420    }
421}
422
423unsafe extern "C" fn osi_assert(ln: u32, fn_name: *const c_void, param1: u32, param2: u32) {
424    unsafe {
425        let name_str = str_from_c(fn_name as _);
426        panic!("ASSERT {}:{} {} {}", name_str, ln, param1, param2);
427    }
428}
429
430unsafe extern "C" fn esp_intr_free(_ret_handle: *mut *mut c_void) -> i32 {
431    todo!();
432}
433
434#[repr(C)]
435#[allow(non_camel_case_types)]
436/// Contains pointers to functions used by the BLE NPL (Non-Preemptive Layer).
437pub(crate) struct npl_funcs_t {
438    p_ble_npl_os_started: Option<unsafe extern "C" fn() -> bool>,
439    p_ble_npl_get_current_task_id: Option<unsafe extern "C" fn() -> *const c_void>,
440    p_ble_npl_eventq_init: Option<unsafe extern "C" fn(queue: *mut ble_npl_eventq)>,
441    p_ble_npl_eventq_deinit: Option<unsafe extern "C" fn(queue: *mut ble_npl_eventq)>,
442    p_ble_npl_eventq_get: Option<
443        unsafe extern "C" fn(
444            queue: *mut ble_npl_eventq,
445            time: ble_npl_time_t,
446        ) -> *const ble_npl_event,
447    >,
448    p_ble_npl_eventq_put:
449        Option<unsafe extern "C" fn(queue: *mut ble_npl_eventq, event: *const ble_npl_event)>,
450    p_ble_npl_eventq_remove:
451        Option<unsafe extern "C" fn(queue: *mut ble_npl_eventq, event: *const ble_npl_event)>,
452    p_ble_npl_event_run: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
453    p_ble_npl_eventq_is_empty: Option<unsafe extern "C" fn(queue: *mut ble_npl_eventq) -> bool>,
454    p_ble_npl_event_init: Option<
455        unsafe extern "C" fn(
456            event: *const ble_npl_event,
457            func: *const ble_npl_event_fn,
458            *const c_void,
459        ),
460    >,
461    p_ble_npl_event_deinit: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
462    p_ble_npl_event_reset: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
463    p_ble_npl_event_is_queued: Option<unsafe extern "C" fn(event: *const ble_npl_event) -> bool>,
464    p_ble_npl_event_get_arg:
465        Option<unsafe extern "C" fn(event: *const ble_npl_event) -> *const c_void>,
466    p_ble_npl_event_set_arg:
467        Option<unsafe extern "C" fn(event: *const ble_npl_event, arg: *const c_void)>,
468    p_ble_npl_mutex_init:
469        Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
470    p_ble_npl_mutex_deinit:
471        Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
472    p_ble_npl_mutex_pend: Option<
473        unsafe extern "C" fn(mutex: *const ble_npl_mutex, time: ble_npl_time_t) -> ble_npl_error_t,
474    >,
475    p_ble_npl_mutex_release:
476        Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
477    p_ble_npl_sem_init:
478        Option<unsafe extern "C" fn(sem: *const ble_npl_sem, val: u16) -> ble_npl_error_t>,
479    p_ble_npl_sem_deinit: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> ble_npl_error_t>,
480    p_ble_npl_sem_pend: Option<
481        unsafe extern "C" fn(sem: *const ble_npl_sem, time: ble_npl_time_t) -> ble_npl_error_t,
482    >,
483    p_ble_npl_sem_release: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> ble_npl_error_t>,
484    p_ble_npl_sem_get_count: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> u16>,
485    p_ble_npl_callout_init: Option<
486        unsafe extern "C" fn(
487            callout: *const ble_npl_callout,
488            eventq: *const ble_npl_eventq,
489            func: *const ble_npl_event_fn,
490            args: *const c_void,
491        ) -> i32,
492    >,
493    p_ble_npl_callout_reset: Option<
494        unsafe extern "C" fn(
495            callout: *const ble_npl_callout,
496            time: ble_npl_time_t,
497        ) -> ble_npl_error_t,
498    >,
499    p_ble_npl_callout_stop: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
500    p_ble_npl_callout_deinit: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
501    p_ble_npl_callout_mem_reset: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
502    p_ble_npl_callout_is_active:
503        Option<unsafe extern "C" fn(callout: *const ble_npl_callout) -> bool>,
504    p_ble_npl_callout_get_ticks:
505        Option<unsafe extern "C" fn(callout: *const ble_npl_callout) -> ble_npl_time_t>,
506    p_ble_npl_callout_remaining_ticks:
507        Option<unsafe extern "C" fn(callout: *const ble_npl_callout, time: ble_npl_time_t) -> u32>,
508    p_ble_npl_callout_set_arg:
509        Option<unsafe extern "C" fn(callout: *const ble_npl_callout, arg: *const c_void)>,
510    p_ble_npl_time_get: Option<unsafe extern "C" fn() -> u32>,
511    p_ble_npl_time_ms_to_ticks:
512        Option<unsafe extern "C" fn(ms: u32, p_time: *mut ble_npl_time_t) -> ble_npl_error_t>,
513    p_ble_npl_time_ticks_to_ms:
514        Option<unsafe extern "C" fn(time: ble_npl_time_t, *mut u32) -> ble_npl_error_t>,
515    p_ble_npl_time_ms_to_ticks32: Option<unsafe extern "C" fn(ms: u32) -> ble_npl_time_t>,
516    p_ble_npl_time_ticks_to_ms32: Option<unsafe extern "C" fn(time: ble_npl_time_t) -> u32>,
517    p_ble_npl_time_delay: Option<unsafe extern "C" fn(time: ble_npl_time_t)>,
518    p_ble_npl_hw_set_isr: Option<unsafe extern "C" fn(no: i32, mask: u32)>,
519    p_ble_npl_hw_enter_critical: Option<unsafe extern "C" fn() -> u32>,
520    p_ble_npl_hw_exit_critical: Option<unsafe extern "C" fn(mask: u32)>,
521    p_ble_npl_get_time_forever: Option<unsafe extern "C" fn() -> u32>,
522    p_ble_npl_hw_is_in_critical: Option<unsafe extern "C" fn() -> u8>,
523}
524
525static mut G_NPL_FUNCS: npl_funcs_t = npl_funcs_t {
526    p_ble_npl_os_started: Some(ble_npl_os_started),
527    p_ble_npl_get_current_task_id: Some(ble_npl_get_current_task_id),
528    p_ble_npl_eventq_init: Some(ble_npl_eventq_init),
529    p_ble_npl_eventq_deinit: Some(ble_npl_eventq_deinit),
530    p_ble_npl_eventq_get: Some(ble_npl_eventq_get),
531    p_ble_npl_eventq_put: Some(ble_npl_eventq_put),
532    p_ble_npl_eventq_remove: Some(ble_npl_eventq_remove),
533    p_ble_npl_event_run: Some(ble_npl_event_run),
534    p_ble_npl_eventq_is_empty: Some(ble_npl_eventq_is_empty),
535    p_ble_npl_event_init: Some(ble_npl_event_init),
536    p_ble_npl_event_deinit: Some(ble_npl_event_deinit),
537    p_ble_npl_event_reset: Some(ble_npl_event_reset),
538    p_ble_npl_event_is_queued: Some(ble_npl_event_is_queued),
539    p_ble_npl_event_get_arg: Some(ble_npl_event_get_arg),
540    p_ble_npl_event_set_arg: Some(ble_npl_event_set_arg),
541    p_ble_npl_mutex_init: Some(ble_npl_mutex_init),
542    p_ble_npl_mutex_deinit: Some(ble_npl_mutex_deinit),
543    p_ble_npl_mutex_pend: Some(ble_npl_mutex_pend),
544    p_ble_npl_mutex_release: Some(ble_npl_mutex_release),
545    p_ble_npl_sem_init: Some(ble_npl_sem_init),
546    p_ble_npl_sem_deinit: Some(ble_npl_sem_deinit),
547    p_ble_npl_sem_pend: Some(ble_npl_sem_pend),
548    p_ble_npl_sem_release: Some(ble_npl_sem_release),
549    p_ble_npl_sem_get_count: Some(ble_npl_sem_get_count),
550    p_ble_npl_callout_init: Some(ble_npl_callout_init),
551    p_ble_npl_callout_reset: Some(ble_npl_callout_reset),
552    p_ble_npl_callout_stop: Some(ble_npl_callout_stop),
553    p_ble_npl_callout_deinit: Some(ble_npl_callout_deinit),
554    p_ble_npl_callout_mem_reset: Some(ble_npl_callout_mem_reset),
555    p_ble_npl_callout_is_active: Some(ble_npl_callout_is_active),
556    p_ble_npl_callout_get_ticks: Some(ble_npl_callout_get_ticks),
557    p_ble_npl_callout_remaining_ticks: Some(ble_npl_callout_remaining_ticks),
558    p_ble_npl_callout_set_arg: Some(ble_npl_callout_set_arg),
559    p_ble_npl_time_get: Some(ble_npl_time_get),
560    p_ble_npl_time_ms_to_ticks: Some(ble_npl_time_ms_to_ticks),
561    p_ble_npl_time_ticks_to_ms: Some(ble_npl_time_ticks_to_ms),
562    p_ble_npl_time_ms_to_ticks32: Some(ble_npl_time_ms_to_ticks32),
563    p_ble_npl_time_ticks_to_ms32: Some(ble_npl_time_ticks_to_ms32),
564    p_ble_npl_time_delay: Some(ble_npl_time_delay),
565    p_ble_npl_hw_set_isr: Some(ble_npl_hw_set_isr),
566    p_ble_npl_hw_enter_critical: Some(ble_npl_hw_enter_critical),
567    p_ble_npl_hw_exit_critical: Some(ble_npl_hw_exit_critical),
568    p_ble_npl_get_time_forever: Some(ble_npl_get_time_forever),
569    p_ble_npl_hw_is_in_critical: Some(ble_npl_hw_is_in_critical),
570};
571
572#[repr(C)]
573/// Contains pointers to functions used for BLE coexistence with Wi-Fi.
574pub(crate) struct OsiCoexFuncsT {
575    magic: u32,
576    version: u32,
577    coex_wifi_sleep_set: Option<unsafe extern "C" fn(sleep: bool)>,
578    coex_core_ble_conn_dyn_prio_get:
579        Option<unsafe extern "C" fn(low: *mut bool, high: *mut bool) -> i32>,
580    coex_schm_status_bit_set: Option<unsafe extern "C" fn(_type: u32, status: u32)>,
581    coex_schm_status_bit_clear: Option<unsafe extern "C" fn(_type: u32, status: u32)>,
582}
583
584#[allow(unused)]
585static G_COEX_FUNCS: OsiCoexFuncsT = OsiCoexFuncsT {
586    magic: 0xFADEBEAD,
587    version: 0x00010006,
588    coex_wifi_sleep_set: Some(coex_wifi_sleep_set),
589    coex_core_ble_conn_dyn_prio_get: Some(coex_core_ble_conn_dyn_prio_get),
590    coex_schm_status_bit_set: Some(coex_schm_status_bit_set),
591    coex_schm_status_bit_clear: Some(coex_schm_status_bit_clear),
592};
593
594#[allow(unused)]
595unsafe extern "C" fn coex_wifi_sleep_set(_sleep: bool) {
596    todo!()
597}
598
599#[allow(unused)]
600unsafe extern "C" fn coex_core_ble_conn_dyn_prio_get(_low: *mut bool, _high: *mut bool) -> i32 {
601    todo!()
602}
603
604#[allow(unused)]
605unsafe extern "C" fn coex_schm_status_bit_set(_type: u32, _status: u32) {
606    trace!("coex_schm_status_bit_set is an empty stub");
607}
608
609#[allow(unused)]
610unsafe extern "C" fn coex_schm_status_bit_clear(_type: u32, _status: u32) {
611    trace!("coex_schm_status_bit_clear is an empty stub");
612}
613
614unsafe extern "C" fn ble_npl_hw_is_in_critical() -> u8 {
615    todo!()
616}
617
618unsafe extern "C" fn ble_npl_get_time_forever() -> u32 {
619    trace!("ble_npl_get_time_forever");
620    TIME_FOREVER
621}
622
623unsafe extern "C" fn ble_npl_hw_exit_critical(mask: u32) {
624    trace!("ble_npl_hw_exit_critical {}", mask);
625    unsafe {
626        let token = esp_sync::RestoreState::new(mask);
627        crate::ESP_RADIO_LOCK.release(token);
628    }
629}
630
631unsafe extern "C" fn ble_npl_hw_enter_critical() -> u32 {
632    trace!("ble_npl_hw_enter_critical");
633    unsafe { crate::ESP_RADIO_LOCK.acquire().inner() }
634}
635
636unsafe extern "C" fn ble_npl_hw_set_isr(_no: i32, _mask: u32) {
637    todo!()
638}
639
640unsafe extern "C" fn ble_npl_time_delay(time: ble_npl_time_t) {
641    let time = blob_ticks_to_micros(time);
642    crate::preempt::usleep(time);
643}
644
645unsafe extern "C" fn ble_npl_time_ticks_to_ms32(time: ble_npl_time_t) -> u32 {
646    trace!("ble_npl_time_ticks_to_ms32 {}", time);
647    blob_ticks_to_millis(time)
648}
649
650unsafe extern "C" fn ble_npl_time_ms_to_ticks32(ms: u32) -> ble_npl_time_t {
651    trace!("ble_npl_time_ms_to_ticks32 {}", ms);
652    millis_to_blob_ticks(ms)
653}
654
655unsafe extern "C" fn ble_npl_time_ticks_to_ms(
656    time: ble_npl_time_t,
657    p_ms: *mut u32,
658) -> ble_npl_error_t {
659    trace!("ble_npl_time_ticks_to_ms {}", time);
660    unsafe { *p_ms = blob_ticks_to_millis(time) };
661    0
662}
663
664unsafe extern "C" fn ble_npl_time_ms_to_ticks(
665    ms: u32,
666    p_time: *mut ble_npl_time_t,
667) -> ble_npl_error_t {
668    trace!("ble_npl_time_ms_to_ticks {}", ms);
669    unsafe { *p_time = millis_to_blob_ticks(ms) };
670    0
671}
672
673unsafe extern "C" fn ble_npl_time_get() -> u32 {
674    trace!("ble_npl_time_get");
675    Instant::now().duration_since_epoch().as_millis() as u32
676}
677
678unsafe extern "C" fn ble_npl_callout_set_arg(
679    _callout: *const ble_npl_callout,
680    _arg: *const c_void,
681) {
682    todo!()
683}
684
685unsafe extern "C" fn ble_npl_callout_remaining_ticks(
686    _callout: *const ble_npl_callout,
687    _time: ble_npl_time_t,
688) -> u32 {
689    todo!()
690}
691
692unsafe extern "C" fn ble_npl_callout_get_ticks(_callout: *const ble_npl_callout) -> ble_npl_time_t {
693    todo!()
694}
695
696unsafe extern "C" fn ble_npl_callout_is_active(callout: *const ble_npl_callout) -> bool {
697    debug!(
698        "Missing real implementation: ble_npl_callout_is_active {:?}",
699        callout
700    );
701
702    assert!(unsafe { (*callout).dummy != 0 });
703
704    unsafe {
705        let co = (*callout).dummy as *mut Callout;
706        compat::timer_compat::compat_timer_is_active(&raw mut (*co).timer_handle)
707    }
708}
709
710unsafe extern "C" fn ble_npl_callout_mem_reset(callout: *const ble_npl_callout) {
711    trace!("ble_npl_callout_mem_reset");
712    unsafe {
713        ble_npl_callout_stop(callout);
714    }
715}
716
717unsafe extern "C" fn ble_npl_callout_deinit(callout: *const ble_npl_callout) {
718    trace!("ble_npl_callout_deinit");
719    unsafe {
720        ble_npl_callout_stop(callout);
721    }
722}
723
724unsafe extern "C" fn ble_npl_callout_stop(callout: *const ble_npl_callout) {
725    trace!("ble_npl_callout_stop {:?}", callout);
726
727    assert!(unsafe { (*callout).dummy != 0 });
728
729    unsafe {
730        let co = (*callout).dummy as *mut Callout;
731        // stop timer
732        compat::timer_compat::compat_timer_disarm(&raw mut (*co).timer_handle);
733    }
734}
735
736unsafe extern "C" fn ble_npl_callout_reset(
737    callout: *const ble_npl_callout,
738    time: ble_npl_time_t,
739) -> ble_npl_error_t {
740    trace!("ble_npl_callout_reset {:?} {}", callout, time);
741
742    let co = unsafe { (*callout).dummy } as *mut Callout;
743    unsafe {
744        // start timer
745        compat::timer_compat::compat_timer_arm(
746            &raw mut (*co).timer_handle,
747            blob_ticks_to_millis(time),
748            false,
749        );
750    }
751    0
752}
753
754unsafe extern "C" fn ble_npl_sem_get_count(_sem: *const ble_npl_sem) -> u16 {
755    todo!()
756}
757
758unsafe extern "C" fn ble_npl_sem_release(_sem: *const ble_npl_sem) -> ble_npl_error_t {
759    todo!()
760}
761
762unsafe extern "C" fn ble_npl_sem_pend(
763    _sem: *const ble_npl_sem,
764    _time: ble_npl_time_t,
765) -> ble_npl_error_t {
766    todo!()
767}
768
769unsafe extern "C" fn ble_npl_sem_deinit(_sem: *const ble_npl_sem) -> ble_npl_error_t {
770    todo!()
771}
772
773unsafe extern "C" fn ble_npl_sem_init(_sem: *const ble_npl_sem, _val: u16) -> ble_npl_error_t {
774    todo!()
775}
776
777unsafe extern "C" fn ble_npl_mutex_release(_mutex: *const ble_npl_mutex) -> ble_npl_error_t {
778    todo!()
779}
780
781unsafe extern "C" fn ble_npl_mutex_pend(
782    _mutex: *const ble_npl_mutex,
783    _time: ble_npl_time_t,
784) -> ble_npl_error_t {
785    todo!()
786}
787
788unsafe extern "C" fn ble_npl_mutex_deinit(_mutex: *const ble_npl_mutex) -> ble_npl_error_t {
789    todo!()
790}
791
792unsafe extern "C" fn ble_npl_event_set_arg(event: *const ble_npl_event, arg: *const c_void) {
793    trace!("ble_npl_event_set_arg {:?} {:?}", event, arg);
794
795    let evt = unsafe { (*event).dummy } as *mut Event;
796    assert!(!evt.is_null());
797
798    unsafe {
799        (*evt).ev_arg_ptr = arg;
800    }
801}
802
803unsafe extern "C" fn ble_npl_event_get_arg(event: *const ble_npl_event) -> *const c_void {
804    trace!("ble_npl_event_get_arg {:?}", event);
805
806    unsafe {
807        let evt = (*event).dummy as *mut Event;
808        assert!(!evt.is_null());
809
810        let arg_ptr = (*evt).ev_arg_ptr;
811
812        trace!("returning arg {:x}", arg_ptr as usize);
813
814        arg_ptr
815    }
816}
817
818unsafe extern "C" fn ble_npl_event_is_queued(event: *const ble_npl_event) -> bool {
819    trace!("ble_npl_event_is_queued {:?}", event);
820
821    let evt = unsafe { (*event).dummy } as *mut Event;
822    assert!(!evt.is_null());
823
824    unsafe { (*evt).queued }
825}
826
827unsafe extern "C" fn ble_npl_event_reset(event: *const ble_npl_event) {
828    trace!("ble_npl_event_reset {:?}", event);
829
830    let evt = unsafe { (*event).dummy } as *mut Event;
831    assert!(!evt.is_null());
832
833    unsafe { (*evt).queued = false }
834}
835
836unsafe extern "C" fn ble_npl_event_deinit(event: *const ble_npl_event) {
837    trace!("ble_npl_event_deinit {:?}", event);
838
839    let event = event as *mut ble_npl_event;
840    let evt = unsafe { (*event).dummy } as *mut Event;
841    assert!(!evt.is_null());
842
843    unsafe {
844        crate::compat::malloc::free(evt.cast());
845    }
846
847    unsafe {
848        (*event).dummy = 0;
849    }
850}
851
852unsafe extern "C" fn ble_npl_event_init(
853    event: *const ble_npl_event,
854    func: *const ble_npl_event_fn,
855    arg: *const c_void,
856) {
857    trace!("ble_npl_event_init {:?} {:?} {:?}", event, func, arg);
858
859    if unsafe { (*event).dummy } == 0 {
860        unsafe {
861            let evt = crate::compat::malloc::calloc(1, core::mem::size_of::<Event>()) as *mut Event;
862
863            (*evt).event_fn_ptr = func;
864            (*evt).ev_arg_ptr = arg;
865            (*evt).queued = false;
866
867            let event = event.cast_mut();
868            (*event).dummy = evt as i32;
869        }
870    }
871}
872
873unsafe extern "C" fn ble_npl_eventq_is_empty(queue: *mut ble_npl_eventq) -> bool {
874    trace!("ble_npl_eventq_is_empty {:?}", queue);
875    let wrapper = unwrap!(unsafe { queue.as_mut() }, "queue wrapper is null");
876
877    queue::queue_messages_waiting(wrapper.dummy as _) == 0
878}
879
880unsafe extern "C" fn ble_npl_event_run(event: *const ble_npl_event) {
881    trace!("ble_npl_event_run {:?}", event);
882
883    let evt = unsafe { (*event).dummy } as *mut Event;
884    assert!(!evt.is_null());
885
886    trace!(
887        "info {:?} with arg {:x}",
888        unsafe { (*evt).event_fn_ptr },
889        event as u32
890    );
891    unsafe {
892        let func: unsafe extern "C" fn(u32) = transmute((*evt).event_fn_ptr);
893        func(event as u32);
894    }
895
896    trace!("ble_npl_event_run done");
897}
898
899unsafe extern "C" fn ble_npl_eventq_remove(
900    queue: *mut ble_npl_eventq,
901    event: *const ble_npl_event,
902) {
903    trace!("ble_npl_eventq_remove {:?} {:?}", queue, event);
904
905    unsafe {
906        let evt = (*event).dummy as *mut Event;
907        assert!(!evt.is_null());
908
909        if !(*evt).queued {
910            return;
911        }
912
913        let wrapper = unwrap!(queue.as_mut(), "queue wrapper is null");
914        queue::queue_remove(wrapper.dummy as _, (&raw const event).cast());
915
916        (*evt).queued = false;
917    }
918}
919
920unsafe extern "C" fn ble_npl_eventq_put(queue: *mut ble_npl_eventq, event: *const ble_npl_event) {
921    trace!("ble_npl_eventq_put {:?} {:?}", queue, event);
922
923    let evt = unsafe { (*event).dummy } as *mut Event;
924    assert!(!evt.is_null());
925
926    if unsafe { (*evt).queued } {
927        trace!("Event already queued, skipping put");
928        return;
929    }
930
931    unsafe {
932        (*evt).queued = true;
933    }
934
935    let wrapper = unwrap!(unsafe { queue.as_mut() }, "queue wrapper is null");
936
937    // Store the pointer to the ble_npl_event in the queue - this is what we'll need to dequeue.
938    queue::queue_send_to_back(
939        wrapper.dummy as _,
940        (&raw const event).cast(),
941        OSI_FUNCS_TIME_BLOCKING,
942    );
943}
944
945unsafe extern "C" fn ble_npl_eventq_get(
946    queue: *mut ble_npl_eventq,
947    timeout: ble_npl_time_t,
948) -> *const ble_npl_event {
949    trace!("ble_npl_eventq_get {:?} {}", queue, timeout);
950
951    let mut evt = core::ptr::null_mut::<ble_npl_event>();
952    let wrapper = unwrap!(unsafe { queue.as_mut() }, "queue wrapper is null");
953
954    if queue::queue_receive(
955        wrapper.dummy as _,
956        (&raw mut evt).cast(),
957        blob_ticks_to_micros(timeout),
958    ) == 1
959    {
960        trace!("got {:x}", evt as usize);
961        unsafe {
962            let evt = (*evt).dummy as *mut Event;
963            (*evt).queued = false;
964        }
965    }
966
967    evt.cast_const()
968}
969
970unsafe extern "C" fn ble_npl_eventq_init(queue: *mut ble_npl_eventq) {
971    trace!("ble_npl_eventq_init {:?}", queue);
972
973    let queue_ptr = queue::queue_create(EVENT_QUEUE_SIZE as _, core::mem::size_of::<usize>() as _);
974
975    unsafe {
976        (*queue).dummy = queue_ptr as i32;
977    }
978}
979
980unsafe extern "C" fn ble_npl_eventq_deinit(queue: *mut ble_npl_eventq) {
981    trace!("ble_npl_eventq_deinit {:?}", queue);
982
983    let wrapper = unwrap!(unsafe { queue.as_mut() }, "queue wrapper is null");
984    queue::queue_delete(wrapper.dummy as _);
985    wrapper.dummy = 0;
986}
987
988unsafe extern "C" fn ble_npl_callout_init(
989    callout: *const ble_npl_callout,
990    eventq: *const ble_npl_eventq,
991    func: *const ble_npl_event_fn,
992    args: *const c_void,
993) -> i32 {
994    trace!(
995        "ble_npl_callout_init {:?} {:?} {:?} {:?}",
996        callout, eventq, func, args
997    );
998
999    if unsafe { (*callout).dummy } == 0 {
1000        let callout = callout.cast_mut();
1001
1002        unsafe {
1003            let new_callout =
1004                crate::compat::malloc::calloc(1, core::mem::size_of::<Callout>()) as *mut Callout;
1005            ble_npl_event_init(addr_of_mut!((*new_callout).events), func, args);
1006            (*callout).dummy = new_callout as i32;
1007
1008            crate::compat::timer_compat::compat_timer_setfn(
1009                addr_of_mut!((*new_callout).timer_handle),
1010                callout_timer_callback_wrapper,
1011                callout as *mut c_void,
1012            );
1013        }
1014    }
1015
1016    0
1017}
1018
1019unsafe extern "C" fn callout_timer_callback_wrapper(arg: *mut c_void) {
1020    trace!("callout_timer_callback_wrapper {:?}", arg);
1021    let co = unsafe { (*(arg as *mut ble_npl_callout)).dummy } as *mut Callout;
1022
1023    unsafe {
1024        if !(*co).eventq.is_null() {
1025            ble_npl_eventq_put((*co).eventq.cast_mut(), addr_of!((*co).events));
1026        } else {
1027            ble_npl_event_run(addr_of!((*co).events));
1028        }
1029    }
1030}
1031
1032unsafe extern "C" fn ble_npl_mutex_init(_mutex: *const ble_npl_mutex) -> u32 {
1033    todo!()
1034}
1035
1036unsafe extern "C" fn ble_npl_get_current_task_id() -> *const c_void {
1037    todo!()
1038}
1039
1040unsafe extern "C" fn ble_npl_os_started() -> bool {
1041    todo!();
1042}
1043
1044#[repr(C)]
1045/// Contains information about the BLE NPL (Non-Preemptive Layer) elements.
1046pub(crate) struct BleNplCountInfoT {
1047    evt_count: u16,
1048    evtq_count: u16,
1049    co_count: u16,
1050    sem_count: u16,
1051    mutex_count: u16,
1052}
1053
1054pub(crate) fn ble_init(config: &Config) -> PhyInitGuard<'static> {
1055    let phy_init_guard;
1056    unsafe {
1057        (*addr_of_mut!(HCI_OUT_COLLECTOR)).write(HciOutCollector::new());
1058
1059        // turn on logging
1060        #[allow(static_mut_refs)]
1061        #[cfg(all(feature = "sys-logs", esp32c2))]
1062        {
1063            extern "C" {
1064                static mut g_ble_plf_log_level: u32;
1065            }
1066
1067            debug!("g_ble_plf_log_level = {}", g_ble_plf_log_level);
1068            g_ble_plf_log_level = 10;
1069        }
1070
1071        self::ble_os_adapter_chip_specific::ble_rtc_clk_init();
1072
1073        let cfg = ble_os_adapter_chip_specific::create_ble_config(config);
1074
1075        let res = esp_register_ext_funcs(&G_OSI_FUNCS as *const ExtFuncsT);
1076        assert!(res == 0, "esp_register_ext_funcs returned {}", res);
1077
1078        #[cfg(esp32c2)]
1079        {
1080            debug!("Init esp_ble_rom_func_ptr_init_all");
1081            unsafe extern "C" {
1082                fn esp_ble_rom_func_ptr_init_all() -> i32;
1083            }
1084            let res = esp_ble_rom_func_ptr_init_all();
1085            assert!(res == 0, "esp_ble_rom_func_ptr_init_all returned {}", res);
1086        }
1087
1088        #[cfg(coex)]
1089        {
1090            let res = crate::wifi::coex_init();
1091            assert!(res == 0, "coex_init failed");
1092        }
1093
1094        ble_os_adapter_chip_specific::bt_periph_module_enable();
1095
1096        ble_os_adapter_chip_specific::disable_sleep_mode();
1097
1098        let res = esp_register_npl_funcs(core::ptr::addr_of!(G_NPL_FUNCS));
1099        assert!(res == 0, "esp_register_npl_funcs returned {}", res);
1100
1101        let npl_info = BleNplCountInfoT {
1102            evt_count: 0,
1103            evtq_count: 0,
1104            co_count: 0,
1105            sem_count: 0,
1106            mutex_count: 0,
1107        };
1108        #[cfg(esp32c2)]
1109        let res = ble_get_npl_element_info(
1110            &cfg as *const esp_bt_controller_config_t,
1111            &npl_info as *const BleNplCountInfoT,
1112        );
1113        #[cfg(not(esp32c2))]
1114        let res = r_ble_get_npl_element_info(
1115            &cfg as *const esp_bt_controller_config_t,
1116            &npl_info as *const BleNplCountInfoT,
1117        );
1118        assert!(res == 0, "ble_get_npl_element_info returned {}", res);
1119
1120        // not really using npl_info here ... remove it?
1121
1122        #[cfg(esp32c2)]
1123        {
1124            // Initialize the global memory pool
1125            let ret = os_msys_buf_alloc();
1126            assert!(ret, "os_msys_buf_alloc failed");
1127
1128            os_msys_init();
1129        }
1130
1131        phy_init_guard = esp_hal::peripherals::BT::steal().enable_phy();
1132
1133        // init bb
1134        bt_bb_v2_init_cmplx(1);
1135
1136        coex_pti_v2();
1137
1138        #[cfg(coex)]
1139        {
1140            let rc = ble_osi_coex_funcs_register(&G_COEX_FUNCS as *const OsiCoexFuncsT);
1141            assert!(rc == 0, "ble_osi_coex_funcs_register returned {}", rc);
1142        }
1143
1144        #[cfg(not(esp32c2))]
1145        {
1146            unsafe extern "C" {
1147                fn esp_ble_register_bb_funcs() -> i32;
1148            }
1149            let res = esp_ble_register_bb_funcs();
1150            assert!(res == 0, "esp_ble_register_bb_funcs returned {}", res);
1151        }
1152
1153        #[cfg(esp32c2)]
1154        let res = ble_controller_init(&cfg as *const esp_bt_controller_config_t);
1155        #[cfg(not(esp32c2))]
1156        let res = r_ble_controller_init(&cfg as *const esp_bt_controller_config_t);
1157
1158        assert!(res == 0, "ble_controller_init returned {}", res);
1159
1160        #[cfg(not(esp32c2))]
1161        {
1162            unsafe extern "C" {
1163                fn r_esp_ble_msys_init(
1164                    msys_size1: u16,
1165                    msys_size2: u16,
1166                    msys_cnt1: u16,
1167                    msys_cnt2: u16,
1168                    from_heap: u8,
1169                ) -> i32;
1170
1171                fn base_stack_initEnv() -> i32;
1172                fn conn_stack_initEnv() -> i32;
1173                fn adv_stack_initEnv() -> i32;
1174                fn extAdv_stack_initEnv() -> i32;
1175                fn sync_stack_initEnv() -> i32;
1176            }
1177
1178            let res = base_stack_initEnv();
1179            assert!(res == 0, "base_stack_initEnv returned {}", res);
1180
1181            let res = conn_stack_initEnv();
1182            assert!(res == 0, "conn_stack_initEnv returned {}", res);
1183
1184            let res = adv_stack_initEnv();
1185            assert!(res == 0, "adv_stack_initEnv returned {}", res);
1186
1187            let res = extAdv_stack_initEnv();
1188            if res != 0 {
1189                panic!("extAdv_stack_initEnv returned {}", res);
1190            }
1191
1192            let res = sync_stack_initEnv();
1193            assert!(res == 0, "sync_stack_initEnv returned {}", res);
1194
1195            let res = r_esp_ble_msys_init(256, 320, 12, 24, 1);
1196            assert!(res == 0, "esp_ble_msys_init returned {}", res);
1197        }
1198
1199        #[cfg(coex)]
1200        crate::binary::include::coex_enable();
1201
1202        let mut mac = [0u8; 6];
1203        crate::common_adapter::read_mac(mac.as_mut_ptr(), 2);
1204        mac.reverse();
1205
1206        #[cfg(esp32c2)]
1207        esp_ble_ll_set_public_addr(&mac as *const u8);
1208        #[cfg(not(esp32c2))]
1209        r_esp_ble_ll_set_public_addr(&mac as *const u8);
1210
1211        unsafe extern "C" {
1212            fn r_ble_hci_trans_init(m: u8);
1213        }
1214        r_ble_hci_trans_init(0);
1215
1216        r_ble_hci_trans_cfg_hs(
1217            Some(ble_hs_hci_rx_evt),
1218            core::ptr::null(),
1219            Some(ble_hs_rx_data),
1220            core::ptr::null(),
1221        );
1222
1223        #[cfg(esp32c2)]
1224        let res = ble_controller_enable(1); // 1 = BLE
1225        #[cfg(not(esp32c2))]
1226        let res = r_ble_controller_enable(1); // 1 = BLE
1227        assert!(res == 0, "ble_controller_enable returned {}", res);
1228
1229        // this is to avoid (ASSERT r_ble_hci_ram_hs_cmd_tx:34 0 0)
1230        // we wait a bit to make sure the ble task initialized everything
1231        crate::preempt::usleep(10_000);
1232    }
1233
1234    // At some point the "High-speed ADC" entropy source became available.
1235    unsafe { esp_hal::rng::TrngSource::increase_entropy_source_counter() };
1236
1237    debug!("The ble_controller_init was initialized");
1238    phy_init_guard
1239}
1240
1241pub(crate) fn ble_deinit() {
1242    esp_hal::rng::TrngSource::decrease_entropy_source_counter(unsafe {
1243        esp_hal::Internal::conjure()
1244    });
1245
1246    #[cfg(not(esp32c2))]
1247    unsafe extern "C" {
1248        fn base_stack_deinitEnv() -> i32;
1249        fn conn_stack_deinitEnv() -> i32;
1250        fn adv_stack_deinitEnv() -> i32;
1251        fn extAdv_stack_deinitEnv() -> i32;
1252        fn sync_stack_deinitEnv() -> i32;
1253    }
1254
1255    unsafe {
1256        // Prevent ASSERT r_ble_ll_reset:1069 ... ...
1257        // TODO: the cause of the issue is that the BLE controller can be dropped while the driver
1258        // is in the process of handling a HCI command.
1259        crate::preempt::usleep(10_000);
1260        // HCI deinit
1261        npl::r_ble_hci_trans_cfg_hs(None, core::ptr::null(), None, core::ptr::null());
1262
1263        #[cfg(not(esp32c2))]
1264        npl::r_ble_controller_disable();
1265
1266        #[cfg(not(esp32c2))]
1267        {
1268            conn_stack_deinitEnv();
1269            sync_stack_deinitEnv();
1270            extAdv_stack_deinitEnv();
1271            adv_stack_deinitEnv();
1272            base_stack_deinitEnv();
1273        }
1274
1275        #[cfg(not(esp32c2))]
1276        let res = npl::r_ble_controller_deinit();
1277
1278        #[cfg(esp32c2)]
1279        let res = npl::ble_controller_deinit();
1280
1281        if res != 0 {
1282            panic!("ble_controller_deinit returned {}", res);
1283        }
1284
1285        npl::esp_unregister_npl_funcs();
1286
1287        npl::esp_unregister_ext_funcs();
1288    }
1289}
1290
1291#[cfg(esp32c2)]
1292fn os_msys_buf_alloc() -> bool {
1293    unsafe {
1294        OS_MSYS_INIT_1_DATA = crate::compat::malloc::calloc(
1295            1,
1296            core::mem::size_of::<OsMembufT>() * SYSINIT_MSYS_1_MEMPOOL_SIZE,
1297        ) as *mut u32;
1298        OS_MSYS_INIT_2_DATA = crate::compat::malloc::calloc(
1299            1,
1300            core::mem::size_of::<OsMembufT>() * SYSINIT_MSYS_2_MEMPOOL_SIZE,
1301        ) as *mut u32;
1302
1303        !(OS_MSYS_INIT_1_DATA.is_null() || OS_MSYS_INIT_2_DATA.is_null())
1304    }
1305}
1306
1307#[cfg(esp32c2)]
1308fn os_msys_init() {
1309    static MSYS1: &[u8] = b"msys_1\0";
1310    static MSYS2: &[u8] = b"msys_2\0";
1311
1312    unsafe {
1313        r_os_msys_reset();
1314
1315        let rc = r_mem_init_mbuf_pool(
1316            OS_MSYS_INIT_1_DATA as *const c_void,
1317            addr_of!(OS_MSYS_INIT_1_MEMPOOL),
1318            addr_of!(OS_MSYS_INIT_1_MBUF_POOL),
1319            OS_MSYS_1_BLOCK_COUNT,
1320            SYSINIT_MSYS_1_MEMBLOCK_SIZE,
1321            MSYS1 as *const _ as *const u8,
1322        );
1323        if rc != 0 {
1324            panic!("r_mem_init_mbuf_pool failed");
1325        }
1326
1327        let rc = r_os_msys_register(addr_of!(OS_MSYS_INIT_1_MBUF_POOL));
1328        if rc != 0 {
1329            panic!("r_os_msys_register failed");
1330        }
1331
1332        let rc = r_mem_init_mbuf_pool(
1333            OS_MSYS_INIT_2_DATA as *const c_void,
1334            addr_of!(OS_MSYS_INIT_2_MEMPOOL),
1335            addr_of!(OS_MSYS_INIT_2_MBUF_POOL),
1336            OS_MSYS_2_BLOCK_COUNT,
1337            SYSINIT_MSYS_2_MEMBLOCK_SIZE,
1338            MSYS2 as *const _ as *const u8,
1339        );
1340        if rc != 0 {
1341            panic!("r_mem_init_mbuf_pool failed");
1342        }
1343
1344        let rc = r_os_msys_register(addr_of!(OS_MSYS_INIT_2_MBUF_POOL));
1345        if rc != 0 {
1346            panic!("r_os_msys_register failed");
1347        }
1348    }
1349}
1350
1351unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) -> i32 {
1352    trace!("ble_hs_hci_rx_evt {:?} {:?}", cmd, arg);
1353    trace!("$ cmd = {:x}", unsafe { *cmd });
1354    trace!("$ len = {:x}", unsafe { *(cmd.offset(1)) });
1355
1356    let event = unsafe { *cmd };
1357    let len = unsafe { *(cmd.offset(1)) } as usize;
1358    let payload = unsafe { core::slice::from_raw_parts(cmd.offset(2), len) };
1359    trace!("$ pld = {:?}", payload);
1360
1361    super::BT_STATE.with(|state| {
1362        let mut data = [0u8; 256];
1363
1364        data[0] = 0x04; // this is an event
1365        data[1] = event;
1366        data[2] = len as u8;
1367        data[3..][..len].copy_from_slice(payload);
1368
1369        state.rx_queue.push_back(ReceivedPacket {
1370            data: Box::from(&data[..len + 3]),
1371        });
1372
1373        dump_packet_info(&data[..(len + 3)]);
1374    });
1375
1376    unsafe {
1377        r_ble_hci_trans_buf_free(cmd);
1378    }
1379
1380    crate::ble::controller::hci_read_data_available();
1381
1382    0
1383}
1384
1385unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) -> i32 {
1386    trace!("ble_hs_rx_data {:?} {:?}", om, arg);
1387
1388    let data_ptr = unsafe { (*om).om_data };
1389    let len = unsafe { (*om).om_len };
1390    let data_slice = unsafe { core::slice::from_raw_parts(data_ptr, len as usize) };
1391
1392    super::BT_STATE.with(|state| {
1393        let mut data = [0u8; 256];
1394
1395        data[0] = 0x02; // ACL
1396        data[1..][..data_slice.len()].copy_from_slice(data_slice);
1397
1398        state.rx_queue.push_back(ReceivedPacket {
1399            data: Box::from(&data[..data_slice.len() + 1]),
1400        });
1401
1402        super::dump_packet_info(&data[..(len + 1) as usize]);
1403    });
1404
1405    unsafe {
1406        r_os_mbuf_free_chain(om as *mut _);
1407    }
1408
1409    crate::ble::controller::hci_read_data_available();
1410
1411    0
1412}
1413
1414/// Sends HCI data to the Bluetooth controller.
1415#[instability::unstable]
1416pub fn send_hci(data: &[u8]) {
1417    let hci_out = unsafe { (*addr_of_mut!(HCI_OUT_COLLECTOR)).assume_init_mut() };
1418    hci_out.push(data);
1419
1420    if hci_out.is_ready() {
1421        let packet = hci_out.packet();
1422
1423        unsafe {
1424            const DATA_TYPE_COMMAND: u8 = 1;
1425            const DATA_TYPE_ACL: u8 = 2;
1426
1427            dump_packet_info(packet);
1428
1429            super::BT_STATE.with(|_state| {
1430                if packet[0] == DATA_TYPE_COMMAND {
1431                    let cmd = r_ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
1432                    core::ptr::copy_nonoverlapping(
1433                        &packet[1] as *const _ as *mut u8, // don't send the TYPE
1434                        cmd as *mut u8,
1435                        packet.len() - 1,
1436                    );
1437
1438                    let res = r_ble_hci_trans_hs_cmd_tx(cmd);
1439
1440                    if res != 0 {
1441                        warn!("ble_hci_trans_hs_cmd_tx res == {}", res);
1442                    }
1443                } else if packet[0] == DATA_TYPE_ACL {
1444                    let om = r_os_msys_get_pkthdr(
1445                        packet.len() as u16,
1446                        ACL_DATA_MBUF_LEADINGSPACE as u16,
1447                    );
1448
1449                    let res =
1450                        r_os_mbuf_append(om, packet.as_ptr().offset(1), (packet.len() - 1) as u16);
1451                    if res != 0 {
1452                        panic!("r_os_mbuf_append returned {}", res);
1453                    }
1454
1455                    // this modification of the ACL data packet makes it getting sent and
1456                    // received by the other side
1457                    *((*om).om_data as *mut u8).offset(1) = 0;
1458
1459                    let res = r_ble_hci_trans_hs_acl_tx(om);
1460                    if res != 0 {
1461                        panic!("ble_hci_trans_hs_acl_tx returned {}", res);
1462                    }
1463                    trace!("ACL tx done");
1464                }
1465            });
1466        }
1467
1468        hci_out.reset();
1469    }
1470}