From 8a5141ac2610b0656146d0a00ed176375db1d117 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Mon, 8 Apr 2024 11:11:36 +0200 Subject: [PATCH] update to support extended advertising --- .../nrf-sdc/src/bin/ble_bas_peripheral.rs | 21 +- examples/nrf-sdc/src/bin/ble_l2cap_central.rs | 5 +- .../nrf-sdc/src/bin/ble_l2cap_peripheral.rs | 19 +- examples/serial-hci/src/main.rs | 18 +- host/src/adapter.rs | 154 ++++++------ host/src/advertise.rs | 234 ++++++++++-------- host/src/lib.rs | 7 +- 7 files changed, 254 insertions(+), 204 deletions(-) diff --git a/examples/nrf-sdc/src/bin/ble_bas_peripheral.rs b/examples/nrf-sdc/src/bin/ble_bas_peripheral.rs index 3433632a..c91ac24a 100644 --- a/examples/nrf-sdc/src/bin/ble_bas_peripheral.rs +++ b/examples/nrf-sdc/src/bin/ble_bas_peripheral.rs @@ -112,7 +112,9 @@ async fn main(spawner: Spawner) { StaticCell::new(); let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::None)); - let adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = Adapter::new(sdc, host_resources); + let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = + Adapter::new(sdc, host_resources); + unwrap!(adapter.set_random_address(my_addr()).await); let mut table: AttributeTable<'_, NoopRawMutex, 10> = AttributeTable::new(); @@ -140,7 +142,15 @@ async fn main(spawner: Spawner) { }; let server = adapter.gatt_server(&table); - unwrap!(adapter.set_random_address(my_addr()).await); + let mut adv_data = [0; 31]; + unwrap!(AdStructure::encode_slice( + &[ + AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), + AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]), + AdStructure::CompleteLocalName(b"Trouble"), + ], + &mut adv_data[..], + )); info!("Starting advertising and GATT service"); let _ = join3( @@ -163,11 +173,8 @@ async fn main(spawner: Spawner) { .advertise( &Default::default(), Advertisement::ConnectableScannableUndirected { - adv_data: &[ - AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), - AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]), - ], - scan_data: &[AdStructure::CompleteLocalName(b"Trouble")], + adv_data: &adv_data[..], + scan_data: &[], } ) .await diff --git a/examples/nrf-sdc/src/bin/ble_l2cap_central.rs b/examples/nrf-sdc/src/bin/ble_l2cap_central.rs index c9502602..cfba565c 100644 --- a/examples/nrf-sdc/src/bin/ble_l2cap_central.rs +++ b/examples/nrf-sdc/src/bin/ble_l2cap_central.rs @@ -120,7 +120,9 @@ async fn main(spawner: Spawner) { StaticCell::new(); let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::Guaranteed(4))); - let adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = Adapter::new(sdc, host_resources); + let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = + Adapter::new(sdc, host_resources); + unwrap!(adapter.set_random_address(my_addr()).await); let config = ScanConfig { params: None, @@ -129,7 +131,6 @@ async fn main(spawner: Spawner) { // NOTE: Modify this to match the address of the peripheral you want to connect to let target: Address = Address::random([0xf5, 0x9f, 0x1a, 0x05, 0xe4, 0xee]); - unwrap!(adapter.set_random_address(my_addr()).await); info!("Scanning for peripheral..."); let _ = join(adapter.run(), async { diff --git a/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs b/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs index 4f28574b..eb6b141e 100644 --- a/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs +++ b/examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs @@ -119,9 +119,20 @@ async fn main(spawner: Spawner) { StaticCell::new(); let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::Guaranteed(4))); - let adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = Adapter::new(sdc, host_resources); - + let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> = + Adapter::new(sdc, host_resources); unwrap!(adapter.set_random_address(my_addr()).await); + let mut adv_data = [0; 31]; + unwrap!(AdStructure::encode_slice( + &[AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),], + &mut adv_data[..], + )); + + let mut scan_data = [0; 31]; + unwrap!(AdStructure::encode_slice( + &[AdStructure::CompleteLocalName(b"Trouble"),], + &mut scan_data[..], + )); let _ = join(adapter.run(), async { loop { @@ -131,8 +142,8 @@ async fn main(spawner: Spawner) { .advertise( &Default::default(), Advertisement::ConnectableScannableUndirected { - adv_data: &[AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),], - scan_data: &[AdStructure::CompleteLocalName(b"Trouble")], + adv_data: &adv_data[..], + scan_data: &scan_data[..], } ) .await diff --git a/examples/serial-hci/src/main.rs b/examples/serial-hci/src/main.rs index 010f4b07..aaf99acb 100644 --- a/examples/serial-hci/src/main.rs +++ b/examples/serial-hci/src/main.rs @@ -88,6 +88,17 @@ async fn main() { ) }; + let mut adv_data = [0; 31]; + AdStructure::encode_slice( + &[ + AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), + AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]), + AdStructure::CompleteLocalName(b"Trouble HCI"), + ], + &mut adv_data[..], + ) + .unwrap(); + let server = adapter.gatt_server(&table); info!("Starting advertising and GATT service"); @@ -110,11 +121,8 @@ async fn main() { .advertise( &Default::default(), Advertisement::ConnectableScannableUndirected { - adv_data: &[ - AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED), - AdStructure::ServiceUuids16(&[Uuid::Uuid16([0x0f, 0x18])]), - ], - scan_data: &[AdStructure::CompleteLocalName(b"Trouble HCI")], + adv_data: &adv_data[..], + scan_data: &[], }, ) .await diff --git a/host/src/adapter.rs b/host/src/adapter.rs index dd78eef4..b92d1b24 100644 --- a/host/src/adapter.rs +++ b/host/src/adapter.rs @@ -1,4 +1,4 @@ -use crate::advertise::{AdvertisementConfig, AdvertisementKind, RawAdvertisement}; +use crate::advertise::{AdvertisementConfig, RawAdvertisement}; use crate::channel_manager::ChannelManager; use crate::connection::Connection; use crate::connection_manager::{ConnectionInfo, ConnectionManager}; @@ -13,8 +13,8 @@ use crate::{AdapterError, Error}; use bt_hci::cmd::controller_baseband::{Reset, SetEventMask}; use bt_hci::cmd::le::{ LeAddDeviceToFilterAcceptList, LeClearAdvSets, LeClearFilterAcceptList, LeCreateConn, LeCreateConnParams, - LeReadBufferSize, LeSetAdvData, LeSetAdvEnable, LeSetAdvParams, LeSetExtAdvEnable, LeSetExtAdvParams, - LeSetRandomAddr, LeSetScanEnable, LeSetScanParams, LeSetScanResponseData, + LeReadBufferSize, LeSetAdvSetRandomAddr, LeSetExtAdvData, LeSetExtAdvEnable, LeSetExtAdvParams, + LeSetExtScanResponseData, LeSetRandomAddr, LeSetScanEnable, LeSetScanParams, }; use bt_hci::cmd::link_control::{Disconnect, DisconnectParams}; use bt_hci::cmd::{AsyncCmd, SyncCmd}; @@ -23,7 +23,7 @@ use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync}; use bt_hci::data::{AclBroadcastFlag, AclPacket, AclPacketBoundary}; use bt_hci::event::le::LeEvent; use bt_hci::event::Event; -use bt_hci::param::{AddrKind, AdvHandle, BdAddr, ConnHandle, DisconnectReason, EventMask}; +use bt_hci::param::{AddrKind, AdvHandle, BdAddr, ConnHandle, DisconnectReason, EventMask, Operation}; use bt_hci::ControllerToHostPacket; use core::task::Poll; use embassy_futures::select::{select, Either}; @@ -106,11 +106,12 @@ where } } - pub async fn set_random_address(&self, address: Address) -> Result<(), AdapterError> + pub async fn set_random_address(&mut self, address: Address) -> Result<(), AdapterError> where T: ControllerCmdSync, { LeSetRandomAddr::new(address.addr).exec(&self.controller).await?; + self.address.replace(address); Ok(()) } @@ -164,102 +165,88 @@ where params: impl Into>, ) -> Result, AdapterError> where - T: ControllerCmdSync - + ControllerCmdSync + T: for<'t> ControllerCmdSync> + ControllerCmdSync - + ControllerCmdSync + ControllerCmdSync - + ControllerCmdSync> - + ControllerCmdSync, + + ControllerCmdSync + + for<'t> ControllerCmdSync> + + for<'t> ControllerCmdSync>, { // May fail if already disabled - let _ = LeSetAdvEnable::new(false).exec(&self.controller).await; let _ = LeSetExtAdvEnable::new(false, &[]).exec(&self.controller).await; let _ = LeClearAdvSets::new().exec(&self.controller).await; - - let params = params.into(); - match params.kind { - AdvertisementKind::Legacy(kind) => { - let peer = params.peer.unwrap_or(Address { - kind: AddrKind::RANDOM, - addr: BdAddr::default(), - }); - LeSetAdvParams::new( - bt_hci::param::Duration::from_micros(config.interval_min.as_micros()), - bt_hci::param::Duration::from_micros(config.interval_min.as_micros()), - kind, - self.address.map(|a| a.kind).unwrap_or(AddrKind::RANDOM), - peer.kind, - peer.addr, - config.channel_map, - config.filter_policy, - ) - .exec(&self.controller) - .await?; - } - AdvertisementKind::Extended(props) => { - let peer = params.peer.unwrap_or(Address { - kind: AddrKind::RANDOM, - addr: BdAddr::default(), - }); - LeSetExtAdvParams::new( - AdvHandle::new(0), - props, - bt_hci::param::ExtDuration::from_micros(config.interval_min.as_micros()), - bt_hci::param::ExtDuration::from_micros(config.interval_min.as_micros()), - config.channel_map, - self.address.map(|a| a.kind).unwrap_or(AddrKind::RANDOM), - peer.kind, - peer.addr, - config.filter_policy, - config.tx_power as i8, - config.primary_phy, - 0, - config.secondary_phy, - params.set_id, - params.anonymous, - ) + let handle = AdvHandle::new(0); // TODO: Configurable? + + let mut params = params.into(); + let timeout = config + .timeout + .map(|m| bt_hci::param::Duration::from_micros(m.as_micros())) + .unwrap_or(bt_hci::param::Duration::from_secs(0)); + let max_events = config.max_events.unwrap_or(0); + + params.set.duration = timeout; + params.set.max_ext_adv_events = max_events; + + let peer = params.peer.unwrap_or(Address { + kind: AddrKind::RANDOM, + addr: BdAddr::default(), + }); + LeSetExtAdvParams::new( + handle, + params.props, + bt_hci::param::ExtDuration::from_micros(config.interval_min.as_micros()), + bt_hci::param::ExtDuration::from_micros(config.interval_min.as_micros()), + config.channel_map, + self.address.map(|a| a.kind).unwrap_or(AddrKind::RANDOM), + peer.kind, + peer.addr, + config.filter_policy, + config.tx_power as i8, + config.primary_phy, + 0, + config.secondary_phy, + params.set.adv_handle.as_raw(), + false, + ) + .exec(&self.controller) + .await?; + + if let Some(address) = self.address { + LeSetAdvSetRandomAddr::new(handle, address.addr) .exec(&self.controller) .await?; - } } if !params.adv_data.is_empty() { - let mut data = [0; 31]; - let mut w = WriteCursor::new(&mut data[..]); - for item in params.adv_data.iter() { - item.encode(&mut w)?; - } - let len = w.len(); - LeSetAdvData::new(len as u8, data).exec(&self.controller).await?; + // let mut data = [0; 31]; + // let mut w = WriteCursor::new(&mut data[..]); + // for item in params.adv_data.iter() { + // item.encode(&mut w)?; + // } + // let len = w.len(); + LeSetExtAdvData::new(handle, Operation::Complete, false, params.adv_data) + .exec(&self.controller) + .await?; } if !params.scan_data.is_empty() { - let mut data = [0; 31]; - let mut w = WriteCursor::new(&mut data[..]); - for item in params.scan_data.iter() { - item.encode(&mut w)?; - } - let len = w.len(); - LeSetScanResponseData::new(len as u8, data) + //let mut data = [0; 31]; + //let mut w = WriteCursor::new(&mut data[..]); + //for item in params.scan_data.iter() { + // item.encode(&mut w)?; + //} + //let len = w.len(); + LeSetExtScanResponseData::new(handle, Operation::Complete, false, params.scan_data) .exec(&self.controller) .await?; } - match params.kind { - AdvertisementKind::Legacy(_) => { - LeSetAdvEnable::new(true).exec(&self.controller).await?; - let conn = Connection::accept(self).await; - LeSetAdvEnable::new(false).exec(&self.controller).await?; - Ok(conn) - } - AdvertisementKind::Extended(_) => { - LeSetExtAdvEnable::new(true, &[]).exec(&self.controller).await?; - let conn = Connection::accept(self).await; - LeSetExtAdvEnable::new(false, &[]).exec(&self.controller).await?; - Ok(conn) - } - } + LeSetExtAdvEnable::new(true, &[params.set]) + .exec(&self.controller) + .await?; + let conn = Connection::accept(self).await; + LeSetExtAdvEnable::new(false, &[]).exec(&self.controller).await?; + Ok(conn) } /// Creates a GATT server capable of processing the GATT protocol using the provided table of attributes. @@ -325,7 +312,6 @@ where + ControllerCmdSync + ControllerCmdSync + ControllerCmdAsync - + ControllerCmdSync // + ControllerCmdSync // + ControllerCmdSync + ControllerCmdSync, diff --git a/host/src/advertise.rs b/host/src/advertise.rs index f4a582c8..b18fa2c7 100644 --- a/host/src/advertise.rs +++ b/host/src/advertise.rs @@ -4,9 +4,11 @@ use crate::{ types::uuid::Uuid, Address, }; -use bt_hci::param::{AdvChannelMap, AdvEventProps, AdvFilterPolicy, AdvKind, PhyKind}; +use bt_hci::param::{AdvEventProps, AdvHandle, AdvSet}; use embassy_time::Duration; +pub use bt_hci::param::{AdvChannelMap, AdvFilterPolicy, PhyKind}; + #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Eq, PartialEq, Copy, Clone)] #[repr(i8)] @@ -18,17 +20,12 @@ pub enum TxPower { Minus8dBm = -8, Minus4dBm = -4, ZerodBm = 0, - #[cfg(feature = "s140")] Plus2dBm = 2, Plus3dBm = 3, Plus4dBm = 4, - #[cfg(feature = "s140")] Plus5dBm = 5, - #[cfg(feature = "s140")] Plus6dBm = 6, - #[cfg(feature = "s140")] Plus7dBm = 7, - #[cfg(feature = "s140")] Plus8dBm = 8, } @@ -66,88 +63,75 @@ impl Default for AdvertisementConfig { } } -#[derive(Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub(crate) enum AdvertisementKind { - Legacy(AdvKind), - Extended(AdvEventProps), -} - #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RawAdvertisement<'d> { - pub(crate) kind: AdvertisementKind, - pub(crate) adv_data: &'d [AdStructure<'d>], - pub(crate) scan_data: &'d [AdStructure<'d>], + pub(crate) props: AdvEventProps, + pub(crate) adv_data: &'d [u8], + pub(crate) scan_data: &'d [u8], pub(crate) peer: Option
, - pub(crate) anonymous: bool, - pub(crate) set_id: u8, + pub(crate) set: AdvSet, } impl<'d> Default for RawAdvertisement<'d> { fn default() -> Self { Self { - kind: AdvertisementKind::Legacy(AdvKind::AdvInd), + props: AdvEventProps::new() + .set_connectable_adv(true) + .set_scannable_adv(true) + .set_legacy_adv(true), adv_data: &[], scan_data: &[], peer: None, - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, } } } /// Legacy advertisement types, which works with BLE 4.0 and newer pub enum Advertisement<'d> { - ConnectableScannableUndirected { - adv_data: &'d [AdStructure<'d>], - scan_data: &'d [AdStructure<'d>], - }, - ConnectableNonscannableDirected { - peer: Address, - }, - ConnectableNonscannableDirectedHighDuty { - peer: Address, - }, - NonconnectableScannableUndirected { - adv_data: &'d [AdStructure<'d>], - scan_data: &'d [AdStructure<'d>], - }, - NonconnectableNonscannableUndirected { - adv_data: &'d [AdStructure<'d>], - }, + ConnectableScannableUndirected { adv_data: &'d [u8], scan_data: &'d [u8] }, + ConnectableNonscannableDirected { peer: Address }, + ConnectableNonscannableDirectedHighDuty { peer: Address }, + NonconnectableScannableUndirected { adv_data: &'d [u8], scan_data: &'d [u8] }, + NonconnectableNonscannableUndirected { adv_data: &'d [u8] }, + Extended(ExtendedAdvertisement<'d>), } /// Extended advertisement types, which works with BLE 5.0 and newer pub enum ExtendedAdvertisement<'d> { ConnectableNonscannableUndirected { set_id: u8, - adv_data: &'d [AdStructure<'d>], + adv_data: &'d [u8], }, ConnectableNonscannableDirected { set_id: u8, peer: Address, - adv_data: &'d [AdStructure<'d>], + adv_data: &'d [u8], }, NonconnectableScannableUndirected { set_id: u8, - scan_data: &'d [AdStructure<'d>], + scan_data: &'d [u8], }, NonconnectableScannableDirected { set_id: u8, peer: Address, - scan_data: &'d [AdStructure<'d>], + scan_data: &'d [u8], }, NonconnectableNonscannableUndirected { set_id: u8, anonymous: bool, - adv_data: &'d [AdStructure<'d>], + adv_data: &'d [u8], }, NonconnectableNonscannableDirected { set_id: u8, anonymous: bool, peer: Address, - adv_data: &'d [AdStructure<'d>], + adv_data: &'d [u8], }, } @@ -155,45 +139,83 @@ impl<'d> From> for RawAdvertisement<'d> { fn from(val: Advertisement<'d>) -> RawAdvertisement<'d> { match val { Advertisement::ConnectableScannableUndirected { adv_data, scan_data } => RawAdvertisement { - kind: AdvertisementKind::Legacy(AdvKind::AdvInd), + props: AdvEventProps::new() + .set_connectable_adv(true) + .set_scannable_adv(true) + .set_anonymous_adv(false) + .set_legacy_adv(true), adv_data, scan_data, peer: None, - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, Advertisement::ConnectableNonscannableDirected { peer } => RawAdvertisement { - kind: AdvertisementKind::Legacy(AdvKind::AdvDirectIndLow), + props: AdvEventProps::new() + .set_connectable_adv(true) + .set_scannable_adv(false) + .set_directed_adv(true) + .set_anonymous_adv(false) + .set_legacy_adv(true), adv_data: &[], scan_data: &[], peer: Some(peer), - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, Advertisement::ConnectableNonscannableDirectedHighDuty { peer } => RawAdvertisement { - kind: AdvertisementKind::Legacy(AdvKind::AdvDirectIndHigh), + props: AdvEventProps::new() + .set_connectable_adv(true) + .set_scannable_adv(false) + .set_high_duty_cycle_directed_connectable_adv(true) + .set_anonymous_adv(false) + .set_legacy_adv(true), adv_data: &[], scan_data: &[], peer: Some(peer), - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, Advertisement::NonconnectableScannableUndirected { adv_data, scan_data } => RawAdvertisement { - kind: AdvertisementKind::Legacy(AdvKind::AdvScanInd), + props: AdvEventProps::new() + .set_connectable_adv(false) + .set_scannable_adv(true) + .set_anonymous_adv(false) + .set_legacy_adv(true), adv_data, scan_data, peer: None, - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, Advertisement::NonconnectableNonscannableUndirected { adv_data } => RawAdvertisement { - kind: AdvertisementKind::Legacy(AdvKind::AdvNonconnInd), + props: AdvEventProps::new() + .set_connectable_adv(false) + .set_scannable_adv(false) + .set_anonymous_adv(false) + .set_legacy_adv(true), adv_data, scan_data: &[], peer: None, - anonymous: false, - set_id: 0, + set: AdvSet { + adv_handle: AdvHandle::new(0), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, + Advertisement::Extended(ext) => ext.into(), } } } @@ -202,69 +224,75 @@ impl<'d> From> for RawAdvertisement<'d> { fn from(val: ExtendedAdvertisement<'d>) -> RawAdvertisement<'d> { match val { ExtendedAdvertisement::ConnectableNonscannableUndirected { adv_data, set_id } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new().set_connectable_adv(true).set_scannable_adv(false), - ), + props: AdvEventProps::new().set_connectable_adv(true).set_scannable_adv(false), adv_data, scan_data: &[], peer: None, - anonymous: false, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, ExtendedAdvertisement::ConnectableNonscannableDirected { adv_data, peer, set_id } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new().set_connectable_adv(true).set_scannable_adv(false), - ), + props: AdvEventProps::new().set_connectable_adv(true).set_scannable_adv(false), adv_data, scan_data: &[], peer: Some(peer), - anonymous: false, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, ExtendedAdvertisement::NonconnectableScannableUndirected { scan_data, set_id } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new().set_connectable_adv(false).set_scannable_adv(false), - ), + props: AdvEventProps::new().set_connectable_adv(false).set_scannable_adv(false), adv_data: &[], scan_data, peer: None, - anonymous: false, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, ExtendedAdvertisement::NonconnectableScannableDirected { scan_data, peer, set_id, } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new() - .set_connectable_adv(false) - .set_scannable_adv(true) - .set_directed_adv(true), - ), + props: AdvEventProps::new() + .set_connectable_adv(false) + .set_scannable_adv(true) + .set_directed_adv(true), adv_data: &[], scan_data, peer: Some(peer), - anonymous: false, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, ExtendedAdvertisement::NonconnectableNonscannableUndirected { adv_data, anonymous, set_id, } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new() - .set_connectable_adv(false) - .set_scannable_adv(false) - .set_directed_adv(false), - ), + props: AdvEventProps::new() + .set_connectable_adv(false) + .set_scannable_adv(false) + .set_anonymous_adv(anonymous) + .set_directed_adv(false), adv_data, scan_data: &[], peer: None, - anonymous, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, ExtendedAdvertisement::NonconnectableNonscannableDirected { adv_data, @@ -272,17 +300,19 @@ impl<'d> From> for RawAdvertisement<'d> { anonymous, set_id, } => RawAdvertisement { - kind: AdvertisementKind::Extended( - AdvEventProps::new() - .set_connectable_adv(false) - .set_scannable_adv(false) - .set_directed_adv(true), - ), + props: AdvEventProps::new() + .set_connectable_adv(false) + .set_scannable_adv(false) + .set_anonymous_adv(anonymous) + .set_directed_adv(true), adv_data, scan_data: &[], peer: Some(peer), - anonymous, - set_id, + set: AdvSet { + adv_handle: AdvHandle::new(set_id), + duration: bt_hci::param::Duration::from_millis(0), + max_ext_adv_events: 0, + }, }, } } @@ -346,6 +376,14 @@ pub enum AdStructure<'a> { } impl<'d> AdStructure<'d> { + pub fn encode_slice(data: &[AdStructure<'_>], dest: &mut [u8]) -> Result { + let mut w = WriteCursor::new(dest); + for item in data.iter() { + item.encode(&mut w)?; + } + Ok(w.len()) + } + pub fn encode(&self, w: &mut WriteCursor<'_>) -> Result<(), codec::Error> { match self { AdStructure::Flags(flags) => { diff --git a/host/src/lib.rs b/host/src/lib.rs index f0d7b708..26f45c8c 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -4,10 +4,9 @@ #![allow(unused_variables)] use advertise::AdvertisementDataError; -use bt_hci::{ - param::{AddrKind, BdAddr}, - FromHciBytesError, -}; +use bt_hci::FromHciBytesError; + +pub use bt_hci::param::{AddrKind, BdAddr, LeConnRole as Role}; mod fmt;