From ef8469ecc3cac8b88e16e951058e2b663e51aee6 Mon Sep 17 00:00:00 2001 From: Alex Moon Date: Mon, 18 Mar 2024 19:54:57 -0400 Subject: [PATCH 1/4] Add a `reason` field to `DisconnectedError` It is useful in some applications to know why the connection was disconnected. This keeps track of the disconnection reason provided by the Softdevice and returns it in the `DisconnectedError`. A new method `Connection::disconnect_with_reason()` has also been added to allow the user to indicate the reason for a locally initiated disconnection to the remote device. --- nrf-softdevice/src/ble/central.rs | 2 +- nrf-softdevice/src/ble/connection.rs | 62 ++++++++++---- nrf-softdevice/src/ble/gatt_client.rs | 3 +- nrf-softdevice/src/ble/gatt_server.rs | 5 +- nrf-softdevice/src/ble/peripheral.rs | 2 +- nrf-softdevice/src/ble/types.rs | 119 ++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 23 deletions(-) diff --git a/nrf-softdevice/src/ble/central.rs b/nrf-softdevice/src/ble/central.rs index 8a133054..1d4adf15 100644 --- a/nrf-softdevice/src/ble/central.rs +++ b/nrf-softdevice/src/ble/central.rs @@ -102,7 +102,7 @@ where Err(_) => { raw::sd_ble_gap_disconnect( conn_handle, - raw::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as _, + raw::BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES as _, ); Err(ConnectError::NoFreeConn) } diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index f373409c..0d342744 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -3,12 +3,13 @@ use core::iter::FusedIterator; use raw::ble_gap_conn_params_t; -use super::PhySet; +use super::{HciStatus, PhySet}; #[cfg(feature = "ble-central")] use crate::ble::gap::default_security_params; #[cfg(feature = "ble-sec")] use crate::ble::security::SecurityHandler; use crate::ble::types::{Address, AddressType, Role, SecurityMode}; +use crate::util::get_union_field; use crate::{raw, RawError}; #[cfg(any(feature = "s113", feature = "s132", feature = "s140"))] @@ -20,7 +21,17 @@ pub(crate) struct OutOfConnsError; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct DisconnectedError; +pub struct DisconnectedError { + pub reason: HciStatus, +} + +impl DisconnectedError { + pub(crate) fn from_raw(reason: u8) -> Self { + Self { + reason: HciStatus::new(reason), + } + } +} #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -199,7 +210,7 @@ pub(crate) struct ConnectionState { // However, disconnection is not complete until the event GAP_DISCONNECTED. // so there's a small gap of time where the ConnectionState is not "free" even if refcount=0. pub refcount: u8, - pub conn_handle: Option, + pub conn_handle: Result, pub disconnecting: bool, pub role: Role, @@ -226,7 +237,9 @@ impl ConnectionState { // can go into .bss instead of .data, which saves flash space. Self { refcount: 0, - conn_handle: None, + conn_handle: Err(DisconnectedError { + reason: HciStatus::CONN_FAILED_TO_BE_ESTABLISHED, + }), #[cfg(feature = "ble-central")] role: Role::Central, #[cfg(not(feature = "ble-central"))] @@ -251,25 +264,28 @@ impl ConnectionState { } } pub(crate) fn check_connected(&mut self) -> Result { - self.conn_handle.ok_or(DisconnectedError) + self.conn_handle } pub(crate) fn disconnect(&mut self) -> Result<(), DisconnectedError> { + self.disconnect_with_reason(HciStatus::REMOTE_USER_TERMINATED_CONNECTION) + } + + pub(crate) fn disconnect_with_reason(&mut self, reason: HciStatus) -> Result<(), DisconnectedError> { let conn_handle = self.check_connected()?; if self.disconnecting { return Ok(()); } - let ret = - unsafe { raw::sd_ble_gap_disconnect(conn_handle, raw::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as u8) }; + let ret = unsafe { raw::sd_ble_gap_disconnect(conn_handle, reason.into()) }; unwrap!(RawError::convert(ret), "sd_ble_gap_disconnect"); self.disconnecting = true; Ok(()) } - pub(crate) fn on_disconnected(&mut self, _ble_evt: *const raw::ble_evt_t) { + pub(crate) fn on_disconnected(&mut self, ble_evt: *const raw::ble_evt_t) { let conn_handle = unwrap!(self.conn_handle, "bug: on_disconnected when already disconnected"); let ibh = index_by_handle(conn_handle); @@ -283,17 +299,23 @@ impl ConnectionState { ibh.set(None); - self.conn_handle = None; + let reason = unsafe { + get_union_field(ble_evt, &(*ble_evt).evt.gap_evt) + .params + .disconnected + .reason + }; + self.conn_handle = Err(DisconnectedError::from_raw(reason)); // Signal possible in-progess operations that the connection has disconnected. #[cfg(feature = "ble-gatt-client")] - crate::ble::gatt_client::portal(conn_handle).call(_ble_evt); + crate::ble::gatt_client::portal(conn_handle).call(ble_evt); #[cfg(feature = "ble-gatt-client")] - crate::ble::gatt_client::hvx_portal(conn_handle).call(_ble_evt); + crate::ble::gatt_client::hvx_portal(conn_handle).call(ble_evt); #[cfg(feature = "ble-gatt-server")] - crate::ble::gatt_server::portal(conn_handle).call(_ble_evt); + crate::ble::gatt_server::portal(conn_handle).call(ble_evt); #[cfg(feature = "ble-l2cap")] - crate::ble::l2cap::portal(conn_handle).call(_ble_evt); + crate::ble::l2cap::portal(conn_handle).call(ble_evt); trace!("conn {:?}: disconnected", _index); } @@ -346,7 +368,7 @@ impl Drop for Connection { ); if state.refcount == 0 { - if state.conn_handle.is_some() { + if state.conn_handle.is_ok() { trace!("conn {:?}: dropped, disconnecting", self.index); // We still leave conn_handle set, because the connection is // not really disconnected until we get GAP_DISCONNECTED event. @@ -382,8 +404,12 @@ impl Connection { self.with_state(|state| state.disconnect()) } + pub fn disconnect_with_reason(&self, reason: HciStatus) -> Result<(), DisconnectedError> { + self.with_state(|state| state.disconnect_with_reason(reason)) + } + pub fn handle(&self) -> Option { - self.with_state(|state| state.conn_handle) + self.with_state(|state| state.conn_handle.ok()) } pub fn from_handle(conn_handle: u16) -> Option { @@ -405,7 +431,7 @@ impl Connection { // Initialize *state = ConnectionState { refcount: 1, - conn_handle: Some(conn_handle), + conn_handle: Ok(conn_handle), role, peer_address, security_mode: SecurityMode::Open, @@ -727,7 +753,7 @@ impl Iterator for ConnectionIter { unsafe { for (i, s) in STATES[n..].iter().enumerate() { let state = &mut *s.get(); - if state.conn_handle.is_some() { + if state.conn_handle.is_ok() { let index = (n + i) as u8; state.refcount = unwrap!(state.refcount.checked_add(1), "Too many references to same connection"); @@ -769,7 +795,7 @@ fn allocate_index(f: impl FnOnce(u8, &mut ConnectionState) -> T) -> Result handle, - Err(DisconnectedError) => return DisconnectedError, + Err(err) => return err, }; portal(conn_handle) .wait_many(|ble_evt| unsafe { let ble_evt = &*ble_evt; if u32::from(ble_evt.header.evt_id) == raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED { - return Some(DisconnectedError); + let gap_evt = get_union_field(ble_evt, &ble_evt.evt.gap_evt); + return Some(DisconnectedError::from_raw(gap_evt.params.disconnected.reason)); } // If evt_id is not BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, then it must be a GATTS event diff --git a/nrf-softdevice/src/ble/peripheral.rs b/nrf-softdevice/src/ble/peripheral.rs index 4acfbda2..4eabe13d 100644 --- a/nrf-softdevice/src/ble/peripheral.rs +++ b/nrf-softdevice/src/ble/peripheral.rs @@ -374,7 +374,7 @@ where Err(_) => { raw::sd_ble_gap_disconnect( conn_handle, - raw::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION as _, + raw::BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES as _, ); Err(AdvertiseError::NoFreeConn) } diff --git a/nrf-softdevice/src/ble/types.rs b/nrf-softdevice/src/ble/types.rs index 41d52213..2209d86f 100644 --- a/nrf-softdevice/src/ble/types.rs +++ b/nrf-softdevice/src/ble/types.rs @@ -611,3 +611,122 @@ error_codes! { /// ATT Common Profile and Service Error: Out Of Range. (ATTERR_CPS_OUT_OF_RANGE, BLE_GATT_STATUS_ATTERR_CPS_OUT_OF_RANGE, "Out of Range"); } + +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct HciStatus(u8); + +impl HciStatus { + pub const fn new(status: u8) -> Self { + Self(status) + } +} + +impl From for HciStatus { + fn from(value: u8) -> Self { + Self(value) + } +} + +impl From for u8 { + fn from(value: HciStatus) -> Self { + value.0 + } +} + +macro_rules! hci_status_codes { + ( + $( + $(#[$docs:meta])* + ($konst:ident, $raw:expr, $phrase:expr); + )+ + ) => { + impl HciStatus { + $( + $(#[$docs])* + pub const $konst: HciStatus = HciStatus($raw as u8); + )+ + } + + #[cfg(feature = "defmt")] + impl defmt::Format for HciStatus { + fn format(&self, fmt: defmt::Formatter) { + match *self { + $( + Self::$konst => defmt::write!(fmt, $phrase), + )+ + _ => defmt::write!(fmt, "Unknown HCI status: 0x{:02x}", self.0), + } + } + } + + impl core::fmt::Debug for HciStatus { + fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match *self { + $( + Self::$konst => core::write!(fmt, $phrase), + )+ + _ => core::write!(fmt, "Unknown HCI status: 0x{:02x}", self.0), + } + } + } + } +} + +hci_status_codes! { + /// Success + (SUCCESS, raw::BLE_HCI_STATUS_CODE_SUCCESS, "Success"); + /// Unknown HCI Command + (UNKNOWN_BTLE_COMMAND, raw::BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND, "Unknown HCI Command"); + /// Unknown Connection Identifier + (UNKNOWN_CONNECTION_IDENTIFIER, raw::BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER, "Unknown Connection Identifier"); + /// Authentication Failure + (AUTHENTICATION_FAILURE, raw::BLE_HCI_AUTHENTICATION_FAILURE, "Authentication Failure"); + /// PIN Or Key Missing + (PIN_OR_KEY_MISSING, raw::BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING, "PIN Or Key Missing"); + /// Memory Capacity Exceeded + (MEMORY_CAPACITY_EXCEEDED, raw::BLE_HCI_MEMORY_CAPACITY_EXCEEDED, "Memory Capacity Exceeded"); + /// Connection Timeout + (CONNECTION_TIMEOUT, raw::BLE_HCI_CONNECTION_TIMEOUT, "Connection Timeout"); + /// Command Disallowed + (COMMAND_DISALLOWED, raw::BLE_HCI_STATUS_CODE_COMMAND_DISALLOWED, "Command Disallowed"); + /// Invalid HCI Command Parameters + (INVALID_BTLE_COMMAND_PARAMETERS, raw::BLE_HCI_STATUS_CODE_INVALID_BTLE_COMMAND_PARAMETERS, "Invalid HCI Command Parameters"); + /// Remote User Terminated Connection + (REMOTE_USER_TERMINATED_CONNECTION, raw::BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION, "Remote User Terminated Connection"); + /// Remote Device Terminated Connection due to Low Resources + (REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES, raw::BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES, "Remote Device Terminated Connection due to Low Resources"); + /// Remote Device Terminated Connection due to Power Off + (REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF, raw::BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF, "Remote Device Terminated Connection due to Power Off"); + /// Connection Terminated by Local Host + (LOCAL_HOST_TERMINATED_CONNECTION, raw::BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION, "Connection Terminated by Local Host"); + /// Unsupported Remote Feature + (UNSUPPORTED_REMOTE_FEATURE, raw::BLE_HCI_UNSUPPORTED_REMOTE_FEATURE, "Unsupported Remote Feature"); + /// Invalid LMP Parameters + (INVALID_LMP_PARAMETERS, raw::BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS, "Invalid LMP Parameters"); + /// Unspecified Error + (UNSPECIFIED_ERROR, raw::BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR, "Unspecified Error"); + /// LMP Response Timeout + (LMP_RESPONSE_TIMEOUT, raw::BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT, "LMP Response Timeout"); + /// LMP Error Transaction Collision + (LMP_ERROR_TRANSACTION_COLLISION, raw::BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION, "LMP Error Transaction Collision"); + /// LMP PDU Not Allowed + (LMP_PDU_NOT_ALLOWED, raw::BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED, "LMP PDU Not Allowed"); + /// Instant Passed + (INSTANT_PASSED, raw::BLE_HCI_INSTANT_PASSED, "Instant Passed"); + /// Pairing With Unit Key Not Supported + (PAIRING_WITH_UNIT_KEY_UNSUPPORTED, raw::BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED, "Pairing With Unit Key Not Supported"); + /// Different Transaction Collision + (DIFFERENT_TRANSACTION_COLLISION, raw::BLE_HCI_DIFFERENT_TRANSACTION_COLLISION, "Different Transaction Collision"); + /// Parameter Out Of Mandatory Range + (PARAMETER_OUT_OF_MANDATORY_RANGE, raw::BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE, "Parameter Out Of Mandatory Range"); + /// Controller Busy + (CONTROLLER_BUSY, raw::BLE_HCI_CONTROLLER_BUSY, "Controller Busy"); + /// Unacceptable Connection Parameters + (CONN_INTERVAL_UNACCEPTABLE, raw::BLE_HCI_CONN_INTERVAL_UNACCEPTABLE, "Unacceptable Connection Parameters"); + /// Advertising Timeout + (DIRECTED_ADVERTISER_TIMEOUT, raw::BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT, "Advertising Timeout"); + /// Connection Terminated due to MIC Failure + (CONN_TERMINATED_DUE_TO_MIC_FAILURE, raw::BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE, "Connection Terminated due to MIC Failure"); + /// Connection Failed to be Established + (CONN_FAILED_TO_BE_ESTABLISHED, raw::BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED, "Connection Failed to be Established"); +} From cd489ed31190978f4583b9b6706359a5587d260d Mon Sep 17 00:00:00 2001 From: Alex Moon Date: Tue, 19 Mar 2024 08:22:04 -0400 Subject: [PATCH 2/4] Use custom ConnHandle type Allows the `Disconnected` state to be represented by all zeros so `ConnectionState` can be put in bss. --- nrf-softdevice/src/ble/connection.rs | 52 +++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index 0d342744..d612530b 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -33,6 +33,33 @@ impl DisconnectedError { } } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub(crate) enum ConnHandle { + Disconnected(HciStatus), + Connected(u16), +} + +impl ConnHandle { + const fn to_result(self) -> Result { + match self { + ConnHandle::Disconnected(reason) => Err(DisconnectedError { reason }), + ConnHandle::Connected(handle) => Ok(handle), + } + } + + const fn handle(self) -> Option { + match self { + ConnHandle::Disconnected(_) => None, + ConnHandle::Connected(handle) => Some(handle), + } + } + + const fn is_connected(&self) -> bool { + matches!(self, ConnHandle::Connected(_)) + } +} + #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SetConnParamsError { @@ -210,7 +237,7 @@ pub(crate) struct ConnectionState { // However, disconnection is not complete until the event GAP_DISCONNECTED. // so there's a small gap of time where the ConnectionState is not "free" even if refcount=0. pub refcount: u8, - pub conn_handle: Result, + pub conn_handle: ConnHandle, pub disconnecting: bool, pub role: Role, @@ -237,9 +264,7 @@ impl ConnectionState { // can go into .bss instead of .data, which saves flash space. Self { refcount: 0, - conn_handle: Err(DisconnectedError { - reason: HciStatus::CONN_FAILED_TO_BE_ESTABLISHED, - }), + conn_handle: ConnHandle::Disconnected(HciStatus::SUCCESS), #[cfg(feature = "ble-central")] role: Role::Central, #[cfg(not(feature = "ble-central"))] @@ -264,7 +289,7 @@ impl ConnectionState { } } pub(crate) fn check_connected(&mut self) -> Result { - self.conn_handle + self.conn_handle.to_result() } pub(crate) fn disconnect(&mut self) -> Result<(), DisconnectedError> { @@ -286,7 +311,10 @@ impl ConnectionState { } pub(crate) fn on_disconnected(&mut self, ble_evt: *const raw::ble_evt_t) { - let conn_handle = unwrap!(self.conn_handle, "bug: on_disconnected when already disconnected"); + let conn_handle = unwrap!( + self.conn_handle.to_result(), + "bug: on_disconnected when already disconnected" + ); let ibh = index_by_handle(conn_handle); let _index = unwrap!(ibh.get(), "bug: conn_handle has no index"); @@ -305,7 +333,7 @@ impl ConnectionState { .disconnected .reason }; - self.conn_handle = Err(DisconnectedError::from_raw(reason)); + self.conn_handle = ConnHandle::Disconnected(HciStatus::new(reason)); // Signal possible in-progess operations that the connection has disconnected. #[cfg(feature = "ble-gatt-client")] @@ -368,7 +396,7 @@ impl Drop for Connection { ); if state.refcount == 0 { - if state.conn_handle.is_ok() { + if state.conn_handle.is_connected() { trace!("conn {:?}: dropped, disconnecting", self.index); // We still leave conn_handle set, because the connection is // not really disconnected until we get GAP_DISCONNECTED event. @@ -409,7 +437,7 @@ impl Connection { } pub fn handle(&self) -> Option { - self.with_state(|state| state.conn_handle.ok()) + self.with_state(|state| state.conn_handle.handle()) } pub fn from_handle(conn_handle: u16) -> Option { @@ -431,7 +459,7 @@ impl Connection { // Initialize *state = ConnectionState { refcount: 1, - conn_handle: Ok(conn_handle), + conn_handle: ConnHandle::Connected(conn_handle), role, peer_address, security_mode: SecurityMode::Open, @@ -753,7 +781,7 @@ impl Iterator for ConnectionIter { unsafe { for (i, s) in STATES[n..].iter().enumerate() { let state = &mut *s.get(); - if state.conn_handle.is_ok() { + if state.conn_handle.is_connected() { let index = (n + i) as u8; state.refcount = unwrap!(state.refcount.checked_add(1), "Too many references to same connection"); @@ -795,7 +823,7 @@ fn allocate_index(f: impl FnOnce(u8, &mut ConnectionState) -> T) -> Result Date: Tue, 19 Mar 2024 11:51:32 -0400 Subject: [PATCH 3/4] Add DisconnectedError to Disconnected error variants L2cap errors are omitted due to ambiguity between channel disconnection vs connection disconnection. --- nrf-softdevice/src/ble/connection.rs | 62 +++++++++++++------------ nrf-softdevice/src/ble/gap.rs | 2 +- nrf-softdevice/src/ble/gatt_client.rs | 65 ++++++++++++++++----------- nrf-softdevice/src/ble/gatt_server.rs | 27 ++++++----- 4 files changed, 82 insertions(+), 74 deletions(-) diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index d612530b..77a8bf22 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -21,29 +21,32 @@ pub(crate) struct OutOfConnsError; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct DisconnectedError { - pub reason: HciStatus, -} +pub struct DisconnectedError(pub HciStatus); impl DisconnectedError { - pub(crate) fn from_raw(reason: u8) -> Self { - Self { - reason: HciStatus::new(reason), - } + pub(crate) unsafe fn from_evt(ble_evt: *const raw::ble_evt_t) -> Self { + assert_eq!( + u32::from((*ble_evt).header.evt_id), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, + "bug: creating DisconnectedError from non-disconnect event" + ); + let gap_evt = get_union_field(ble_evt, &(*ble_evt).evt.gap_evt); + let reason = HciStatus::new(gap_evt.params.disconnected.reason); + Self(reason) } } #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum ConnHandle { - Disconnected(HciStatus), + Disconnected(DisconnectedError), Connected(u16), } impl ConnHandle { const fn to_result(self) -> Result { match self { - ConnHandle::Disconnected(reason) => Err(DisconnectedError { reason }), + ConnHandle::Disconnected(reason) => Err(reason), ConnHandle::Connected(handle) => Ok(handle), } } @@ -63,13 +66,13 @@ impl ConnHandle { #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SetConnParamsError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } impl From for SetConnParamsError { - fn from(_err: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -83,14 +86,14 @@ impl From for SetConnParamsError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(feature = "ble-peripheral")] pub enum IgnoreSlaveLatencyError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } #[cfg(feature = "ble-peripheral")] impl From for IgnoreSlaveLatencyError { - fn from(_err: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -118,13 +121,13 @@ impl From for DataLengthUpdateError { } pub enum PhyUpdateError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } impl From for PhyUpdateError { - fn from(_err: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -138,14 +141,14 @@ impl From for PhyUpdateError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(any(feature = "ble-central", feature = "ble-peripheral"))] pub enum AuthenticateError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } #[cfg(any(feature = "ble-central", feature = "ble-peripheral"))] impl From for AuthenticateError { - fn from(_err: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -160,7 +163,7 @@ impl From for AuthenticateError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(all(feature = "ble-central", feature = "ble-sec"))] pub enum EncryptError { - Disconnected, + Disconnected(DisconnectedError), NoSecurityHandler, PeerKeysNotFound, Raw(RawError), @@ -168,8 +171,8 @@ pub enum EncryptError { #[cfg(all(feature = "ble-central", feature = "ble-sec"))] impl From for EncryptError { - fn from(_err: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -264,7 +267,7 @@ impl ConnectionState { // can go into .bss instead of .data, which saves flash space. Self { refcount: 0, - conn_handle: ConnHandle::Disconnected(HciStatus::SUCCESS), + conn_handle: ConnHandle::Disconnected(DisconnectedError(HciStatus::SUCCESS)), #[cfg(feature = "ble-central")] role: Role::Central, #[cfg(not(feature = "ble-central"))] @@ -327,13 +330,8 @@ impl ConnectionState { ibh.set(None); - let reason = unsafe { - get_union_field(ble_evt, &(*ble_evt).evt.gap_evt) - .params - .disconnected - .reason - }; - self.conn_handle = ConnHandle::Disconnected(HciStatus::new(reason)); + let reason = unsafe { DisconnectedError::from_evt(ble_evt) }; + self.conn_handle = ConnHandle::Disconnected(reason); // Signal possible in-progess operations that the connection has disconnected. #[cfg(feature = "ble-gatt-client")] diff --git a/nrf-softdevice/src/ble/gap.rs b/nrf-softdevice/src/ble/gap.rs index cec25a01..0e51b4af 100644 --- a/nrf-softdevice/src/ble/gap.rs +++ b/nrf-softdevice/src/ble/gap.rs @@ -357,7 +357,7 @@ pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { Err(EncryptError::NoSecurityHandler) | Err(EncryptError::PeerKeysNotFound) => { conn.request_pairing() } - Err(EncryptError::Disconnected) => Err(AuthenticateError::Disconnected), + Err(EncryptError::Disconnected(err)) => Err(AuthenticateError::Disconnected(err)), Err(EncryptError::Raw(err)) => Err(AuthenticateError::Raw(err)), }; #[cfg(not(feature = "ble-sec"))] diff --git a/nrf-softdevice/src/ble/gatt_client.rs b/nrf-softdevice/src/ble/gatt_client.rs index 1ecfa314..4c1b2f96 100644 --- a/nrf-softdevice/src/ble/gatt_client.rs +++ b/nrf-softdevice/src/ble/gatt_client.rs @@ -79,7 +79,7 @@ pub trait Client { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DiscoverError { /// Connection is disconnected. - Disconnected, + Disconnected(DisconnectedError), /// No service with the given UUID found in the server. ServiceNotFound, /// Service with the given UUID found, but it's missing some required characteristics. @@ -89,8 +89,8 @@ pub enum DiscoverError { } impl From for DiscoverError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -120,7 +120,9 @@ pub(crate) async fn discover_service(conn: &Connection, uuid: Uuid) -> Result return Err(DiscoverError::Disconnected), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.prim_srvc_disc_rsp); @@ -170,7 +172,9 @@ async fn discover_characteristics( portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(DiscoverError::Disconnected), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.char_disc_rsp); @@ -211,7 +215,9 @@ async fn discover_descriptors( portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(DiscoverError::Disconnected), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.desc_disc_rsp); @@ -315,15 +321,15 @@ pub async fn discover(conn: &Connection) -> Result #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ReadError { - Disconnected, + Disconnected(DisconnectedError), Truncated, Gatt(GattError), Raw(RawError), } impl From for ReadError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -351,7 +357,9 @@ pub async fn read(conn: &Connection, handle: u16, buf: &mut [u8]) -> Result return Some(Err(ReadError::Disconnected)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Some(Err(ReadError::Disconnected(DisconnectedError::from_evt(ble_evt)))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => { let gattc_evt = match check_status(ble_evt) { Ok(evt) => evt, @@ -376,15 +384,15 @@ pub async fn read(conn: &Connection, handle: u16, buf: &mut [u8]) -> Result for WriteError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -422,7 +430,9 @@ pub async fn write(conn: &Connection, handle: u16, buf: &[u8]) -> Result<(), Wri portal(conn_handle) .wait_many(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Some(Err(WriteError::Disconnected)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Some(Err(WriteError::Disconnected(DisconnectedError::from_evt(ble_evt)))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => { match check_status(ble_evt) { Ok(_) => {} @@ -430,9 +440,7 @@ pub async fn write(conn: &Connection, handle: u16, buf: &[u8]) -> Result<(), Wri }; Some(Ok(())) } - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => { - return Some(Err(WriteError::Timeout)); - } + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => Some(Err(WriteError::Timeout)), _ => None, } }) @@ -463,7 +471,9 @@ pub async fn write_without_response(conn: &Connection, handle: u16, buf: &[u8]) portal(conn_handle) .wait_many(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Some(Err(WriteError::Disconnected)), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Some(Err(WriteError::Disconnected(DisconnectedError::from_evt(ble_evt)))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => Some(Ok(())), _ => None, } @@ -475,15 +485,15 @@ pub async fn write_without_response(conn: &Connection, handle: u16, buf: &[u8]) #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TryWriteError { - Disconnected, + Disconnected(DisconnectedError), BufferFull, Gatt(GattError), Raw(RawError), } impl From for TryWriteError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -538,14 +548,14 @@ pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MtuExchangeError { /// Connection is disconnected. - Disconnected, + Disconnected(DisconnectedError), Gatt(GattError), Raw(RawError), } impl From for MtuExchangeError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -589,7 +599,9 @@ pub(crate) async fn att_mtu_exchange(conn: &Connection, mtu: u16) -> Result<(), portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(MtuExchangeError::Disconnected), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { + Err(MtuExchangeError::Disconnected(DisconnectedError::from_evt(ble_evt))) + } raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => { let gattc_evt = match check_status(ble_evt) { Ok(evt) => evt, @@ -632,8 +644,7 @@ where .wait_many(|ble_evt| unsafe { let ble_evt = &*ble_evt; if u32::from(ble_evt.header.evt_id) == raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED { - let gap_evt = get_union_field(ble_evt, &ble_evt.evt.gap_evt); - return Some(DisconnectedError::from_raw(gap_evt.params.disconnected.reason)); + return Some(DisconnectedError::from_evt(ble_evt)); } // We have a GATTC event diff --git a/nrf-softdevice/src/ble/gatt_server.rs b/nrf-softdevice/src/ble/gatt_server.rs index ee446b4e..23263c20 100644 --- a/nrf-softdevice/src/ble/gatt_server.rs +++ b/nrf-softdevice/src/ble/gatt_server.rs @@ -177,8 +177,7 @@ where .wait_many(|ble_evt| unsafe { let ble_evt = &*ble_evt; if u32::from(ble_evt.header.evt_id) == raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED { - let gap_evt = get_union_field(ble_evt, &ble_evt.evt.gap_evt); - return Some(DisconnectedError::from_raw(gap_evt.params.disconnected.reason)); + return Some(DisconnectedError::from_evt(ble_evt)); } // If evt_id is not BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, then it must be a GATTS event @@ -324,7 +323,7 @@ pub fn set_value(_sd: &Softdevice, handle: u16, val: &[u8]) -> Result<(), SetVal #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum NotifyValueError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } @@ -335,8 +334,8 @@ impl From for NotifyValueError { } impl From for NotifyValueError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -361,7 +360,7 @@ pub fn notify_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), No #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum IndicateValueError { - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } @@ -372,8 +371,8 @@ impl From for IndicateValueError { } impl From for IndicateValueError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -399,13 +398,13 @@ pub fn indicate_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum GetSysAttrsError { DataSize(usize), - Disconnected, + Disconnected(DisconnectedError), Raw(RawError), } impl From for GetSysAttrsError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } @@ -424,13 +423,13 @@ pub fn get_sys_attrs(conn: &Connection, buf: &mut [u8]) -> Result for SetSysAttrsError { - fn from(_: DisconnectedError) -> Self { - Self::Disconnected + fn from(err: DisconnectedError) -> Self { + Self::Disconnected(err) } } From 73d5ae3b390ebca2c4416dce056be6d729b220e4 Mon Sep 17 00:00:00 2001 From: Alex Moon Date: Fri, 22 Mar 2024 10:56:49 -0400 Subject: [PATCH 4/4] Simplify changes for semver compatibility --- nrf-softdevice/src/ble/connection.rs | 92 ++++++++++++++------------- nrf-softdevice/src/ble/gap.rs | 2 +- nrf-softdevice/src/ble/gatt_client.rs | 64 ++++++++----------- nrf-softdevice/src/ble/gatt_server.rs | 28 ++++---- 4 files changed, 90 insertions(+), 96 deletions(-) diff --git a/nrf-softdevice/src/ble/connection.rs b/nrf-softdevice/src/ble/connection.rs index 77a8bf22..fe492eca 100644 --- a/nrf-softdevice/src/ble/connection.rs +++ b/nrf-softdevice/src/ble/connection.rs @@ -21,58 +21,52 @@ pub(crate) struct OutOfConnsError; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct DisconnectedError(pub HciStatus); - -impl DisconnectedError { - pub(crate) unsafe fn from_evt(ble_evt: *const raw::ble_evt_t) -> Self { - assert_eq!( - u32::from((*ble_evt).header.evt_id), - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, - "bug: creating DisconnectedError from non-disconnect event" - ); - let gap_evt = get_union_field(ble_evt, &(*ble_evt).evt.gap_evt); - let reason = HciStatus::new(gap_evt.params.disconnected.reason); - Self(reason) - } -} +pub struct DisconnectedError; #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub(crate) enum ConnHandle { - Disconnected(DisconnectedError), +pub(crate) enum ConnHandleState { + Disconnected(HciStatus), Connected(u16), } -impl ConnHandle { +impl ConnHandleState { const fn to_result(self) -> Result { match self { - ConnHandle::Disconnected(reason) => Err(reason), - ConnHandle::Connected(handle) => Ok(handle), + ConnHandleState::Disconnected(_) => Err(DisconnectedError), + ConnHandleState::Connected(handle) => Ok(handle), } } const fn handle(self) -> Option { match self { - ConnHandle::Disconnected(_) => None, - ConnHandle::Connected(handle) => Some(handle), + ConnHandleState::Disconnected(_) => None, + ConnHandleState::Connected(handle) => Some(handle), } } const fn is_connected(&self) -> bool { - matches!(self, ConnHandle::Connected(_)) + matches!(self, ConnHandleState::Connected(_)) + } + + const fn disconnect_reason(self) -> Option { + match self { + ConnHandleState::Disconnected(reason) => Some(reason), + ConnHandleState::Connected(_) => None, + } } } #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SetConnParamsError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } impl From for SetConnParamsError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_err: DisconnectedError) -> Self { + Self::Disconnected } } @@ -86,14 +80,14 @@ impl From for SetConnParamsError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(feature = "ble-peripheral")] pub enum IgnoreSlaveLatencyError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } #[cfg(feature = "ble-peripheral")] impl From for IgnoreSlaveLatencyError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_err: DisconnectedError) -> Self { + Self::Disconnected } } @@ -121,13 +115,13 @@ impl From for DataLengthUpdateError { } pub enum PhyUpdateError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } impl From for PhyUpdateError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_err: DisconnectedError) -> Self { + Self::Disconnected } } @@ -141,14 +135,14 @@ impl From for PhyUpdateError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(any(feature = "ble-central", feature = "ble-peripheral"))] pub enum AuthenticateError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } #[cfg(any(feature = "ble-central", feature = "ble-peripheral"))] impl From for AuthenticateError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_err: DisconnectedError) -> Self { + Self::Disconnected } } @@ -163,7 +157,7 @@ impl From for AuthenticateError { #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(all(feature = "ble-central", feature = "ble-sec"))] pub enum EncryptError { - Disconnected(DisconnectedError), + Disconnected, NoSecurityHandler, PeerKeysNotFound, Raw(RawError), @@ -171,8 +165,8 @@ pub enum EncryptError { #[cfg(all(feature = "ble-central", feature = "ble-sec"))] impl From for EncryptError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_err: DisconnectedError) -> Self { + Self::Disconnected } } @@ -240,7 +234,7 @@ pub(crate) struct ConnectionState { // However, disconnection is not complete until the event GAP_DISCONNECTED. // so there's a small gap of time where the ConnectionState is not "free" even if refcount=0. pub refcount: u8, - pub conn_handle: ConnHandle, + pub conn_handle: ConnHandleState, pub disconnecting: bool, pub role: Role, @@ -267,7 +261,7 @@ impl ConnectionState { // can go into .bss instead of .data, which saves flash space. Self { refcount: 0, - conn_handle: ConnHandle::Disconnected(DisconnectedError(HciStatus::SUCCESS)), + conn_handle: ConnHandleState::Disconnected(HciStatus::SUCCESS), #[cfg(feature = "ble-central")] role: Role::Central, #[cfg(not(feature = "ble-central"))] @@ -315,7 +309,7 @@ impl ConnectionState { pub(crate) fn on_disconnected(&mut self, ble_evt: *const raw::ble_evt_t) { let conn_handle = unwrap!( - self.conn_handle.to_result(), + self.conn_handle.handle(), "bug: on_disconnected when already disconnected" ); @@ -330,8 +324,16 @@ impl ConnectionState { ibh.set(None); - let reason = unsafe { DisconnectedError::from_evt(ble_evt) }; - self.conn_handle = ConnHandle::Disconnected(reason); + let reason = unsafe { + assert_eq!( + u32::from((*ble_evt).header.evt_id), + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, + "bug: on_disconnected called with non-disconnect event" + ); + let gap_evt = get_union_field(ble_evt, &(*ble_evt).evt.gap_evt); + HciStatus::new(gap_evt.params.disconnected.reason) + }; + self.conn_handle = ConnHandleState::Disconnected(reason); // Signal possible in-progess operations that the connection has disconnected. #[cfg(feature = "ble-gatt-client")] @@ -434,6 +436,10 @@ impl Connection { self.with_state(|state| state.disconnect_with_reason(reason)) } + pub fn disconnect_reason(&self) -> Option { + self.with_state(|state| state.conn_handle.disconnect_reason()) + } + pub fn handle(&self) -> Option { self.with_state(|state| state.conn_handle.handle()) } @@ -457,7 +463,7 @@ impl Connection { // Initialize *state = ConnectionState { refcount: 1, - conn_handle: ConnHandle::Connected(conn_handle), + conn_handle: ConnHandleState::Connected(conn_handle), role, peer_address, security_mode: SecurityMode::Open, diff --git a/nrf-softdevice/src/ble/gap.rs b/nrf-softdevice/src/ble/gap.rs index 0e51b4af..cec25a01 100644 --- a/nrf-softdevice/src/ble/gap.rs +++ b/nrf-softdevice/src/ble/gap.rs @@ -357,7 +357,7 @@ pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { Err(EncryptError::NoSecurityHandler) | Err(EncryptError::PeerKeysNotFound) => { conn.request_pairing() } - Err(EncryptError::Disconnected(err)) => Err(AuthenticateError::Disconnected(err)), + Err(EncryptError::Disconnected) => Err(AuthenticateError::Disconnected), Err(EncryptError::Raw(err)) => Err(AuthenticateError::Raw(err)), }; #[cfg(not(feature = "ble-sec"))] diff --git a/nrf-softdevice/src/ble/gatt_client.rs b/nrf-softdevice/src/ble/gatt_client.rs index 4c1b2f96..e9d0cd66 100644 --- a/nrf-softdevice/src/ble/gatt_client.rs +++ b/nrf-softdevice/src/ble/gatt_client.rs @@ -79,7 +79,7 @@ pub trait Client { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DiscoverError { /// Connection is disconnected. - Disconnected(DisconnectedError), + Disconnected, /// No service with the given UUID found in the server. ServiceNotFound, /// Service with the given UUID found, but it's missing some required characteristics. @@ -89,8 +89,8 @@ pub enum DiscoverError { } impl From for DiscoverError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -120,9 +120,7 @@ pub(crate) async fn discover_service(conn: &Connection, uuid: Uuid) -> Result { - Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(DiscoverError::Disconnected), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.prim_srvc_disc_rsp); @@ -172,9 +170,7 @@ async fn discover_characteristics( portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { - Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(DiscoverError::Disconnected), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_CHAR_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.char_disc_rsp); @@ -215,9 +211,7 @@ async fn discover_descriptors( portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { - Err(DiscoverError::Disconnected(DisconnectedError::from_evt(ble_evt))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(DiscoverError::Disconnected), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_DESC_DISC_RSP => { let gattc_evt = check_status(ble_evt)?; let params = get_union_field(ble_evt, &gattc_evt.params.desc_disc_rsp); @@ -321,15 +315,15 @@ pub async fn discover(conn: &Connection) -> Result #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ReadError { - Disconnected(DisconnectedError), + Disconnected, Truncated, Gatt(GattError), Raw(RawError), } impl From for ReadError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -357,9 +351,7 @@ pub async fn read(conn: &Connection, handle: u16, buf: &mut [u8]) -> Result { - Some(Err(ReadError::Disconnected(DisconnectedError::from_evt(ble_evt)))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Some(Err(ReadError::Disconnected)), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_READ_RSP => { let gattc_evt = match check_status(ble_evt) { Ok(evt) => evt, @@ -384,15 +376,15 @@ pub async fn read(conn: &Connection, handle: u16, buf: &mut [u8]) -> Result for WriteError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -430,9 +422,7 @@ pub async fn write(conn: &Connection, handle: u16, buf: &[u8]) -> Result<(), Wri portal(conn_handle) .wait_many(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { - Some(Err(WriteError::Disconnected(DisconnectedError::from_evt(ble_evt)))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Some(Err(WriteError::Disconnected)), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_RSP => { match check_status(ble_evt) { Ok(_) => {} @@ -440,7 +430,9 @@ pub async fn write(conn: &Connection, handle: u16, buf: &[u8]) -> Result<(), Wri }; Some(Ok(())) } - raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => Some(Err(WriteError::Timeout)), + raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_TIMEOUT => { + return Some(Err(WriteError::Timeout)); + } _ => None, } }) @@ -471,9 +463,7 @@ pub async fn write_without_response(conn: &Connection, handle: u16, buf: &[u8]) portal(conn_handle) .wait_many(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { - Some(Err(WriteError::Disconnected(DisconnectedError::from_evt(ble_evt)))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Some(Err(WriteError::Disconnected)), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE => Some(Ok(())), _ => None, } @@ -485,15 +475,15 @@ pub async fn write_without_response(conn: &Connection, handle: u16, buf: &[u8]) #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TryWriteError { - Disconnected(DisconnectedError), + Disconnected, BufferFull, Gatt(GattError), Raw(RawError), } impl From for TryWriteError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -548,14 +538,14 @@ pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MtuExchangeError { /// Connection is disconnected. - Disconnected(DisconnectedError), + Disconnected, Gatt(GattError), Raw(RawError), } impl From for MtuExchangeError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -599,9 +589,7 @@ pub(crate) async fn att_mtu_exchange(conn: &Connection, mtu: u16) -> Result<(), portal(conn_handle) .wait_once(|ble_evt| unsafe { match (*ble_evt).header.evt_id as u32 { - raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => { - Err(MtuExchangeError::Disconnected(DisconnectedError::from_evt(ble_evt))) - } + raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED => return Err(MtuExchangeError::Disconnected), raw::BLE_GATTC_EVTS_BLE_GATTC_EVT_EXCHANGE_MTU_RSP => { let gattc_evt = match check_status(ble_evt) { Ok(evt) => evt, @@ -644,7 +632,7 @@ where .wait_many(|ble_evt| unsafe { let ble_evt = &*ble_evt; if u32::from(ble_evt.header.evt_id) == raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED { - return Some(DisconnectedError::from_evt(ble_evt)); + return Some(DisconnectedError); } // We have a GATTC event diff --git a/nrf-softdevice/src/ble/gatt_server.rs b/nrf-softdevice/src/ble/gatt_server.rs index 23263c20..3c183e02 100644 --- a/nrf-softdevice/src/ble/gatt_server.rs +++ b/nrf-softdevice/src/ble/gatt_server.rs @@ -170,14 +170,14 @@ where { let conn_handle = match conn.with_state(|state| state.check_connected()) { Ok(handle) => handle, - Err(err) => return err, + Err(DisconnectedError) => return DisconnectedError, }; portal(conn_handle) .wait_many(|ble_evt| unsafe { let ble_evt = &*ble_evt; if u32::from(ble_evt.header.evt_id) == raw::BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED { - return Some(DisconnectedError::from_evt(ble_evt)); + return Some(DisconnectedError); } // If evt_id is not BLE_GAP_EVTS_BLE_GAP_EVT_DISCONNECTED, then it must be a GATTS event @@ -323,7 +323,7 @@ pub fn set_value(_sd: &Softdevice, handle: u16, val: &[u8]) -> Result<(), SetVal #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum NotifyValueError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } @@ -334,8 +334,8 @@ impl From for NotifyValueError { } impl From for NotifyValueError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -360,7 +360,7 @@ pub fn notify_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), No #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum IndicateValueError { - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } @@ -371,8 +371,8 @@ impl From for IndicateValueError { } impl From for IndicateValueError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -398,13 +398,13 @@ pub fn indicate_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum GetSysAttrsError { DataSize(usize), - Disconnected(DisconnectedError), + Disconnected, Raw(RawError), } impl From for GetSysAttrsError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } } @@ -423,13 +423,13 @@ pub fn get_sys_attrs(conn: &Connection, buf: &mut [u8]) -> Result for SetSysAttrsError { - fn from(err: DisconnectedError) -> Self { - Self::Disconnected(err) + fn from(_: DisconnectedError) -> Self { + Self::Disconnected } }