Skip to content

Commit

Permalink
update to support extended advertising
Browse files Browse the repository at this point in the history
  • Loading branch information
lulf committed Apr 8, 2024
1 parent a3517d6 commit 8a5141a
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 204 deletions.
21 changes: 14 additions & 7 deletions examples/nrf-sdc/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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(
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions examples/nrf-sdc/src/bin/ble_l2cap_central.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down
19 changes: 15 additions & 4 deletions examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
18 changes: 13 additions & 5 deletions examples/serial-hci/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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
Expand Down
154 changes: 70 additions & 84 deletions host/src/adapter.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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};
Expand All @@ -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};
Expand Down Expand Up @@ -106,11 +106,12 @@ where
}
}

pub async fn set_random_address(&self, address: Address) -> Result<(), AdapterError<T::Error>>
pub async fn set_random_address(&mut self, address: Address) -> Result<(), AdapterError<T::Error>>
where
T: ControllerCmdSync<LeSetRandomAddr>,
{
LeSetRandomAddr::new(address.addr).exec(&self.controller).await?;
self.address.replace(address);
Ok(())
}

Expand Down Expand Up @@ -164,102 +165,88 @@ where
params: impl Into<RawAdvertisement<'k>>,
) -> Result<Connection<'m>, AdapterError<T::Error>>
where
T: ControllerCmdSync<LeSetAdvData>
+ ControllerCmdSync<LeSetAdvEnable>
T: for<'t> ControllerCmdSync<LeSetExtAdvData<'t>>
+ ControllerCmdSync<LeClearAdvSets>
+ ControllerCmdSync<LeSetAdvParams>
+ ControllerCmdSync<LeSetExtAdvParams>
+ ControllerCmdSync<LeSetExtAdvEnable<'k>>
+ ControllerCmdSync<LeSetScanResponseData>,
+ ControllerCmdSync<LeSetAdvSetRandomAddr>
+ for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
+ for<'t> ControllerCmdSync<LeSetExtScanResponseData<'t>>,
{
// 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.
Expand Down Expand Up @@ -325,7 +312,6 @@ where
+ ControllerCmdSync<SetEventMask>
+ ControllerCmdSync<Reset>
+ ControllerCmdAsync<LeCreateConn>
+ ControllerCmdSync<LeSetScanEnable>
// + ControllerCmdSync<LeReadLocalSupportedFeatures>
// + ControllerCmdSync<LeReadNumberOfSupportedAdvSets>
+ ControllerCmdSync<LeReadBufferSize>,
Expand Down
Loading

0 comments on commit 8a5141a

Please sign in to comment.