diff options
author | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2021-06-29 02:39:14 +0200 |
---|---|---|
committer | Dario Nieuwenhuis <dirbaio@dirbaio.net> | 2021-06-29 02:39:14 +0200 |
commit | f78135ec68586fb7d85af80e6e1f3be4d93ccbda (patch) | |
tree | e21ca881b354269575698a759015743ed7e1beda | |
parent | a5935e927bb2f8cc4b38dfe8b95eac600d8cc2fc (diff) | |
download | nrf-softdevice-f78135ec68586fb7d85af80e6e1f3be4d93ccbda.zip |
ble/conn: allow get/set the conn params.
-rw-r--r-- | nrf-softdevice/src/ble/central.rs | 3 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/connection.rs | 59 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/gap.rs | 14 | ||||
-rw-r--r-- | nrf-softdevice/src/ble/peripheral.rs | 3 |
4 files changed, 72 insertions, 7 deletions
diff --git a/nrf-softdevice/src/ble/central.rs b/nrf-softdevice/src/ble/central.rs index 9e2ffde..c2356d4 100644 --- a/nrf-softdevice/src/ble/central.rs +++ b/nrf-softdevice/src/ble/central.rs @@ -69,9 +69,10 @@ pub async fn connect( let conn_handle = gap_evt.conn_handle; let role = Role::from_raw(params.role); let peer_address = Address::from_raw(params.peer_addr); + let conn_params = params.conn_params; debug!("connected role={:?} peer_addr={:?}", role, peer_address); - match Connection::new(conn_handle, role, peer_address) { + match Connection::new(conn_handle, role, peer_address, conn_params) { Ok(conn) => { #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] gap::do_data_length_update(conn_handle, ptr::null()); diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index c4e3fa9..342524f 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -1,6 +1,8 @@ use core::cell::Cell; use core::cell::UnsafeCell; +use raw::ble_gap_conn_params_t; + use crate::ble::types::*; use crate::ble::*; use crate::raw; @@ -16,6 +18,25 @@ pub(crate) struct OutOfConnsError; #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisconnectedError; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum SetConnParamsError { + Disconnected, + Raw(RawError), +} + +impl From<DisconnectedError> for SetConnParamsError { + fn from(_err: DisconnectedError) -> Self { + SetConnParamsError::Disconnected + } +} + +impl From<RawError> for SetConnParamsError { + fn from(err: RawError) -> Self { + SetConnParamsError::Raw(err) + } +} + // Highest ever the softdevice can support. pub(crate) const CONNS_MAX: usize = 20; @@ -43,6 +64,8 @@ pub(crate) struct ConnectionState { pub role: Role, pub peer_address: Address, + pub conn_params: ble_gap_conn_params_t, + pub att_mtu: u16, // Effective ATT_MTU size (in bytes). #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] pub data_length_effective: u8, // Effective data length (in bytes). @@ -61,6 +84,12 @@ impl ConnectionState { role: Role::Peripheral, peer_address: Address::new(AddressType::Public, [0; 6]), disconnecting: false, + conn_params: ble_gap_conn_params_t { + conn_sup_timeout: 0, + max_conn_interval: 0, + min_conn_interval: 0, + slave_latency: 0, + }, att_mtu: 0, #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] data_length_effective: 0, @@ -173,6 +202,7 @@ impl Connection { conn_handle: u16, role: Role, peer_address: Address, + conn_params: ble_gap_conn_params_t, ) -> Result<Self, OutOfConnsError> { allocate_index(|index, state| { // Initialize @@ -184,6 +214,7 @@ impl Connection { disconnecting: false, + conn_params, att_mtu: raw::BLE_GATT_ATT_MTU_DEFAULT as _, #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] @@ -200,6 +231,34 @@ impl Connection { }) } + /// Get the currently active connection params. + pub fn conn_params(&self) -> ble_gap_conn_params_t { + with_state(self.index, |s| s.conn_params) + } + + /// Set the connection params. + /// + /// Note that this just initiates the connection param change, it does not wait for completion. + /// Immediately after return, the active params will still be the old ones, and after some time they + /// should change to the new ones. + /// + /// For central connections, this will initiate a Link Layer connection parameter update procedure. + /// For peripheral connections, this will send the corresponding L2CAP request to the central. It is then + /// up to the central to accept or deny the request. + pub fn set_conn_params( + &self, + conn_params: ble_gap_conn_params_t, + ) -> Result<(), SetConnParamsError> { + let conn_handle = self.with_state(|state| state.check_connected())?; + let ret = unsafe { raw::sd_ble_gap_conn_param_update(conn_handle, &conn_params) }; + if let Err(err) = RawError::convert(ret) { + warn!("sd_ble_gap_conn_param_update err {:?}", err); + return Err(err.into()); + } + + Ok(()) + } + pub(crate) fn with_state<T>(&self, f: impl FnOnce(&mut ConnectionState) -> T) -> T { with_state(self.index, f) } diff --git a/nrf-softdevice/src/ble/gap.rs b/nrf-softdevice/src/ble/gap.rs index b195c5f..fc8f135 100644 --- a/nrf-softdevice/src/ble/gap.rs +++ b/nrf-softdevice/src/ble/gap.rs @@ -40,16 +40,20 @@ pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { }); } raw::BLE_GAP_EVTS_BLE_GAP_EVT_CONN_PARAM_UPDATE => { - let _conn_params = gap_evt.params.conn_param_update.conn_params; + let conn_params = gap_evt.params.conn_param_update.conn_params; debug!( "on_conn_param_update conn_handle={:?} conn_sup_timeout={:?} max_conn_interval={:?} min_conn_interval={:?} slave_latency={:?}", gap_evt.conn_handle, - _conn_params.conn_sup_timeout, - _conn_params.max_conn_interval, - _conn_params.min_conn_interval, - _conn_params.slave_latency, + conn_params.conn_sup_timeout, + conn_params.max_conn_interval, + conn_params.min_conn_interval, + conn_params.slave_latency, ); + + connection::with_state_by_conn_handle(gap_evt.conn_handle, |state| { + state.conn_params = conn_params; + }); } raw::BLE_GAP_EVTS_BLE_GAP_EVT_TIMEOUT => { trace!("on_timeout conn_handle={:?}", gap_evt.conn_handle); diff --git a/nrf-softdevice/src/ble/peripheral.rs b/nrf-softdevice/src/ble/peripheral.rs index a232e14..c3e920b 100644 --- a/nrf-softdevice/src/ble/peripheral.rs +++ b/nrf-softdevice/src/ble/peripheral.rs @@ -298,9 +298,10 @@ pub async fn advertise_connectable( let conn_handle = gap_evt.conn_handle; let role = Role::from_raw(params.role); let peer_address = Address::from_raw(params.peer_addr); + let conn_params = params.conn_params; debug!("connected role={:?} peer_addr={:?}", role, peer_address); - match Connection::new(conn_handle, role, peer_address) { + match Connection::new(conn_handle, role, peer_address, conn_params) { Ok(conn) => { #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] gap::do_data_length_update(conn_handle, ptr::null()); |