Skip to content

Commit

Permalink
Move channel and connection logic into inner types
Browse files Browse the repository at this point in the history
* Reduce cloning and copying
* Reduce size of connection and channel
  • Loading branch information
lulf committed Apr 19, 2024
1 parent 8ca7865 commit 6c0cc99
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 356 deletions.
2 changes: 1 addition & 1 deletion examples/nrf-sdc/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async fn main(spawner: Spawner) {
StaticCell::new();
let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::None));

let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU> =
Adapter::new(sdc, host_resources);
adapter.set_random_address(my_addr());

Expand Down
8 changes: 4 additions & 4 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,7 @@ async fn main(spawner: Spawner) {
StaticCell::new();
let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::Guaranteed(4)));

let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU> =
Adapter::new(sdc, host_resources);
adapter.set_random_address(my_addr());

Expand All @@ -141,17 +141,17 @@ async fn main(spawner: Spawner) {
let conn = unwrap!(adapter.connect(&config).await);
info!("Connected, creating l2cap channel");
const PAYLOAD_LEN: usize = 27;
let mut ch1: L2capChannel<'_, '_, _, PAYLOAD_LEN> =
let mut ch1 =
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];
unwrap!(ch1.send(&tx).await);
unwrap!(ch1.send(&adapter, &tx).await);
}
info!("Sent data, waiting for them to be sent back");
let mut rx = [0; PAYLOAD_LEN];
for i in 0..10 {
let len = unwrap!(ch1.receive(&mut rx).await);
let len = unwrap!(ch1.receive(&adapter, &mut rx).await);
assert_eq!(len, rx.len());
assert_eq!(rx, [i; PAYLOAD_LEN]);
}
Expand Down
8 changes: 4 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,7 +119,7 @@ async fn main(spawner: Spawner) {
StaticCell::new();
let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::Guaranteed(4)));

let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX> =
let mut adapter: Adapter<'_, NoopRawMutex, _, CONNECTIONS_MAX, L2CAP_CHANNELS_MAX, L2CAP_MTU> =
Adapter::new(sdc, host_resources);
adapter.set_random_address(my_addr());
let mut adv_data = [0; 31];
Expand Down Expand Up @@ -151,7 +151,7 @@ async fn main(spawner: Spawner) {

info!("Connection established");

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

info!("L2CAP channel accepted");
Expand All @@ -160,7 +160,7 @@ async fn main(spawner: Spawner) {
const PAYLOAD_LEN: usize = 27;
let mut rx = [0; PAYLOAD_LEN];
for i in 0..10 {
let len = unwrap!(ch1.receive(&mut rx).await);
let len = unwrap!(ch1.receive(&adapter, &mut rx).await);
assert_eq!(len, rx.len());
assert_eq!(rx, [i; PAYLOAD_LEN]);
}
Expand All @@ -169,7 +169,7 @@ async fn main(spawner: Spawner) {
Timer::after(Duration::from_secs(1)).await;
for i in 0..10 {
let tx = [i; PAYLOAD_LEN];
unwrap!(ch1.send(&tx).await);
unwrap!(ch1.send(&adapter, &tx).await);
}
info!("L2CAP data echoed");

Expand Down
2 changes: 1 addition & 1 deletion examples/serial-hci/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async fn main() {
static HOST_RESOURCES: StaticCell<HostResources<NoopRawMutex, 4, 32, 27>> = StaticCell::new();
let host_resources = HOST_RESOURCES.init(HostResources::new(PacketQos::None));

let adapter: Adapter<'_, NoopRawMutex, _, 2, 4, 1, 1> = Adapter::new(controller, host_resources);
let adapter: Adapter<'_, NoopRawMutex, _, 2, 4, 27, 1, 1> = Adapter::new(controller, host_resources);

let mut table: AttributeTable<'_, NoopRawMutex, 10> = AttributeTable::new();

Expand Down
60 changes: 44 additions & 16 deletions host/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub struct Adapter<
T,
const CONNS: usize,
const CHANNELS: usize,
const L2CAP_MTU: usize,
const L2CAP_TXQ: usize = 1,
const L2CAP_RXQ: usize = 1,
> where
Expand All @@ -74,16 +75,24 @@ pub struct Adapter<
pub(crate) controller: T,
pub(crate) connections: ConnectionManager<M, CONNS>,
pub(crate) reassembly: PacketReassembly<'d, CONNS>,
pub(crate) channels: ChannelManager<'d, M, CHANNELS, L2CAP_TXQ, L2CAP_RXQ>,
pub(crate) channels: ChannelManager<'d, M, CHANNELS, L2CAP_MTU, L2CAP_TXQ, L2CAP_RXQ>,
pub(crate) att_inbound: Channel<M, (ConnHandle, Pdu<'d>), L2CAP_RXQ>,
pub(crate) pool: &'d dyn DynamicPacketPool<'d>,
pub(crate) permits: LocalSemaphore,

pub(crate) scanner: Channel<M, Option<ScanReport>, 1>,
}

impl<'d, M, T, const CONNS: usize, const CHANNELS: usize, const L2CAP_TXQ: usize, const L2CAP_RXQ: usize>
Adapter<'d, M, T, CONNS, CHANNELS, L2CAP_TXQ, L2CAP_RXQ>
impl<
'd,
M,
T,
const CONNS: usize,
const CHANNELS: usize,
const L2CAP_MTU: usize,
const L2CAP_TXQ: usize,
const L2CAP_RXQ: usize,
> Adapter<'d, M, T, CONNS, CHANNELS, L2CAP_MTU, L2CAP_TXQ, L2CAP_RXQ>
where
M: RawMutex,
T: Controller,
Expand All @@ -94,7 +103,7 @@ where
///
/// The adapter requires a HCI driver (a particular HCI-compatible controller implementing the required traits), and
/// a reference to resources that are created outside the adapter but which the adapter is the only accessor of.
pub fn new<const PACKETS: usize, const L2CAP_MTU: usize>(
pub fn new<const PACKETS: usize>(
controller: T,
host_resources: &'d mut HostResources<M, CHANNELS, PACKETS, L2CAP_MTU>,
) -> Self {
Expand Down Expand Up @@ -139,6 +148,22 @@ where
Ok(ret)
}

pub fn try_command<C>(&self, cmd: C) -> Result<C::Return, AdapterError<T::Error>>
where
C: SyncCmd,
T: ControllerCmdSync<C>,
{
let fut = cmd.exec(&self.controller);
match embassy_futures::poll_once(fut) {
Poll::Ready(result) => match result {
Ok(r) => Ok(r),
Err(CmdError::Io(e)) => Err(AdapterError::Controller(e)),
Err(CmdError::Hci(e)) => Err(e.into()),
},
Poll::Pending => Err(Error::Busy.into()),
}
}

pub async fn async_command<C>(&self, cmd: C) -> Result<(), AdapterError<T::Error>>
where
C: AsyncCmd,
Expand Down Expand Up @@ -193,8 +218,8 @@ where
phy_params,
))
.await?;
let info = self.connections.accept(config.scan_config.filter_accept_list).await;
Ok(Connection { info })
let handle = self.connections.accept(config.scan_config.filter_accept_list).await;
Ok(Connection::new(handle))
} else {
self.async_command(LeCreateConn::new(
config.scan_config.interval.into(),
Expand All @@ -211,8 +236,8 @@ where
config.connect_params.event_length.into(),
))
.await?;
let info = self.connections.accept(config.scan_config.filter_accept_list).await;
Ok(Connection { info })
let handle = self.connections.accept(config.scan_config.filter_accept_list).await;
Ok(Connection::new(handle))
}
}

Expand Down Expand Up @@ -396,9 +421,9 @@ where
}

