* Don't activate additional features in esp-hal * Apply `clippy --fix` * Clippy * Clippy * Clippy * Clippy * Enable linting esp-wifi * Fix * Fix typo
1394 lines
43 KiB
Rust
1394 lines
43 KiB
Rust
use core::{
|
|
cell::RefCell,
|
|
ptr::{addr_of, addr_of_mut},
|
|
};
|
|
|
|
use critical_section::Mutex;
|
|
|
|
use super::*;
|
|
use crate::{
|
|
binary::{
|
|
c_types::{c_char, c_void},
|
|
include::*,
|
|
},
|
|
compat,
|
|
compat::{common::str_from_c, queue::SimpleQueue, task_runner::spawn_task},
|
|
timer::yield_task,
|
|
};
|
|
|
|
#[cfg_attr(esp32c2, path = "os_adapter_esp32c2.rs")]
|
|
#[cfg_attr(esp32c6, path = "os_adapter_esp32c6.rs")]
|
|
#[cfg_attr(esp32h2, path = "os_adapter_esp32h2.rs")]
|
|
pub(crate) mod ble_os_adapter_chip_specific;
|
|
|
|
const TIME_FOREVER: u32 = u32::MAX;
|
|
|
|
#[cfg(esp32c2)]
|
|
const OS_MSYS_1_BLOCK_COUNT: i32 = 24;
|
|
#[cfg(esp32c2)]
|
|
const SYSINIT_MSYS_1_MEMPOOL_SIZE: usize = 768;
|
|
#[cfg(esp32c2)]
|
|
const SYSINIT_MSYS_1_MEMBLOCK_SIZE: i32 = 128;
|
|
#[cfg(esp32c2)]
|
|
const OS_MSYS_2_BLOCK_COUNT: i32 = 24;
|
|
#[cfg(esp32c2)]
|
|
const SYSINIT_MSYS_2_MEMPOOL_SIZE: usize = 1920;
|
|
#[cfg(esp32c2)]
|
|
const SYSINIT_MSYS_2_MEMBLOCK_SIZE: i32 = 320;
|
|
|
|
const BLE_HCI_TRANS_BUF_CMD: i32 = 3;
|
|
|
|
// ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data
|
|
const ACL_DATA_MBUF_LEADINGSPACE: usize = 4;
|
|
|
|
#[derive(Copy, Clone)]
|
|
struct Callout {
|
|
_callout: *const ble_npl_callout,
|
|
eventq: *const ble_npl_eventq,
|
|
timer_handle: ets_timer,
|
|
events: ble_npl_event,
|
|
}
|
|
|
|
static mut CALLOUTS: [Option<Callout>; 18] = [None; 18];
|
|
|
|
#[derive(Copy, Clone)]
|
|
struct Event {
|
|
event: *const ble_npl_event,
|
|
event_fn_ptr: *const ble_npl_event_fn,
|
|
ev_arg_ptr: *const c_void,
|
|
queued: bool,
|
|
}
|
|
|
|
static mut EVENTS: [Option<Event>; 95] = [None; 95];
|
|
|
|
static mut EVENT_QUEUE: SimpleQueue<usize, 10> = SimpleQueue::new();
|
|
|
|
static BT_RECEIVE_QUEUE: Mutex<RefCell<SimpleQueue<ReceivedPacket, 10>>> =
|
|
Mutex::new(RefCell::new(SimpleQueue::new()));
|
|
|
|
#[cfg(esp32c2)]
|
|
type OsMembufT = u32;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
pub struct ReceivedPacket {
|
|
pub len: u8,
|
|
pub data: [u8; 256],
|
|
}
|
|
|
|
/// Memory pool
|
|
#[repr(C)]
|
|
pub(crate) struct OsMempool {
|
|
/// Size of the memory blocks, in bytes.
|
|
mp_block_size: u32,
|
|
/// The number of memory blocks.
|
|
mp_num_blocks: u16,
|
|
/// The number of free blocks left
|
|
mp_num_free: u16,
|
|
/// The lowest number of free blocks seen
|
|
mp_min_free: u16,
|
|
/// Bitmap of OS_MEMPOOL_F_[...] values.
|
|
mp_flags: u8,
|
|
/// Address of memory buffer used by pool
|
|
mp_membuf_addr: u32,
|
|
|
|
// STAILQ_ENTRY(os_mempool) mp_list;
|
|
next: *const OsMempool,
|
|
|
|
// SLIST_HEAD(,os_memblock);
|
|
first: *const c_void,
|
|
|
|
/// Name for memory block
|
|
name: *const u8,
|
|
}
|
|
|
|
#[cfg(esp32c2)]
|
|
impl OsMempool {
|
|
const fn zeroed() -> Self {
|
|
Self {
|
|
mp_block_size: 0,
|
|
mp_num_blocks: 0,
|
|
mp_num_free: 0,
|
|
mp_min_free: 0,
|
|
mp_flags: 0,
|
|
mp_membuf_addr: 0,
|
|
next: core::ptr::null(),
|
|
first: core::ptr::null(),
|
|
name: core::ptr::null(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A mbuf pool from which to allocate mbufs. This contains a pointer to the os
|
|
/// mempool to allocate mbufs out of, the total number of elements in the pool,
|
|
/// and the amount of "user" data in a non-packet header mbuf. The total pool
|
|
/// size, in bytes, should be:
|
|
/// os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
|
|
#[repr(C)]
|
|
pub(crate) struct OsMbufPool {
|
|
/// Total length of the databuf in each mbuf. This is the size of the
|
|
/// mempool block, minus the mbuf header
|
|
omp_databuf_len: u16,
|
|
/// The memory pool which to allocate mbufs out of
|
|
omp_pool: *const OsMempool,
|
|
|
|
// STAILQ_ENTRY(os_mbuf_pool) omp_next;
|
|
next: *const OsMbufPool,
|
|
}
|
|
|
|
#[cfg(esp32c2)]
|
|
impl OsMbufPool {
|
|
const fn zeroed() -> Self {
|
|
Self {
|
|
omp_databuf_len: 0,
|
|
omp_pool: core::ptr::null(),
|
|
next: core::ptr::null(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Chained memory buffer.
|
|
#[repr(C)]
|
|
pub struct OsMbuf {
|
|
/// Current pointer to data in the structure
|
|
om_data: *const u8,
|
|
/// Flags associated with this buffer, see OS_MBUF_F_* defintions
|
|
om_flags: u8,
|
|
/// Length of packet header
|
|
om_pkthdr_len: u8,
|
|
/// Length of data in this buffer
|
|
om_len: u16,
|
|
|
|
/// The mbuf pool this mbuf was allocated out of
|
|
om_omp: *const OsMbufPool,
|
|
|
|
// SLIST_ENTRY(os_mbuf) om_next;
|
|
next: *const OsMbuf,
|
|
|
|
/// Pointer to the beginning of the data, after this buffer
|
|
om_databuf: u32,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct OsMempoolExt {
|
|
mpe_mp: OsMempool,
|
|
|
|
// Callback that is executed immediately when a block is freed.
|
|
mpe_put_cb: OsMempoolPutFn,
|
|
mpe_put_arg: *const c_void,
|
|
}
|
|
|
|
type OsMempoolPutFn = Option<
|
|
unsafe extern "C" fn(ome: *const OsMempoolExt, data: *const c_void, arg: *const c_void) -> i32,
|
|
>;
|
|
|
|
#[repr(C)]
|
|
pub struct BleHciTransFuncsT {
|
|
ble_hci_trans_hs_acl_tx: Option<unsafe extern "C" fn(om: *const OsMbuf) -> i32>,
|
|
ble_hci_trans_hs_cmd_tx: Option<unsafe extern "C" fn(cmd: *const u8) -> i32>,
|
|
ble_hci_trans_ll_acl_tx: Option<unsafe extern "C" fn(om: *const OsMbuf) -> i32>,
|
|
ble_hci_trans_ll_evt_tx: Option<unsafe extern "C" fn(hci_ev: *const u8) -> i32>,
|
|
ble_hci_trans_reset: Option<unsafe extern "C" fn() -> i32>,
|
|
ble_hci_trans_set_acl_free_cb:
|
|
Option<unsafe extern "C" fn(cb: OsMempoolPutFn, arg: *const c_void) -> i32>,
|
|
}
|
|
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_1_DATA: *mut OsMembufT = core::ptr::null_mut();
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_1_MBUF_POOL: OsMbufPool = OsMbufPool::zeroed();
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_1_MEMPOOL: OsMempool = OsMempool::zeroed();
|
|
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_2_DATA: *mut OsMembufT = core::ptr::null_mut();
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_2_MBUF_POOL: OsMbufPool = OsMbufPool::zeroed();
|
|
#[cfg(esp32c2)]
|
|
pub(crate) static mut OS_MSYS_INIT_2_MEMPOOL: OsMempool = OsMempool::zeroed();
|
|
|
|
extern "C" {
|
|
static ble_hci_trans_funcs_ptr: &'static BleHciTransFuncsT;
|
|
|
|
#[cfg(esp32c2)]
|
|
static mut r_ble_stub_funcs_ptr: *mut u32;
|
|
|
|
pub(crate) fn ble_controller_init(cfg: *const esp_bt_controller_config_t) -> i32;
|
|
|
|
pub(crate) fn ble_controller_enable(mode: u8) -> i32;
|
|
|
|
pub(crate) fn esp_register_ext_funcs(funcs: *const ext_funcs_t) -> i32;
|
|
|
|
pub(crate) fn esp_register_npl_funcs(funcs: *const npl_funcs_t) -> i32;
|
|
|
|
pub(crate) fn ble_get_npl_element_info(
|
|
cfg: *const esp_bt_controller_config_t,
|
|
npl_info: *const ble_npl_count_info_t,
|
|
) -> i32;
|
|
|
|
pub(crate) fn bt_bb_v2_init_cmplx(value: u8);
|
|
|
|
pub(crate) fn r_ble_hci_trans_cfg_hs(
|
|
evt: Option<unsafe extern "C" fn(cmd: *const u8, arg: *const c_void)>, /* ble_hci_trans_rx_cmd_fn */
|
|
evt_arg: *const c_void,
|
|
acl_cb: Option<unsafe extern "C" fn(om: *const OsMbuf, arg: *const c_void)>, /* ble_hci_trans_rx_acl_fn */
|
|
acl_arg: *const c_void,
|
|
);
|
|
|
|
pub(crate) fn esp_ble_ll_set_public_addr(addr: *const u8);
|
|
|
|
#[cfg(esp32c2)]
|
|
pub(crate) fn r_mem_init_mbuf_pool(
|
|
mem: *const c_void,
|
|
mempool: *const OsMempool,
|
|
mbuf_pool: *const OsMbufPool,
|
|
num_blocks: i32,
|
|
block_size: i32,
|
|
name: *const u8,
|
|
) -> i32;
|
|
|
|
#[cfg(esp32c2)]
|
|
pub(crate) fn r_os_msys_reset();
|
|
|
|
#[cfg(esp32c2)]
|
|
pub(crate) fn r_os_msys_register(mbuf_pool: *const OsMbufPool) -> i32;
|
|
|
|
#[allow(unused)]
|
|
pub(crate) fn ble_osi_coex_funcs_register(coex_funcs: *const osi_coex_funcs_t) -> i32;
|
|
|
|
pub(crate) fn r_os_msys_get_pkthdr(dsize: u16, user_hdr_len: u16) -> *mut OsMbuf;
|
|
|
|
pub(crate) fn r_os_mbuf_append(om: *mut OsMbuf, src: *const u8, len: u16) -> i32;
|
|
|
|
pub(crate) fn r_os_mbuf_free_chain(om: *mut OsMbuf) -> i32;
|
|
|
|
pub(crate) fn r_ble_hci_trans_buf_alloc(typ: i32) -> *const u8;
|
|
|
|
pub(crate) fn r_ble_hci_trans_buf_free(buf: *const u8);
|
|
|
|
static mut ble_hci_trans_env_p: u32;
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct ext_funcs_t {
|
|
ext_version: u32,
|
|
esp_intr_alloc: Option<
|
|
unsafe extern "C" fn(
|
|
source: u32,
|
|
flags: u32,
|
|
handler: *mut c_void,
|
|
arg: *mut c_void,
|
|
ret_handle: *mut *mut c_void,
|
|
) -> i32,
|
|
>,
|
|
esp_intr_free: Option<unsafe extern "C" fn(ret_handle: *mut *mut c_void) -> i32>,
|
|
malloc: Option<unsafe extern "C" fn(size: u32) -> *mut c_void>,
|
|
free: Option<unsafe extern "C" fn(*mut c_void)>,
|
|
hal_uart_start_tx: Option<unsafe extern "C" fn(i32)>,
|
|
hal_uart_init_cbs: Option<
|
|
unsafe extern "C" fn(i32, *const c_void, *const c_void, *const c_void, c_void) -> i32,
|
|
>,
|
|
hal_uart_config: Option<unsafe extern "C" fn(i32, i32, u8, u8, u8, u8) -> i32>,
|
|
hal_uart_close: Option<unsafe extern "C" fn(i32) -> i32>,
|
|
hal_uart_blocking_tx: Option<unsafe extern "C" fn(i32, u8)>,
|
|
hal_uart_init: Option<unsafe extern "C" fn(i32, *const c_void) -> i32>,
|
|
task_create: Option<
|
|
unsafe extern "C" fn(
|
|
*const c_void,
|
|
*const c_char,
|
|
u32,
|
|
*const c_void,
|
|
u32,
|
|
*const c_void,
|
|
u32,
|
|
) -> i32,
|
|
>,
|
|
task_delete: Option<unsafe extern "C" fn(*const c_void)>,
|
|
osi_assert: Option<unsafe extern "C" fn(u32, *const c_void, u32, u32)>,
|
|
os_random: Option<unsafe extern "C" fn() -> u32>,
|
|
ecc_gen_key_pair: Option<unsafe extern "C" fn(*const u8, *const u8) -> i32>,
|
|
ecc_gen_dh_key: Option<unsafe extern "C" fn(*const u8, *const u8, *const u8, *const u8) -> i32>,
|
|
esp_reset_rpa_moudle: Option<unsafe extern "C" fn()>,
|
|
#[cfg(esp32c2)]
|
|
esp_bt_track_pll_cap: Option<unsafe extern "C" fn()>,
|
|
magic: u32,
|
|
}
|
|
|
|
static G_OSI_FUNCS: ext_funcs_t = ext_funcs_t {
|
|
ext_version: 0x20221122,
|
|
esp_intr_alloc: Some(self::ble_os_adapter_chip_specific::esp_intr_alloc),
|
|
esp_intr_free: Some(esp_intr_free),
|
|
malloc: Some(crate::ble::malloc),
|
|
free: Some(crate::ble::free),
|
|
hal_uart_start_tx: None,
|
|
hal_uart_init_cbs: None,
|
|
hal_uart_config: None,
|
|
hal_uart_close: None,
|
|
hal_uart_blocking_tx: None,
|
|
hal_uart_init: None,
|
|
task_create: Some(task_create),
|
|
task_delete: Some(task_delete),
|
|
osi_assert: Some(osi_assert),
|
|
os_random: Some(os_random),
|
|
ecc_gen_key_pair: Some(ecc_gen_key_pair),
|
|
ecc_gen_dh_key: Some(ecc_gen_dh_key),
|
|
esp_reset_rpa_moudle: Some(self::ble_os_adapter_chip_specific::esp_reset_rpa_moudle),
|
|
#[cfg(esp32c2)]
|
|
esp_bt_track_pll_cap: None,
|
|
magic: 0xA5A5A5A5,
|
|
};
|
|
|
|
unsafe extern "C" fn ecc_gen_dh_key(_: *const u8, _: *const u8, _: *const u8, _: *const u8) -> i32 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ecc_gen_key_pair(_: *const u8, _: *const u8) -> i32 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn os_random() -> u32 {
|
|
trace!("os_random");
|
|
(crate::common_adapter::random() & u32::MAX) as u32
|
|
}
|
|
|
|
unsafe extern "C" fn task_create(
|
|
task_func: *const c_void,
|
|
name: *const c_char,
|
|
stack_depth: u32,
|
|
param: *const c_void,
|
|
prio: u32,
|
|
task_handle: *const c_void,
|
|
core_id: u32,
|
|
) -> i32 {
|
|
let name_str = str_from_c(name as *const u8);
|
|
trace!(
|
|
"task_create {:?} {} {} {:?} {} {:?} {}",
|
|
task_func,
|
|
name_str,
|
|
stack_depth,
|
|
param,
|
|
prio,
|
|
task_handle,
|
|
core_id,
|
|
);
|
|
|
|
*(task_handle as *mut usize) = 0; // we will run it in task 0
|
|
|
|
if spawn_task(
|
|
task_func as *mut c_void,
|
|
name as *const c_char,
|
|
stack_depth,
|
|
param as *mut c_void,
|
|
prio,
|
|
task_handle as *mut c_void,
|
|
core_id,
|
|
) {
|
|
1
|
|
} else {
|
|
0
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn task_delete(_: *const c_void) {
|
|
todo!();
|
|
}
|
|
|
|
unsafe extern "C" fn osi_assert(ln: u32, fn_name: *const c_void, param1: u32, param2: u32) {
|
|
let name_str = str_from_c(fn_name as *const u8);
|
|
panic!("ASSERT {}:{} {} {}", name_str, ln, param1, param2);
|
|
}
|
|
|
|
unsafe extern "C" fn esp_intr_free(_ret_handle: *mut *mut c_void) -> i32 {
|
|
todo!();
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct npl_funcs_t {
|
|
p_ble_npl_os_started: Option<unsafe extern "C" fn() -> bool>,
|
|
p_ble_npl_get_current_task_id: Option<unsafe extern "C" fn() -> *const c_void>,
|
|
p_ble_npl_eventq_init: Option<unsafe extern "C" fn(queue: *const ble_npl_eventq)>,
|
|
p_ble_npl_eventq_deinit: Option<unsafe extern "C" fn(queue: *const ble_npl_eventq)>,
|
|
p_ble_npl_eventq_get: Option<
|
|
unsafe extern "C" fn(
|
|
queue: *const ble_npl_eventq,
|
|
time: ble_npl_time_t,
|
|
) -> *const ble_npl_event,
|
|
>,
|
|
p_ble_npl_eventq_put:
|
|
Option<unsafe extern "C" fn(queue: *const ble_npl_eventq, event: *const ble_npl_event)>,
|
|
p_ble_npl_eventq_remove:
|
|
Option<unsafe extern "C" fn(queue: *const ble_npl_eventq, event: *const ble_npl_event)>,
|
|
p_ble_npl_event_run: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
|
|
p_ble_npl_eventq_is_empty: Option<unsafe extern "C" fn(queue: *const ble_npl_eventq) -> bool>,
|
|
p_ble_npl_event_init: Option<
|
|
unsafe extern "C" fn(
|
|
event: *const ble_npl_event,
|
|
func: *const ble_npl_event_fn,
|
|
*const c_void,
|
|
),
|
|
>,
|
|
p_ble_npl_event_deinit: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
|
|
p_ble_npl_event_reset: Option<unsafe extern "C" fn(event: *const ble_npl_event)>,
|
|
p_ble_npl_event_is_queued: Option<unsafe extern "C" fn(event: *const ble_npl_event) -> bool>,
|
|
p_ble_npl_event_get_arg:
|
|
Option<unsafe extern "C" fn(event: *const ble_npl_event) -> *const c_void>,
|
|
p_ble_npl_event_set_arg:
|
|
Option<unsafe extern "C" fn(event: *const ble_npl_event, arg: *const c_void)>,
|
|
p_ble_npl_mutex_init:
|
|
Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
|
|
p_ble_npl_mutex_deinit:
|
|
Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
|
|
p_ble_npl_mutex_pend: Option<
|
|
unsafe extern "C" fn(mutex: *const ble_npl_mutex, time: ble_npl_time_t) -> ble_npl_error_t,
|
|
>,
|
|
p_ble_npl_mutex_release:
|
|
Option<unsafe extern "C" fn(mutex: *const ble_npl_mutex) -> ble_npl_error_t>,
|
|
p_ble_npl_sem_init:
|
|
Option<unsafe extern "C" fn(sem: *const ble_npl_sem, val: u16) -> ble_npl_error_t>,
|
|
p_ble_npl_sem_deinit: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> ble_npl_error_t>,
|
|
p_ble_npl_sem_pend: Option<
|
|
unsafe extern "C" fn(sem: *const ble_npl_sem, time: ble_npl_time_t) -> ble_npl_error_t,
|
|
>,
|
|
p_ble_npl_sem_release: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> ble_npl_error_t>,
|
|
p_ble_npl_sem_get_count: Option<unsafe extern "C" fn(sem: *const ble_npl_sem) -> u16>,
|
|
p_ble_npl_callout_init: Option<
|
|
unsafe extern "C" fn(
|
|
callout: *const ble_npl_callout,
|
|
eventq: *const ble_npl_eventq,
|
|
func: *const ble_npl_event_fn,
|
|
args: *const c_void,
|
|
) -> i32,
|
|
>,
|
|
p_ble_npl_callout_reset: Option<
|
|
unsafe extern "C" fn(
|
|
callout: *const ble_npl_callout,
|
|
time: ble_npl_time_t,
|
|
) -> ble_npl_error_t,
|
|
>,
|
|
p_ble_npl_callout_stop: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
|
|
p_ble_npl_callout_deinit: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
|
|
p_ble_npl_callout_mem_reset: Option<unsafe extern "C" fn(callout: *const ble_npl_callout)>,
|
|
p_ble_npl_callout_is_active:
|
|
Option<unsafe extern "C" fn(callout: *const ble_npl_callout) -> bool>,
|
|
p_ble_npl_callout_get_ticks:
|
|
Option<unsafe extern "C" fn(callout: *const ble_npl_callout) -> ble_npl_time_t>,
|
|
p_ble_npl_callout_remaining_ticks:
|
|
Option<unsafe extern "C" fn(callout: *const ble_npl_callout, time: ble_npl_time_t) -> u32>,
|
|
p_ble_npl_callout_set_arg:
|
|
Option<unsafe extern "C" fn(callout: *const ble_npl_callout, arg: *const c_void)>,
|
|
p_ble_npl_time_get: Option<unsafe extern "C" fn() -> u32>,
|
|
p_ble_npl_time_ms_to_ticks:
|
|
Option<unsafe extern "C" fn(ms: u32, p_time: *const ble_npl_time_t) -> ble_npl_error_t>,
|
|
p_ble_npl_time_ticks_to_ms:
|
|
Option<unsafe extern "C" fn(time: ble_npl_time_t, *const u32) -> ble_npl_error_t>,
|
|
p_ble_npl_time_ms_to_ticks32: Option<unsafe extern "C" fn(ms: u32) -> ble_npl_time_t>,
|
|
p_ble_npl_time_ticks_to_ms32: Option<unsafe extern "C" fn(time: ble_npl_time_t) -> u32>,
|
|
p_ble_npl_time_delay: Option<unsafe extern "C" fn(time: ble_npl_time_t)>,
|
|
p_ble_npl_hw_set_isr: Option<unsafe extern "C" fn(no: i32, mask: u32)>,
|
|
p_ble_npl_hw_enter_critical: Option<unsafe extern "C" fn() -> u32>,
|
|
p_ble_npl_hw_exit_critical: Option<unsafe extern "C" fn(mask: u32)>,
|
|
p_ble_npl_get_time_forever: Option<unsafe extern "C" fn() -> u32>,
|
|
p_ble_npl_hw_is_in_critical: Option<unsafe extern "C" fn() -> u8>,
|
|
}
|
|
|
|
static mut G_NPL_FUNCS: npl_funcs_t = npl_funcs_t {
|
|
p_ble_npl_os_started: Some(ble_npl_os_started),
|
|
p_ble_npl_get_current_task_id: Some(ble_npl_get_current_task_id),
|
|
p_ble_npl_eventq_init: Some(ble_npl_eventq_init),
|
|
p_ble_npl_eventq_deinit: Some(ble_npl_eventq_deinit),
|
|
p_ble_npl_eventq_get: Some(ble_npl_eventq_get),
|
|
p_ble_npl_eventq_put: Some(ble_npl_eventq_put),
|
|
p_ble_npl_eventq_remove: Some(ble_npl_eventq_remove),
|
|
p_ble_npl_event_run: Some(ble_npl_event_run),
|
|
p_ble_npl_eventq_is_empty: Some(ble_npl_eventq_is_empty),
|
|
p_ble_npl_event_init: Some(ble_npl_event_init),
|
|
p_ble_npl_event_deinit: Some(ble_npl_event_deinit),
|
|
p_ble_npl_event_reset: Some(ble_npl_event_reset),
|
|
p_ble_npl_event_is_queued: Some(ble_npl_event_is_queued),
|
|
p_ble_npl_event_get_arg: Some(ble_npl_event_get_arg),
|
|
p_ble_npl_event_set_arg: Some(ble_npl_event_set_arg),
|
|
p_ble_npl_mutex_init: Some(ble_npl_mutex_init),
|
|
p_ble_npl_mutex_deinit: Some(ble_npl_mutex_deinit),
|
|
p_ble_npl_mutex_pend: Some(ble_npl_mutex_pend),
|
|
p_ble_npl_mutex_release: Some(ble_npl_mutex_release),
|
|
p_ble_npl_sem_init: Some(ble_npl_sem_init),
|
|
p_ble_npl_sem_deinit: Some(ble_npl_sem_deinit),
|
|
p_ble_npl_sem_pend: Some(ble_npl_sem_pend),
|
|
p_ble_npl_sem_release: Some(ble_npl_sem_release),
|
|
p_ble_npl_sem_get_count: Some(ble_npl_sem_get_count),
|
|
p_ble_npl_callout_init: Some(ble_npl_callout_init),
|
|
p_ble_npl_callout_reset: Some(ble_npl_callout_reset),
|
|
p_ble_npl_callout_stop: Some(ble_npl_callout_stop),
|
|
p_ble_npl_callout_deinit: Some(ble_npl_callout_deinit),
|
|
p_ble_npl_callout_mem_reset: Some(ble_npl_callout_mem_reset),
|
|
p_ble_npl_callout_is_active: Some(ble_npl_callout_is_active),
|
|
p_ble_npl_callout_get_ticks: Some(ble_npl_callout_get_ticks),
|
|
p_ble_npl_callout_remaining_ticks: Some(ble_npl_callout_remaining_ticks),
|
|
p_ble_npl_callout_set_arg: Some(ble_npl_callout_set_arg),
|
|
p_ble_npl_time_get: Some(ble_npl_time_get),
|
|
p_ble_npl_time_ms_to_ticks: Some(ble_npl_time_ms_to_ticks),
|
|
p_ble_npl_time_ticks_to_ms: Some(ble_npl_time_ticks_to_ms),
|
|
p_ble_npl_time_ms_to_ticks32: Some(ble_npl_time_ms_to_ticks32),
|
|
p_ble_npl_time_ticks_to_ms32: Some(ble_npl_time_ticks_to_ms32),
|
|
p_ble_npl_time_delay: Some(ble_npl_time_delay),
|
|
p_ble_npl_hw_set_isr: Some(ble_npl_hw_set_isr),
|
|
p_ble_npl_hw_enter_critical: Some(ble_npl_hw_enter_critical),
|
|
p_ble_npl_hw_exit_critical: Some(ble_npl_hw_exit_critical),
|
|
p_ble_npl_get_time_forever: Some(ble_npl_get_time_forever),
|
|
p_ble_npl_hw_is_in_critical: Some(ble_npl_hw_is_in_critical),
|
|
};
|
|
|
|
#[repr(C)]
|
|
pub struct osi_coex_funcs_t {
|
|
magic: u32,
|
|
version: u32,
|
|
coex_wifi_sleep_set: Option<unsafe extern "C" fn(sleep: bool)>,
|
|
coex_core_ble_conn_dyn_prio_get:
|
|
Option<unsafe extern "C" fn(low: *mut bool, high: *mut bool) -> i32>,
|
|
coex_schm_status_bit_set: Option<unsafe extern "C" fn(_type: u32, status: u32)>,
|
|
coex_schm_status_bit_clear: Option<unsafe extern "C" fn(_type: u32, status: u32)>,
|
|
}
|
|
|
|
#[allow(unused)]
|
|
static G_COEX_FUNCS: osi_coex_funcs_t = osi_coex_funcs_t {
|
|
magic: 0xFADEBEAD,
|
|
version: 0x00010006,
|
|
coex_wifi_sleep_set: Some(coex_wifi_sleep_set),
|
|
coex_core_ble_conn_dyn_prio_get: Some(coex_core_ble_conn_dyn_prio_get),
|
|
coex_schm_status_bit_set: Some(coex_schm_status_bit_set),
|
|
coex_schm_status_bit_clear: Some(coex_schm_status_bit_clear),
|
|
};
|
|
|
|
#[allow(unused)]
|
|
unsafe extern "C" fn coex_wifi_sleep_set(_sleep: bool) {
|
|
todo!()
|
|
}
|
|
|
|
#[allow(unused)]
|
|
unsafe extern "C" fn coex_core_ble_conn_dyn_prio_get(_low: *mut bool, _high: *mut bool) -> i32 {
|
|
todo!()
|
|
}
|
|
|
|
#[allow(unused)]
|
|
unsafe extern "C" fn coex_schm_status_bit_set(_type: u32, _status: u32) {
|
|
trace!("coex_schm_status_bit_set is an empty stub");
|
|
}
|
|
|
|
#[allow(unused)]
|
|
unsafe extern "C" fn coex_schm_status_bit_clear(_type: u32, _status: u32) {
|
|
trace!("coex_schm_status_bit_clear is an empty stub");
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_hw_is_in_critical() -> u8 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_get_time_forever() -> u32 {
|
|
trace!("ble_npl_get_time_forever");
|
|
TIME_FOREVER
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_hw_exit_critical(mask: u32) {
|
|
trace!("ble_npl_hw_exit_critical {}", mask);
|
|
critical_section::release(core::mem::transmute::<u8, critical_section::RestoreState>(
|
|
mask as u8,
|
|
));
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_hw_enter_critical() -> u32 {
|
|
trace!("ble_npl_hw_enter_critical");
|
|
let as_u8: u8 = core::mem::transmute(critical_section::acquire());
|
|
as_u8 as u32
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_hw_set_isr(_no: i32, _mask: u32) {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_delay(_time: ble_npl_time_t) {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_ticks_to_ms32(_time: ble_npl_time_t) -> u32 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_ms_to_ticks32(ms: u32) -> ble_npl_time_t {
|
|
trace!("ble_npl_time_ms_to_ticks32 {}", ms);
|
|
ms
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_ticks_to_ms(
|
|
_time: ble_npl_time_t,
|
|
_p_ms: *const u32,
|
|
) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_ms_to_ticks(
|
|
_ms: u32,
|
|
_p_time: *const ble_npl_time_t,
|
|
) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_time_get() -> u32 {
|
|
trace!("ble_npl_time_get");
|
|
crate::current_millis() as u32
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_set_arg(
|
|
_callout: *const ble_npl_callout,
|
|
_arg: *const c_void,
|
|
) {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_remaining_ticks(
|
|
_callout: *const ble_npl_callout,
|
|
_time: ble_npl_time_t,
|
|
) -> u32 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_get_ticks(_callout: *const ble_npl_callout) -> ble_npl_time_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_is_active(_callout: *const ble_npl_callout) -> bool {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_mem_reset(callout: *const ble_npl_callout) {
|
|
trace!("ble_npl_callout_mem_reset");
|
|
|
|
ble_npl_callout_stop(callout);
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_deinit(callout: *const ble_npl_callout) {
|
|
trace!("ble_npl_callout_deinit");
|
|
|
|
ble_npl_callout_stop(callout);
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_stop(callout: *const ble_npl_callout) {
|
|
trace!("ble_npl_callout_stop {:?}", callout);
|
|
|
|
if (*callout).dummy == 0 {
|
|
panic!("Trying to stop an uninitialzed callout");
|
|
}
|
|
|
|
let co = unwrap!(CALLOUTS[((*callout).dummy - 1) as usize].as_mut());
|
|
|
|
// stop timer
|
|
compat::timer_compat::compat_timer_disarm(addr_of_mut!(co.timer_handle));
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_reset(
|
|
callout: *const ble_npl_callout,
|
|
time: ble_npl_time_t,
|
|
) -> ble_npl_error_t {
|
|
trace!("ble_npl_callout_reset {:?} {}", callout, time);
|
|
|
|
let co = unwrap!(CALLOUTS[((*callout).dummy - 1) as usize].as_mut());
|
|
|
|
// start timer
|
|
compat::timer_compat::compat_timer_arm(addr_of_mut!(co.timer_handle), time, false);
|
|
|
|
0
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_sem_get_count(_sem: *const ble_npl_sem) -> u16 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_sem_release(_sem: *const ble_npl_sem) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_sem_pend(
|
|
_sem: *const ble_npl_sem,
|
|
_time: ble_npl_time_t,
|
|
) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_sem_deinit(_sem: *const ble_npl_sem) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_sem_init(_sem: *const ble_npl_sem, _val: u16) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_mutex_release(_mutex: *const ble_npl_mutex) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_mutex_pend(
|
|
_mutex: *const ble_npl_mutex,
|
|
_time: ble_npl_time_t,
|
|
) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_mutex_deinit(_mutex: *const ble_npl_mutex) -> ble_npl_error_t {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_set_arg(event: *const ble_npl_event, arg: *const c_void) {
|
|
trace!("ble_npl_event_set_arg {:?} {:?}", event, arg);
|
|
if (*event).dummy == 0 {
|
|
panic!("Call set_arg on uninitialized event");
|
|
}
|
|
|
|
unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).ev_arg_ptr = arg;
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_get_arg(event: *const ble_npl_event) -> *const c_void {
|
|
trace!("ble_npl_event_get_arg {:?}", event);
|
|
if (*event).dummy == 0 {
|
|
panic!("Call get_arg on uninitialized event");
|
|
}
|
|
|
|
let arg_ptr = unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).ev_arg_ptr;
|
|
|
|
trace!("returning arg {:x}", arg_ptr as usize);
|
|
|
|
arg_ptr
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_is_queued(event: *const ble_npl_event) -> bool {
|
|
trace!("ble_npl_event_is_queued {:?}", event);
|
|
if (*event).dummy == 0 {
|
|
panic!("Call is_queued on uninitialized event");
|
|
}
|
|
|
|
unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_reset(event: *const ble_npl_event) {
|
|
trace!("ble_npl_event_reset {:?}", event);
|
|
|
|
let event = event as *mut ble_npl_event;
|
|
if (*event).dummy == 0 {
|
|
panic!("Trying to reset an uninitialized event");
|
|
} else {
|
|
unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = false;
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_deinit(_event: *const ble_npl_event) {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_init(
|
|
event: *const ble_npl_event,
|
|
func: *const ble_npl_event_fn,
|
|
arg: *const c_void,
|
|
) {
|
|
trace!("ble_npl_event_init {:?} {:?} {:?}", event, func, arg);
|
|
|
|
if (*event).dummy == 0 {
|
|
let idx = unwrap!(EVENTS.iter().position(|item| item.is_none()));
|
|
EVENTS[idx] = Some(Event {
|
|
event,
|
|
event_fn_ptr: func,
|
|
ev_arg_ptr: arg,
|
|
queued: false,
|
|
});
|
|
|
|
let event = event.cast_mut();
|
|
(*event).dummy = (idx + 1) as i32;
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_is_empty(queue: *const ble_npl_eventq) -> bool {
|
|
trace!("ble_npl_eventq_is_empty {:?}", queue);
|
|
|
|
if (*queue).dummy == 0 {
|
|
panic!("Try to use uninitialized queue");
|
|
}
|
|
|
|
critical_section::with(|_| EVENT_QUEUE.is_empty())
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_event_run(event: *const ble_npl_event) {
|
|
trace!("ble_npl_event_run {:?}", event);
|
|
|
|
let event = event as *mut ble_npl_event;
|
|
if (*event).dummy == 0 {
|
|
panic!("Trying to run an uninitialized event");
|
|
} else {
|
|
let ev = unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut());
|
|
trace!("info {:?} with arg {:x}", ev.event_fn_ptr, event as u32);
|
|
let func: unsafe extern "C" fn(u32) = core::mem::transmute(ev.event_fn_ptr);
|
|
func(event as u32);
|
|
}
|
|
|
|
trace!("ble_npl_event_run done");
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_remove(
|
|
queue: *const ble_npl_eventq,
|
|
event: *const ble_npl_event,
|
|
) {
|
|
trace!("ble_npl_eventq_remove {:?} {:?}", queue, event);
|
|
|
|
if (*queue).dummy == 0 {
|
|
panic!("Try to use uninitialized queue");
|
|
}
|
|
|
|
if (*event).dummy == 0 {
|
|
panic!("Try to use uninitialized event");
|
|
}
|
|
|
|
critical_section::with(|_| {
|
|
unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = false;
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_put(queue: *const ble_npl_eventq, event: *const ble_npl_event) {
|
|
trace!("ble_npl_eventq_put {:?} {:?}", queue, event);
|
|
|
|
if (*queue).dummy == 0 {
|
|
panic!("Try to use uninitialized queue");
|
|
}
|
|
|
|
if (*event).dummy == 0 {
|
|
panic!("Try to use uninitialized event");
|
|
}
|
|
|
|
critical_section::with(|_| {
|
|
unwrap!(EVENTS[((*event).dummy - 1) as usize].as_mut()).queued = true;
|
|
unwrap!(EVENT_QUEUE.enqueue((*event).dummy as usize));
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_get(
|
|
queue: *const ble_npl_eventq,
|
|
time: ble_npl_time_t,
|
|
) -> *const ble_npl_event {
|
|
trace!("ble_npl_eventq_get {:?} {}", queue, time);
|
|
|
|
if time == TIME_FOREVER {
|
|
loop {
|
|
let dequeued = critical_section::with(|_| EVENT_QUEUE.dequeue());
|
|
|
|
if let Some(event_idx) = dequeued {
|
|
let evt = unwrap!(EVENTS[event_idx - 1].as_mut());
|
|
if evt.queued {
|
|
trace!("got {:x}", evt.event as usize);
|
|
evt.queued = false;
|
|
return evt.event;
|
|
}
|
|
}
|
|
|
|
yield_task();
|
|
}
|
|
} else {
|
|
panic!("timed eventq_get not yet supported - go implement it!");
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_deinit(_queue: *const ble_npl_eventq) {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_callout_init(
|
|
callout: *const ble_npl_callout,
|
|
eventq: *const ble_npl_eventq,
|
|
func: *const ble_npl_event_fn,
|
|
args: *const c_void,
|
|
) -> i32 {
|
|
trace!(
|
|
"ble_npl_callout_init {:?} {:?} {:?} {:?}",
|
|
callout,
|
|
eventq,
|
|
func,
|
|
args
|
|
);
|
|
|
|
if (*callout).dummy == 0 {
|
|
let callout = callout.cast_mut();
|
|
let idx = unwrap!(CALLOUTS.iter().position(|item| item.is_none()));
|
|
|
|
let new_callout = CALLOUTS[idx].insert(Callout {
|
|
_callout: callout,
|
|
eventq,
|
|
timer_handle: ets_timer {
|
|
next: core::ptr::null_mut(),
|
|
expire: 0,
|
|
period: 0,
|
|
func: None,
|
|
priv_: core::ptr::null_mut(),
|
|
},
|
|
events: ble_npl_event { dummy: 0 },
|
|
});
|
|
|
|
ble_npl_event_init(addr_of_mut!(new_callout.events), func, args);
|
|
|
|
crate::compat::timer_compat::compat_timer_setfn(
|
|
addr_of_mut!(new_callout.timer_handle),
|
|
callout_timer_callback_wrapper,
|
|
idx as *mut c_void,
|
|
);
|
|
|
|
(*callout).dummy = (idx + 1) as i32;
|
|
}
|
|
|
|
0
|
|
}
|
|
|
|
unsafe extern "C" fn callout_timer_callback_wrapper(arg: *mut c_void) {
|
|
info!("callout_timer_callback_wrapper {:?}", arg);
|
|
let co = unwrap!(CALLOUTS[arg as usize].as_mut());
|
|
|
|
if co.eventq.is_null() {
|
|
ble_npl_eventq_put(addr_of!(co.events).cast(), addr_of!(co.events));
|
|
} else {
|
|
ble_npl_event_run(addr_of!(co.events));
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_eventq_init(queue: *const ble_npl_eventq) {
|
|
trace!("ble_npl_eventq_init {:?}", queue);
|
|
|
|
critical_section::with(|_cs| {
|
|
let queue = queue as *mut ble_npl_eventq;
|
|
|
|
if (*queue).dummy == 0 {
|
|
(*queue).dummy = 1;
|
|
} else {
|
|
panic!("Only one emulated queue supported");
|
|
}
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_mutex_init(_mutex: *const ble_npl_mutex) -> u32 {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_get_current_task_id() -> *const c_void {
|
|
todo!()
|
|
}
|
|
|
|
unsafe extern "C" fn ble_npl_os_started() -> bool {
|
|
todo!();
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct ble_npl_count_info_t {
|
|
evt_count: u16,
|
|
evtq_count: u16,
|
|
co_count: u16,
|
|
sem_count: u16,
|
|
mutex_count: u16,
|
|
}
|
|
|
|
pub(crate) fn ble_init() {
|
|
unsafe {
|
|
*(HCI_OUT_COLLECTOR.as_mut_ptr()) = HciOutCollector::new();
|
|
|
|
// turn on logging
|
|
#[cfg(feature = "wifi-logs")]
|
|
{
|
|
extern "C" {
|
|
static mut g_ble_plf_log_level: u32;
|
|
}
|
|
|
|
debug!("g_ble_plf_log_level = {}", g_ble_plf_log_level);
|
|
g_ble_plf_log_level = 10;
|
|
}
|
|
|
|
self::ble_os_adapter_chip_specific::ble_rtc_clk_init();
|
|
|
|
let cfg = ble_os_adapter_chip_specific::BLE_CONFIG;
|
|
|
|
let res = esp_register_ext_funcs(&G_OSI_FUNCS as *const ext_funcs_t);
|
|
if res != 0 {
|
|
panic!("esp_register_ext_funcs returned {}", res);
|
|
}
|
|
|
|
#[cfg(coex)]
|
|
{
|
|
let res = crate::wifi::coex_init();
|
|
if res != 0 {
|
|
panic!("got error");
|
|
}
|
|
}
|
|
|
|
ble_os_adapter_chip_specific::bt_periph_module_enable();
|
|
|
|
ble_os_adapter_chip_specific::disable_sleep_mode();
|
|
|
|
let res = esp_register_npl_funcs(core::ptr::addr_of!(G_NPL_FUNCS));
|
|
if res != 0 {
|
|
panic!("esp_register_npl_funcs returned {}", res);
|
|
}
|
|
|
|
let npl_info = ble_npl_count_info_t {
|
|
evt_count: 0,
|
|
evtq_count: 0,
|
|
co_count: 0,
|
|
sem_count: 0,
|
|
mutex_count: 0,
|
|
};
|
|
let res = ble_get_npl_element_info(
|
|
&cfg as *const esp_bt_controller_config_t,
|
|
&npl_info as *const ble_npl_count_info_t,
|
|
);
|
|
if res != 0 {
|
|
panic!("ble_get_npl_element_info returned {}", res);
|
|
}
|
|
// not really using npl_info here ... remove it?
|
|
|
|
#[cfg(esp32c2)]
|
|
{
|
|
// Initialize the global memory pool
|
|
let ret = os_msys_buf_alloc();
|
|
if !ret {
|
|
panic!("os_msys_buf_alloc failed");
|
|
}
|
|
|
|
os_msys_init();
|
|
}
|
|
|
|
crate::common_adapter::chip_specific::phy_enable();
|
|
|
|
// init bb
|
|
bt_bb_v2_init_cmplx(1);
|
|
|
|
#[cfg(coex)]
|
|
{
|
|
let rc = ble_osi_coex_funcs_register(&G_COEX_FUNCS as *const osi_coex_funcs_t);
|
|
if rc != 0 {
|
|
panic!("ble_osi_coex_funcs_register returned {}", rc);
|
|
}
|
|
}
|
|
|
|
let res = ble_controller_init(&cfg as *const esp_bt_controller_config_t);
|
|
|
|
if res != 0 {
|
|
panic!("ble_controller_init returned {}", res);
|
|
}
|
|
|
|
#[cfg(not(esp32c2))]
|
|
{
|
|
extern "C" {
|
|
fn esp_ble_msys_init(
|
|
msys_size1: u16,
|
|
msys_size2: u16,
|
|
msys_cnt1: u16,
|
|
msys_cnt2: u16,
|
|
from_heap: u8,
|
|
) -> i32;
|
|
}
|
|
|
|
let res = esp_ble_msys_init(256, 320, 12, 24, 1);
|
|
if res != 0 {
|
|
panic!("esp_ble_msys_init returned {}", res);
|
|
}
|
|
}
|
|
|
|
#[cfg(coex)]
|
|
crate::binary::include::coex_enable();
|
|
|
|
let mut mac = [0u8; 6];
|
|
crate::common_adapter::read_mac(mac.as_mut_ptr(), 2);
|
|
mac.reverse();
|
|
|
|
esp_ble_ll_set_public_addr(&mac as *const u8);
|
|
|
|
r_ble_hci_trans_cfg_hs(
|
|
Some(ble_hs_hci_rx_evt),
|
|
core::ptr::null(),
|
|
Some(ble_hs_rx_data),
|
|
core::ptr::null(),
|
|
);
|
|
|
|
let res = ble_controller_enable(1); // 1 = BLE
|
|
if res != 0 {
|
|
panic!("ble_controller_enable returned {}", res);
|
|
}
|
|
|
|
// "patch" r_ble_ll_random - it needs syscall_table_ptr
|
|
// probably long term we should rather initialize syscall_table_ptr
|
|
#[cfg(esp32c2)]
|
|
{
|
|
*(r_ble_stub_funcs_ptr.offset(0x7dc / 4)) =
|
|
self::ble_os_adapter_chip_specific::ble_ll_random_override as *const u32 as u32;
|
|
}
|
|
|
|
// this is to avoid (ASSERT r_ble_hci_ram_hs_cmd_tx:34 0 0)
|
|
// r_ble_hci_trans_cfg_ll initializes ble_hci_trans_env_p + 0x34
|
|
// it's called by r_ble_ll_task which is run in another task
|
|
// in r_ble_hci_ram_hs_cmd_tx this is checked for non-null
|
|
while (ble_hci_trans_env_p as *const u32)
|
|
.add(0x34 / 4)
|
|
.read_volatile()
|
|
== 0
|
|
{
|
|
// wait
|
|
}
|
|
|
|
debug!("The ble_controller_init was initialized");
|
|
}
|
|
}
|
|
|
|
#[cfg(esp32c2)]
|
|
fn os_msys_buf_alloc() -> bool {
|
|
unsafe {
|
|
OS_MSYS_INIT_1_DATA = crate::compat::malloc::calloc(
|
|
1,
|
|
core::mem::size_of::<OsMembufT>() * SYSINIT_MSYS_1_MEMPOOL_SIZE,
|
|
) as *mut u32;
|
|
OS_MSYS_INIT_2_DATA = crate::compat::malloc::calloc(
|
|
1,
|
|
core::mem::size_of::<OsMembufT>() * SYSINIT_MSYS_2_MEMPOOL_SIZE,
|
|
) as *mut u32;
|
|
|
|
!(OS_MSYS_INIT_1_DATA.is_null() || OS_MSYS_INIT_2_DATA.is_null())
|
|
}
|
|
}
|
|
|
|
#[cfg(esp32c2)]
|
|
fn os_msys_init() {
|
|
static MSYS1: &[u8] = b"msys_1\0";
|
|
static MSYS2: &[u8] = b"msys_2\0";
|
|
|
|
unsafe {
|
|
r_os_msys_reset();
|
|
|
|
let rc = r_mem_init_mbuf_pool(
|
|
OS_MSYS_INIT_1_DATA as *const c_void,
|
|
addr_of!(OS_MSYS_INIT_1_MEMPOOL),
|
|
addr_of!(OS_MSYS_INIT_1_MBUF_POOL),
|
|
OS_MSYS_1_BLOCK_COUNT,
|
|
SYSINIT_MSYS_1_MEMBLOCK_SIZE,
|
|
MSYS1 as *const _ as *const u8,
|
|
);
|
|
if rc != 0 {
|
|
panic!("r_mem_init_mbuf_pool failed");
|
|
}
|
|
|
|
let rc = r_os_msys_register(addr_of!(OS_MSYS_INIT_1_MBUF_POOL));
|
|
if rc != 0 {
|
|
panic!("r_os_msys_register failed");
|
|
}
|
|
|
|
let rc = r_mem_init_mbuf_pool(
|
|
OS_MSYS_INIT_2_DATA as *const c_void,
|
|
addr_of!(OS_MSYS_INIT_2_MEMPOOL),
|
|
addr_of!(OS_MSYS_INIT_2_MBUF_POOL),
|
|
OS_MSYS_2_BLOCK_COUNT,
|
|
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
|
|
MSYS2 as *const _ as *const u8,
|
|
);
|
|
if rc != 0 {
|
|
panic!("r_mem_init_mbuf_pool failed");
|
|
}
|
|
|
|
let rc = r_os_msys_register(addr_of!(OS_MSYS_INIT_2_MBUF_POOL));
|
|
if rc != 0 {
|
|
panic!("r_os_msys_register failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn ble_hs_hci_rx_evt(cmd: *const u8, arg: *const c_void) {
|
|
trace!("ble_hs_hci_rx_evt {:?} {:?}", cmd, arg);
|
|
debug!("$ cmd = {:x}", *cmd);
|
|
debug!("$ len = {:x}", *(cmd.offset(1)));
|
|
|
|
let event = *cmd;
|
|
let len = *(cmd.offset(1)) as usize;
|
|
let payload = core::slice::from_raw_parts(cmd.offset(2), len);
|
|
debug!("$ pld = {:?}", payload);
|
|
|
|
critical_section::with(|cs| {
|
|
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
|
|
let mut data = [0u8; 256];
|
|
|
|
data[0] = 0x04; // this is an event
|
|
data[1] = event;
|
|
data[2] = len as u8;
|
|
data[3..][..len].copy_from_slice(payload);
|
|
|
|
if queue
|
|
.enqueue(ReceivedPacket {
|
|
len: (len + 3) as u8,
|
|
data,
|
|
})
|
|
.is_err()
|
|
{
|
|
warn!("Dropping BLE packet");
|
|
}
|
|
|
|
dump_packet_info(&data[..(len + 3)]);
|
|
});
|
|
|
|
r_ble_hci_trans_buf_free(cmd);
|
|
|
|
#[cfg(feature = "async")]
|
|
crate::ble::controller::asynch::hci_read_data_available();
|
|
}
|
|
|
|
unsafe extern "C" fn ble_hs_rx_data(om: *const OsMbuf, arg: *const c_void) {
|
|
trace!("ble_hs_rx_data {:?} {:?}", om, arg);
|
|
|
|
let data_ptr = (*om).om_data;
|
|
let len = (*om).om_len;
|
|
let data_slice = core::slice::from_raw_parts(data_ptr, len as usize);
|
|
|
|
critical_section::with(|cs| {
|
|
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
|
|
let mut data = [0u8; 256];
|
|
|
|
data[0] = 0x02; // ACL
|
|
data[1..][..data_slice.len()].copy_from_slice(data_slice);
|
|
|
|
if queue
|
|
.enqueue(ReceivedPacket {
|
|
len: (len + 1) as u8,
|
|
data,
|
|
})
|
|
.is_err()
|
|
{
|
|
warn!("Dropping BLE packet");
|
|
}
|
|
|
|
dump_packet_info(&data[..(len + 1) as usize]);
|
|
});
|
|
|
|
r_os_mbuf_free_chain(om as *mut _);
|
|
|
|
#[cfg(feature = "async")]
|
|
crate::ble::controller::asynch::hci_read_data_available();
|
|
}
|
|
|
|
static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256];
|
|
static mut BLE_HCI_READ_DATA_INDEX: usize = 0;
|
|
static mut BLE_HCI_READ_DATA_LEN: usize = 0;
|
|
|
|
#[cfg(feature = "async")]
|
|
pub fn have_hci_read_data() -> bool {
|
|
critical_section::with(|cs| {
|
|
let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
|
|
!queue.is_empty()
|
|
|| unsafe {
|
|
BLE_HCI_READ_DATA_LEN > 0 && (BLE_HCI_READ_DATA_LEN >= BLE_HCI_READ_DATA_INDEX)
|
|
}
|
|
})
|
|
}
|
|
|
|
pub(crate) fn read_next(data: &mut [u8]) -> usize {
|
|
critical_section::with(|cs| {
|
|
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
|
|
|
|
match queue.dequeue() {
|
|
Some(packet) => {
|
|
data[..packet.len as usize].copy_from_slice(&packet.data[..packet.len as usize]);
|
|
packet.len as usize
|
|
}
|
|
None => 0,
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn read_hci(data: &mut [u8]) -> usize {
|
|
unsafe {
|
|
if BLE_HCI_READ_DATA_LEN == 0 {
|
|
critical_section::with(|cs| {
|
|
let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
|
|
|
|
if let Some(packet) = queue.dequeue() {
|
|
BLE_HCI_READ_DATA[..packet.len as usize]
|
|
.copy_from_slice(&packet.data[..packet.len as usize]);
|
|
BLE_HCI_READ_DATA_LEN = packet.len as usize;
|
|
BLE_HCI_READ_DATA_INDEX = 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
if BLE_HCI_READ_DATA_LEN > 0 {
|
|
data[0] = BLE_HCI_READ_DATA[BLE_HCI_READ_DATA_INDEX];
|
|
BLE_HCI_READ_DATA_INDEX += 1;
|
|
|
|
if BLE_HCI_READ_DATA_INDEX >= BLE_HCI_READ_DATA_LEN {
|
|
BLE_HCI_READ_DATA_LEN = 0;
|
|
BLE_HCI_READ_DATA_INDEX = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
0
|
|
}
|
|
|
|
pub fn send_hci(data: &[u8]) {
|
|
let hci_out = unsafe { &mut *HCI_OUT_COLLECTOR.as_mut_ptr() };
|
|
hci_out.push(data);
|
|
|
|
if hci_out.is_ready() {
|
|
let packet = hci_out.packet();
|
|
|
|
unsafe {
|
|
const DATA_TYPE_COMMAND: u8 = 1;
|
|
const DATA_TYPE_ACL: u8 = 2;
|
|
|
|
dump_packet_info(packet);
|
|
|
|
critical_section::with(|_cs| {
|
|
if packet[0] == DATA_TYPE_COMMAND {
|
|
let cmd = r_ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
|
|
core::ptr::copy_nonoverlapping(
|
|
&packet[1] as *const _ as *mut u8, // don't send the TYPE
|
|
cmd as *mut u8,
|
|
packet.len() - 1,
|
|
);
|
|
|
|
let res = unwrap!(ble_hci_trans_funcs_ptr.ble_hci_trans_hs_cmd_tx)(cmd);
|
|
|
|
if res != 0 {
|
|
warn!("ble_hci_trans_hs_cmd_tx res == {}", res);
|
|
}
|
|
} else if packet[0] == DATA_TYPE_ACL {
|
|
let om = r_os_msys_get_pkthdr(
|
|
packet.len() as u16,
|
|
ACL_DATA_MBUF_LEADINGSPACE as u16,
|
|
);
|
|
|
|
let res =
|
|
r_os_mbuf_append(om, packet.as_ptr().offset(1), (packet.len() - 1) as u16);
|
|
if res != 0 {
|
|
panic!("r_os_mbuf_append returned {}", res);
|
|
}
|
|
|
|
// this modification of the ACL data packet makes it getting sent and
|
|
// received by the other side
|
|
*((*om).om_data as *mut u8).offset(1) = 0;
|
|
|
|
let res = unwrap!(ble_hci_trans_funcs_ptr.ble_hci_trans_hs_acl_tx)(om);
|
|
if res != 0 {
|
|
panic!("ble_hci_trans_hs_acl_tx returned {}", res);
|
|
}
|
|
trace!("ACL tx done");
|
|
}
|
|
});
|
|
}
|
|
|
|
hci_out.reset();
|
|
}
|
|
}
|
|
|
|
#[allow(unreachable_code, unused_variables)]
|
|
fn dump_packet_info(buffer: &[u8]) {
|
|
#[cfg(not(feature = "dump-packets"))]
|
|
return;
|
|
|
|
critical_section::with(|cs| {
|
|
info!("@HCIFRAME {:?}", buffer);
|
|
});
|
|
}
|