Skip to main content

esp_radio/ble/
npl.rs

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