esp_radio/ble/
os_adapter_esp32.rs

1use core::ptr::addr_of_mut;
2
3use procmacros::BuilderLite;
4
5use super::*;
6use crate::{
7    binary::include::{
8        esp_bt_controller_config_t,
9        esp_bt_mode_t,
10        esp_bt_mode_t_ESP_BT_MODE_BLE,
11        esp_bt_mode_t_ESP_BT_MODE_BTDM,
12        esp_bt_mode_t_ESP_BT_MODE_CLASSIC_BT,
13        esp_bt_mode_t_ESP_BT_MODE_IDLE,
14    },
15    ble::InvalidConfigError,
16    common_adapter::*,
17    hal::{interrupt, peripherals::Interrupt},
18};
19
20pub(crate) static mut ISR_INTERRUPT_5: (*mut c_void, *mut c_void) =
21    (core::ptr::null_mut(), core::ptr::null_mut());
22
23pub(crate) static mut ISR_INTERRUPT_8: (*mut c_void, *mut c_void) =
24    (core::ptr::null_mut(), core::ptr::null_mut());
25
26pub(crate) static mut ISR_INTERRUPT_7: (*mut c_void, *mut c_void) =
27    (core::ptr::null_mut(), core::ptr::null_mut());
28
29#[repr(C)]
30pub(super) struct osi_funcs_s {
31    version: u32,
32    set_isr: Option<unsafe extern "C" fn(i32, unsafe extern "C" fn(), *const ()) -> i32>,
33    ints_on: Option<unsafe extern "C" fn(u32)>,
34    interrupt_disable: Option<unsafe extern "C" fn()>,
35    interrupt_restore: Option<unsafe extern "C" fn()>,
36    task_yield: Option<unsafe extern "C" fn()>,
37    task_yield_from_isr: Option<unsafe extern "C" fn()>,
38    semphr_create: Option<unsafe extern "C" fn(u32, u32) -> *mut c_void>,
39    semphr_delete: Option<unsafe extern "C" fn(*mut c_void)>,
40    semphr_take_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut bool) -> i32>,
41    semphr_give_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut bool) -> i32>,
42    semphr_take: Option<unsafe extern "C" fn(*mut c_void, u32) -> i32>,
43    semphr_give: Option<unsafe extern "C" fn(*mut c_void) -> i32>,
44    mutex_create: Option<unsafe extern "C" fn() -> *const ()>,
45    mutex_delete: Option<unsafe extern "C" fn(*const ())>,
46    mutex_lock: Option<unsafe extern "C" fn(*const ()) -> i32>,
47    mutex_unlock: Option<unsafe extern "C" fn(*const ()) -> i32>,
48    queue_create: Option<unsafe extern "C" fn(u32, u32) -> *mut c_void>,
49    queue_delete: Option<unsafe extern "C" fn(*mut c_void)>,
50    queue_send: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, u32) -> i32>,
51    queue_send_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void) -> i32>,
52    queue_recv: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, u32) -> i32>,
53    queue_recv_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void) -> i32>,
54    task_create: Option<
55        unsafe extern "C" fn(
56            *mut c_void,
57            *const c_char,
58            u32,
59            *mut c_void,
60            u32,
61            *mut c_void,
62            u32,
63        ) -> i32,
64    >,
65    task_delete: Option<unsafe extern "C" fn(*mut ())>,
66    is_in_isr: Option<unsafe extern "C" fn() -> i32>,
67    cause_sw_intr_to_core: Option<unsafe extern "C" fn(i32, i32) -> i32>,
68    malloc: Option<unsafe extern "C" fn(u32) -> *mut c_void>,
69    malloc_internal: Option<unsafe extern "C" fn(u32) -> *mut c_void>,
70    free: Option<unsafe extern "C" fn(*mut c_void)>,
71    read_efuse_mac: Option<unsafe extern "C" fn(*const ()) -> i32>,
72    srand: Option<unsafe extern "C" fn(u32)>,
73    rand: Option<unsafe extern "C" fn() -> i32>,
74    btdm_lpcycles_2_hus: Option<unsafe extern "C" fn(u32, u32) -> u32>,
75    btdm_hus_2_lpcycles: Option<unsafe extern "C" fn(u32) -> u32>,
76    btdm_sleep_check_duration: Option<unsafe extern "C" fn(i32) -> i32>,
77    btdm_sleep_enter_phase1: Option<unsafe extern "C" fn(i32)>,
78    btdm_sleep_enter_phase2: Option<unsafe extern "C" fn()>,
79    btdm_sleep_exit_phase1: Option<unsafe extern "C" fn()>,
80    btdm_sleep_exit_phase2: Option<unsafe extern "C" fn()>,
81    btdm_sleep_exit_phase3: Option<unsafe extern "C" fn()>,
82    coex_bt_wakeup_request: Option<unsafe extern "C" fn() -> bool>,
83    coex_bt_wakeup_request_end: Option<unsafe extern "C" fn()>,
84    coex_bt_request: Option<unsafe extern "C" fn(u32, u32, u32) -> i32>,
85    coex_bt_release: Option<unsafe extern "C" fn(u32) -> i32>,
86    coex_register_bt_cb: Option<unsafe extern "C" fn(unsafe extern "C" fn()) -> i32>,
87    coex_bb_reset_lock: Option<unsafe extern "C" fn() -> u32>,
88    coex_bb_reset_unlock: Option<unsafe extern "C" fn(u32)>,
89    coex_schm_register_btdm_callback: Option<unsafe extern "C" fn(unsafe extern "C" fn()) -> i32>,
90    coex_schm_status_bit_clear: Option<unsafe extern "C" fn(i32, i32)>,
91    coex_schm_status_bit_set: Option<unsafe extern "C" fn(i32, i32)>,
92    coex_schm_interval_get: Option<unsafe extern "C" fn() -> u32>,
93    coex_schm_curr_period_get: Option<unsafe extern "C" fn() -> u8>,
94    coex_schm_curr_phase_get: Option<unsafe extern "C" fn() -> *const ()>,
95    coex_wifi_channel_get: Option<unsafe extern "C" fn(*mut u8, *mut u8) -> i32>,
96    coex_register_wifi_channel_change_callback:
97        Option<unsafe extern "C" fn(unsafe extern "C" fn()) -> i32>,
98    set_isr13: Option<unsafe extern "C" fn(i32, unsafe extern "C" fn(), *const ()) -> i32>,
99    interrupt_l3_disable: Option<unsafe extern "C" fn()>,
100    interrupt_l3_restore: Option<unsafe extern "C" fn()>,
101    custom_queue_create: Option<unsafe extern "C" fn(u32, u32) -> *mut c_void>,
102    coex_version_get: Option<unsafe extern "C" fn(*mut c_uint, *mut c_uint, *mut c_uint) -> c_int>,
103    patch_apply: Option<unsafe extern "C" fn()>,
104    magic: u32,
105}
106
107pub(super) static G_OSI_FUNCS: osi_funcs_s = osi_funcs_s {
108    version: 0x00010005,
109    set_isr: Some(ble_os_adapter_chip_specific::set_isr),
110    ints_on: Some(ble_os_adapter_chip_specific::ints_on),
111    interrupt_disable: Some(interrupt_disable),
112    interrupt_restore: Some(interrupt_enable),
113    task_yield: Some(task_yield),
114    task_yield_from_isr: Some(task_yield_from_isr),
115    semphr_create: Some(semphr_create),
116    semphr_delete: Some(semphr_delete),
117    semphr_take_from_isr: Some(semphr_take_from_isr),
118    semphr_give_from_isr: Some(semphr_give_from_isr),
119    semphr_take: Some(semphr_take),
120    semphr_give: Some(semphr_give),
121    mutex_create: Some(mutex_create),
122    mutex_delete: Some(mutex_delete),
123    mutex_lock: Some(mutex_lock),
124    mutex_unlock: Some(mutex_unlock),
125    queue_create: Some(queue_create),
126    queue_delete: Some(queue_delete),
127    queue_send: Some(queue_send),
128    queue_send_from_isr: Some(queue_send_from_isr),
129    queue_recv: Some(queue_recv),
130    queue_recv_from_isr: Some(queue_recv_from_isr),
131    task_create: Some(task_create),
132    task_delete: Some(task_delete),
133    is_in_isr: Some(is_in_isr),
134    cause_sw_intr_to_core: Some(cause_sw_intr_to_core),
135    malloc: Some(crate::ble::malloc),
136    malloc_internal: Some(crate::ble::malloc_internal),
137    free: Some(crate::ble::free),
138    read_efuse_mac: Some(read_efuse_mac),
139    srand: Some(crate::ble::btdm::srand),
140    rand: Some(crate::ble::btdm::rand),
141    btdm_lpcycles_2_hus: Some(btdm_lpcycles_2_hus),
142    btdm_hus_2_lpcycles: Some(btdm_hus_2_lpcycles),
143    btdm_sleep_check_duration: Some(btdm_sleep_check_duration),
144    btdm_sleep_enter_phase1: Some(btdm_sleep_enter_phase1),
145    btdm_sleep_enter_phase2: Some(btdm_sleep_enter_phase2),
146    btdm_sleep_exit_phase1: Some(btdm_sleep_exit_phase1),
147    btdm_sleep_exit_phase2: Some(btdm_sleep_exit_phase2),
148    btdm_sleep_exit_phase3: Some(btdm_sleep_exit_phase3),
149    coex_bt_wakeup_request: Some(ble_os_adapter_chip_specific::coex_bt_wakeup_request),
150    coex_bt_wakeup_request_end: Some(ble_os_adapter_chip_specific::coex_bt_wakeup_request_end),
151    coex_bt_request: Some(ble_os_adapter_chip_specific::coex_bt_request),
152    coex_bt_release: Some(ble_os_adapter_chip_specific::coex_bt_release),
153    coex_register_bt_cb: Some(ble_os_adapter_chip_specific::coex_register_bt_cb_wrapper),
154    coex_bb_reset_lock: Some(ble_os_adapter_chip_specific::coex_bb_reset_lock),
155    coex_bb_reset_unlock: Some(ble_os_adapter_chip_specific::coex_bb_reset_unlock),
156    coex_schm_register_btdm_callback: Some(
157        ble_os_adapter_chip_specific::coex_schm_register_btdm_callback_wrapper,
158    ),
159    coex_schm_status_bit_clear: Some(coex_schm_status_bit_clear),
160    coex_schm_status_bit_set: Some(coex_schm_status_bit_set),
161    coex_schm_interval_get: Some(ble_os_adapter_chip_specific::coex_schm_interval_get),
162    coex_schm_curr_period_get: Some(ble_os_adapter_chip_specific::coex_schm_curr_period_get),
163    coex_schm_curr_phase_get: Some(ble_os_adapter_chip_specific::coex_schm_curr_phase_get),
164    coex_wifi_channel_get: Some(ble_os_adapter_chip_specific::coex_wifi_channel_get),
165    coex_register_wifi_channel_change_callback: Some(
166        ble_os_adapter_chip_specific::coex_register_wifi_channel_change_callback,
167    ),
168    set_isr13: Some(set_isr13),
169    interrupt_l3_disable: Some(interrupt_l3_disable),
170    interrupt_l3_restore: Some(interrupt_l3_restore),
171    custom_queue_create: Some(custom_queue_create),
172    coex_version_get: Some(coex_version_get_wrapper),
173    patch_apply: Some(patch_apply),
174    magic: 0xfadebead,
175};
176
177extern "C" fn patch_apply() {
178    trace!("patch apply");
179
180    unsafe extern "C" {
181        fn config_ble_funcs_reset();
182        fn config_btdm_funcs_reset();
183    }
184
185    unsafe {
186        config_btdm_funcs_reset();
187        config_ble_funcs_reset();
188    }
189}
190
191extern "C" fn coex_version_get_wrapper(major: *mut u32, minor: *mut u32, patch: *mut u32) -> i32 {
192    unsafe {
193        let mut version = crate::binary::include::coex_version_t {
194            major: 0,
195            minor: 0,
196            patch: 0,
197        };
198        if coex_version_get_value(&mut version) == 0 {
199            info!(
200                "COEX Version {}.{}.{}",
201                version.major, version.minor, version.patch
202            );
203
204            major.write_volatile(version.major as u32);
205            minor.write_volatile(version.minor as u32);
206            patch.write_volatile(version.patch as u32);
207        } else {
208            error!("Unable to get COEX version");
209        }
210    }
211
212    0
213}
214
215#[repr(C)]
216struct btdm_dram_available_region_t {
217    mode: esp_bt_mode_t,
218    start: u32, // ptr
219    end: u32,   // ptr
220}
221
222const SOC_MEM_BT_DATA_START: u32 = 0x3ffae6e0;
223const SOC_MEM_BT_DATA_END: u32 = 0x3ffaff10;
224const SOC_MEM_BT_EM_BTDM0_START: u32 = 0x3ffb0000;
225const SOC_MEM_BT_EM_BTDM0_END: u32 = 0x3ffb09a8;
226const SOC_MEM_BT_EM_BLE_START: u32 = 0x3ffb09a8;
227const SOC_MEM_BT_EM_BLE_END: u32 = 0x3ffb1ddc;
228const SOC_MEM_BT_EM_BTDM1_START: u32 = 0x3ffb1ddc;
229const SOC_MEM_BT_EM_BTDM1_END: u32 = 0x3ffb2730;
230const SOC_MEM_BT_EM_BREDR_START: u32 = 0x3ffb2730;
231const SOC_MEM_BT_BSS_START: u32 = 0x3ffb8000;
232const SOC_MEM_BT_BSS_END: u32 = 0x3ffb9a20;
233const SOC_MEM_BT_MISC_START: u32 = 0x3ffbdb28;
234const SOC_MEM_BT_MISC_END: u32 = 0x3ffbdb5c;
235
236const SOC_MEM_BT_EM_BREDR_REAL_END: u32 = 0x3ffb6388; //  (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF
237// * SOC_MEM_BT_EM_PER_SYNC_SIZE);
238
239static BTDM_DRAM_AVAILABLE_REGION: [btdm_dram_available_region_t; 7] = [
240    // following is .data
241    btdm_dram_available_region_t {
242        mode: esp_bt_mode_t_ESP_BT_MODE_BTDM,
243        start: SOC_MEM_BT_DATA_START,
244        end: SOC_MEM_BT_DATA_END,
245    },
246    // following is memory which HW will use
247    btdm_dram_available_region_t {
248        mode: esp_bt_mode_t_ESP_BT_MODE_BTDM,
249        start: SOC_MEM_BT_EM_BTDM0_START,
250        end: SOC_MEM_BT_EM_BTDM0_END,
251    },
252    btdm_dram_available_region_t {
253        mode: esp_bt_mode_t_ESP_BT_MODE_BLE,
254        start: SOC_MEM_BT_EM_BLE_START,
255        end: SOC_MEM_BT_EM_BLE_END,
256    },
257    btdm_dram_available_region_t {
258        mode: esp_bt_mode_t_ESP_BT_MODE_BTDM,
259        start: SOC_MEM_BT_EM_BTDM1_START,
260        end: SOC_MEM_BT_EM_BTDM1_END,
261    },
262    btdm_dram_available_region_t {
263        mode: esp_bt_mode_t_ESP_BT_MODE_CLASSIC_BT,
264        start: SOC_MEM_BT_EM_BREDR_START,
265        end: SOC_MEM_BT_EM_BREDR_REAL_END,
266    },
267    // following is .bss
268    btdm_dram_available_region_t {
269        mode: esp_bt_mode_t_ESP_BT_MODE_BTDM,
270        start: SOC_MEM_BT_BSS_START,
271        end: SOC_MEM_BT_BSS_END,
272    },
273    btdm_dram_available_region_t {
274        mode: esp_bt_mode_t_ESP_BT_MODE_BTDM,
275        start: SOC_MEM_BT_MISC_START,
276        end: SOC_MEM_BT_MISC_END,
277    },
278];
279
280/// Bluetooth controller configuration.
281#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
282#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
283#[cfg_attr(feature = "defmt", derive(defmt::Format))]
284pub struct Config {
285    /// The priority of the RTOS task.
286    task_priority: u8,
287
288    /// The stack size of the RTOS task.
289    task_stack_size: u16,
290
291    /// The maximum number of simultaneous connections.
292    ///
293    /// Range: 1 - 9
294    max_connections: u8,
295
296    /// Maximum number of devices in scan duplicate filtering list.
297    ///
298    /// Range: 10 - 1000
299    scan_duplicate_list_count: u16,
300
301    /// Scan duplicate filtering list refresh period in seconds.
302    ///
303    /// Range: 0 - 1000 seconds
304    scan_duplicate_refresh_period: u16,
305
306    /// Enable BLE scan backoff.
307    ble_scan_backoff: bool,
308
309    /// Minimum encryption key size.
310    ///
311    /// Range: 7 - 16
312    enc_key_sz_min: u8,
313
314    /// Enable verification of the Access Address within the `CONNECT_IND` PDU.
315    verify_access_address: bool,
316
317    /// Enable BLE channel assessment.
318    channel_assessment: bool,
319
320    /// Enable BLE ping procedure.
321    ping: bool,
322
323    /// Disconnect when Instant Passed (0x28) occurs during ACL connection update.
324    disconnect_llcp_conn_update: bool,
325
326    /// Disconnect when Instant Passed (0x28) occurs during ACL channel map update.
327    disconnect_llcp_chan_map_update: bool,
328}
329
330impl Default for Config {
331    fn default() -> Self {
332        Self {
333            // same priority as the wifi task, when using esp-rtos (I'm assuming it's MAX_PRIO - 2)
334            task_priority: 29,
335            task_stack_size: 4096,
336            max_connections: CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF as _,
337            scan_duplicate_list_count: CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE as _,
338            scan_duplicate_refresh_period: SCAN_DUPL_CACHE_REFRESH_PERIOD as _,
339            ble_scan_backoff: false,
340            enc_key_sz_min: 7,
341            verify_access_address: false,
342            channel_assessment: false,
343            ping: false,
344            disconnect_llcp_conn_update: false,
345            disconnect_llcp_chan_map_update: false,
346        }
347    }
348}
349
350impl Config {
351    pub(crate) fn validate(&self) -> Result<(), InvalidConfigError> {
352        crate::ble::validate_range!(self, max_connections, 1, 9);
353        crate::ble::validate_range!(self, scan_duplicate_list_count, 10, 1000);
354        crate::ble::validate_range!(self, scan_duplicate_refresh_period, 0, 1000);
355        crate::ble::validate_range!(self, enc_key_sz_min, 7, 16);
356
357        Ok(())
358    }
359}
360
361pub(crate) fn create_ble_config(config: &Config) -> esp_bt_controller_config_t {
362    // keep them aligned with BT_CONTROLLER_INIT_CONFIG_DEFAULT in ESP-IDF
363    // ideally _some_ of these values should be configurable
364    esp_bt_controller_config_t {
365        controller_task_stack_size: config.task_stack_size,
366        controller_task_prio: config.task_priority,
367
368        // We're using VHCI but esp-idf has these defaults:
369        hci_uart_no: 1,
370        hci_uart_baudrate: 921600,
371        // Bluetooth mesh options, currently not supported
372        scan_duplicate_mode: 0, // normal mode
373        scan_duplicate_type: 0,
374        mesh_adv_size: 0,
375
376        normal_adv_size: config.scan_duplicate_list_count,
377        send_adv_reserved_size: SCAN_SEND_ADV_RESERVED_SIZE as _,
378        controller_debug_flag: BTDM_CTRL_CONTROLLER_DEBUG_FLAG as _,
379        mode: esp_bt_mode_t_ESP_BT_MODE_BLE as _,
380        ble_max_conn: config.max_connections,
381        bt_max_acl_conn: 0,
382        bt_sco_datapath: 0,
383        auto_latency: false,
384        bt_legacy_auth_vs_evt: false,
385        bt_max_sync_conn: 1,
386        ble_sca: 1,
387        pcm_role: 0,
388        pcm_polar: 0,
389        hli: false,
390        dup_list_refresh_period: config.scan_duplicate_refresh_period,
391        ble_scan_backoff: config.ble_scan_backoff,
392        pcm_fsyncshp: 0,
393        enc_key_sz_min: config.enc_key_sz_min,
394        ble_llcp_disc_flag: config.disconnect_llcp_conn_update as u8
395            | ((config.disconnect_llcp_chan_map_update as u8) << 1),
396        ble_aa_check: config.verify_access_address,
397        ble_chan_ass_en: config.channel_assessment as u8,
398        ble_ping_en: config.ping as u8,
399        magic: ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL,
400    }
401}
402
403pub(crate) fn btdm_controller_mem_init() {
404    unsafe extern "C" {
405        static mut _data_start_btdm: u32;
406        static mut _data_end_btdm: u32;
407        static _data_start_btdm_rom: u32;
408    }
409
410    // initialise .data section
411    unsafe {
412        let data_start = addr_of_mut!(_data_start_btdm).cast::<u8>();
413        let data_end = addr_of_mut!(_data_end_btdm).cast::<u8>();
414
415        // `_data_start_btdm_rom` is a pointer to the actual initialization data in the
416        // ROM.
417        let data_start_rom = _data_start_btdm_rom as *const u8;
418
419        let len = data_end as usize - data_start as usize;
420
421        core::ptr::copy_nonoverlapping(data_start_rom, data_start, len);
422
423        debug!(
424            "btdm_controller_mem_init {:?} {:?} {}",
425            data_start_rom, data_start, len,
426        );
427    }
428
429    // initialize em, .bss section
430    let btdm_dram_regions = BTDM_DRAM_AVAILABLE_REGION.len();
431
432    #[allow(clippy::needless_range_loop)] // the alternative looks worse
433    for i in 1..btdm_dram_regions {
434        if BTDM_DRAM_AVAILABLE_REGION[i].mode != esp_bt_mode_t_ESP_BT_MODE_IDLE {
435            unsafe {
436                core::ptr::write_bytes(
437                    BTDM_DRAM_AVAILABLE_REGION[i].start as *mut u8,
438                    0x0,
439                    (BTDM_DRAM_AVAILABLE_REGION[i].end - BTDM_DRAM_AVAILABLE_REGION[i].start)
440                        as usize,
441                );
442            }
443            debug!(
444                ".bss initialise {:x} - {:x}\n",
445                BTDM_DRAM_AVAILABLE_REGION[i].start, BTDM_DRAM_AVAILABLE_REGION[i].end
446            );
447        }
448    }
449
450    debug!("btdm_controller_mem_init done");
451}
452
453pub(crate) fn bt_periph_module_enable() {
454    // nothing
455}
456
457pub(crate) fn disable_sleep_mode() {
458    unsafe extern "C" {
459        fn btdm_controller_set_sleep_mode(mode: u8);
460    }
461
462    const BTDM_MODEM_SLEEP_MODE_NONE: u8 = 0;
463
464    unsafe {
465        btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE);
466    }
467}
468
469pub(crate) unsafe extern "C" fn coex_bt_wakeup_request() -> bool {
470    trace!("coex_bt_wakeup_request");
471
472    // This should really be
473    // ```rust,norun
474    // #[cfg(coex)]
475    // return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
476    // #[cfg(not(coex))]
477    // true
478    // ```
479    //
480    // But doing the right thing here keeps BT from working.
481    // In a similar scenario this function isn't called in ESP-IDF.
482    true
483}
484
485pub(crate) unsafe extern "C" fn coex_bt_wakeup_request_end() {
486    trace!("coex_bt_wakeup_request_end");
487
488    // This should really be
489    // ```rust,norun
490    // #[cfg(coex)]
491    // async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
492    // ```
493    //
494    // But doing the right thing here keeps BT from working.
495    // In a similar scenario this function isn't called in ESP-IDF.
496}
497
498#[allow(unused_variables)]
499pub(crate) unsafe extern "C" fn coex_bt_request(event: u32, latency: u32, duration: u32) -> i32 {
500    trace!("coex_bt_request");
501    unsafe extern "C" {
502        #[cfg(coex)]
503        fn coex_bt_request(event: u32, latency: u32, duration: u32) -> i32;
504    }
505
506    #[cfg(coex)]
507    return unsafe { coex_bt_request(event, latency, duration) };
508
509    #[cfg(not(coex))]
510    0
511}
512
513#[allow(unused_variables)]
514pub(crate) unsafe extern "C" fn coex_bt_release(event: u32) -> i32 {
515    trace!("coex_bt_release");
516    unsafe extern "C" {
517        #[cfg(coex)]
518        fn coex_bt_release(event: u32) -> i32;
519    }
520
521    #[cfg(coex)]
522    return unsafe { coex_bt_release(event) };
523
524    #[cfg(not(coex))]
525    0
526}
527
528pub(crate) unsafe extern "C" fn coex_register_bt_cb_wrapper(
529    callback: unsafe extern "C" fn(),
530) -> i32 {
531    trace!("coex_register_bt_cb {:?}", callback);
532    unsafe extern "C" {
533        #[cfg(coex)]
534        fn coex_register_bt_cb(callback: unsafe extern "C" fn()) -> i32;
535    }
536
537    #[cfg(coex)]
538    return unsafe { coex_register_bt_cb(callback) };
539
540    #[cfg(not(coex))]
541    0
542}
543
544pub(crate) unsafe extern "C" fn coex_bb_reset_lock() -> u32 {
545    trace!("coex_bb_reset_lock");
546    unsafe extern "C" {
547        #[cfg(coex)]
548        fn coex_bb_reset_lock() -> u32;
549    }
550
551    #[cfg(coex)]
552    return unsafe { coex_bb_reset_lock() };
553
554    #[cfg(not(coex))]
555    0
556}
557
558#[allow(unused_variables)]
559pub(crate) unsafe extern "C" fn coex_bb_reset_unlock(event: u32) {
560    trace!("coex_bb_reset_unlock");
561    unsafe extern "C" {
562        #[cfg(coex)]
563        fn coex_bb_reset_unlock(event: u32);
564    }
565
566    #[cfg(coex)]
567    unsafe {
568        coex_bb_reset_unlock(event)
569    };
570}
571
572pub(crate) unsafe extern "C" fn coex_schm_register_btdm_callback_wrapper(
573    callback: unsafe extern "C" fn(),
574) -> i32 {
575    trace!("coex_schm_register_btdm_callback {:?}", callback);
576    unsafe extern "C" {
577        #[cfg(coex)]
578        fn coex_schm_register_callback(kind: u32, callback: unsafe extern "C" fn()) -> i32;
579    }
580
581    #[cfg(coex)]
582    return unsafe { coex_schm_register_callback(1, callback) }; // COEX_SCHM_CALLBACK_TYPE_BT = 1
583
584    #[cfg(not(coex))]
585    0
586}
587
588pub(crate) unsafe extern "C" fn coex_schm_interval_get() -> u32 {
589    trace!("coex_schm_interval_get");
590
591    #[cfg(coex)]
592    return unsafe { crate::binary::include::coex_schm_interval_get() };
593
594    #[cfg(not(coex))]
595    0
596}
597
598pub(crate) unsafe extern "C" fn coex_schm_curr_period_get() -> u8 {
599    trace!("coex_schm_curr_period_get");
600
601    #[cfg(coex)]
602    return unsafe { crate::binary::include::coex_schm_curr_period_get() };
603
604    #[cfg(not(coex))]
605    0
606}
607
608pub(crate) unsafe extern "C" fn coex_schm_curr_phase_get() -> *const () {
609    trace!("coex_schm_curr_phase_get");
610
611    #[cfg(coex)]
612    return unsafe { crate::binary::include::coex_schm_curr_phase_get() } as *const ();
613
614    #[cfg(not(coex))]
615    return core::ptr::null::<()>();
616}
617
618#[allow(unused_variables)]
619pub(crate) unsafe extern "C" fn coex_wifi_channel_get(primary: *mut u8, secondary: *mut u8) -> i32 {
620    trace!("coex_wifi_channel_get");
621    unsafe extern "C" {
622        #[cfg(coex)]
623        fn coex_wifi_channel_get(primary: *mut u8, secondary: *mut u8) -> i32;
624    }
625
626    #[cfg(coex)]
627    return unsafe { coex_wifi_channel_get(primary, secondary) };
628
629    #[cfg(not(coex))]
630    -1
631}
632
633#[allow(unused_variables)]
634pub(crate) unsafe extern "C" fn coex_register_wifi_channel_change_callback(
635    callback: unsafe extern "C" fn(),
636) -> i32 {
637    trace!("coex_register_wifi_channel_change_callback");
638    unsafe extern "C" {
639        #[cfg(coex)]
640        fn coex_register_wifi_channel_change_callback(callback: unsafe extern "C" fn()) -> i32;
641    }
642
643    #[cfg(coex)]
644    return unsafe { coex_register_wifi_channel_change_callback(callback) };
645
646    #[cfg(not(coex))]
647    0
648}
649
650pub(crate) unsafe extern "C" fn set_isr(n: i32, f: unsafe extern "C" fn(), arg: *const ()) -> i32 {
651    trace!("set_isr called {} {:?} {:?}", n, f, arg);
652
653    match n {
654        5 => {
655            unsafe {
656                ISR_INTERRUPT_5 = (f as *mut c_void, arg as *mut c_void);
657            }
658            unwrap!(interrupt::enable(
659                Interrupt::RWBT,
660                interrupt::Priority::Priority1
661            ));
662            unwrap!(interrupt::enable(
663                Interrupt::RWBLE,
664                interrupt::Priority::Priority1
665            ));
666        }
667        7 => unsafe {
668            ISR_INTERRUPT_7 = (f as *mut c_void, arg as *mut c_void);
669        },
670        8 => {
671            unsafe {
672                ISR_INTERRUPT_8 = (f as *mut c_void, arg as *mut c_void);
673            }
674            unwrap!(interrupt::enable(
675                Interrupt::BT_BB,
676                interrupt::Priority::Priority1,
677            ));
678        }
679        _ => panic!("set_isr - unsupported interrupt number {}", n),
680    }
681
682    0
683}
684
685pub(crate) unsafe extern "C" fn ints_on(mask: u32) {
686    trace!("chip_ints_on esp32 {:b}", mask);
687    unsafe {
688        crate::hal::xtensa_lx::interrupt::enable_mask(mask);
689    }
690}
691
692#[cfg(coex)]
693pub(crate) const BTDM_ASYNC_WAKEUP_REQ_HCI: i32 = 0;
694
695#[cfg(coex)]
696pub(crate) const BTDM_ASYNC_WAKEUP_REQ_COEX: i32 = 1;
697
698// const BTDM_ASYNC_WAKEUP_REQMAX: i32 = 2;
699
700/// **************************************************************************
701/// Name: async_wakeup_request
702///
703/// Description:
704///   Request the BLE Controller to wakeup
705///
706/// Input Parameters:
707///   event - the event that triggered the wakeup
708///
709/// Returned Value:
710///   true if request lock is needed, false otherwise
711///
712/// *************************************************************************
713#[cfg(coex)]
714pub(crate) fn async_wakeup_request(event: i32) -> bool {
715    trace!("async_wakeup_request {}", event);
716
717    unsafe extern "C" {
718        fn btdm_in_wakeup_requesting_set(set: bool);
719
720        fn btdm_power_state_active() -> bool;
721
722        fn btdm_wakeup_request();
723    }
724
725    match event {
726        e if e == BTDM_ASYNC_WAKEUP_REQ_HCI => {
727            unsafe {
728                btdm_in_wakeup_requesting_set(true);
729            }
730            false
731        }
732        e if e == BTDM_ASYNC_WAKEUP_REQ_COEX => {
733            unsafe {
734                btdm_in_wakeup_requesting_set(true);
735            }
736
737            if !unsafe { btdm_power_state_active() } {
738                unsafe {
739                    btdm_wakeup_request();
740                }
741                true
742            } else {
743                false
744            }
745        }
746        _ => false,
747    }
748}
749
750/// **************************************************************************
751/// Name: async_wakeup_request_end
752///
753/// Description:
754///   Finish a wakeup request
755///
756/// Input Parameters:
757///   event - the event that triggered the wakeup
758///
759/// Returned Value:
760///   true if request lock is needed, false otherwise
761///
762/// *************************************************************************
763#[cfg(coex)]
764pub(crate) fn async_wakeup_request_end(event: i32) {
765    trace!("async_wakeup_request_end {}", event);
766
767    let request_lock = match event {
768        e if e == BTDM_ASYNC_WAKEUP_REQ_HCI => true,
769        e if e == BTDM_ASYNC_WAKEUP_REQ_COEX => false,
770        _ => return,
771    };
772
773    unsafe extern "C" {
774        fn btdm_in_wakeup_requesting_set(set: bool);
775    }
776
777    if request_lock {
778        unsafe { btdm_in_wakeup_requesting_set(false) };
779    }
780}