esp_radio/ble/
os_adapter_esp32.rs

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