Skip to content

Commit

Permalink
get rid of dedicated signal channel
Browse files Browse the repository at this point in the history
  • Loading branch information
lulf committed Mar 21, 2024
1 parent 39edc3d commit 3c00a81
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 81 deletions.
76 changes: 31 additions & 45 deletions host/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use bt_hci::event::Event;
use bt_hci::param::{BdAddr, ConnHandle, DisconnectReason, EventMask};
use bt_hci::{Controller, ControllerToHostPacket};
use bt_hci::{ControllerCmdAsync, ControllerCmdSync};
use embassy_futures::select::{select3, Either3};
use embassy_futures::select::{select, Either};
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::channel::Channel;
use futures_intrusive::sync::LocalSemaphore;
Expand Down Expand Up @@ -341,49 +341,10 @@ where
Ok(())
};

// L2cap signal handling
// TODO: Could also be done 'directly' rather than going via a channel.
let signal_fut = async {
let (handle, response) = self.channels.signal().await;
// info!("Outgoing signal: {:?}", response);
let mut tx = [0; 64];
let mut w = WriteCursor::new(&mut tx);
let (mut header, mut body) = w.split(4)?;

body.write(response)?;

// TODO: Move into l2cap packet type
header.write(body.len() as u16)?;
header.write(L2CAP_CID_LE_U_SIGNAL)?;
let len = header.len() + body.len();

header.finish();
body.finish();
w.finish();

let acl = AclPacket::new(
handle,
AclPacketBoundary::FirstNonFlushable,
AclBroadcastFlag::PointToPoint,
&tx[..len],
);
self.permits.acquire(1).await.disarm();
match self.controller.write_acl_data(&acl).await {
Ok(_) => {}
Err(e) => {
#[cfg(feature = "defmt")]
let e = defmt::Debug2Format(&e);
warn!("Error writing some ACL data to controller: {:?}", e);
panic!(":(");
}
}
Ok(())
};
// info!("Entering select loop");
let result: Result<(), AdapterError<T::Error>> = match select3(rx_fut, control_fut, signal_fut).await {
Either3::First(result) => result,
Either3::Second(result) => result,
Either3::Third(result) => result,
let result: Result<(), AdapterError<T::Error>> = match select(rx_fut, control_fut).await {
Either::First(result) => result,
Either::Second(result) => result,
};
result?;
}
Expand All @@ -403,18 +364,43 @@ pub struct HciController<'d, T: Controller> {
}

