Skip to main content

esp_radio/ble/
os_adapter_esp32c3_s3.rs

1use procmacros::BuilderLite;
2
3use super::*;
4#[cfg(multi_core)]
5use crate::hal::system::Cpu;
6use crate::{
7    ble::InvalidConfigError,
8    common_adapter::*,
9    hal::{interrupt::Priority, peripherals::BT},
10    interrupt_dispatch::Handler,
11};
12
13static ISR_INTERRUPT_5: Handler = Handler::new();
14static ISR_INTERRUPT_8: Handler = Handler::new();
15
16#[repr(C)]
17pub(super) struct osi_funcs_s {
18    magic: u32,
19    version: u32,
20    interrupt_alloc: Option<
21        unsafe extern "C" fn(i32, i32, extern "C" fn(*const ()), *const (), *mut *const ()) -> i32,
22    >,
23    interrupt_free: Option<unsafe extern "C" fn(*const ()) -> i32>,
24    interrupt_handler_set: Option<unsafe extern "C" fn(i32, extern "C" fn(*const ()), *const ())>,
25    interrupt_disable: Option<unsafe extern "C" fn()>,
26    interrupt_restore: Option<unsafe extern "C" fn()>,
27    task_yield: Option<unsafe extern "C" fn()>,
28    task_yield_from_isr: Option<unsafe extern "C" fn()>,
29    semphr_create: Option<unsafe extern "C" fn(u32, u32) -> *mut c_void>,
30    semphr_delete: Option<unsafe extern "C" fn(*mut c_void)>,
31    semphr_take_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut bool) -> i32>,
32    semphr_give_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut bool) -> i32>,
33    semphr_take: Option<unsafe extern "C" fn(*mut c_void, u32) -> i32>,
34    semphr_give: Option<unsafe extern "C" fn(*mut c_void) -> i32>,
35    mutex_create: Option<unsafe extern "C" fn() -> *const ()>,
36    mutex_delete: Option<unsafe extern "C" fn(*const ())>,
37    mutex_lock: Option<unsafe extern "C" fn(*const ()) -> i32>,
38    mutex_unlock: Option<unsafe extern "C" fn(*const ()) -> i32>,
39    queue_create: Option<unsafe extern "C" fn(u32, u32) -> *mut c_void>,
40    queue_delete: Option<unsafe extern "C" fn(*mut c_void)>,
41    queue_send: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, u32) -> i32>,
42    queue_send_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void) -> i32>,
43    queue_recv: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, u32) -> i32>,
44    queue_recv_from_isr: Option<unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void) -> i32>,
45    task_create: Option<
46        unsafe extern "C" fn(
47            *mut c_void,
48            *const c_char,
49            u32,
50            *mut c_void,
51            u32,
52            *mut c_void,
53            u32,
54        ) -> i32,
55    >,
56    task_delete: Option<unsafe extern "C" fn(*mut ())>,
57    is_in_isr: Option<unsafe extern "C" fn() -> i32>,
58    cause_sw_intr_to_core: Option<unsafe extern "C" fn(i32, i32) -> i32>,
59    malloc: Option<unsafe extern "C" fn(u32) -> *mut c_void>,
60    malloc_internal: Option<unsafe extern "C" fn(u32) -> *mut c_void>,
61    free: Option<unsafe extern "C" fn(*mut c_void)>,
62    read_efuse_mac: Option<unsafe extern "C" fn(*const ()) -> i32>,
63    srand: Option<unsafe extern "C" fn(u32)>,
64    rand: Option<unsafe extern "C" fn() -> i32>,
65    btdm_lpcycles_2_hus: Option<unsafe extern "C" fn(u32, u32) -> u32>,
66    btdm_hus_2_lpcycles: Option<unsafe extern "C" fn(u32) -> u32>,
67    btdm_sleep_check_duration: Option<unsafe extern "C" fn(i32) -> i32>,
68    btdm_sleep_enter_phase1: Option<unsafe extern "C" fn(i32)>,
69    btdm_sleep_enter_phase2: Option<unsafe extern "C" fn()>,
70    btdm_sleep_exit_phase1: Option<unsafe extern "C" fn()>,
71    btdm_sleep_exit_phase2: Option<unsafe extern "C" fn()>,
72    btdm_sleep_exit_phase3: Option<unsafe extern "C" fn()>,
73    coex_wifi_sleep_set: Option<unsafe extern "C" fn(i32)>,
74    coex_core_ble_conn_dyn_prio_get: Option<unsafe extern "C" fn(*mut i32, *mut i32) -> i32>,
75    coex_schm_register_btdm_callback: Option<unsafe extern "C" fn(*mut c_void) -> i32>,
76    coex_schm_status_bit_set: Option<unsafe extern "C" fn(i32, i32)>,
77    coex_schm_status_bit_clear: Option<unsafe extern "C" fn(i32, i32)>,
78    coex_schm_interval_get: Option<unsafe extern "C" fn() -> u32>,
79    coex_schm_curr_period_get: Option<unsafe extern "C" fn() -> u8>,
80    coex_schm_curr_phase_get: Option<unsafe extern "C" fn() -> *mut c_void>,
81    interrupt_on: Option<unsafe extern "C" fn(i32) -> i32>,
82    interrupt_off: Option<unsafe extern "C" fn(i32) -> i32>,
83    esp_hw_power_down: Option<unsafe extern "C" fn()>,
84    esp_hw_power_up: Option<unsafe extern "C" fn()>,
85    ets_backup_dma_copy: Option<unsafe extern "C" fn(u32, u32, u32, i32)>,
86    malloc_retention: Option<unsafe extern "C" fn(u32) -> *mut c_void>,
87    ets_delay_us: Option<unsafe extern "C" fn(u32)>,
88    btdm_rom_table_ready: Option<unsafe extern "C" fn()>,
89    coex_bt_wakeup_request: Option<unsafe extern "C" fn()>,
90    coex_bt_wakeup_request_end: Option<unsafe extern "C" fn()>,
91    get_time_us: Option<unsafe extern "C" fn() -> u64>,
92    assert: Option<unsafe extern "C" fn()>,
93}
94
95pub(super) static G_OSI_FUNCS: osi_funcs_s = osi_funcs_s {
96    magic: 0xfadebead,
97    version: 0x0001000B,
98    interrupt_alloc: Some(interrupt_set),
99    interrupt_free: Some(interrupt_clear),
100    interrupt_handler_set: Some(interrupt_handler_set),
101    interrupt_disable: Some(interrupt_disable),
102    interrupt_restore: Some(interrupt_enable),
103    task_yield: Some(task_yield),
104    task_yield_from_isr: Some(task_yield_from_isr),
105    semphr_create: Some(semphr_create),
106    semphr_delete: Some(semphr_delete),
107    semphr_take_from_isr: Some(semphr_take_from_isr),
108    semphr_give_from_isr: Some(semphr_give_from_isr),
109    semphr_take: Some(semphr_take),
110    semphr_give: Some(semphr_give),
111    mutex_create: Some(mutex_create),
112    mutex_delete: Some(mutex_delete),
113    mutex_lock: Some(mutex_lock),
114    mutex_unlock: Some(mutex_unlock),
115    queue_create: Some(queue_create),
116    queue_delete: Some(queue_delete),
117    queue_send: Some(queue_send),
118    queue_send_from_isr: Some(queue_send_from_isr),
119    queue_recv: Some(queue_recv),
120    queue_recv_from_isr: Some(queue_recv_from_isr),
121    task_create: Some(task_create),
122    task_delete: Some(task_delete),
123    is_in_isr: Some(is_in_isr),
124    cause_sw_intr_to_core: None,
125    malloc: Some(crate::ble::malloc),
126    malloc_internal: Some(crate::ble::malloc_internal),
127    free: Some(crate::ble::free),
128    read_efuse_mac: Some(read_efuse_mac),
129    srand: Some(crate::ble::btdm::srand),
130    rand: Some(crate::ble::btdm::rand),
131    btdm_lpcycles_2_hus: Some(btdm_lpcycles_2_hus),
132    btdm_hus_2_lpcycles: Some(btdm_hus_2_lpcycles),
133    btdm_sleep_check_duration: Some(btdm_sleep_check_duration),
134    btdm_sleep_enter_phase1: Some(btdm_sleep_enter_phase1),
135    btdm_sleep_enter_phase2: Some(btdm_sleep_enter_phase2),
136    btdm_sleep_exit_phase1: Some(btdm_sleep_exit_phase1),
137    btdm_sleep_exit_phase2: Some(btdm_sleep_exit_phase2),
138    btdm_sleep_exit_phase3: Some(btdm_sleep_exit_phase3),
139    coex_wifi_sleep_set: Some(coex_wifi_sleep_set),
140    coex_core_ble_conn_dyn_prio_get: Some(coex_core_ble_conn_dyn_prio_get),
141    coex_schm_register_btdm_callback: Some(coex_schm_register_btdm_callback),
142    coex_schm_status_bit_set: Some(coex_schm_status_bit_set),
143    coex_schm_status_bit_clear: Some(coex_schm_status_bit_clear),
144    coex_schm_interval_get: Some(coex_schm_interval_get),
145    coex_schm_curr_period_get: Some(coex_schm_curr_period_get),
146    coex_schm_curr_phase_get: Some(coex_schm_curr_phase_get),
147    interrupt_on: Some(interrupt_on),
148    interrupt_off: Some(interrupt_off),
149    esp_hw_power_down: Some(esp_hw_power_down),
150    esp_hw_power_up: Some(esp_hw_power_up),
151    ets_backup_dma_copy: Some(ets_backup_dma_copy),
152    malloc_retention: Some(crate::ble::malloc_retention),
153    ets_delay_us: Some(ets_delay_us_wrapper),
154    btdm_rom_table_ready: Some(btdm_rom_table_ready_wrapper),
155    coex_bt_wakeup_request: Some(coex_bt_wakeup_request),
156    coex_bt_wakeup_request_end: Some(coex_bt_wakeup_request_end),
157    get_time_us: Some(get_time_us_wrapper),
158    assert: Some(assert_wrapper),
159};
160
161extern "C" fn get_time_us_wrapper() -> u64 {
162    // Get time in microseconds since boot
163    crate::preempt::now()
164}
165
166extern "C" fn assert_wrapper() {
167    panic!("assert_wrapper called - inspect the logs");
168}
169
170extern_coex_fns! {
171    fn coex_core_ble_conn_dyn_prio_get(low: *mut i32, high: *mut i32) -> i32;
172}
173
174coex_fns! {
175    fn coex_schm_interval_get() -> u32;
176    fn coex_schm_curr_period_get() -> u8;
177    fn coex_schm_curr_phase_get() -> *mut c_void;
178}
179
180extern "C" fn coex_schm_register_btdm_callback(_callback: *mut c_void) -> i32 {
181    trace!("coex_schm_register_btdm_callback");
182
183    cfg_select! {
184        feature = "coex" => unsafe {
185            const COEX_SCHM_CALLBACK_TYPE_BT: u32 = 1;
186            coex_schm_register_callback(COEX_SCHM_CALLBACK_TYPE_BT, _callback)
187        },
188        _ => 0,
189    }
190}
191
192extern "C" fn coex_bt_wakeup_request() {
193    trace!("coex_bt_wakeup_request");
194
195    unsafe extern "C" {
196        fn btdm_wakeup_request();
197    }
198
199    unsafe {
200        btdm_wakeup_request();
201    }
202}
203
204extern "C" fn coex_bt_wakeup_request_end() {
205    trace!("coex_bt_wakeup_request_end");
206
207    unsafe extern "C" {
208        fn btdm_in_wakeup_requesting_set(set: bool);
209    }
210
211    unsafe {
212        btdm_in_wakeup_requesting_set(false);
213    }
214}
215
216extern "C" fn ets_delay_us_wrapper(us: u32) {
217    unsafe extern "C" {
218        fn ets_delay_us(us: u32);
219    }
220
221    unsafe {
222        ets_delay_us(us);
223    }
224}
225
226extern "C" fn btdm_rom_table_ready_wrapper() {
227    trace!("btdm_rom_table_ready_wrapper");
228
229    unsafe extern "C" {
230        // fn ble_cca_funcs_reset();
231        fn ble_dtm_funcs_reset();
232        fn ble_42_adv_funcs_reset();
233        fn ble_init_funcs_reset();
234        fn ble_con_funcs_reset();
235        fn ble_scan_funcs_reset();
236        fn ble_ext_adv_funcs_reset();
237        fn ble_ext_scan_funcs_reset();
238        fn ble_base_funcs_reset();
239        fn ble_enc_funcs_reset();
240    }
241
242    unsafe {
243        ble_base_funcs_reset();
244        ble_42_adv_funcs_reset();
245        ble_ext_adv_funcs_reset();
246        ble_dtm_funcs_reset();
247        ble_scan_funcs_reset();
248        ble_ext_scan_funcs_reset();
249        ble_enc_funcs_reset();
250        ble_init_funcs_reset();
251        ble_con_funcs_reset();
252    }
253}
254
255unsafe extern "C" {
256    fn btdm_controller_rom_data_init() -> i32;
257}
258
259/// Antenna Selection
260#[derive(Default, Clone, Copy, Eq, PartialEq)]
261#[cfg_attr(feature = "defmt", derive(defmt::Format))]
262pub enum Antenna {
263    /// Use Antenna 0
264    #[default]
265    Antenna0 = 0,
266    /// Use Antenna 1
267    Antenna1 = 1,
268}
269
270/// Transmission Power Level
271#[derive(Default, Clone, Copy, Eq, PartialEq)]
272#[cfg_attr(feature = "defmt", derive(defmt::Format))]
273pub enum TxPower {
274    /// -15 dBm
275    N15,
276    /// -12 dBm
277    N12,
278    /// -9 dBm
279    N9,
280    /// -6 dBm
281    N6,
282    /// -3 dBm
283    N3,
284    /// 0 dBm
285    N0,
286    /// 3 dBm
287    P3,
288    /// 6 dBm
289    P6,
290    /// 9 dBm
291    #[default]
292    P9,
293    /// 12 dBm
294    P12,
295    /// 15 dBm
296    P15,
297    /// 18 dBm
298    P18,
299    /// 20 dBm
300    P20,
301}
302
303impl TxPower {
304    fn idx(self) -> esp_power_level_t {
305        match self {
306            Self::N15 => esp_power_level_t_ESP_PWR_LVL_N15,
307            Self::N12 => esp_power_level_t_ESP_PWR_LVL_N12,
308            Self::N9 => esp_power_level_t_ESP_PWR_LVL_N9,
309            Self::N6 => esp_power_level_t_ESP_PWR_LVL_N6,
310            Self::N3 => esp_power_level_t_ESP_PWR_LVL_N3,
311            Self::N0 => esp_power_level_t_ESP_PWR_LVL_N0,
312            Self::P3 => esp_power_level_t_ESP_PWR_LVL_P3,
313            Self::P6 => esp_power_level_t_ESP_PWR_LVL_P6,
314            Self::P9 => esp_power_level_t_ESP_PWR_LVL_P9,
315            Self::P12 => esp_power_level_t_ESP_PWR_LVL_P12,
316            Self::P15 => esp_power_level_t_ESP_PWR_LVL_P15,
317            Self::P18 => esp_power_level_t_ESP_PWR_LVL_P18,
318            Self::P20 => esp_power_level_t_ESP_PWR_LVL_P20,
319        }
320    }
321
322    #[allow(dead_code)]
323    fn dbm(self) -> i8 {
324        match self {
325            Self::N15 => -15,
326            Self::N12 => -12,
327            Self::N9 => -9,
328            Self::N6 => -6,
329            Self::N3 => -3,
330            Self::N0 => 0,
331            Self::P3 => 3,
332            Self::P6 => 6,
333            Self::P9 => 9,
334            Self::P12 => 12,
335            Self::P15 => 15,
336            Self::P18 => 18,
337            Self::P20 => 20,
338        }
339    }
340}
341
342/// BLE CCA mode.
343#[derive(Default, Clone, Copy, Eq, PartialEq)]
344#[cfg_attr(feature = "defmt", derive(defmt::Format))]
345pub enum CcaMode {
346    /// Disabled
347    #[default]
348    Disabled          = 0,
349    /// Hardware Triggered
350    HardwareTriggered = 1,
351    /// Software Triggered (experimental)
352    SoftwareTriggered = 2,
353}
354
355/// Bluetooth controller configuration.
356#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358pub struct Config {
359    /// The priority of the RTOS task.
360    task_priority: u8,
361
362    /// The stack size of the RTOS task.
363    task_stack_size: u16,
364
365    /// The CPU core on which the BLE controller task should run.
366    #[cfg(multi_core)]
367    task_cpu: Cpu,
368
369    /// The maximum number of simultaneous connections.
370    ///
371    /// Range: 1 - 10
372    max_connections: u8,
373
374    /// Enable QA test mode.
375    qa_test_mode: bool,
376
377    /// Maximum number of devices in scan duplicate filtering list.
378    ///
379    /// Range: 10 - 1000
380    scan_duplicate_list_count: u16,
381
382    /// Scan duplicate filtering list refresh period in seconds.
383    ///
384    /// Range: 0 - 1000 seconds
385    scan_duplicate_refresh_period: u16,
386
387    /// Enables verification of the Access Address within the `CONNECT_IND` PDU.
388    ///
389    /// Enabling this option will add stricter verification of the Access Address in the
390    /// `CONNECT_IND` PDU. This improves security by ensuring that only connection requests with
391    /// valid Access Addresses are accepted. If disabled, only basic checks are applied,
392    /// improving compatibility.
393    // TODO: this needs additional setup
394    verify_access_address: bool,
395
396    /// Enable BLE channel assessment.
397    channel_assessment: bool,
398
399    /// Enable BLE ping procedure.
400    ping: bool,
401
402    /// Default TX antenna.
403    default_tx_antenna: Antenna,
404
405    /// Default RX antenna.
406    default_rx_antenna: Antenna,
407
408    /// Default TX power.
409    default_tx_power: TxPower,
410
411    /// Coexistence: limit on MAX Tx/Rx time for coded-PHY connection.
412    limit_time_for_coded_phy_connection: bool,
413
414    /// Enable / disable uncoded phy / coded phy hardware re-correction.
415    hw_recorrect_en: bool,
416
417    /// BLE Clear Channel Assessment (CCA) mode.
418    cca_mode: CcaMode,
419
420    /// Absolute value of hardware-triggered CCA threshold.
421    ///
422    /// The CCA threshold is always negative.
423    ///
424    /// If the channel assessment result exceeds the CCA threshold (e.g. -75 dBm), indicating
425    /// the channel is busy, the hardware will not transmit packets on that channel.
426    ///
427    /// Range: 20 dBm - 100 dBm
428    cca_threshold: u8,
429
430    /// Enable / disable auxiliary packets when the extended ADV data length is zero.
431    data_length_zero_aux: bool,
432
433    /// Enable / disable DTM.
434    dtm: bool,
435
436    /// Enable / disable encryption.
437    encryption: bool,
438
439    /// Enable / disable connection.
440    connection: bool,
441
442    /// Enable / disable scanning.
443    scan: bool,
444
445    /// Enable / disable ADV.
446    adv: bool,
447
448    /// Disconnect when Instant Passed (0x28) occurs during ACL connection update.
449    disconnect_llcp_conn_update: bool,
450
451    /// Disconnect when Instant Passed (0x28) occurs during ACL channel map update.
452    disconnect_llcp_chan_map_update: bool,
453
454    /// Disconnect when Instant Passed (0x28) occurs during ACL PHY update.
455    disconnect_llcp_phy_update: bool,
456}
457
458impl Default for Config {
459    fn default() -> Self {
460        Self {
461            task_priority: crate::preempt::max_task_priority()
462                .saturating_sub(2)
463                .min(255) as u8,
464            task_stack_size: 8192, // 4096?
465            #[cfg(multi_core)]
466            task_cpu: Cpu::ProCpu,
467            max_connections: 6,
468            qa_test_mode: false,
469            scan_duplicate_list_count: 100,
470            scan_duplicate_refresh_period: 0,
471            verify_access_address: true,
472            channel_assessment: false,
473            ping: false,
474            default_tx_antenna: Antenna::default(),
475            default_rx_antenna: Antenna::default(),
476            default_tx_power: TxPower::default(),
477            limit_time_for_coded_phy_connection: false,
478            hw_recorrect_en: AGC_RECORRECT_EN != 0,
479            cca_threshold: 75, // CONFIG_BT_CTRL_HW_CCA_VAL is 0 which is not valid
480            cca_mode: CcaMode::default(),
481            data_length_zero_aux: false,
482            dtm: true,
483            encryption: true,
484            connection: true,
485            scan: true,
486            adv: true,
487            disconnect_llcp_conn_update: false,
488            disconnect_llcp_chan_map_update: false,
489            disconnect_llcp_phy_update: false,
490        }
491    }
492}
493
494impl Config {
495    pub(crate) fn validate(&self) -> Result<(), InvalidConfigError> {
496        crate::ble::validate_range!(
497            self,
498            task_priority,
499            0,
500            crate::preempt::max_task_priority().min(255) as u8
501        );
502        crate::ble::validate_range!(self, max_connections, 1, 10);
503        crate::ble::validate_range!(self, scan_duplicate_list_count, 10, 1000);
504        crate::ble::validate_range!(self, scan_duplicate_refresh_period, 0, 1000);
505        crate::ble::validate_range!(self, cca_threshold, 20, 100);
506
507        Ok(())
508    }
509}
510
511pub(crate) fn create_ble_config(config: &Config) -> esp_bt_controller_config_t {
512    // keep them aligned with BT_CONTROLLER_INIT_CONFIG_DEFAULT in ESP-IDF
513    // ideally _some_ of these values should be configurable
514    esp_bt_controller_config_t {
515        version: 0x02509280,
516        controller_task_stack_size: config.task_stack_size,
517        controller_task_prio: config.task_priority,
518        #[cfg(multi_core)]
519        controller_task_run_cpu: config.task_cpu as u8,
520        #[cfg(single_core)]
521        controller_task_run_cpu: 0,
522
523        bluetooth_mode: esp_bt_mode_t_ESP_BT_MODE_BLE as _,
524
525        ble_max_act: config.max_connections,
526        sleep_mode: 0,
527        sleep_clock: 0,
528        ble_st_acl_tx_buf_nb: 0,
529        ble_hw_cca_check: 0,
530        ble_adv_dup_filt_max: 30,
531        coex_param_en: false,
532        ce_len_type: 0,
533        coex_use_hooks: false,
534        hci_tl_type: 1,
535        hci_tl_funcs: core::ptr::null_mut(),
536        txant_dft: config.default_tx_antenna as u8,
537        rxant_dft: config.default_rx_antenna as u8,
538        // `txpwr_dft` expects an `esp_power_level_t` index, which is offset by 3
539        // from the plain `TxPower` discriminant (`ESP_PWR_LVL_N15` is 3, not 0).
540        txpwr_dft: config.default_tx_power.idx() as u8,
541        cfg_mask: CFG_MASK,
542
543        // Bluetooth mesh options, currently not supported
544        scan_duplicate_mode: 0, // normal mode
545        scan_duplicate_type: 0,
546        mesh_adv_size: 0,
547
548        normal_adv_size: config.scan_duplicate_list_count,
549        coex_phy_coded_tx_rx_time_limit: if cfg!(feature = "coex") {
550            config.limit_time_for_coded_phy_connection as u8
551        } else {
552            0
553        },
554        hw_target_code: if cfg!(esp32c3) {
555            0x01010000
556        } else {
557            0x02010000
558        },
559        // esp-idf: "Please do not modify this value"
560        slave_ce_len_min: SLAVE_CE_LEN_MIN_DEFAULT as _,
561        hw_recorrect_en: config.hw_recorrect_en as u8,
562        cca_thresh: config.cca_threshold,
563        dup_list_refresh_period: config.scan_duplicate_refresh_period,
564        scan_backoff_upperlimitmax: 0,
565        ble_50_feat_supp: BT_CTRL_50_FEATURE_SUPPORT != 0,
566        ble_cca_mode: config.cca_mode as u8,
567        ble_chan_ass_en: config.channel_assessment as u8,
568        ble_data_lenth_zero_aux: config.data_length_zero_aux as u8,
569        ble_ping_en: config.ping as u8,
570        ble_llcp_disc_flag: config.disconnect_llcp_conn_update as u8
571            | ((config.disconnect_llcp_chan_map_update as u8) << 1)
572            | ((config.disconnect_llcp_phy_update as u8) << 2),
573        run_in_flash: false,
574        dtm_en: config.dtm,
575        enc_en: config.encryption,
576        qa_test: config.qa_test_mode,
577        connect_en: config.connection,
578        scan_en: config.scan,
579        ble_aa_check: config.verify_access_address,
580        adv_en: config.adv,
581        magic: ESP_BT_CTRL_CONFIG_MAGIC_VAL,
582    }
583}
584
585pub(crate) unsafe extern "C" fn interrupt_on(intr_num: i32) -> i32 {
586    trace!("interrupt_on {}", intr_num);
587
588    // NO-OP
589    0
590}
591
592pub(crate) unsafe extern "C" fn interrupt_off(_intr_num: i32) -> i32 {
593    todo!();
594}
595
596pub(crate) fn btdm_controller_mem_init() {
597    unsafe {
598        btdm_controller_rom_data_init();
599    }
600}
601
602pub(crate) fn bt_periph_module_enable() {
603    // nothing
604}
605
606pub(crate) fn disable_sleep_mode() {
607    // nothing
608}
609
610// OSI functions
611
612pub(crate) unsafe extern "C" fn interrupt_set(
613    cpu_no: i32,
614    intr_source: i32,
615    handler: extern "C" fn(*const ()),
616    arg: *const (),
617    ret_handle: *mut *const (),
618) -> i32 {
619    trace!(
620        "interrupt_set {} {} {} {} {}",
621        cpu_no, intr_source, handler as usize, arg as u32, ret_handle as usize,
622    );
623
624    unsafe {
625        interrupt_handler_set(intr_source, handler, arg);
626    }
627
628    0
629}
630
631pub(crate) unsafe extern "C" fn interrupt_clear(_handler: *const ()) -> i32 {
632    todo!();
633}
634
635pub(crate) unsafe extern "C" fn interrupt_handler_set(
636    interrupt_no: i32,
637    func: extern "C" fn(*const ()),
638    arg: *const (),
639) {
640    trace!(
641        "interrupt_handler_set {} {:?} {:?}",
642        interrupt_no, func, arg
643    );
644
645    match interrupt_no {
646        5 => unsafe {
647            ISR_INTERRUPT_5.set(func as *const c_void, arg.cast());
648            #[cfg(esp32c3)]
649            BT::steal().enable_rwbt_interrupt(Priority::Priority1);
650            BT::steal().enable_bb_interrupt(Priority::Priority1);
651        },
652        8 => unsafe {
653            ISR_INTERRUPT_8.set(func as *const c_void, arg.cast());
654            BT::steal().enable_rwble_interrupt(Priority::Priority1);
655        },
656        _ => panic!("Unsupported interrupt number {}", interrupt_no),
657    }
658}
659
660pub(crate) unsafe extern "C" fn coex_wifi_sleep_set(sleep: i32) {
661    trace!(
662        "ignored coex_wifi_sleep_set {} - because original implementation does the same",
663        sleep
664    );
665}
666
667pub(crate) unsafe extern "C" fn esp_hw_power_down() {
668    todo!();
669}
670
671pub(crate) unsafe extern "C" fn esp_hw_power_up() {
672    todo!();
673}
674
675pub(crate) unsafe extern "C" fn ets_backup_dma_copy(
676    _reg: u32,
677    _mem_addr: u32,
678    _num: u32,
679    _to_rem: i32,
680) {
681    todo!();
682}
683
684#[cfg(esp32c3)]
685#[unsafe(no_mangle)]
686#[crate::hal::ram]
687extern "C" fn RWBT() {
688    ISR_INTERRUPT_5.dispatch();
689}
690
691#[unsafe(no_mangle)]
692#[crate::hal::ram]
693extern "C" fn RWBLE() {
694    ISR_INTERRUPT_8.dispatch();
695}
696
697#[unsafe(no_mangle)]
698#[crate::hal::ram]
699extern "C" fn BT_BB() {
700    ISR_INTERRUPT_5.dispatch();
701}
702
703pub(crate) fn shutdown_ble_isr() {
704    unsafe {
705        #[cfg(esp32c3)]
706        BT::steal().disable_rwbt_interrupt_on_all_cores();
707        BT::steal().disable_rwble_interrupt_on_all_cores();
708        BT::steal().disable_bb_interrupt_on_all_cores();
709    }
710}