1use esp_hal::efuse::Efuse;
2use procmacros::BuilderLite;
3
4use super::*;
5use crate::{
6 binary::include::esp_bt_controller_config_t,
7 ble::InvalidConfigError,
8 hal::{
9 clock::ModemClockController,
10 interrupt,
11 peripherals::{BT, Interrupt},
12 },
13};
14
15pub(crate) static mut ISR_INTERRUPT_4: (*mut c_void, *mut c_void) =
16 (core::ptr::null_mut(), core::ptr::null_mut());
17
18pub(crate) static mut ISR_INTERRUPT_7: (*mut c_void, *mut c_void) =
19 (core::ptr::null_mut(), core::ptr::null_mut());
20
21#[derive(Default, Clone, Copy, Eq, PartialEq)]
23#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum TxPower {
26 N15,
28 N12,
30 N9,
32 N6,
34 N3,
36 N0,
38 P3,
40 P6,
42 #[default]
44 P9,
45 P12,
47 P15,
49 P18,
51 P20,
53}
54
55#[allow(dead_code)]
56impl TxPower {
57 fn idx(self) -> esp_power_level_t {
58 match self {
59 Self::N15 => esp_power_level_t_ESP_PWR_LVL_N15,
60 Self::N12 => esp_power_level_t_ESP_PWR_LVL_N12,
61 Self::N9 => esp_power_level_t_ESP_PWR_LVL_N9,
62 Self::N6 => esp_power_level_t_ESP_PWR_LVL_N6,
63 Self::N3 => esp_power_level_t_ESP_PWR_LVL_N3,
64 Self::N0 => esp_power_level_t_ESP_PWR_LVL_N0,
65 Self::P3 => esp_power_level_t_ESP_PWR_LVL_P3,
66 Self::P6 => esp_power_level_t_ESP_PWR_LVL_P6,
67 Self::P9 => esp_power_level_t_ESP_PWR_LVL_P9,
68 Self::P12 => esp_power_level_t_ESP_PWR_LVL_P12,
69 Self::P15 => esp_power_level_t_ESP_PWR_LVL_P15,
70 Self::P18 => esp_power_level_t_ESP_PWR_LVL_P18,
71 Self::P20 => esp_power_level_t_ESP_PWR_LVL_P20,
72 }
73 }
74
75 fn dbm(self) -> i8 {
76 match self {
77 Self::N15 => -15,
78 Self::N12 => -12,
79 Self::N9 => -9,
80 Self::N6 => -6,
81 Self::N3 => -3,
82 Self::N0 => 0,
83 Self::P3 => 3,
84 Self::P6 => 6,
85 Self::P9 => 9,
86 Self::P12 => 12,
87 Self::P15 => 15,
88 Self::P18 => 18,
89 Self::P20 => 20,
90 }
91 }
92}
93
94#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
96#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
97#[cfg_attr(feature = "defmt", derive(defmt::Format))]
98pub struct Config {
99 task_priority: u8,
101
102 task_stack_size: u16,
104
105 max_connections: u16,
109
110 qa_test_mode: bool,
112
113 bqb_test: bool,
115
116 ll_resolv_list_size: u16,
118
119 ll_sync_list_cnt: u8,
123
124 ll_sync_cnt: u8,
128
129 ll_rsp_dup_list_count: u16,
133
134 ll_adv_dup_list_count: u16,
138
139 verify_access_address: bool,
146
147 channel_assessment: bool,
149
150 default_tx_power: TxPower,
152
153 hci_high_buffer_count: u16,
155
156 hci_low_buffer_count: u16,
158
159 whitelist_size: u8,
161
162 acl_buf_size: u16,
164
165 acl_buf_count: u16,
167
168 hci_evt_buf_size: u16,
170
171 multi_adv_instances: u16,
173
174 ext_adv_max_size: u16,
178
179 dis_scan_backoff: bool,
181
182 scan_backoff_max: u16,
188
189 cca: bool,
191
192 cca_threshold: u8,
201
202 data_length_zero_aux: bool,
204
205 disconnect_llcp_conn_update: bool,
207
208 disconnect_llcp_chan_map_update: bool,
210
211 disconnect_llcp_phy_update: bool,
213}
214
215impl Default for Config {
216 fn default() -> Self {
217 Self {
218 task_priority: 29,
220 task_stack_size: 4096,
221 max_connections: 2,
222 qa_test_mode: false,
223 bqb_test: false,
224 ll_resolv_list_size: 4,
225 ll_sync_list_cnt: 5,
226 ll_sync_cnt: 0,
227 ll_rsp_dup_list_count: 20,
228 ll_adv_dup_list_count: 20,
229 default_tx_power: TxPower::default(),
230 hci_high_buffer_count: 30,
231 hci_low_buffer_count: 8,
232 whitelist_size: 12,
233 acl_buf_size: 255,
234 acl_buf_count: 24,
235 hci_evt_buf_size: 70,
236 multi_adv_instances: 1,
237 ext_adv_max_size: 31,
238 dis_scan_backoff: false,
239 scan_backoff_max: 256,
240 verify_access_address: false,
241 disconnect_llcp_conn_update: false,
242 disconnect_llcp_chan_map_update: false,
243 disconnect_llcp_phy_update: false,
244 cca_threshold: 65,
245 cca: false,
246 channel_assessment: false,
247 data_length_zero_aux: false,
248 }
249 }
250}
251
252impl Config {
253 pub(crate) fn validate(&self) -> Result<(), InvalidConfigError> {
254 crate::ble::validate_range!(self, max_connections, 1, 70);
255 crate::ble::validate_range!(self, ll_sync_cnt, 0, 3);
256 crate::ble::validate_range!(self, ll_sync_list_cnt, 1, 5);
257 crate::ble::validate_range!(self, ll_rsp_dup_list_count, 1, 100);
258 crate::ble::validate_range!(self, ll_adv_dup_list_count, 1, 100);
259 crate::ble::validate_range!(self, whitelist_size, 1, 31);
260 crate::ble::validate_range!(self, multi_adv_instances, 0, 4);
261 crate::ble::validate_range!(self, ext_adv_max_size, 0, 1650);
262 crate::ble::validate_range!(self, scan_backoff_max, 1, 256);
263 crate::ble::validate_range!(self, cca_threshold, 20, 100);
264 Ok(())
265 }
266}
267
268pub(crate) fn create_ble_config(config: &Config) -> esp_bt_controller_config_t {
269 esp_bt_controller_config_t {
272 config_version: CONFIG_VERSION,
273 ble_ll_resolv_list_size: config.ll_resolv_list_size,
274 ble_hci_evt_hi_buf_count: config.hci_high_buffer_count,
275 ble_hci_evt_lo_buf_count: config.hci_low_buffer_count,
276 ble_ll_sync_list_cnt: config.ll_sync_list_cnt,
277 ble_ll_sync_cnt: config.ll_sync_cnt,
278 ble_ll_rsp_dup_list_count: config.ll_rsp_dup_list_count,
279 ble_ll_adv_dup_list_count: config.ll_adv_dup_list_count,
280 ble_ll_tx_pwr_dbm: config.default_tx_power.dbm() as u8,
281 rtc_freq: 32000,
282 ble_ll_sca: 60,
283 ble_ll_scan_phy_number: 2,
284 ble_ll_conn_def_auth_pyld_tmo: 3000,
285 ble_ll_jitter_usecs: 16,
286 ble_ll_sched_max_adv_pdu_usecs: 376,
287 ble_ll_sched_direct_adv_max_usecs: 502,
288 ble_ll_sched_adv_max_usecs: 852,
289 ble_scan_rsp_data_max_len: 31,
290 ble_ll_cfg_num_hci_cmd_pkts: 1,
291 ble_ll_ctrl_proc_timeout_ms: 40000,
292 nimble_max_connections: config.max_connections,
293 ble_whitelist_size: config.whitelist_size,
294 ble_acl_buf_size: config.acl_buf_size,
295 ble_acl_buf_count: config.acl_buf_count,
296 ble_hci_evt_buf_size: config.hci_evt_buf_size,
297 ble_multi_adv_instances: config.multi_adv_instances,
298 ble_ext_adv_max_size: config.ext_adv_max_size,
299 controller_task_stack_size: config.task_stack_size,
300 controller_task_prio: config.task_priority,
301 controller_run_cpu: 0,
302 enable_qa_test: config.qa_test_mode as u8,
303 enable_bqb_test: config.bqb_test as u8,
304 enable_tx_cca: config.cca as u8,
305 cca_rssi_thresh: (256 - config.cca_threshold as u32) as u8,
306 sleep_en: 0,
307 coex_phy_coded_tx_rx_time_limit: 0,
308 dis_scan_backoff: config.dis_scan_backoff as u8,
309 ble_scan_classify_filter_enable: 1,
310 cca_drop_mode: 0, cca_low_tx_pwr: 0, main_xtal_freq: 40,
313 ignore_wl_for_direct_adv: 0,
314 cpu_freq_mhz: 160,
315 enable_pcl: 0, version_num: Efuse::minor_chip_version() as u32,
317 csa2_select: 1,
318 enable_csr: 0,
319 ble_aa_check: config.verify_access_address as u8,
320 ble_llcp_disc_flag: config.disconnect_llcp_conn_update as u8
321 | ((config.disconnect_llcp_chan_map_update as u8) << 1)
322 | ((config.disconnect_llcp_phy_update as u8) << 2),
323 scan_backoff_upperlimitmax: config.scan_backoff_max,
324 ble_chan_ass_en: config.channel_assessment as u8,
325 ble_data_lenth_zero_aux: config.data_length_zero_aux as u8,
326 vhci_enabled: 1,
327 ptr_check_enabled: 0,
328 ble_adv_tx_options: 0,
329 skip_unnecessary_checks_en: 0,
330 fast_conn_data_tx_en: 0,
331 ch39_txpwr: 9,
332 adv_rsv_cnt: 1,
333 conn_rsv_cnt: 2,
334 config_magic: CONFIG_MAGIC,
335 }
336}
337
338pub(crate) fn bt_periph_module_enable() {
339 let mut bt = unsafe { BT::steal() };
342 bt.enable_modem_clock(true);
343}
344
345pub(crate) fn disable_sleep_mode() {
346 }
348
349pub(super) unsafe extern "C" fn esp_intr_alloc(
350 source: u32,
351 flags: u32,
352 handler: *mut c_void,
353 arg: *mut c_void,
354 ret_handle: *mut *mut c_void,
355) -> i32 {
356 trace!(
357 "esp_intr_alloc {} {} {:?} {:?} {:?}",
358 source, flags, handler, arg, ret_handle
359 );
360
361 unsafe {
362 match source {
363 4 => {
364 ISR_INTERRUPT_4 = (handler, arg);
365 unwrap!(interrupt::enable(
366 Interrupt::BT_MAC,
367 interrupt::Priority::Priority1
368 ));
369 }
370 7 => {
371 ISR_INTERRUPT_7 = (handler, arg);
372 unwrap!(interrupt::enable(
373 Interrupt::LP_TIMER,
374 interrupt::Priority::Priority1
375 ));
376 }
377 _ => panic!("Unexpected interrupt source {}", source),
378 }
379 }
380
381 0
382}
383
384pub(super) fn ble_rtc_clk_init() {
385 let mut bt = unsafe { BT::steal() };
388 bt.ble_rtc_clk_init();
389}
390
391pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() {
392 trace!("esp_reset_rpa_moudle");
393 let mut bt = unsafe { BT::steal() };
396 bt.reset_rpa();
397}