impl<'d, T: Controller> HciController<'d, T> {
pub(crate) async fn send(&self, handle: ConnHandle, pdu: Pdu<'_>) -> Result<(), AdapterError<T::Error>> {
pub(crate) async fn send(&self, handle: ConnHandle, pdu: &[u8]) -> Result<(), AdapterError<T::Error>> {
self.permits.acquire(1).await.disarm();
let acl = AclPacket::new(
handle,
AclPacketBoundary::FirstNonFlushable,
AclBroadcastFlag::PointToPoint,
&pdu.as_ref(),
pdu,
);
self.controller
.write_acl_data(&acl)
.await
.map_err(AdapterError::Controller)?;
Ok(())
}

pub(crate) async fn signal(
&self,
handle: ConnHandle,
response: L2capLeSignal,
) -> Result<(), AdapterError<T::Error>> {
// TODO: Refactor signal to avoid encode/decode
let mut tx = [0; 64];
let mut w = WriteCursor::new(&mut tx);
let (mut header, mut body) = w.split(4)?;

body.write(response)?;

// TODO: Move into l2cap packet type
header.write(body.len() as u16)?;
header.write(L2CAP_CID_LE_U_SIGNAL)?;
let len = header.len() + body.len();

header.finish();
body.finish();
w.finish();
self.send(handle, &tx[..len]).await?;

Ok(())
}
}
43 changes: 15 additions & 28 deletions host/src/channel_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@ use core::{
task::{Context, Poll},
};

use bt_hci::param::ConnHandle;
use bt_hci::{param::ConnHandle, Controller};
use embassy_sync::{
blocking_mutex::{raw::RawMutex, Mutex},
channel::{Channel, DynamicReceiver, DynamicSendFuture},
channel::{Channel, DynamicReceiver},
waitqueue::WakerRegistration,
};

use crate::{
adapter::HciController,
l2cap::L2capPacket,
packet_pool::{AllocId, DynamicPacketPool},
pdu::Pdu,
types::l2cap::{
L2capLeSignal, L2capLeSignalData, LeCreditConnReq, LeCreditConnRes, LeCreditConnResultCode, LeCreditFlowInd,
},
Error,
AdapterError, Error,
};

const BASE_ID: u16 = 0x40;
Expand All @@ -34,18 +35,13 @@ struct State<const CHANNELS: usize> {
pub struct ChannelManager<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP_RXQ: usize> {
pool: &'d dyn DynamicPacketPool<'d>,
state: Mutex<M, RefCell<State<CHANNELS>>>,
signal: Channel<M, (ConnHandle, L2capLeSignal), 1>,
inbound: [Channel<M, Option<Pdu<'d>>, L2CAP_RXQ>; CHANNELS],
//outbound: [Channel<M, Pdu<'d>, L2CAP_TXQ>; CHANNELS],
}

pub trait DynamicChannelManager<'d> {
fn poll_request_to_send(&self, cid: u16, credits: usize, cx: &mut Context<'_>) -> Poll<Result<(), Error>>;
fn confirm_received(
&self,
cid: u16,
credits: usize,
) -> Result<DynamicSendFuture<'_, (ConnHandle, L2capLeSignal)>, Error>;
fn confirm_received(&self, cid: u16, credits: usize) -> Result<(ConnHandle, L2capLeSignal), Error>;
fn confirm_disconnected(&self, cid: u16) -> Result<(), Error>;
}

Expand All @@ -65,16 +61,10 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
create_waker: WakerRegistration::new(),
credit_wakers: [Self::CREDIT_WAKER; CHANNELS],
})),
signal: Channel::new(),
inbound: [Self::RX_CHANNEL; CHANNELS],
//outbound: [Self::TX_CHANNEL; CHANNELS],
}
}

pub(crate) async fn signal(&self) -> (ConnHandle, L2capLeSignal) {
self.signal.receive().await
}

async fn disconnect(&self, cid: u16) -> Result<(), Error> {
let idx = self.state.lock(|state| {
let mut state = state.borrow_mut();
Expand Down Expand Up @@ -197,12 +187,13 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
})
}

