Skip to content

Commit

Permalink
reduce connection manager size
Browse files Browse the repository at this point in the history
  • Loading branch information
lulf committed Apr 23, 2024
1 parent f39bd83 commit 03813d2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 83 deletions.
17 changes: 2 additions & 15 deletions host/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use futures_intrusive::sync::LocalSemaphore;
use crate::advertise::{Advertisement, AdvertisementConfig, RawAdvertisement};
use crate::channel_manager::ChannelManager;
use crate::connection::{ConnectConfig, Connection};
use crate::connection_manager::{ConnectionInfo, ConnectionManager};
use crate::connection_manager::ConnectionManager;
use crate::cursor::WriteCursor;
use crate::l2cap::sar::PacketReassembly;
use crate::packet_pool::{AllocId, DynamicPacketPool, PacketPool, Qos};
Expand Down Expand Up @@ -697,20 +697,7 @@ where
Event::Le(event) => match event {
LeEvent::LeConnectionComplete(e) => match e.status.to_result() {
Ok(_) => {
if let Err(err) = self.connections.connect(
e.handle,
ConnectionInfo {
handle: e.handle,
status: e.status,
role: e.role,
peer_addr_kind: e.peer_addr_kind,
peer_address: e.peer_addr,
interval: e.conn_interval.as_u16(),
latency: e.peripheral_latency,
timeout: e.supervision_timeout.as_u16(),
att_mtu: 23,
},
) {
if let Err(err) = self.connections.connect(e.handle, &e) {
warn!("Error establishing connection: {:?}", err);
self.command(Disconnect::new(
e.handle,
Expand Down
9 changes: 3 additions & 6 deletions host/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_time::Duration;

use crate::adapter::Adapter;
pub use crate::connection_manager::ConnectionInfo;
use crate::scan::ScanConfig;
use crate::AdapterError;

Expand Down Expand Up @@ -78,7 +77,7 @@ impl Connection {
&self,
adapter: &Adapter<'_, M, T, CONNS, CHANNELS, L2CAP_MTU, L2CAP_TXQ, L2CAP_RXQ>,
) -> Result<LeConnRole, AdapterError<T::Error>> {
let role = adapter.connections.with_connection(self.handle, |info| info.role)?;
let role = adapter.connections.role(self.handle)?;
Ok(role)
}

Expand All @@ -94,10 +93,8 @@ impl Connection {
&self,
adapter: &Adapter<'_, M, T, CONNS, CHANNELS, L2CAP_MTU, L2CAP_TXQ, L2CAP_RXQ>,
) -> Result<BdAddr, AdapterError<T::Error>> {
let role = adapter
.connections
.with_connection(self.handle, |info| info.peer_address)?;
Ok(role)
let addr = adapter.connections.peer_address(self.handle)?;
Ok(addr)
}

pub async fn rssi<
Expand Down
143 changes: 81 additions & 62 deletions host/src/connection_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use core::cell::RefCell;
use core::future::poll_fn;
use core::task::{Context, Poll};

use bt_hci::param::{AddrKind, BdAddr, ConnHandle, LeConnRole, Status};
use bt_hci::event::le::LeConnectionComplete;
use bt_hci::param::{AddrKind, BdAddr, ConnHandle, LeConnRole};
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::signal::Signal;
Expand All @@ -11,68 +12,78 @@ use embassy_sync::waitqueue::WakerRegistration;
use crate::Error;

struct State<const CONNS: usize> {
connections: [ConnectionState; CONNS],
connections: [ConnectionStorage; CONNS],
waker: WakerRegistration,
}

pub struct ConnectionManager<M: RawMutex, const CONNS: usize> {
pub(crate) struct ConnectionManager<M: RawMutex, const CONNS: usize> {
state: Mutex<M, RefCell<State<CONNS>>>,
canceled: Signal<M, ()>,
}

impl<M: RawMutex, const CONNS: usize> ConnectionManager<M, CONNS> {
const DISCONNECTED: ConnectionState = ConnectionState::Disconnected;
pub fn new() -> Self {
pub(crate) fn new() -> Self {
Self {
state: Mutex::new(RefCell::new(State {
connections: [Self::DISCONNECTED; CONNS],
connections: [ConnectionStorage::DISCONNECTED; CONNS],
waker: WakerRegistration::new(),
})),
canceled: Signal::new(),
}
}

pub fn disconnect(&self, h: ConnHandle) -> Result<(), Error> {
pub(crate) fn role(&self, h: ConnHandle) -> Result<LeConnRole, Error> {
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
match storage {
ConnectionState::Connecting(handle, _) if *handle == h => {
*storage = ConnectionState::Disconnected;
}
ConnectionState::Connected(handle, _) if *handle == h => {
*storage = ConnectionState::Disconnected;
}
_ => {}
let state = state.borrow();
for storage in state.connections.iter() {
if storage.state == ConnectionState::Connected && storage.handle.unwrap() == h {
return Ok(storage.role.unwrap());
}
}
Ok(())
Err(Error::NotFound)
})
}

pub(crate) fn with_connection<F: FnOnce(&ConnectionInfo) -> R, R>(
&self,
handle: ConnHandle,
f: F,
) -> Result<R, Error> {
pub(crate) fn peer_address(&self, h: ConnHandle) -> Result<BdAddr, Error> {
self.state.lock(|state| {
let state = state.borrow();
for storage in state.connections.iter() {
match storage {
ConnectionState::Connected(h, info) if *h == handle => return Ok(f(info)),
_ => {}
if storage.state == ConnectionState::Connected && storage.handle.unwrap() == h {
return Ok(storage.peer_addr.unwrap());
}
}
Err(Error::NotFound)
})
}

pub fn connect(&self, handle: ConnHandle, info: ConnectionInfo) -> Result<(), Error> {
pub(crate) fn disconnect(&self, h: ConnHandle) -> Result<(), Error> {
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
if let ConnectionState::Disconnected = storage {
*storage = ConnectionState::Connecting(handle, Some(info));
match storage.state {
ConnectionState::Connecting if storage.handle.unwrap() == h => {
storage.state = ConnectionState::Disconnected;
}
ConnectionState::Connected if storage.handle.unwrap() == h => {
storage.state = ConnectionState::Disconnected;
}
_ => {}
}
}
Ok(())
})
}

pub(crate) fn connect(&self, handle: ConnHandle, info: &LeConnectionComplete) -> Result<(), Error> {
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
if let ConnectionState::Disconnected = storage.state {
storage.state = ConnectionState::Connecting;
storage.handle.replace(handle);
storage.peer_addr_kind.replace(info.peer_addr_kind);
storage.peer_addr.replace(info.peer_addr);
storage.role.replace(info.role);
state.waker.wake();
return Ok(());
}
Expand All @@ -81,32 +92,30 @@ impl<M: RawMutex, const CONNS: usize> ConnectionManager<M, CONNS> {
})
}

pub async fn wait_canceled(&self) {
pub(crate) async fn wait_canceled(&self) {
self.canceled.wait().await;
self.canceled.reset();
}

pub fn canceled(&self) {
pub(crate) fn canceled(&self) {
self.canceled.signal(());
}

pub fn poll_accept(&self, peers: &[(AddrKind, &BdAddr)], cx: &mut Context<'_>) -> Poll<ConnHandle> {
pub(crate) fn poll_accept(&self, peers: &[(AddrKind, &BdAddr)], cx: &mut Context<'_>) -> Poll<ConnHandle> {
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
if let ConnectionState::Connecting(handle, info) = storage {
let handle = *handle;
if let ConnectionState::Connecting = storage.state {
let handle = storage.handle.unwrap();
if !peers.is_empty() {
for peer in peers.iter() {
if info.as_ref().unwrap().peer_addr_kind == peer.0
&& &info.as_ref().unwrap().peer_address == peer.1
{
*storage = ConnectionState::Connected(handle, info.take().unwrap());
if storage.peer_addr_kind.unwrap() == peer.0 && &storage.peer_addr.unwrap() == peer.1 {
storage.state = ConnectionState::Connected;
return Poll::Ready(handle);
}
}
} else {
*storage = ConnectionState::Connected(handle, info.take().unwrap());
storage.state = ConnectionState::Connected;
return Poll::Ready(handle);
}
}
Expand All @@ -116,17 +125,11 @@ impl<M: RawMutex, const CONNS: usize> ConnectionManager<M, CONNS> {
})
}

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

pub enum ConnectionState {
Disconnected,
Connecting(ConnHandle, Option<ConnectionInfo>),
Connected(ConnHandle, ConnectionInfo),
}

pub trait DynamicConnectionManager {
fn get_att_mtu(&self, conn: ConnHandle) -> u16;
fn exchange_att_mtu(&self, conn: ConnHandle, mtu: u16) -> u16;
Expand All @@ -137,9 +140,9 @@ impl<M: RawMutex, const CONNS: usize> DynamicConnectionManager for ConnectionMan
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
match storage {
ConnectionState::Connected(handle, info) if *handle == conn => {
return info.att_mtu;
match storage.state {
ConnectionState::Connected if storage.handle.unwrap() == conn => {
return storage.att_mtu;
}
_ => {}
}
Expand All @@ -151,10 +154,10 @@ impl<M: RawMutex, const CONNS: usize> DynamicConnectionManager for ConnectionMan
self.state.lock(|state| {
let mut state = state.borrow_mut();
for storage in state.connections.iter_mut() {
match storage {
ConnectionState::Connected(handle, info) if *handle == conn => {
info.att_mtu = info.att_mtu.min(mtu);
return info.att_mtu;
match storage.state {
ConnectionState::Connected if storage.handle.unwrap() == conn => {
storage.att_mtu = storage.att_mtu.min(mtu);
return storage.att_mtu;
}
_ => {}
}
Expand All @@ -166,14 +169,30 @@ impl<M: RawMutex, const CONNS: usize> DynamicConnectionManager for ConnectionMan

#[derive(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,
pub timeout: u16,
pub struct ConnectionStorage {
pub state: ConnectionState,
pub handle: Option<ConnHandle>,
pub role: Option<LeConnRole>,
pub peer_addr_kind: Option<AddrKind>,
pub peer_addr: Option<BdAddr>,
pub att_mtu: u16,
}

impl ConnectionStorage {
const DISCONNECTED: ConnectionStorage = ConnectionStorage {
state: ConnectionState::Disconnected,
handle: None,
role: None,
peer_addr_kind: None,
peer_addr: None,
att_mtu: 23,
};
}

#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ConnectionState {
Disconnected,
Connecting,
Connected,
}

0 comments on commit 03813d2

Please sign in to comment.