Skip to content

Commit

Permalink
improve scanning and connection handling
Browse files Browse the repository at this point in the history
* Fix a bug issuing credits with the wrong channel id
* Add flow control policies to allow more configurability
* Use filter_accept_list rather than scanning and specifying peer for
  connecting.
* Support reassembly of ACL packets.
* Indicate to controller size of buffers.
* Allow accepting multiple l2cap PSMs
  • Loading branch information
lulf committed Apr 10, 2024
1 parent b840eb0 commit 9535313
Show file tree
Hide file tree
Showing 12 changed files with 632 additions and 240 deletions.
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_l2cap_central.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ async fn main(spawner: Spawner) {
info!("Connected, creating l2cap channel");
const PAYLOAD_LEN: usize = 27;
let mut ch1: L2capChannel<'_, '_, _, PAYLOAD_LEN> =
unwrap!(L2capChannel::create(&adapter, &conn, 0x2349, PAYLOAD_LEN as u16).await);
unwrap!(L2capChannel::create(&adapter, &conn, 0x2349, PAYLOAD_LEN as u16, Default::default()).await);
info!("New l2cap channel created, sending some data!");
for i in 0..10 {
let tx = [i; PAYLOAD_LEN];
Expand Down
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_l2cap_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async fn main(spawner: Spawner) {
info!("Connection established");

let mut ch1: L2capChannel<'_, '_, _, PAYLOAD_LEN> =
unwrap!(L2capChannel::accept(&adapter, &conn, 0x2349, PAYLOAD_LEN as u16).await);
unwrap!(L2capChannel::accept(&adapter, &conn, &[0x2349], PAYLOAD_LEN as u16, Default::default()).await);

info!("L2CAP channel accepted");

Expand Down
2 changes: 1 addition & 1 deletion host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ categories = [
resolver = "2"

[dependencies]
bt-hci = { version = "0.1.0" }
bt-hci = { version = "0.1.0", features = ["embassy-time"] }
embedded-io-async = { version = "0.6" }
embassy-sync = "0.5"
embassy-time = "0.3"
Expand Down
254 changes: 143 additions & 111 deletions host/src/adapter.rs

Large diffs are not rendered by default.

363 changes: 286 additions & 77 deletions host/src/channel_manager.rs

Large diffs are not rendered by default.

40 changes: 36 additions & 4 deletions host/src/connection.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use bt_hci::{
cmd::{
le::{
LeAddDeviceToFilterAcceptList, LeClearFilterAcceptList, LeCreateConn, LeExtCreateConn, LeSetExtScanEnable,
LeSetExtScanParams, LeSetScanEnable, LeSetScanParams,
LeAddDeviceToFilterAcceptList, LeClearFilterAcceptList, LeConnUpdate, LeCreateConn, LeExtCreateConn,
LeSetExtScanEnable, LeSetExtScanParams, LeSetScanEnable, LeSetScanParams,
},
link_control::DisconnectParams,
status::ReadRssi,
Expand Down Expand Up @@ -34,6 +34,7 @@ pub struct ConnectParams {
pub min_connection_interval: Duration,
pub max_connection_interval: Duration,
pub max_latency: u16,
pub event_length: Duration,
pub supervision_timeout: Duration,
}

Expand All @@ -43,6 +44,7 @@ impl Default for ConnectParams {
min_connection_interval: Duration::from_millis(80),
max_connection_interval: Duration::from_millis(80),
max_latency: 0,
event_length: Duration::from_secs(0),
supervision_timeout: Duration::from_secs(8),
}
}
Expand All @@ -63,7 +65,7 @@ impl<'d> Connection<'d> {
>(
adapter: &'d Adapter<'_, M, T, CONNS, CHANNELS, L2CAP_TXQ, L2CAP_RXQ>,
) -> Self {
let info = adapter.connections.accept(None).await;
let info = adapter.connections.accept(&[]).await;
Connection {
info,
control: adapter.control.sender().into(),
Expand Down Expand Up @@ -101,7 +103,37 @@ impl<'d> Connection<'d> {
where
T: ControllerCmdSync<ReadRssi>,
{
adapter.read_rssi(self.info.handle).await
let ret = adapter.command(ReadRssi::new(self.info.handle)).await?;
Ok(ret.rssi)
}

pub async fn set_connection_params<
M: RawMutex,
T,
const CONNS: usize,
const CHANNELS: usize,
const L2CAP_TXQ: usize,
const L2CAP_RXQ: usize,
>(
&self,
adapter: &'d Adapter<'_, M, T, CONNS, CHANNELS, L2CAP_TXQ, L2CAP_RXQ>,
params: ConnectParams,
) -> Result<(), AdapterError<T::Error>>
where
T: ControllerCmdAsync<LeConnUpdate>,
{
let ret = adapter
.async_command(LeConnUpdate::new(
self.info.handle,
params.min_connection_interval.into(),
params.max_connection_interval.into(),
params.max_latency,
params.supervision_timeout.into(),
bt_hci::param::Duration::from_secs(0),
bt_hci::param::Duration::from_secs(0),
))
.await?;
Ok(())
}

pub async fn connect<
Expand Down
24 changes: 14 additions & 10 deletions host/src/connection_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::{
task::{Context, Poll},
};

use bt_hci::param::{BdAddr, ConnHandle, LeConnRole, Status};
use bt_hci::param::{AddrKind, BdAddr, ConnHandle, LeConnRole, Status};
use embassy_sync::{
blocking_mutex::{raw::RawMutex, Mutex},
waitqueue::WakerRegistration,
Expand Down Expand Up @@ -64,16 +64,18 @@ impl<M: RawMutex, const CONNS: usize> ConnectionManager<M, CONNS> {
})
}

pub fn poll_accept(&self, peer: Option<BdAddr>, cx: &mut Context<'_>) -> Poll<ConnectionInfo> {
pub fn poll_accept(&self, peers: &[(AddrKind, &BdAddr)], cx: &mut Context<'_>) -> Poll<ConnectionInfo> {
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
if let ConnectionState::Connecting(handle, info) = storage {
if let Some(peer) = peer {
if info.peer_address == peer {
let i = *info;
*storage = ConnectionState::Connected(*handle, *info);
return Poll::Ready(i);
if !peers.is_empty() {
for peer in peers.iter() {
if info.peer_addr_kind == peer.0 && &info.peer_address == peer.1 {
let i = *info;
*storage = ConnectionState::Connected(*handle, *info);
return Poll::Ready(i);
}
}
} else {
let i = *info;
Expand All @@ -87,8 +89,8 @@ impl<M: RawMutex, const CONNS: usize> ConnectionManager<M, CONNS> {
})
}

pub async fn accept(&self, peer: Option<BdAddr>) -> ConnectionInfo {
poll_fn(move |cx| self.poll_accept(peer, cx)).await
pub async fn accept(&self, peers: &[(AddrKind, &BdAddr)]) -> ConnectionInfo {
poll_fn(move |cx| self.poll_accept(peers, cx)).await
}

pub fn info(&self, handle: ConnHandle) -> Result<ConnectionInfo, Error> {
Expand Down Expand Up @@ -149,11 +151,13 @@ impl<M: RawMutex, const CONNS: usize> DynamicConnectionManager for ConnectionMan
}
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ConnectionInfo {
pub handle: ConnHandle,
pub status: Status,
pub role: LeConnRole,
pub peer_addr_kind: AddrKind,
pub peer_address: BdAddr,
pub interval: u16,
pub latency: u16,
Expand Down
Loading

0 comments on commit 9535313

Please sign in to comment.