Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move channel and connection logic into inner types #19

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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