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, end: u32, }
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; static BTDM_DRAM_AVAILABLE_REGION: [btdm_dram_available_region_t; 7] = [
232 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 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 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#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
274#[cfg_attr(feature = "defmt", derive(defmt::Format))]
275pub struct Config {
276 task_priority: u8,
278
279 task_stack_size: u16,
281
282 max_connections: u8,
286
287 scan_duplicate_list_count: u16,
291
292 scan_duplicate_refresh_period: u16,
296
297 ble_scan_backoff: bool,
299
300 enc_key_sz_min: u8,
304
305 verify_access_address: bool,
307
308 channel_assessment: bool,
310
311 ping: bool,
313
314 disconnect_llcp_conn_update: bool,
316
317 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 esp_bt_controller_config_t {
363 controller_task_stack_size: config.task_stack_size,
364 controller_task_prio: config.task_priority,
365
366 hci_uart_no: 1,
368 hci_uart_baudrate: 921600,
369 scan_duplicate_mode: 0, 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 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 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 let btdm_dram_regions = BTDM_DRAM_AVAILABLE_REGION.len();
429
430 #[allow(clippy::needless_range_loop)] 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 }
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 true
481}
482
483pub(crate) unsafe extern "C" fn coex_bt_wakeup_request_end() {
484 trace!("coex_bt_wakeup_request_end");
485
486 }
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#[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#[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}