pub(crate) async fn accept(
pub(crate) async fn accept<T: Controller>(
&self,
conn: ConnHandle,
psm: u16,
mut mtu: u16,
) -> Result<(ConnectedState, DynamicReceiver<'_, Option<Pdu<'d>>>), Error> {
controller: &HciController<'_, T>,
) -> Result<(ConnectedState, DynamicReceiver<'_, Option<Pdu<'d>>>), AdapterError<T::Error>> {
let mut req_id = 0;
let (idx, state) = poll_fn(|cx| {
self.poll_accept(conn, psm, cx, |idx, req| {
Expand Down Expand Up @@ -236,16 +227,17 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
}),
);

self.signal.send((conn, response)).await;
controller.signal(conn, response).await?;
Ok((state, self.inbound[idx].receiver().into()))
}

pub(crate) async fn create(
pub(crate) async fn create<T: Controller>(
&self,
conn: ConnHandle,
psm: u16,
mtu: u16,
) -> Result<(ConnectedState, DynamicReceiver<'_, Option<Pdu<'d>>>), Error> {
controller: &HciController<'_, T>,
) -> Result<(ConnectedState, DynamicReceiver<'_, Option<Pdu<'d>>>), AdapterError<T::Error>> {
let state = ConnectingState {
conn,
cid: 0,
Expand All @@ -268,7 +260,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
credits: self.pool.min_available(AllocId::dynamic(idx)) as u16,
}),
);
self.signal.send((conn, command)).await;
controller.signal(conn, command).await?;

let (idx, state) = poll_fn(|cx| {
self.state.lock(|state| {
Expand Down Expand Up @@ -378,11 +370,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP_RXQ: usize> DynamicChannelManager<'d>
for ChannelManager<'d, M, CHANNELS, L2CAP_TXQ, L2CAP_RXQ>
{
fn confirm_received(
&self,
cid: u16,
credits: usize,
) -> Result<DynamicSendFuture<'_, (ConnHandle, L2capLeSignal)>, Error> {
fn confirm_received(&self, cid: u16, credits: usize) -> Result<(ConnHandle, L2capLeSignal), Error> {
let (conn, signal) = self.state.lock(|state| {
let mut state = state.borrow_mut();
for (idx, storage) in state.channels.iter_mut().enumerate() {
Expand All @@ -407,8 +395,7 @@ impl<'d, M: RawMutex, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP
}
return Err(Error::NotFound);
})?;
let f = self.signal.send((conn, signal));
Ok(f.into())
Ok((conn, signal))
}

fn confirm_disconnected(&self, cid: u16) -> Result<(), Error> {
Expand Down
6 changes: 3 additions & 3 deletions host/src/gatt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi
drop(header);
drop(data);
drop(w);
self.tx.send(handle, Pdu::new(response, len)).await?;
self.tx.send(handle, Pdu::new(response, len).as_ref()).await?;
}
_ => match self.server.process(handle, att, data.write_buf()) {
Ok(Some(written)) => {
Expand All @@ -63,7 +63,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi
drop(header);
drop(data);
drop(w);
self.tx.send(handle, Pdu::new(response, len)).await?;
self.tx.send(handle, Pdu::new(response, len).as_ref()).await?;
}
Ok(None) => {
debug!("No response sent");
Expand Down Expand Up @@ -117,7 +117,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi
drop(header);
drop(data);
drop(w);
self.tx.send(conn, Pdu::new(packet, total)).await?;
self.tx.send(conn, Pdu::new(packet, total).as_ref()).await?;
Ok(())
}
}
Expand Down
16 changes: 11 additions & 5 deletions host/src/l2cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> {
w.len()
};
let pdu = Pdu::new(packet, len);
self.tx.send(self.conn, pdu).await?;
self.tx.send(self.conn, pdu.as_ref()).await?;
} else {
return Err(Error::OutOfMemory.into());
}
Expand All @@ -102,7 +102,7 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> {
w.len()
};
let pdu = Pdu::new(packet, len);
self.tx.send(self.conn, pdu).await?;
self.tx.send(self.conn, pdu.as_ref()).await?;
} else {
return Err(Error::OutOfMemory.into());
}
Expand Down Expand Up @@ -145,7 +145,8 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> {
remaining -= packet.len;
}

self.manager.confirm_received(self.cid, n_received)?.await;
let (handle, response) = self.manager.confirm_received(self.cid, n_received)?;
self.tx.signal(handle, response).await?;

Ok(pos)
}
Expand All @@ -164,7 +165,9 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> {
let connections = &adapter.connections;
let channels = &adapter.channels;

let (state, rx) = channels.accept(connection.handle(), psm, MTU as u16).await?;
let (state, rx) = channels
.accept(connection.handle(), psm, MTU as u16, &adapter.hci())
.await?;

Ok(Self {
conn: connection.handle(),
Expand Down Expand Up @@ -193,7 +196,10 @@ impl<'a, 'd, T: Controller, const MTU: usize> L2capChannel<'a, 'd, T, MTU> {
where {
// TODO: Use unique signal ID to ensure no collision of signal messages
//
let (state, rx) = adapter.channels.create(connection.handle(), psm, MTU as u16).await?;
let (state, rx) = adapter
.channels
.create(connection.handle(), psm, MTU as u16, &adapter.hci())
.await?;

Ok(Self {
conn: connection.handle(),
Expand Down

0 comments on commit 3c00a81

Please sign in to comment.