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