diff --git a/bleps-dedup/src/lib.rs b/bleps-dedup/src/lib.rs index c251ca0..162d731 100644 --- a/bleps-dedup/src/lib.rs +++ b/bleps-dedup/src/lib.rs @@ -1,4 +1,4 @@ -use proc_macro::TokenStream; +use proc_macro::{Delimiter, TokenStream}; use proc_macro_error::proc_macro_error; #[derive(Debug)] @@ -40,7 +40,7 @@ pub fn dedup(input: TokenStream) -> TokenStream { current.extend([tok]); } }, - proc_macro::TokenTree::Group(_group) => { + proc_macro::TokenTree::Group(group) if group.delimiter() == Delimiter::Brace => { if !current.is_empty() { impls.push(Implementation { is_async: impl_is_async, diff --git a/bleps/src/async_attribute_server.rs b/bleps/src/async_attribute_server.rs index 44113c7..d04898d 100644 --- a/bleps/src/async_attribute_server.rs +++ b/bleps/src/async_attribute_server.rs @@ -30,6 +30,9 @@ where #[cfg(feature = "crypto")] pub(crate) security_manager: AsyncSecurityManager<'a, Ble, R>, + #[cfg(feature = "crypto")] + pub(crate) pin_callback: Option<&'a mut dyn FnMut(u32)>, + #[cfg(not(feature = "crypto"))] phantom: PhantomData, } @@ -38,6 +41,9 @@ impl<'a, T, R: CryptoRng + RngCore> AttributeServer<'a, T, R> where T: embedded_io_async::Read + embedded_io_async::Write, { + /// Create a new instance of the AttributeServer + /// + /// When _NOT_ using the `crypto` feature you can pass a mutual reference to `bleps::no_rng::NoRng` pub fn new( ble: &'a mut Ble, attributes: &'a mut [Attribute<'a>], @@ -91,6 +97,9 @@ where #[cfg(feature = "crypto")] security_manager, + #[cfg(feature = "crypto")] + pin_callback: None, + #[cfg(not(feature = "crypto"))] phantom: PhantomData::default(), } diff --git a/bleps/src/attribute_server.rs b/bleps/src/attribute_server.rs index b9aae69..52809ff 100644 --- a/bleps/src/attribute_server.rs +++ b/bleps/src/attribute_server.rs @@ -75,6 +75,9 @@ pub struct AttributeServer<'a, R: CryptoRng + RngCore> { #[cfg(feature = "crypto")] security_manager: SecurityManager<'a, Ble<'a>, R>, + #[cfg(feature = "crypto")] + pub(crate) pin_callback: Option<&'a mut dyn FnMut(u32)>, + #[cfg(not(feature = "crypto"))] phantom: PhantomData, } @@ -192,7 +195,7 @@ bleps_dedup::dedup! { // handle SM #[cfg(feature = "crypto")] self.security_manager - .handle(self.ble, src_handle, l2cap_packet.payload).await?; + .handle(self.ble, src_handle, l2cap_packet.payload, &mut self.pin_callback).await?; Ok(WorkResult::DidWork) } else { let packet = Att::decode(l2cap_packet)?; @@ -559,6 +562,9 @@ bleps_dedup::dedup! { } impl<'a, R: CryptoRng + RngCore> AttributeServer<'a, R> { + /// Create a new instance of the AttributeServer + /// + /// When _NOT_ using the `crypto` feature you can pass a mutual reference to `bleps::no_rng::NoRng` pub fn new( ble: &'a mut Ble<'a>, attributes: &'a mut [Attribute<'a>], @@ -611,6 +617,8 @@ impl<'a, R: CryptoRng + RngCore> AttributeServer<'a, R> { #[cfg(feature = "crypto")] security_manager, + #[cfg(feature = "crypto")] + pin_callback: None, #[cfg(not(feature = "crypto"))] phantom: PhantomData::default(), @@ -625,6 +633,11 @@ impl<'a, R: CryptoRng + RngCore> AttributeServer<'a, R> { #[cfg(not(feature = "crypto"))] None } + + #[cfg(feature = "crypto")] + pub fn set_pin_callback(&mut self, pin_callback: Option<&'a mut dyn FnMut(u32)>) { + self.pin_callback = pin_callback; + } } #[derive(Debug)] diff --git a/bleps/src/l2cap.rs b/bleps/src/l2cap.rs index a231892..2294744 100644 --- a/bleps/src/l2cap.rs +++ b/bleps/src/l2cap.rs @@ -15,7 +15,7 @@ pub enum L2capDecodeError { impl L2capPacket { pub fn decode(packet: AclPacket) -> Result<(u16, Self), L2capDecodeError> { let data = packet.data.as_slice(); - log::info!("{:02x?}", data); + log::debug!("L2CAP {:02x?}", data); let length = (data[0] as u16) + ((data[1] as u16) << 8); let channel = (data[2] as u16) + ((data[3] as u16) << 8); let payload = Data::new(&data[4..]); diff --git a/bleps/src/sm.rs b/bleps/src/sm.rs index 108fe3a..3e47fbe 100644 --- a/bleps/src/sm.rs +++ b/bleps/src/sm.rs @@ -206,7 +206,7 @@ bleps_dedup::dedup! { impl<'a, B, R> SYNC SecurityManager<'a, B, R> where B: BleWriter, R: CryptoRng + RngCore impl<'a, B, R> ASYNC AsyncSecurityManager<'a, B, R> where B: AsyncBleWriter, R: CryptoRng + RngCore { - pub(crate) async fn handle(&mut self, ble: &mut B, src_handle: u16, payload: crate::Data) -> Result<(), AttributeServerError> { + pub(crate) async fn handle(&mut self, ble: &mut B, src_handle: u16, payload: crate::Data, pin_callback: &mut Option<&mut dyn FnMut(u32)>) -> Result<(), AttributeServerError> { log::info!("SM packet {:02x?}", payload.as_slice()); let data = &payload.as_slice()[1..]; @@ -220,7 +220,7 @@ impl<'a, B, R> ASYNC AsyncSecurityManager<'a, B, R> where B: AsyncBleWriter, R: self.handle_pairing_public_key(ble, src_handle, data).await?; } SM_PAIRING_RANDOM => { - self.handle_pairing_random(ble, src_handle, data).await?; + self.handle_pairing_random(ble, src_handle, data, pin_callback).await?; } SM_PAIRING_DHKEY_CHECK => { self.handle_pairing_dhkey_check(ble, src_handle, data).await?; @@ -301,7 +301,7 @@ impl<'a, B, R> ASYNC AsyncSecurityManager<'a, B, R> where B: AsyncBleWriter, R: Ok(()) } - async fn handle_pairing_random(&mut self, ble: &mut B, src_handle: u16, random: &[u8]) -> Result<(), AttributeServerError> { + async fn handle_pairing_random(&mut self, ble: &mut B, src_handle: u16, random: &[u8], pin_callback: &mut Option<&mut dyn FnMut(u32)>) -> Result<(), AttributeServerError> { log::info!("got pairing random {:02x?}", random); if *&(self.nb).is_none() { @@ -345,6 +345,9 @@ impl<'a, B, R> ASYNC AsyncSecurityManager<'a, B, R> where B: AsyncBleWriter, R: // should display the code and get confirmation from user (pin ok or not) - if not okay send a pairing-failed // assume it's correct or the user will cancel on central log::info!("Display code is {}", vb.0); + if let Some(pin_callback) = pin_callback { + pin_callback(vb.0); + } // Authentication stage 2 and long term key calculation // ([Vol 3] Part H, Section 2.3.5.6.5 and C.2.2.4). diff --git a/example/src/main.rs b/example/src/main.rs index f45e230..069aeec 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -160,6 +160,12 @@ fn main() { &mut rng, ); + let mut pin_callback = |pin: u32| { + println!("PIN is {pin}"); + }; + + srv.set_pin_callback(Some(&mut pin_callback)); + let mut response = [b'H', b'e', b'l', b'l', b'o', b'0']; loop {