summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <dirbaio@dirbaio.net>2021-06-29 02:39:14 +0200
committerDario Nieuwenhuis <dirbaio@dirbaio.net>2021-06-29 02:39:14 +0200
commitf78135ec68586fb7d85af80e6e1f3be4d93ccbda (patch)
treee21ca881b354269575698a759015743ed7e1beda
parenta5935e927bb2f8cc4b38dfe8b95eac600d8cc2fc (diff)
downloadnrf-softdevice-f78135ec68586fb7d85af80e6e1f3be4d93ccbda.zip
ble/conn: allow get/set the conn params.
-rw-r--r--nrf-softdevice/src/ble/central.rs3
-rw-r--r--nrf-softdevice/src/ble/connection.rs59
-rw-r--r--nrf-softdevice/src/ble/gap.rs14
-rw-r--r--nrf-softdevice/src/ble/peripheral.rs3
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());