self.command(LeSetAdvEnable::new(true)).await?;
let conn = Connection::accept(self).await;
let handle = self.connections.accept(&[]).await;
self.command(LeSetAdvEnable::new(false)).await?;
Ok(conn)
Ok(Connection::new(handle))
}

/// Starts sending BLE advertisements according to the provided config.
Expand Down Expand Up @@ -481,9 +506,9 @@ where
}

self.command(LeSetExtAdvEnable::new(true, &[params.set])).await?;
let conn = Connection::accept(self).await;
let handle = self.connections.accept(&[]).await;
self.command(LeSetExtAdvEnable::new(false, &[])).await?;
Ok(conn)
Ok(Connection::new(handle))
}

/// Creates a GATT server capable of processing the GATT protocol using the provided table of attributes.
Expand Down Expand Up @@ -658,6 +683,7 @@ where
pin_mut!(init_fut);

loop {
// info!("[run] permits: {}", self.permits.permits());
// Task handling receiving data from the controller.
let rx_fut = async {
let mut rx = [0u8; MAX_HCI_PACKET_LEN];
Expand All @@ -672,7 +698,6 @@ where
Event::Le(event) => match event {
LeEvent::LeConnectionComplete(e) => match e.status.to_result() {
Ok(_) => {
info!("Connection complete {:?}: {:?}", e.handle, e.peer_addr);
if let Err(err) = self.connections.connect(
e.handle,
ConnectionInfo {
Expand Down Expand Up @@ -726,7 +751,7 @@ where
let _ = self.channels.disconnected_connection(e.handle);
}
Event::NumberOfCompletedPackets(c) => {
// trace!("Confirmed {} packets sent", c.completed_packets.len());
// info!("Confirmed {} packets sent", c.completed_packets.len());
self.permits.release(c.completed_packets.len());
}
Event::Vendor(vendor) => {
Expand Down Expand Up @@ -783,6 +808,7 @@ impl<'d, T: Controller> Clone for HciController<'d, T> {

impl<'d, T: Controller> HciController<'d, T> {
pub(crate) fn try_send(&self, handle: ConnHandle, pdu: &[u8]) -> Result<(), AdapterError<T::Error>> {
// info!("[try_send] permits: {}", self.permits.permits());
let mut permit = self
.permits
.try_acquire(1)
Expand All @@ -800,13 +826,15 @@ impl<'d, T: Controller> HciController<'d, T> {
if result.is_ok() {
permit.disarm();
}

result.map_err(AdapterError::Controller)
}
Poll::Pending => Err(Error::Busy.into()),
}
}

pub(crate) async fn send(&self, handle: ConnHandle, pdu: &[u8]) -> Result<(), AdapterError<T::Error>> {
// info!("[send] permits: {}", self.permits.permits());
self.permits.acquire(1).await.disarm();
let acl = AclPacket::new(
handle,
Expand All @@ -824,15 +852,15 @@ impl<'d, T: Controller> HciController<'d, T> {
pub(crate) async fn signal(
&self,
handle: ConnHandle,
response: L2capLeSignal,
response: &L2capLeSignal,
) -> Result<(), AdapterError<T::Error>> {
// TODO: Refactor signal to avoid encode/decode
// info!("[{}] sending signal: {:?}", handle, response);
let mut tx = [0; 32];
let mut w = WriteCursor::new(&mut tx);
let (mut header, mut body) = w.split(4)?;

body.write(response)?;
body.write_ref(response)?;

// TODO: Move into l2cap packet type
header.write(body.len() as u16)?;
Expand Down
Loading

0 comments on commit 6c0cc99

Please sign in to comment.