1use procmacros::BuilderLite;
2
3use super::*;
4use crate::{
5 binary::include::esp_bt_controller_config_t,
6 ble::InvalidConfigError,
7 hal::{
8 clock::ModemClockController,
9 interrupt,
10 peripherals::{BT, Interrupt},
11 },
12};
13
14pub(crate) static mut ISR_INTERRUPT_15: (*mut c_void, *mut c_void) =
15 (core::ptr::null_mut(), core::ptr::null_mut());
16
17pub(crate) static mut ISR_INTERRUPT_3: (*mut c_void, *mut c_void) =
18 (core::ptr::null_mut(), core::ptr::null_mut());
19
20#[derive(Default, Clone, Copy, Eq, PartialEq)]
22#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub enum TxPower {
25 N24,
27 N21,
29 N18,
31 N15,
33 N12,
35 N9,
37 N6,
39 N3,
41 N0,
43 P3,
45 P6,
47 #[default]
49 P9,
50 P12,
52 P15,
54 P18,
56 P20,
58}
59
60#[allow(dead_code)]
61impl TxPower {
62 fn idx(self) -> esp_power_level_t {
63 match self {
64 Self::N24 => esp_power_level_t_ESP_PWR_LVL_N24,
65 Self::N21 => esp_power_level_t_ESP_PWR_LVL_N21,
66 Self::N18 => esp_power_level_t_ESP_PWR_LVL_N18,
67 Self::N15 => esp_power_level_t_ESP_PWR_LVL_N15,
68 Self::N12 => esp_power_level_t_ESP_PWR_LVL_N12,
69 Self::N9 => esp_power_level_t_ESP_PWR_LVL_N9,
70 Self::N6 => esp_power_level_t_ESP_PWR_LVL_N6,
71 Self::N3 => esp_power_level_t_ESP_PWR_LVL_N3,
72 Self::N0 => esp_power_level_t_ESP_PWR_LVL_N0,
73 Self::P3 => esp_power_level_t_ESP_PWR_LVL_P3,
74 Self::P6 => esp_power_level_t_ESP_PWR_LVL_P6,
75 Self::P9 => esp_power_level_t_ESP_PWR_LVL_P9,
76 Self::P12 => esp_power_level_t_ESP_PWR_LVL_P12,
77 Self::P15 => esp_power_level_t_ESP_PWR_LVL_P15,
78 Self::P18 => esp_power_level_t_ESP_PWR_LVL_P18,
79 Self::P20 => esp_power_level_t_ESP_PWR_LVL_P20,
80 }
81 }
82
83 fn dbm(self) -> i8 {
84 match self {
85 Self::N24 => -24,
86 Self::N21 => -21,
87 Self::N18 => -18,
88 Self::N15 => -15,
89 Self::N12 => -12,
90 Self::N9 => -9,
91 Self::N6 => -6,
92 Self::N3 => -3,
93 Self::N0 => 0,
94 Self::P3 => 3,
95 Self::P6 => 6,
96 Self::P9 => 9,
97 Self::P12 => 12,
98 Self::P15 => 15,
99 Self::P18 => 18,
100 Self::P20 => 20,
101 }
102 }
103}
104
105#[derive(BuilderLite, Clone, Copy, Eq, PartialEq)]
107#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))]
109pub struct Config {
110 task_priority: u8,
112
113 task_stack_size: u16,
115
116 max_connections: u16,
120
121 qa_test_mode: bool,
123
124 bqb_test: bool,
126
127 ll_resolv_list_size: u16,
129
130 ll_sync_list_cnt: u8,
134
135 ll_sync_cnt: u8,
139
140 ll_rsp_dup_list_count: u16,
144
145 ll_adv_dup_list_count: u16,
149
150 verify_access_address: bool,
157
158 channel_assessment: bool,
160
161 default_tx_power: TxPower,
163
164 hci_high_buffer_count: u16,
166
167 hci_low_buffer_count: u16,
169
170 whitelist_size: u8,
172
173 acl_buf_size: u16,
175
176 acl_buf_count: u16,
178
179 hci_evt_buf_size: u16,
181
182 multi_adv_instances: u16,
184
185 ext_adv_max_size: u16,
189
190 dis_scan_backoff: bool,
192
193 scan_backoff_max: u16,
199
200 cca: bool,
202
203 cca_threshold: u8,
212
213 data_length_zero_aux: bool,
215
216 disconnect_llcp_conn_update: bool,
218
219 disconnect_llcp_chan_map_update: bool,
221
222 disconnect_llcp_phy_update: bool,
224}
225
226impl Default for Config {
227 fn default() -> Self {
228 Self {
229 task_priority: 29,
231 task_stack_size: CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE as _,
232 max_connections: CONFIG_BT_LE_MAX_CONNECTIONS as _,
233 qa_test_mode: false,
234 bqb_test: false,
235 ll_resolv_list_size: CONFIG_BT_LE_LL_RESOLV_LIST_SIZE as _,
236 ll_sync_list_cnt: CONFIG_BT_LE_MAX_PERIODIC_ADVERTISER_LIST as _,
237 ll_sync_cnt: CONFIG_BT_LE_MAX_PERIODIC_SYNCS as _,
238 ll_rsp_dup_list_count: CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT as _,
239 ll_adv_dup_list_count: CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT as _,
240 default_tx_power: TxPower::default(),
241 hci_high_buffer_count: CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT as _,
242 hci_low_buffer_count: CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT as _,
243 whitelist_size: CONFIG_BT_LE_WHITELIST_SIZE as _,
244 acl_buf_size: CONFIG_BT_LE_ACL_BUF_SIZE as _,
245 acl_buf_count: CONFIG_BT_LE_ACL_BUF_COUNT as _,
246 hci_evt_buf_size: CONFIG_BT_LE_HCI_EVT_BUF_SIZE as _,
247 multi_adv_instances: CONFIG_BT_LE_MAX_EXT_ADV_INSTANCES as _,
248 ext_adv_max_size: CONFIG_BT_LE_EXT_ADV_MAX_SIZE as _,
249 dis_scan_backoff: false,
250 scan_backoff_max: CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX as _,
251 verify_access_address: false,
252 disconnect_llcp_conn_update: false,
253 disconnect_llcp_chan_map_update: false,
254 disconnect_llcp_phy_update: false,
255 cca_threshold: 65,
256 cca: false,
257 channel_assessment: false,
258 data_length_zero_aux: false,
259 }
260 }
261}
262
263impl Config {
264 pub(crate) fn validate(&self) -> Result<(), InvalidConfigError> {
265 crate::ble::validate_range!(self, max_connections, 1, 35);
266 crate::ble::validate_range!(self, ll_rsp_dup_list_count, 1, 100);
267 crate::ble::validate_range!(self, ll_adv_dup_list_count, 1, 100);
268 crate::ble::validate_range!(self, whitelist_size, 1, 31);
269 crate::ble::validate_range!(self, multi_adv_instances, 0, 4);
270 crate::ble::validate_range!(self, ext_adv_max_size, 0, 1650);
271 crate::ble::validate_range!(self, scan_backoff_max, 1, 256);
272 crate::ble::validate_range!(self, cca_threshold, 20, 100);
273 Ok(())
274 }
275}
276
277pub(crate) fn create_ble_config(config: &Config) -> esp_bt_controller_config_t {
278 esp_bt_controller_config_t {
281 config_version: CONFIG_VERSION,
282 ble_ll_resolv_list_size: config.ll_resolv_list_size,
283 ble_hci_evt_hi_buf_count: config.hci_high_buffer_count,
284 ble_hci_evt_lo_buf_count: config.hci_low_buffer_count,
285 ble_ll_sync_list_cnt: config.ll_sync_list_cnt,
286 ble_ll_sync_cnt: config.ll_sync_cnt,
287 ble_ll_rsp_dup_list_count: config.ll_rsp_dup_list_count,
288 ble_ll_adv_dup_list_count: config.ll_adv_dup_list_count,
289 ble_ll_tx_pwr_dbm: config.default_tx_power.dbm() as u8,
290 rtc_freq: 32000,
291 ble_ll_sca: CONFIG_BT_LE_LL_SCA as _,
292 ble_ll_scan_phy_number: if CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY != 0 {
293 2
294 } else {
295 1
296 },
297 ble_ll_conn_def_auth_pyld_tmo: 3000,
298 ble_ll_jitter_usecs: 16,
299 ble_ll_sched_max_adv_pdu_usecs: 376,
300 ble_ll_sched_direct_adv_max_usecs: 502,
301 ble_ll_sched_adv_max_usecs: 852,
302 ble_scan_rsp_data_max_len: 31,
303 ble_ll_cfg_num_hci_cmd_pkts: 1,
304 ble_ll_ctrl_proc_timeout_ms: 40000,
305 nimble_max_connections: config.max_connections,
306 ble_whitelist_size: config.whitelist_size,
307 ble_acl_buf_size: config.acl_buf_size,
308 ble_acl_buf_count: config.acl_buf_count,
309 ble_hci_evt_buf_size: config.hci_evt_buf_size,
310 ble_multi_adv_instances: config.multi_adv_instances,
311 ble_ext_adv_max_size: config.ext_adv_max_size,
312 controller_task_stack_size: config.task_stack_size,
313 controller_task_prio: config.task_priority,
314 controller_run_cpu: 0,
315 enable_qa_test: config.qa_test_mode as u8,
316 enable_bqb_test: config.bqb_test as u8,
317 enable_tx_cca: config.cca as u8,
318 cca_rssi_thresh: (256 - config.cca_threshold as u32) as u8,
319 sleep_en: 0,
320 coex_phy_coded_tx_rx_time_limit: CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF as _,
321 dis_scan_backoff: config.dis_scan_backoff as u8,
322 ble_scan_classify_filter_enable: 1,
323 cca_drop_mode: 0, cca_low_tx_pwr: 0, main_xtal_freq: 32,
326 ignore_wl_for_direct_adv: 0,
327 cpu_freq_mhz: 96,
328 enable_pcl: 0,
329 csa2_select: CONFIG_BT_LE_50_FEATURE_SUPPORT as _,
331 enable_csr: 0,
332 ble_aa_check: config.verify_access_address as u8,
333 ble_llcp_disc_flag: config.disconnect_llcp_conn_update as u8
334 | ((config.disconnect_llcp_chan_map_update as u8) << 1)
335 | ((config.disconnect_llcp_phy_update as u8) << 2),
336 scan_backoff_upperlimitmax: config.scan_backoff_max,
337 ble_chan_ass_en: config.channel_assessment as u8,
338 ble_data_lenth_zero_aux: config.data_length_zero_aux as u8,
339 vhci_enabled: CONFIG_BT_LE_HCI_INTERFACE_USE_RAM as _,
340 ptr_check_enabled: 0,
341 ble_adv_tx_options: 0,
342 skip_unnecessary_checks_en: 0,
343 fast_conn_data_tx_en: 0,
344 ch39_txpwr: 9,
345 adv_rsv_cnt: 1,
346 conn_rsv_cnt: 2,
347 config_magic: CONFIG_MAGIC,
348 }
349}
350
351pub(crate) fn bt_periph_module_enable() {
352 let mut bt = unsafe { BT::steal() };
355 bt.enable_modem_clock(true);
356}
357
358pub(crate) fn disable_sleep_mode() {
359 }
361
362pub(super) unsafe extern "C" fn esp_intr_alloc(
363 source: u32,
364 flags: u32,
365 handler: *mut c_void,
366 arg: *mut c_void,
367 ret_handle: *mut *mut c_void,
368) -> i32 {
369 trace!(
370 "esp_intr_alloc {} {} {:?} {:?} {:?}",
371 source, flags, handler, arg, ret_handle
372 );
373
374 unsafe {
375 match source {
376 3 => {
377 ISR_INTERRUPT_3 = (handler, arg);
378 unwrap!(interrupt::enable(
379 Interrupt::LP_BLE_TIMER,
380 interrupt::Priority::Priority1
381 ));
382 }
383 15 => {
384 ISR_INTERRUPT_15 = (handler, arg);
385 unwrap!(interrupt::enable(
386 Interrupt::BT_MAC,
387 interrupt::Priority::Priority1
388 ));
389 }
390 _ => panic!("Unexpected interrupt source {}", source),
391 }
392 }
393
394 0
395}
396
397pub(super) fn ble_rtc_clk_init() {
398 let mut bt = unsafe { BT::steal() };
401 bt.ble_rtc_clk_init();
402}