From 3b869f8e25ace92d4444a4ae3351c9cb10691060 Mon Sep 17 00:00:00 2001 From: Albert Skog Date: Thu, 30 Sep 2021 15:07:45 +0200 Subject: add support for indications --- nrf-softdevice-macro/src/lib.rs | 30 +++++++++++++++++++++++++++++ nrf-softdevice/src/ble/gatt_server.rs | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/nrf-softdevice-macro/src/lib.rs b/nrf-softdevice-macro/src/lib.rs index d2e4789..fad3e93 100644 --- a/nrf-softdevice-macro/src/lib.rs +++ b/nrf-softdevice-macro/src/lib.rs @@ -122,6 +122,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { let get_fn = format_ident!("{}_get", ch.name); let set_fn = format_ident!("{}_set", ch.name); let notify_fn = format_ident!("{}_notify", ch.name); + let indicate_fn = format_ident!("{}_indicate", ch.name); let uuid = ch.args.uuid; let read = ch.args.read; @@ -212,6 +213,35 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { } )); + code_event_enum.extend(quote_spanned!(ch.span=> + #case_enabled, + #case_disabled, + )); + code_on_write.extend(quote_spanned!(ch.span=> + if handle == self.#cccd_handle { + if data.len() != 0 && data[0] & 0x01 != 0 { + return Some(#event_enum_name::#case_enabled); + } else { + return Some(#event_enum_name::#case_disabled); + } + } + )); + } + if indicate { + let case_enabled = format_ident!("{}IndicationsEnabled", name_pascal); + let case_disabled = format_ident!("{}IndicationsDisabled", name_pascal); + + code_impl.extend(quote_spanned!(ch.span=> + fn #indicate_fn( + &self, + conn: &#ble::Connection, + val: #ty, + ) -> Result<(), #ble::gatt_server::IndicateValueError> { + let buf = #ty_as_val::to_gatt(&val); + #ble::gatt_server::indicate_value(conn, self.#value_handle, buf) + } + )); + code_event_enum.extend(quote_spanned!(ch.span=> #case_enabled, #case_disabled, diff --git a/nrf-softdevice/src/ble/gatt_server.rs b/nrf-softdevice/src/ble/gatt_server.rs index 58663cc..d6d7f13 100644 --- a/nrf-softdevice/src/ble/gatt_server.rs +++ b/nrf-softdevice/src/ble/gatt_server.rs @@ -266,6 +266,42 @@ pub fn notify_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), No Ok(()) } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum IndicateValueError { + Disconnected, + Raw(RawError), +} + +impl From for IndicateValueError { + fn from(err: RawError) -> Self { + Self::Raw(err) + } +} + +impl From for IndicateValueError { + fn from(_: DisconnectedError) -> Self { + Self::Disconnected + } +} + +pub fn indicate_value(conn: &Connection, handle: u16, val: &[u8]) -> Result<(), IndicateValueError> { + let conn_handle = conn.with_state(|state| state.check_connected())?; + + let mut len: u16 = val.len() as _; + let params = raw::ble_gatts_hvx_params_t { + handle, + type_: raw::BLE_GATT_HVX_INDICATION as u8, + offset: 0, + p_data: val.as_ptr() as _, + p_len: &mut len, + }; + let ret = unsafe { raw::sd_ble_gatts_hvx(conn_handle, ¶ms) }; + RawError::convert(ret)?; + + Ok(()) +} + pub(crate) unsafe fn on_evt(ble_evt: *const raw::ble_evt_t) { let gatts_evt = get_union_field(ble_evt, &(*ble_evt).evt.gatts_evt); match (*ble_evt).header.evt_id as u32 { -- cgit v1.2.3