diff options
author | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2020-09-11 02:45:54 +0200 |
---|---|---|
committer | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2020-09-11 02:45:54 +0200 |
commit | 8d57c0306b0a301684851cbc802f0528c243fe80 (patch) | |
tree | 90791480b4a1ad2bf6be1d9f7dc98e0ad4542c44 | |
parent | a9ffb6eb67d2ebe4425db6a3f5be5648379ba7e4 (diff) | |
download | nrf-softdevice-8d57c0306b0a301684851cbc802f0528c243fe80.zip |
Add features to support all nrf chips and softdevices.
-rw-r--r-- | .vscode/settings.json | 2 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | example/Cargo.toml | 2 | ||||
-rw-r--r-- | example/src/bin/ble_bas_central.rs | 6 | ||||
-rw-r--r-- | example/src/bin/ble_bas_peripheral.rs | 6 | ||||
-rw-r--r-- | example/src/bin/ble_peripheral_gattspam.rs | 6 | ||||
-rw-r--r-- | nrf-softdevice/Cargo.toml | 30 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/connection.rs | 2 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/gap.rs | 254 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/gap_central.rs | 116 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/gap_peripheral.rs | 155 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/mod.rs | 210 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/types.rs | 12 | ||||
-rw-r--r-- | nrf-softdevice/src/error.rs | 1 | ||||
-rw-r--r-- | nrf-softdevice/src/events.rs | 9 | ||||
-rw-r--r-- | nrf-softdevice/src/interrupt.rs | 153 | ||||
-rw-r--r-- | nrf-softdevice/src/lib.rs | 25 | ||||
-rwxr-xr-x | test-build.sh | 65 |
18 files changed, 660 insertions, 397 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index c0d9016..ca67c18 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "editor.formatOnSave": true, + "rust-analyzer.cargo.allFeatures": false, + "rust-analyzer.checkOnSave.allFeatures": false, "rust-analyzer.cargo.target": "thumbv7em-none-eabihf", "rust-analyzer.checkOnSave.allTargets": false, "rust-analyzer.cargo.loadOutDirsFromCheck": true, @@ -25,6 +25,9 @@ cortex-m = { git = "https://github.com/Dirbaio/cortex-m"} panic-probe = { git = "https://github.com/knurling-rs/probe-run", branch="main" } defmt-rtt = { git = "https://github.com/knurling-rs/defmt", branch="main" } defmt = { git = "https://github.com/knurling-rs/defmt", branch="main" } +nrf52810-pac = { git = "https://github.com/Dirbaio/nrf52810-pac" } +nrf52832-pac = { git = "https://github.com/Dirbaio/nrf52832-pac" } +nrf52833-pac = { git = "https://github.com/Dirbaio/nrf52833-pac" } nrf52840-pac = { git = "https://github.com/Dirbaio/nrf52840-pac" } static-executor = { git = "https://github.com/Dirbaio/static-executor" } static-executor-cortex-m = { git = "https://github.com/Dirbaio/static-executor" } diff --git a/example/Cargo.toml b/example/Cargo.toml index e25c06e..268db74 100644 --- a/example/Cargo.toml +++ b/example/Cargo.toml @@ -21,7 +21,7 @@ defmt = "0.1.0" defmt-rtt = "0.1.0" panic-probe = "0.1.0" nrf52840-hal = { version = "0.11.0" } -nrf-softdevice = { version = "0.1.0", path = "../nrf-softdevice", features = ["defmt-trace"] } +nrf-softdevice = { version = "0.1.0", path = "../nrf-softdevice", features = ["defmt-trace", "nrf52840", "s140", "ble-peripheral", "ble-central"] } nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140" } static-executor = { version = "0.1.0", features=["defmt"]} static-executor-cortex-m = { version = "0.1.0" } diff --git a/example/src/bin/ble_bas_central.rs b/example/src/bin/ble_bas_central.rs index f465012..31bd312 100644 --- a/example/src/bin/ble_bas_central.rs +++ b/example/src/bin/ble_bas_central.rs @@ -10,7 +10,7 @@ use core::mem; use cortex_m_rt::entry; use defmt::info; -use nrf_softdevice::{gap, gatt_client, raw, Address, Connection, Uuid}; +use nrf_softdevice::{gap_central, gatt_client, raw, Address, Connection, Uuid}; #[static_executor::task] async fn softdevice_task() { @@ -76,7 +76,9 @@ async fn ble_central_task() { 0x59, 0xf9, 0xb1, 0x9c, 0x01, 0xf5, ])]; - let conn = gap::connect(addrs).await.dexpect(intern!("connect")); + let conn = gap_central::connect(addrs) + .await + .dexpect(intern!("connect")); info!("connected"); let client: BatteryServiceClient = gatt_client::discover(&conn) diff --git a/example/src/bin/ble_bas_peripheral.rs b/example/src/bin/ble_bas_peripheral.rs index a7e5225..533f0dc 100644 --- a/example/src/bin/ble_bas_peripheral.rs +++ b/example/src/bin/ble_bas_peripheral.rs @@ -10,7 +10,7 @@ use core::mem; use cortex_m_rt::entry; use defmt::info; -use nrf_softdevice::{raw, Error, Uuid}; +use nrf_softdevice::{gap_peripheral, raw, Error, Uuid}; #[static_executor::task] async fn softdevice_task() { @@ -91,8 +91,8 @@ async fn bluetooth_task() { ]; loop { - let conn = nrf_softdevice::gap::advertise( - nrf_softdevice::gap::ConnectableAdvertisement::ScannableUndirected { + let conn = gap_peripheral::advertise( + gap_peripheral::ConnectableAdvertisement::ScannableUndirected { adv_data, scan_data, }, diff --git a/example/src/bin/ble_peripheral_gattspam.rs b/example/src/bin/ble_peripheral_gattspam.rs index ae71012..c7d843e 100644 --- a/example/src/bin/ble_peripheral_gattspam.rs +++ b/example/src/bin/ble_peripheral_gattspam.rs @@ -10,7 +10,7 @@ use core::mem; use cortex_m_rt::entry; use defmt::info; -use nrf_softdevice::{raw, Error, Uuid}; +use nrf_softdevice::{gap_peripheral, raw, Error, Uuid}; #[static_executor::task] async fn softdevice_task() { @@ -95,8 +95,8 @@ async fn bluetooth_task() { ]; loop { - let conn = nrf_softdevice::gap::advertise( - nrf_softdevice::gap::ConnectableAdvertisement::ScannableUndirected { + let conn = gap_peripheral::advertise( + gap_peripheral::ConnectableAdvertisement::ScannableUndirected { adv_data, scan_data, }, diff --git a/nrf-softdevice/Cargo.toml b/nrf-softdevice/Cargo.toml index 4b7a3cb..ad0b06f 100644 --- a/nrf-softdevice/Cargo.toml +++ b/nrf-softdevice/Cargo.toml @@ -12,13 +12,37 @@ defmt-info = [] defmt-warn = [] defmt-error = [] +nrf52810 = ["nrf52810-pac"] +nrf52832 = ["nrf52832-pac"] +nrf52833 = ["nrf52833-pac"] +nrf52840 = ["nrf52840-pac"] + +s112 = ["nrf-softdevice-s112"] +s113 = ["nrf-softdevice-s113"] +s122 = ["nrf-softdevice-s122"] +s132 = ["nrf-softdevice-s132"] +s140 = ["nrf-softdevice-s140"] + +ble-peripheral = [] +ble-central = [] +ble-l2cap = [] + [dependencies] num_enum = { version = "0.5.1", default-features = false } async-flash = { version = "0.1.0", path = "../async-flash" } -nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140" } cortex-m = "0.6.2" cortex-m-rt = "0.6.12" bare-metal = { version = "0.2.0", features = ["const-fn"] } -nrf52840-pac = { version = "0.9.0", features = ["rt"] } heapless = "0.5.5" -defmt = "0.1.0"
\ No newline at end of file +defmt = "0.1.0" + +nrf52810-pac = { version = "0.9.0", features = ["rt"], optional = true } +nrf52832-pac = { version = "0.9.0", features = ["rt"], optional = true } +nrf52833-pac = { version = "0.9.0", features = ["rt"], optional = true } +nrf52840-pac = { version = "0.9.0", features = ["rt"], optional = true } + +nrf-softdevice-s112 = { version = "0.1.1", path = "../nrf-softdevice-s112", optional = true } +nrf-softdevice-s113 = { version = "0.1.1", path = "../nrf-softdevice-s113", optional = true } +nrf-softdevice-s122 = { version = "0.1.1", path = "../nrf-softdevice-s122", optional = true } +nrf-softdevice-s132 = { version = "0.1.1", path = "../nrf-softdevice-s132", optional = true } +nrf-softdevice-s140 = { version = "0.1.1", path = "../nrf-softdevice-s140", optional = true } diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index 4325961..8e51bba 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -46,7 +46,7 @@ impl ConnectionState { refcount: Cell::new(0), conn_handle: Cell::new(None), disconnecting: Cell::new(false), - role: Cell::new(Role::Central), + role: Cell::new(Role::whatever()), gattc_portal: Portal::new(), } } diff --git a/nrf-softdevice/src/ble/gap.rs b/nrf-softdevice/src/ble/gap.rs index f3efc13..3bd9894 100644 --- a/nrf-softdevice/src/ble/gap.rs +++ b/nrf-softdevice/src/ble/gap.rs @@ -19,8 +19,10 @@ pub(crate) unsafe fn on_connected(_ble_evt: *const raw::ble_evt_t, gap_evt: &raw state.role.set(role); match role { - Role::Central => CONNECT_SIGNAL.signal(Ok(conn)), - Role::Peripheral => ADV_SIGNAL.signal(Ok(conn)), + #[cfg(feature = "ble-central")] + Role::Central => crate::gap_central::CONNECT_SIGNAL.signal(Ok(conn)), + #[cfg(feature = "ble-peripheral")] + Role::Peripheral => crate::gap_peripheral::ADV_SIGNAL.signal(Ok(conn)), } } @@ -45,12 +47,6 @@ pub(crate) unsafe fn on_sec_params_request( ) { } -pub(crate) unsafe fn on_sec_info_request( - _ble_evt: *const raw::ble_evt_t, - _gap_evt: &raw::ble_gap_evt_t, -) { -} - pub(crate) unsafe fn on_passkey_display( _ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t, @@ -89,8 +85,10 @@ pub(crate) unsafe fn on_conn_sec_update( pub(crate) unsafe fn on_timeout(_ble_evt: *const raw::ble_evt_t, gap_evt: &raw::ble_gap_evt_t) { let params = &gap_evt.params.timeout; match params.src as u32 { - raw::BLE_GAP_TIMEOUT_SRC_CONN => CONNECT_SIGNAL.signal(Err(ConnectError::Stopped)), - x => warn!("unknown timeout src {:u32}", x), + #[cfg(feature = "ble-central")] + raw::BLE_GAP_TIMEOUT_SRC_CONN => crate::gap_central::CONNECT_SIGNAL + .signal(Err(crate::gap_central::ConnectError::Stopped)), + x => depanic!("unknown timeout src {:u32}", x), } } @@ -100,27 +98,12 @@ pub(crate) unsafe fn on_rssi_changed( ) { } -pub(crate) unsafe fn on_adv_report(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) { -} - pub(crate) unsafe fn on_sec_request( _ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t, ) { } -pub(crate) unsafe fn on_conn_param_update_request( - _ble_evt: *const raw::ble_evt_t, - _gap_evt: &raw::ble_gap_evt_t, -) { -} - -pub(crate) unsafe fn on_scan_req_report( - _ble_evt: *const raw::ble_evt_t, - _gap_evt: &raw::ble_gap_evt_t, -) { -} - pub(crate) unsafe fn on_phy_update_request( _ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t, @@ -130,233 +113,16 @@ pub(crate) unsafe fn on_phy_update_request( pub(crate) unsafe fn on_phy_update(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) { } +#[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] pub(crate) unsafe fn on_data_length_update_request( _ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t, ) { } +#[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] pub(crate) unsafe fn on_data_length_update( _ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t, ) { } - -pub(crate) unsafe fn on_qos_channel_survey_report( - _ble_evt: *const raw::ble_evt_t, - _gap_evt: &raw::ble_gap_evt_t, -) { -} - -pub(crate) unsafe fn on_adv_set_terminated( - _ble_evt: *const raw::ble_evt_t, - _gap_evt: &raw::ble_gap_evt_t, -) { - ADV_SIGNAL.signal(Err(AdvertiseError::Stopped)) -} - -pub enum ConnectableAdvertisement<'a> { - ScannableUndirected { - adv_data: &'a [u8], - scan_data: &'a [u8], - }, - NonscannableDirected { - scan_data: &'a [u8], - }, - NonscannableDirectedHighDuty { - scan_data: &'a [u8], - }, - ExtendedNonscannableUndirected { - adv_data: &'a [u8], - }, - ExtendedNonscannableDirected { - adv_data: &'a [u8], - }, -} - -enum NonconnectableAdvertisement { - ScannableUndirected, - NonscannableUndirected, - ExtendedScannableUndirected, - ExtendedScannableDirected, - ExtendedNonscannableUndirected, - ExtendedNonscannableDirected, -} - -static mut ADV_HANDLE: u8 = raw::BLE_GAP_ADV_SET_HANDLE_NOT_SET as u8; - -#[derive(defmt::Format)] -pub enum AdvertiseError { - Stopped, - Raw(Error), -} - -impl From<Error> for AdvertiseError { - fn from(err: Error) -> Self { - AdvertiseError::Raw(err) - } -} - -pub async fn advertise(adv: ConnectableAdvertisement<'_>) -> Result<Connection, AdvertiseError> { - // TODO make these configurable, only the right params based on type? - let mut adv_params: raw::ble_gap_adv_params_t = unsafe { mem::zeroed() }; - adv_params.properties.type_ = raw::BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED as u8; - adv_params.primary_phy = raw::BLE_GAP_PHY_1MBPS as u8; - adv_params.secondary_phy = raw::BLE_GAP_PHY_1MBPS as u8; - adv_params.duration = raw::BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED as u16; - adv_params.interval = 100; - - let (adv_data, scan_data) = match adv { - ConnectableAdvertisement::ScannableUndirected { - adv_data, - scan_data, - } => (Some(adv_data), Some(scan_data)), - ConnectableAdvertisement::NonscannableDirected { scan_data } => (None, Some(scan_data)), - ConnectableAdvertisement::NonscannableDirectedHighDuty { scan_data } => { - (None, Some(scan_data)) - } - ConnectableAdvertisement::ExtendedNonscannableUndirected { adv_data } => { - (Some(adv_data), None) - } - ConnectableAdvertisement::ExtendedNonscannableDirected { adv_data } => { - (Some(adv_data), None) - } - }; - - let map_data = |data: Option<&[u8]>| { - if let Some(data) = data { - assert!(data.len() < u16::MAX as usize); - raw::ble_data_t { - p_data: data.as_ptr() as _, - len: data.len() as u16, - } - } else { - raw::ble_data_t { - p_data: ptr::null_mut(), - len: 0, - } - } - }; - - let datas = raw::ble_gap_adv_data_t { - adv_data: map_data(adv_data), - scan_rsp_data: map_data(scan_data), - }; - - let ret = unsafe { - raw::sd_ble_gap_adv_set_configure(&mut ADV_HANDLE as _, &datas as _, &adv_params as _) - }; - Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_set_configure"))?; - - let ret = unsafe { raw::sd_ble_gap_adv_start(ADV_HANDLE, 1 as u8) }; - Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_start"))?; - - // TODO handle future drop - - info!("Advertising started!"); - - // The advertising data needs to be kept alive for the entire duration of the advertising procedure. - - ADV_SIGNAL.wait().await -} - -static ADV_SIGNAL: Signal<Result<Connection, AdvertiseError>> = Signal::new(); - -#[derive(defmt::Format)] -pub enum AdvertiseStopError { - NotRunning, - Raw(Error), -} - -impl From<Error> for AdvertiseStopError { - fn from(err: Error) -> Self { - AdvertiseStopError::Raw(err) - } -} - -pub fn advertise_stop() -> Result<(), AdvertiseStopError> { - let ret = unsafe { raw::sd_ble_gap_adv_stop(ADV_HANDLE) }; - match Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_stop")) { - Ok(()) => Ok(()), - Err(Error::InvalidState) => Err(AdvertiseStopError::NotRunning), - Err(e) => Err(e.into()), - } -} - -#[derive(defmt::Format)] -pub enum ConnectError { - Stopped, - Raw(Error), -} - -impl From<Error> for ConnectError { - fn from(err: Error) -> Self { - ConnectError::Raw(err) - } -} - -static CONNECT_SIGNAL: Signal<Result<Connection, ConnectError>> = Signal::new(); - -pub async fn connect(whitelist: &[Address]) -> Result<Connection, ConnectError> { - let (addr, fp) = match whitelist.len() { - 0 => depanic!("zero-length whitelist"), - 1 => ( - &whitelist[0] as *const Address as *const raw::ble_gap_addr_t, - raw::BLE_GAP_SCAN_FP_ACCEPT_ALL as u8, - ), - _ => depanic!("todo"), - }; - - // TODO make configurable - let mut scan_params: raw::ble_gap_scan_params_t = unsafe { mem::zeroed() }; - scan_params.set_extended(1); - scan_params.set_active(1); - scan_params.scan_phys = raw::BLE_GAP_PHY_1MBPS as u8; - scan_params.interval = 2732; - scan_params.window = 500; - scan_params.set_filter_policy(fp); - scan_params.timeout = 123; - - // TODO make configurable - let mut conn_params: raw::ble_gap_conn_params_t = unsafe { mem::zeroed() }; - conn_params.min_conn_interval = 50; - conn_params.max_conn_interval = 200; - conn_params.slave_latency = 4; - conn_params.conn_sup_timeout = 400; // 4 s - - let ret = unsafe { raw::sd_ble_gap_connect(addr, &mut scan_params, &mut conn_params, 1) }; - match Error::convert(ret) { - Ok(()) => {} - Err(err) => { - warn!("sd_ble_gap_connect err {:?}", err); - return Err(ConnectError::Raw(err)); - } - } - - info!("connect started"); - - // TODO handle future drop - - CONNECT_SIGNAL.wait().await -} - -#[derive(defmt::Format)] -pub enum ConnectStopError { - NotRunning, - Raw(Error), -} - -impl From<Error> for ConnectStopError { - fn from(err: Error) -> Self { - ConnectStopError::Raw(err) - } -} - -pub fn connect_stop() -> Result<(), ConnectStopError> { - let ret = unsafe { raw::sd_ble_gap_connect_cancel() }; - match Error::convert(ret).dewarn(intern!("sd_ble_gap_connect_cancel")) { - Ok(()) => Ok(()), - Err(Error::InvalidState) => Err(ConnectStopError::NotRunning), - Err(e) => Err(e.into()), - } -} diff --git a/nrf-softdevice/src/ble/gap_central.rs b/nrf-softdevice/src/ble/gap_central.rs new file mode 100644 index 0000000..3b38ff6 --- /dev/null +++ b/nrf-softdevice/src/ble/gap_central.rs @@ -0,0 +1,116 @@ +use core::mem; +use core::ptr; + +use crate::ble::types::*; +use crate::error::Error; +use crate::raw; +use crate::util::*; +use crate::{Connection, ConnectionState, Role}; + + +pub(crate) unsafe fn on_adv_report(_ble_evt: *const raw::ble_evt_t, _gap_evt: &raw::ble_gap_evt_t) { +} + +pub(crate) unsafe fn on_qos_channel_survey_report( + _ble_evt: *const raw::ble_evt_t, + _gap_evt: &raw::ble_gap_evt_t, +) { +} + +pub(crate) unsafe fn on_conn_param_update_request( + _ble_evt: *const raw::ble_evt_t, + _gap_evt: &raw::ble_gap_evt_t, +) { +} + +#[derive(defmt::Format)] +pub enum ConnectError { + Stopped, + Raw(Error), +} + +impl From<Error> for ConnectError { + fn from(err: Error) -> Self { + ConnectError::Raw(err) + } +} + +pub(crate) static CONNECT_SIGNAL: Signal<Result<Connection, ConnectError>> = Signal::new(); + +pub async fn connect(whitelist: &[Address]) -> Result<Connection, ConnectError> { + let (addr, fp) = match whitelist.len() { + 0 => depanic!("zero-length whitelist"), + 1 => ( + &whitelist[0] as *const Address as *const raw::ble_gap_addr_t, + raw::BLE_GAP_SCAN_FP_ACCEPT_ALL as u8, + ), + _ => depanic!("todo"), + }; + + // in units of 625us + let scan_interval: u32 = 2732; + let scan_window: u32 = 500; + + // TODO make configurable + let mut scan_params: raw::ble_gap_scan_params_t = unsafe { mem::zeroed() }; + scan_params.set_extended(1); + scan_params.set_active(1); + scan_params.scan_phys = raw::BLE_GAP_PHY_1MBPS as u8; + scan_params.set_filter_policy(fp); + scan_params.timeout = 123; + + // s122 has these in us instead of 625us :shrug: + #[cfg(not(feature="s122"))] + { + scan_params.interval = scan_interval as u16; + scan_params.window = scan_interval as u16; + } + #[cfg(feature="s122")] + { + scan_params.interval_us = scan_interval * 625; + scan_params.window_us = scan_interval * 625; + } + + // TODO make configurable + let mut conn_params: raw::ble_gap_conn_params_t = unsafe { mem::zeroed() }; + conn_params.min_conn_interval = 50; + conn_params.max_conn_interval = 200; + conn_params.slave_latency = 4; + conn_params.conn_sup_timeout = 400; // 4 s + + let ret = unsafe { raw::sd_ble_gap_connect(addr, &mut scan_params, &mut conn_params, 1) }; + match Error::convert(ret) { + Ok(()) => {} + Err(err) => { + warn!("sd_ble_gap_connect err {:?}", err); + return Err(ConnectError::Raw(err)); + } + } + + info!("connect started"); + + // TODO handle future drop + + CONNECT_SIGNAL.wait().await +} + +#[derive(defmt::Format)] +pub enum ConnectStopError { + NotRunning, + Raw(Error), +} + +impl From<Error> for ConnectStopError { + fn from(err: Error) -> Self { + ConnectStopError::Raw(err) + } +} + +pub fn connect_stop() -> Result<(), ConnectStopError> { + let ret = unsafe { raw::sd_ble_gap_connect_cancel() }; + match Error::convert(ret).dewarn(intern!("sd_ble_gap_connect_cancel")) { + Ok(()) => Ok(()), + Err(Error::InvalidState) => Err(ConnectStopError::NotRunning), + Err(e) => Err(e.into()), + } +} diff --git a/nrf-softdevice/src/ble/gap_peripheral.rs b/nrf-softdevice/src/ble/gap_peripheral.rs new file mode 100644 index 0000000..bd05dbb --- /dev/null +++ b/nrf-softdevice/src/ble/gap_peripheral.rs @@ -0,0 +1,155 @@ +use core::mem; +use core::ptr; + +use crate::ble::types::*; +use crate::error::Error; +use crate::raw; +use crate::util::*; +use crate::{Connection, ConnectionState, Role}; + +pub(crate) unsafe fn on_adv_set_terminated( + _ble_evt: *const raw::ble_evt_t, + _gap_evt: &raw::ble_gap_evt_t, +) { + ADV_SIGNAL.signal(Err(AdvertiseError::Stopped)) +} + +pub(crate) unsafe fn on_scan_req_report( + _ble_evt: *const raw::ble_evt_t, + _gap_evt: &raw::ble_gap_evt_t, +) { +} + +pub(crate) unsafe fn on_sec_info_request( + _ble_evt: *const raw::ble_evt_t, + _gap_evt: &raw::ble_gap_evt_t, +) { +} + +pub enum ConnectableAdvertisement<'a> { + ScannableUndirected { + adv_data: &'a [u8], + scan_data: &'a [u8], + }, + NonscannableDirected { + scan_data: &'a [u8], + }, + NonscannableDirectedHighDuty { + scan_data: &'a [u8], + }, + ExtendedNonscannableUndirected { + adv_data: &'a [u8], + }, + ExtendedNonscannableDirected { + adv_data: &'a [u8], + }, +} + +enum NonconnectableAdvertisement { + ScannableUndirected, + NonscannableUndirected, + ExtendedScannableUndirected, + ExtendedScannableDirected, + ExtendedNonscannableUndirected, + ExtendedNonscannableDirected, +} + +static mut ADV_HANDLE: u8 = raw::BLE_GAP_ADV_SET_HANDLE_NOT_SET as u8; + +#[derive(defmt::Format)] +pub enum AdvertiseError { + Stopped, + Raw(Error), +} + +impl From<Error> for AdvertiseError { + fn from(err: Error) -> Self { + AdvertiseError::Raw(err) + } +} + +pub async fn advertise(adv: ConnectableAdvertisement<'_>) -> Result<Connection, AdvertiseError> { + // TODO make these configurable, only the right params based on type? + let mut adv_params: raw::ble_gap_adv_params_t = unsafe { mem::zeroed() }; + adv_params.properties.type_ = raw::BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED as u8; + adv_params.primary_phy = raw::BLE_GAP_PHY_1MBPS as u8; + adv_params.secondary_phy = raw::BLE_GAP_PHY_1MBPS as u8; + adv_params.duration = raw::BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED as u16; + adv_params.interval = 100; + + let (adv_data, scan_data) = match adv { + ConnectableAdvertisement::ScannableUndirected { + adv_data, + scan_data, + } => (Some(adv_data), Some(scan_data)), + ConnectableAdvertisement::NonscannableDirected { scan_data } => (None, Some(scan_data)), + ConnectableAdvertisement::NonscannableDirectedHighDuty { scan_data } => { + (None, Some(scan_data)) + } + ConnectableAdvertisement::ExtendedNonscannableUndirected { adv_data } => { + (Some(adv_data), None) + } + ConnectableAdvertisement::ExtendedNonscannableDirected { adv_data } => { + (Some(adv_data), None) + } + }; + + let map_data = |data: Option<&[u8]>| { + if let Some(data) = data { + assert!(data.len() < u16::MAX as usize); + raw::ble_data_t { + p_data: data.as_ptr() as _, + len: data.len() as u16, + } + } else { + raw::ble_data_t { + p_data: ptr::null_mut(), + len: 0, + } + } + }; + + let datas = raw::ble_gap_adv_data_t { + adv_data: map_data(adv_data), + scan_rsp_data: map_data(scan_data), + }; + + let ret = unsafe { + raw::sd_ble_gap_adv_set_configure(&mut ADV_HANDLE as _, &datas as _, &adv_params as _) + }; + Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_set_configure"))?; + + let ret = unsafe { raw::sd_ble_gap_adv_start(ADV_HANDLE, 1 as u8) }; + Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_start"))?; + + // TODO handle future drop + + info!("Advertising started!"); + + // The advertising data needs to be kept alive for the entire duration of the advertising procedure. + + ADV_SIGNAL.wait().await +} + +pub(crate) static ADV_SIGNAL: Signal<Result<Connection, AdvertiseError>> = Signal::new(); + +#[derive(defmt::Format)] +pub enum AdvertiseStopError { + NotRunning, + Raw(Error), +} + +impl From<Error> for AdvertiseStopError { + fn from(err: Error) -> Self { + AdvertiseStopError::Raw(err) + } +} + +pub fn advertise_stop() -> Result<(), AdvertiseStopError> { + let ret = unsafe { raw::sd_ble_gap_adv_stop(ADV_HANDLE) }; + match Error::convert(ret).dewarn(intern!("sd_ble_gap_adv_stop")) { + Ok(()) => Ok(()), + Err(Error::InvalidState) => Err(AdvertiseStopError::NotRunning), + Err(e) => Err(e.into()), + } +} diff --git a/nrf-softdevice/src/ble/mod.rs b/nrf-softdevice/src/ble/mod.rs index df02d51..604ce24 100644 --- a/nrf-softdevice/src/ble/mod.rs +++ b/nrf-softdevice/src/ble/mod.rs @@ -7,141 +7,99 @@ mod types; pub use types::*; pub mod gap; +#[cfg(feature = "ble-central")] +pub mod gap_central; +#[cfg(feature = "ble-peripheral")] +pub mod gap_peripheral; pub mod gatt_client; pub mod gatt_server; + +#[cfg(feature = "ble-l2cap")] pub mod l2cap; fn on_user_mem_request(_ble_evt: *const raw::ble_evt_t, _common_evt: &raw::ble_common_evt_t) {} fn on_user_mem_release(_ble_evt: *const raw::ble_evt_t, _common_evt: &raw::ble_common_evt_t) {} -macro_rules! match_event { - ($evt_ptr:ident, $($id:ident => $func:path[$field:ident]),* $(,)? ) => { - let evt = &*$evt_ptr; - defmt::trace!("ble evt {:istr}", evt_str(evt.header.evt_id as u32)); - match evt.header.evt_id as u32 { - $(raw::$id => $func($evt_ptr, get_union_field($evt_ptr, &evt.evt.$field)) ),* , - x => depanic!("Unknown ble evt {:u32}", x), - } - }; -} - #[rustfmt::skip] -pub(crate) unsafe fn on_evt(evt_ptr: *const raw::ble_evt_t) { - match_event!(evt_ptr, - BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => on_user_mem_request[common_evt], - BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => on_user_mem_release[common_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => gap::on_connected[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => gap::on_disconnected[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => gap::on_conn_param_update[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => gap::on_sec_params_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => gap::on_sec_info_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => gap::on_passkey_display[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => gap::on_key_pressed[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => gap::on_auth_key_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => gap::on_lesc_dhkey_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => gap::on_auth_status[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => gap::on_conn_sec_update[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => gap::on_timeout[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => gap::on_rssi_changed[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => gap::on_adv_report[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => gap::on_sec_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => gap::on_conn_param_update_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => gap::on_scan_req_report[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => gap::on_phy_update_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => gap::on_phy_update[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => gap::on_data_length_update_request[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => gap::on_data_length_update[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => gap::on_qos_channel_survey_report[gap_evt], - BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => gap::on_adv_set_terminated[gap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => l2cap::on_ch_setup_request[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => l2cap::on_ch_setup_refused[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => l2cap::on_ch_setup[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => l2cap::on_ch_released[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => l2cap::on_ch_sdu_buf_released[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => l2cap::on_ch_credit[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => l2cap::on_ch_rx[l2cap_evt], - BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => l2cap::on_ch_tx[l2cap_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => gatt_client::on_prim_srvc_disc_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => gatt_client::on_rel_disc_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => gatt_client::on_char_disc_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => gatt_client::on_desc_disc_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => gatt_client::on_attr_info_disc_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => gatt_client::on_char_val_by_uuid_read_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => gatt_client::on_read_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => gatt_client::on_char_vals_read_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => gatt_client::on_write_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => gatt_client::on_hvx[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => gatt_client::on_exchange_mtu_rsp[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => gatt_client::on_timeout[gattc_evt], - BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => gatt_client::on_write_cmd_tx_complete[gattc_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => gatt_server::on_write[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => gatt_server::on_rw_authorize_request[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => gatt_server::on_sys_attr_missing[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => gatt_server::on_hvc[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => gatt_server::on_sc_confirm[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => gatt_server::on_exchange_mtu_request[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => gatt_server::on_timeout[gatts_evt], - BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => gatt_server::on_hvn_tx_complete[gatts_evt], - ); -} +pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { + let evt = &*ble_evt; + //defmt::trace!("ble evt {:istr}", evt_str(evt.header.evt_id as u32)); + match evt.header.evt_id as u32 { + raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => on_user_mem_request(ble_evt, get_union_field(ble_evt, &evt.evt.common_evt)), + raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => on_user_mem_release(ble_evt, get_union_field(ble_evt, &evt.evt.common_evt)), + + raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => gap::on_connected(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => gap::on_disconnected(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => gap::on_conn_param_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => gap::on_sec_params_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-peripheral")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => gap_peripheral::on_sec_info_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => gap::on_passkey_display(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => gap::on_key_pressed(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => gap::on_auth_key_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => gap::on_lesc_dhkey_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => gap::on_auth_status(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => gap::on_conn_sec_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => gap::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => gap::on_rssi_changed(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-central")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => gap_central::on_adv_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => gap::on_sec_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-central")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => gap_central::on_conn_param_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-peripheral")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => gap_peripheral::on_scan_req_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => gap::on_phy_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => gap::on_phy_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(any(feature="s113", feature="s132", feature="s140"))] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => gap::on_data_length_update_request(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(any(feature="s113", feature="s132", feature="s140"))] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => gap::on_data_length_update(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-central")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => gap_central::on_qos_channel_survey_report(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + #[cfg(feature="ble-peripheral")] + raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => gap_peripheral::on_adv_set_terminated(ble_evt, get_union_field(ble_evt, &evt.evt.gap_evt)), + + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => l2cap::on_ch_setup_request(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => l2cap::on_ch_setup_refused(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => l2cap::on_ch_setup(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => l2cap::on_ch_released(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => l2cap::on_ch_sdu_buf_released(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => l2cap::on_ch_credit(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => l2cap::on_ch_rx(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + #[cfg(feature="ble-l2cap")] + raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => l2cap::on_ch_tx(ble_evt, get_union_field(ble_evt, &evt.evt.l2cap_evt)), + + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => gatt_client::on_prim_srvc_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => gatt_client::on_rel_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => gatt_client::on_char_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => gatt_client::on_desc_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => gatt_client::on_attr_info_disc_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => gatt_client::on_char_val_by_uuid_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => gatt_client::on_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => gatt_client::on_char_vals_read_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => gatt_client::on_write_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => gatt_client::on_hvx(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => gatt_client::on_exchange_mtu_rsp(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => gatt_client::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => gatt_client::on_write_cmd_tx_complete(ble_evt, get_union_field(ble_evt, &evt.evt.gattc_evt)), + + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => gatt_server::on_write(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => gatt_server::on_rw_authorize_request(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => gatt_server::on_sys_attr_missing(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => gatt_server::on_hvc(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => gatt_server::on_sc_confirm(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => gatt_server::on_exchange_mtu_request(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => gatt_server::on_timeout(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), + raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => gatt_server::on_hvn_tx_complete(ble_evt, get_union_field(ble_evt, &evt.evt.gatts_evt)), -#[rustfmt::skip] -fn evt_str(evt: u32) -> defmt::Str { - match evt { - raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_REQUEST => defmt::intern!("USER_MEM_REQUEST"), - raw::BLE_COMMON_EVTS_BLE_EVT_USER_MEM_RELEASE => defmt::intern!("USER_MEM_RELEASE"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONNECTED => defmt::intern!("GAP CONNECTED"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => defmt::intern!("GAP DISCONNECTED"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => defmt::intern!("GAP CONN_PARAM_UPDATE"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_PARAMS_REQUEST => defmt::intern!("GAP SEC_PARAMS_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_INFO_REQUEST => defmt::intern!("GAP SEC_INFO_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_PASSKEY_DISPLAY => defmt::intern!("GAP PASSKEY_DISPLAY"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_KEY_PRESSED => defmt::intern!("GAP KEY_PRESSED"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_KEY_REQUEST => defmt::intern!("GAP AUTH_KEY_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_LESC_DHKEY_REQUEST => defmt::intern!("GAP LESC_DHKEY_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_AUTH_STATUS => defmt::intern!("GAP AUTH_STATUS"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_SEC_UPDATE => defmt::intern!("GAP CONN_SEC_UPDATE"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => defmt::intern!("GAP TIMEOUT"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_RSSI_CHANGED => defmt::intern!("GAP RSSI_CHANGED"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_REPORT => defmt::intern!("GAP ADV_REPORT"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_SEC_REQUEST => defmt::intern!("GAP SEC_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST => defmt::intern!("GAP CONN_PARAM_UPDATE_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_SCAN_REQ_REPORT => defmt::intern!("GAP SCAN_REQ_REPORT"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE_REQUEST => defmt::intern!("GAP PHY_UPDATE_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_PHY_UPDATE => defmt::intern!("GAP PHY_UPDATE"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST => defmt::intern!("GAP DATA_LENGTH_UPDATE_REQUEST"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DATA_LENGTH_UPDATE => defmt::intern!("GAP DATA_LENGTH_UPDATE"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT => defmt::intern!("GAP QOS_CHANNEL_SURVEY_REPORT"), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_ADV_SET_TERMINATED => defmt::intern!("GAP ADV_SET_TERMINATED"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REQUEST => defmt::intern!("L2CAP CH_SETUP_REQUEST"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP_REFUSED => defmt::intern!("L2CAP CH_SETUP_REFUSED"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SETUP => defmt::intern!("L2CAP CH_SETUP"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RELEASED => defmt::intern!("L2CAP CH_RELEASED"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED => defmt::intern!("L2CAP CH_SDU_BUF_RELEASED"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_CREDIT => defmt::intern!("L2CAP CH_CREDIT"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_RX => defmt::intern!("L2CAP CH_RX"), - raw::BLE_L2CAP_EVTS_BLE_L2CAP_EVT_CH_TX => defmt::intern!("L2CAP CH_TX"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => defmt::intern!("GATTC PRIM_SRVC_DISC_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_REL_DISC_RSP => defmt::intern!("GATTC REL_DISC_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => defmt::intern!("GATTC CHAR_DISC_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => defmt::intern!("GATTC DESC_DISC_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_ATTR_INFO_DISC_RSP => defmt::intern!("GATTC ATTR_INFO_DISC_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP => defmt::intern!("GATTC CHAR_VAL_BY_UUID_READ_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => defmt::intern!("GATTC READ_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_VALS_READ_RSP => defmt::intern!("GATTC CHAR_VALS_READ_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => defmt::intern!("GATTC WRITE_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_HVX => defmt::intern!("GATTC HVX"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => defmt::intern!("GATTC EXCHANGE_MTU_RSP"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => defmt::intern!("GATTC TIMEOUT"), - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => defmt::intern!("GATTC WRITE_CMD_TX_COMPLETE"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_WRITE => defmt::intern!("GATTS WRITE"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST => defmt::intern!("GATTS RW_AUTHORIZE_REQUEST"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SYS_ATTR_MISSING => defmt::intern!("GATTS SYS_ATTR_MISSING"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVC => defmt::intern!("GATTS HVC"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_SC_CONFIRM => defmt::intern!("GATTS SC_CONFIRM"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST => defmt::intern!("GATTS EXCHANGE_MTU_REQUEST"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_TIMEOUT => defmt::intern!("GATTS TIMEOUT"), - raw::BLE_GATTS_EVTS_BLE_GATTS_EVT_HVN_TX_COMPLETE => defmt::intern!("GATTS HVN_TX_COMPLETE"), x => depanic!("Unknown ble evt {:u32}", x), } } diff --git a/nrf-softdevice/src/ble/types.rs b/nrf-softdevice/src/ble/types.rs index f769aa2..87d4087 100644 --- a/nrf-softdevice/src/ble/types.rs +++ b/nrf-softdevice/src/ble/types.rs @@ -3,18 +3,30 @@ use crate::raw; #[derive(defmt::Format, Copy, Clone, Eq, PartialEq)] pub enum Role { + #[cfg(feature = "ble-central")] Central, + #[cfg(feature = "ble-peripheral")] Peripheral, } impl Role { pub fn from_raw(raw: u8) -> Self { match raw as u32 { + #[cfg(feature = "ble-central")] raw::BLE_GAP_ROLE_CENTRAL => Self::Central, + #[cfg(feature = "ble-peripheral")] raw::BLE_GAP_ROLE_PERIPH => Self::Peripheral, _ => depanic!("unknown role {:u8}", raw), } } + + pub(crate) const fn whatever() -> Self { + #[cfg(not(feature = "ble-peripheral"))] + return Self::Central; + + #[cfg(feature = "ble-peripheral")] + return Self::Peripheral; + } } #[repr(transparent)] diff --git a/nrf-softdevice/src/error.rs b/nrf-softdevice/src/error.rs index ec630dd..c2d22ed 100644 --- a/nrf-softdevice/src/error.rs +++ b/nrf-softdevice/src/error.rs @@ -53,6 +53,7 @@ pub enum Error { BleInvalidRole = raw::BLE_ERROR_INVALID_ROLE, BleBlockedByOtherLinks = raw::BLE_ERROR_BLOCKED_BY_OTHER_LINKS, BleGapUuidListMismatch = raw::BLE_ERROR_GAP_UUID_LIST_MISMATCH, + #[cfg(feature="ble-peripheral")] BleGapDiscoverableWithWhitelist = raw::BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST, BleGapInvalidBleAddr = raw::BLE_ERROR_GAP_INVALID_BLE_ADDR, BleGapWhitelistInUse = raw::BLE_ERROR_GAP_WHITELIST_IN_USE, diff --git a/nrf-softdevice/src/events.rs b/nrf-softdevice/src/events.rs index 79f4be7..aa0196f 100644 --- a/nrf-softdevice/src/events.rs +++ b/nrf-softdevice/src/events.rs @@ -21,8 +21,11 @@ enum SocEvent { RadioSignalCallbackInvalidReturn = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN, RadioSessionIdle = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SESSION_IDLE, RadioSessionClosed = raw::NRF_SOC_EVTS_NRF_EVT_RADIO_SESSION_CLOSED, + #[cfg(any(feature="s113", feature="s122", feature="s140"))] PowerUsbPowerReady = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_POWER_READY, + #[cfg(any(feature="s113", feature="s122", feature="s140"))] PowerUsbDetected = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_DETECTED, + #[cfg(any(feature="s113", feature="s122", feature="s140"))] PowerUsbRemoved = raw::NRF_SOC_EVTS_NRF_EVT_POWER_USB_REMOVED, } @@ -74,7 +77,13 @@ pub async fn run() { } } } +#[cfg(feature = "nrf52810")] +#[interrupt] +unsafe fn SWI2() { + SWI2_SIGNAL.signal(()); +} +#[cfg(not(feature = "nrf52810"))] #[interrupt] unsafe fn SWI2_EGU2() { SWI2_SIGNAL.signal(()); diff --git a/nrf-softdevice/src/interrupt.rs b/nrf-softdevice/src/interrupt.rs index 8a3965e..d4dbb3d 100644 --- a/nrf-softdevice/src/interrupt.rs +++ b/nrf-softdevice/src/interrupt.rs @@ -8,6 +8,21 @@ pub use crate::pac::Interrupt; pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt] pub use bare_metal::{CriticalSection, Mutex}; +#[cfg(feature = "nrf52810")] +const RESERVED_IRQS: [u32; 2] = [ + (1 << (Interrupt::POWER_CLOCK as u8)) + | (1 << (Interrupt::RADIO as u8)) + | (1 << (Interrupt::RTC0 as u8)) + | (1 << (Interrupt::TIMER0 as u8)) + | (1 << (Interrupt::RNG as u8)) + | (1 << (Interrupt::ECB as u8)) + | (1 << (Interrupt::CCM_AAR as u8)) + | (1 << (Interrupt::TEMP as u8)) + | (1 << (Interrupt::SWI5 as u8)), + 0, +]; + +#[cfg(not(feature = "nrf52810"))] const RESERVED_IRQS: [u32; 2] = [ (1 << (Interrupt::POWER_CLOCK as u8)) | (1 << (Interrupt::RADIO as u8)) @@ -130,18 +145,8 @@ where #[inline] fn is_app_accessible_irq(irq: Interrupt) -> bool { - match irq { - Interrupt::POWER_CLOCK - | Interrupt::RADIO - | Interrupt::RTC0 - | Interrupt::TIMER0 - | Interrupt::RNG - | Interrupt::ECB - | Interrupt::CCM_AAR - | Interrupt::TEMP - | Interrupt::SWI5_EGU5 => false, - _ => true, - } + let nr = irq.number(); + (RESERVED_IRQS[usize::from(nr / 32)] & 1 << (nr % 32)) == 0 } #[inline] @@ -253,6 +258,130 @@ pub fn set_priority(irq: Interrupt, prio: Priority) { } } +#[cfg(feature = "nrf52810")] +fn irq_str(irq: Interrupt) -> defmt::Str { + match irq { + POWER_CLOCK => defmt::intern!("POWER_CLOCK"), + RADIO => defmt::intern!("RADIO"), + UARTE0_UART0 => defmt::intern!("UARTE0_UART0"), + TWIM0_TWIS0_TWI0 => defmt::intern!("TWIM0_TWIS0_TWI0"), + SPIM0_SPIS0_SPI0 => defmt::intern!("SPIM0_SPIS0_SPI0"), + GPIOTE => defmt::intern!("GPIOTE"), + SAADC => defmt::intern!("SAADC"), + TIMER0 => defmt::intern!("TIMER0"), + TIMER1 => defmt::intern!("TIMER1"), + TIMER2 => defmt::intern!("TIMER2"), + RTC0 => defmt::intern!("RTC0"), + TEMP => defmt::intern!("TEMP"), + RNG => defmt::intern!("RNG"), + ECB => defmt::intern!("ECB"), + CCM_AAR => defmt::intern!("CCM_AAR"), + WDT => defmt::intern!("WDT"), + RTC1 => defmt::intern!("RTC1"), + QDEC => defmt::intern!("QDEC"), + COMP => defmt::intern!("COMP"), + SWI0_EGU0 => defmt::intern!("SWI0_EGU0"), + SWI1_EGU1 => defmt::intern!("SWI1_EGU1"), + SWI2 => defmt::intern!("SWI2"), + SWI3 => defmt::intern!("SWI3"), + SWI4 => defmt::intern!("SWI4"), + SWI5 => defmt::intern!("SWI5"), + PWM0 => defmt::intern!("PWM0"), + PDM => defmt::intern!("PDM"), + } +} + +#[cfg(feature = "nrf52832")] +fn irq_str(irq: Interrupt) -> defmt::Str { + match irq { + POWER_CLOCK => defmt::intern!("POWER_CLOCK"), + RADIO => defmt::intern!("RADIO"), + UARTE0_UART0 => defmt::intern!("UARTE0_UART0"), + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => defmt::intern!("SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0"), + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => defmt::intern!("SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1"), + NFCT => defmt::intern!("NFCT"), + GPIOTE => defmt::intern!("GPIOTE"), + SAADC => defmt::intern!("SAADC"), + TIMER0 => defmt::intern!("TIMER0"), + TIMER1 => defmt::intern!("TIMER1"), + TIMER2 => defmt::intern!("TIMER2"), + RTC0 => defmt::intern!("RTC0"), + TEMP => defmt::intern!("TEMP"), + RNG => defmt::intern!("RNG"), + ECB => defmt::intern!("ECB"), + CCM_AAR => defmt::intern!("CCM_AAR"), + WDT => defmt::intern!("WDT"), + RTC1 => defmt::intern!("RTC1"), + QDEC => defmt::intern!("QDEC"), + COMP_LPCOMP => defmt::intern!("COMP_LPCOMP"), + SWI0_EGU0 => defmt::intern!("SWI0_EGU0"), + SWI1_EGU1 => defmt::intern!("SWI1_EGU1"), + SWI2_EGU2 => defmt::intern!("SWI2_EGU2"), + SWI3_EGU3 => defmt::intern!("SWI3_EGU3"), + SWI4_EGU4 => defmt::intern!("SWI4_EGU4"), + SWI5_EGU5 => defmt::intern!("SWI5_EGU5"), + TIMER3 => defmt::intern!("TIMER3"), + TIMER4 => defmt::intern!("TIMER4"), + PWM0 => defmt::intern!("PWM0"), + PDM => defmt::intern!("PDM"), + MWU => defmt::intern!("MWU"), + PWM1 => defmt::intern!("PWM1"), + PWM2 => defmt::intern!("PWM2"), + SPIM2_SPIS2_SPI2 => defmt::intern!("SPIM2_SPIS2_SPI2"), + RTC2 => defmt::intern!("RTC2"), + I2S => defmt::intern!("I2S"), + FPU => defmt::intern!("FPU"), + } +} + +#[cfg(feature = "nrf52833")] +fn irq_str(irq: Interrupt) -> defmt::Str { + match irq { + POWER_CLOCK => defmt::intern!("POWER_CLOCK"), + RADIO => defmt::intern!("RADIO"), + UARTE0_UART0 => defmt::intern!("UARTE0_UART0"), + SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0 => defmt::intern!("SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0"), + SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => defmt::intern!("SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1"), + NFCT => defmt::intern!("NFCT"), + GPIOTE => defmt::intern!("GPIOTE"), + SAADC => defmt::intern!("SAADC"), + TIMER0 => defmt::intern!("TIMER0"), + TIMER1 => defmt::intern!("TIMER1"), + TIMER2 => defmt::intern!("TIMER2"), + RTC0 => defmt::intern!("RTC0"), + TEMP => defmt::intern!("TEMP"), + RNG => defmt::intern!("RNG"), + ECB => defmt::intern!("ECB"), + CCM_AAR => defmt::intern!("CCM_AAR"), + WDT => defmt::intern!("WDT"), + RTC1 => defmt::intern!("RTC1"), + QDEC => defmt::intern!("QDEC"), + COMP_LPCOMP => defmt::intern!("COMP_LPCOMP"), + SWI0_EGU0 => defmt::intern!("SWI0_EGU0"), + SWI1_EGU1 => defmt::intern!("SWI1_EGU1"), + SWI2_EGU2 => defmt::intern!("SWI2_EGU2"), + SWI3_EGU3 => defmt::intern!("SWI3_EGU3"), + SWI4_EGU4 => defmt::intern!("SWI4_EGU4"), + SWI5_EGU5 => defmt::intern!("SWI5_EGU5"), + TIMER3 => defmt::intern!("TIMER3"), + TIMER4 => defmt::intern!("TIMER4"), + PWM0 => defmt::intern!("PWM0"), + PDM => defmt::intern!("PDM"), + MWU => defmt::intern!("MWU"), + PWM1 => defmt::intern!("PWM1"), + PWM2 => defmt::intern!("PWM2"), + SPIM2_SPIS2_SPI2 => defmt::intern!("SPIM2_SPIS2_SPI2"), + RTC2 => defmt::intern!("RTC2"), + I2S => defmt::intern!("I2S"), + FPU => defmt::intern!("FPU"), + USBD => defmt::intern!("USBD"), + UARTE1 => defmt::intern!("UARTE1"), + PWM3 => defmt::intern!("PWM3"), + SPIM3 => defmt::intern!("SPIM3"), + } +} + +#[cfg(feature = "nrf52840")] fn irq_str(irq: Interrupt) -> defmt::Str { match irq { POWER_CLOCK => defmt::intern!("POWER_CLOCK"), diff --git a/nrf-softdevice/src/lib.rs b/nrf-softdevice/src/lib.rs index dce15d1..43ae36a 100644 --- a/nrf-softdevice/src/lib.rs +++ b/nrf-softdevice/src/lib.rs @@ -7,9 +7,24 @@ pub(crate) mod util; -// This is here so that the rest of the crate can easily use the right PAC and SD crates. -// TODO change this dynamically based on features. +#[cfg(feature = "nrf52810")] +pub use nrf52810_pac as pac; +#[cfg(feature = "nrf52832")] +pub use nrf52832_pac as pac; +#[cfg(feature = "nrf52833")] +pub use nrf52833_pac as pac; +#[cfg(feature = "nrf52840")] pub use nrf52840_pac as pac; + +#[cfg(feature = "s112")] +pub use nrf_softdevice_s112 as raw; +#[cfg(feature = "s113")] +pub use nrf_softdevice_s113 as raw; +#[cfg(feature = "s122")] +pub use nrf_softdevice_s122 as raw; +#[cfg(feature = "s132")] +pub use nrf_softdevice_s132 as raw; +#[cfg(feature = "s140")] pub use nrf_softdevice_s140 as raw; pub mod interrupt; @@ -41,6 +56,7 @@ pub struct Config { pub conn_gattc: Option<raw::ble_gattc_conn_cfg_t>, pub conn_gatts: Option<raw::ble_gatts_conn_cfg_t>, pub conn_gatt: Option<raw::ble_gatt_conn_cfg_t>, + #[cfg(feature = "ble-l2cap")] pub conn_l2cap: Option<raw::ble_l2cap_conn_cfg_t>, pub common_vs_uuid: Option<raw::ble_common_cfg_vs_uuid_t>, pub gap_role_count: Option<raw::ble_gap_cfg_role_count_t>, @@ -138,6 +154,7 @@ pub unsafe fn enable(config: &Config) { ); } + #[cfg(feature = "ble-l2cap")] if let Some(val) = config.conn_l2cap { cfg_set( raw::BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP, @@ -244,6 +261,9 @@ pub unsafe fn enable(config: &Config) { warn!("You're giving more RAM to the softdevice than needed. You can change your app's RAM start address to {:u32}", wanted_app_ram_base); } + #[cfg(feature = "nrf52810")] + interrupt::enable(interrupt::Interrupt::SWI2); + #[cfg(not(feature = "nrf52810"))] interrupt::enable(interrupt::Interrupt::SWI2_EGU2); } @@ -253,6 +273,7 @@ fn cfg_id_str(id: u32) -> defmt::Str { raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATTC => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATTC"), raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATTS => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATTS"), raw::BLE_CONN_CFGS_BLE_CONN_CFG_GATT => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_GATT"), + #[cfg(feature = "ble-l2cap")] raw::BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP => defmt::intern!("BLE_CONN_CFGS_BLE_CONN_CFG_L2CAP"), raw::BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID => { defmt::intern!("BLE_COMMON_CFGS_BLE_COMMON_CFG_VS_UUID") diff --git a/test-build.sh b/test-build.sh new file mode 100755 index 0000000..b044a90 --- /dev/null +++ b/test-build.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -euxo pipefail + +# Test that build works with all supported combinations. +# TODO l2cap in s113, s132, s140 + +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s112,nrf52810,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s112,nrf52832,ble-peripheral + +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52810,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52832,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52833,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s113,nrf52840,ble-peripheral + +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s122,nrf52833,ble-central + +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-central +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52810,ble-central,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-central +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s132,nrf52832,ble-central,ble-peripheral + +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-central +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52833,ble-central,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-central +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-peripheral +cargo build --target thumbv7em-none-eabihf -p nrf-softdevice --features s140,nrf52840,ble-central,ble-peripheral + +# https://www.nordicsemi.com/Software-and-tools/Software/Bluetooth-Software + +# | Central Peripheral | nrf52805 nrf52810 nrf52811 nrf52820 nrf52832 nrf52833, nrf52840 +# -----|---------------------|-------------------------------------------------------------------------- +# s112 | X | X X X X X +# s113 | X | X X X X X X X +# s122 | X | X X +# s132 | X X | X X +# s140 | X X | X X X X + +# s112 nrf52805 +# s112 nrf52810 +# s112 nrf52811 +# s112 nrf52820 +# s112 nrf52832 +# +# s113 nrf52805 +# s113 nrf52810 +# s113 nrf52811 +# s113 nrf52820 +# s113 nrf52832 +# s113 nrf52833 +# s113 nrf52840 +# +# s122 nrf52820 +# s122 nrf52833 +# +# s132 nrf52810 +# s132 nrf52832 +# +# s140 nrf52811 +# s140 nrf52820 +# s140 nrf52833 +# s140 nrf52840
\ No newline at end of file |