Skip to content

Commit

Permalink
Merge pull request #87 from embassy-rs/tune-defaults
Browse files Browse the repository at this point in the history
Bugfixes
  • Loading branch information
lulf authored Aug 22, 2024
2 parents c980d4c + 69bdc0d commit bb5002c
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 58 deletions.
2 changes: 1 addition & 1 deletion examples/apache-nimble/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ async fn main(spawner: embassy_executor::Spawner) {
Timer::after(Duration::from_secs(10)).await;
test += 1;
info!("updating value: {}", test);
server.notify(handle, &conn, &[test]).await.unwrap();
server.notify(&adapter, handle, &conn, &[test]).await.unwrap();
}
},
)
Expand Down
2 changes: 1 addition & 1 deletion examples/esp32/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async fn main(_s: Spawner) {
loop {
Timer::after(Duration::from_secs(10)).await;
tick += 1;
server.notify(handle, &conn, &[tick]).await.unwrap();
server.notify(&ble, handle, &conn, &[tick]).await.unwrap();
}
},
)
Expand Down
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 @@ -176,7 +176,7 @@ async fn main(spawner: Spawner) {
loop {
Timer::after(Duration::from_secs(10)).await;
tick += 1;
unwrap!(server.notify(level_handle, &conn, &[tick]).await);
unwrap!(server.notify(&ble, level_handle, &conn, &[tick]).await);
}
},
)
Expand Down
2 changes: 1 addition & 1 deletion examples/rp-pico-w/src/bin/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ async fn main(spawner: Spawner) {
loop {
Timer::after(Duration::from_secs(10)).await;
tick += 1;
server.notify(handle, &conn, &[tick]).await.unwrap();
server.notify(&ble, handle, &conn, &[tick]).await.unwrap();
}
},
)
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 @@ -129,7 +129,7 @@ async fn main() {
loop {
tokio::time::sleep(Duration::from_secs(10)).await;
tick += 1;
server.notify(handle, &conn, &[tick]).await.unwrap();
server.notify(&ble, handle, &conn, &[tick]).await.unwrap();
}
},
)
Expand Down
8 changes: 8 additions & 0 deletions host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ l2cap-rx-queue-size-16 = []
l2cap-rx-queue-size-32 = []
l2cap-rx-queue-size-64 = []

l2cap-tx-queue-size-1 = []
l2cap-tx-queue-size-2 = []
l2cap-tx-queue-size-4 = []
l2cap-tx-queue-size-8 = [] # Default
l2cap-tx-queue-size-16 = []
l2cap-tx-queue-size-32 = []
l2cap-tx-queue-size-64 = []

l2cap-rx-packet-pool-size-1 = []
l2cap-rx-packet-pool-size-2 = []
l2cap-rx-packet-pool-size-4 = []
Expand Down
1 change: 1 addition & 0 deletions host/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ static CONFIGS: &[(&str, usize)] = &[
// BEGIN AUTOGENERATED CONFIG FEATURES
// Generated by gen_config.py. DO NOT EDIT.
("L2CAP_RX_QUEUE_SIZE", 8),
("L2CAP_TX_QUEUE_SIZE", 8),
("L2CAP_RX_PACKET_POOL_SIZE", 8),
// END AUTOGENERATED CONFIG FEATURES
];
Expand Down
1 change: 1 addition & 0 deletions host/gen_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def feature(name, default, min=None, max=None, pow2=None, vals=None, factors=[])


feature("l2cap_rx_queue_size", default=8, min=1, max=64, pow2=True)
feature("l2cap_tx_queue_size", default=8, min=1, max=64, pow2=True)
feature("l2cap_rx_packet_pool_size", default=8, min=1, max=512, pow2=True)

# ========= Update Cargo.toml
Expand Down
10 changes: 10 additions & 0 deletions host/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ mod raw {
}

// ======== L2CAP parameters
//
/// L2CAP TX queue size
///
/// This is the tx queue size for l2cap packets not sent directly in HCI (i.e. attributes).
///
/// If the controller does not support tx buffering, increasing this value will allow
/// a higher throughput between the controller and host.
///
/// Default: 1.
pub const L2CAP_TX_QUEUE_SIZE: usize = raw::L2CAP_TX_QUEUE_SIZE;

/// L2CAP RX queue size
///
Expand Down
9 changes: 7 additions & 2 deletions host/src/connection_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ impl<'d> ConnectionManager<'d> {
None
}

pub(crate) fn is_handle_connected(&self, h: ConnHandle) -> bool {
pub(crate) fn is_handle_disconnected(&self, h: ConnHandle) -> bool {
let mut state = self.state.borrow_mut();
for storage in state.connections.iter_mut() {
match (storage.handle, &storage.state) {
(Some(handle), ConnectionState::Connected) if handle == h => {
(Some(handle), ConnectionState::Disconnected) if handle == h => {
return true;
}
_ => {}
Expand Down Expand Up @@ -340,6 +340,7 @@ pub(crate) trait DynamicConnectionManager {
fn disconnect(&self, index: u8, reason: DisconnectReason);
fn get_att_mtu(&self, conn: ConnHandle) -> u16;
fn exchange_att_mtu(&self, conn: ConnHandle, mtu: u16) -> u16;
fn get_connected_handle(&self, h: ConnHandle) -> Option<Connection<'_>>;
}

impl<'d> DynamicConnectionManager for ConnectionManager<'d> {
Expand Down Expand Up @@ -392,6 +393,10 @@ impl<'d> DynamicConnectionManager for ConnectionManager<'d> {
}
mtu
}

fn get_connected_handle(&self, h: ConnHandle) -> Option<Connection<'_>> {
ConnectionManager::get_connected_handle(self, h)
}
}

pub struct DisconnectRequest<'a, 'd> {
Expand Down
88 changes: 44 additions & 44 deletions host/src/gatt.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bt_hci::controller::Controller;
use bt_hci::param::ConnHandle;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::channel::DynamicReceiver;
use embassy_sync::channel::{DynamicReceiver, DynamicSender};
use heapless::Vec;

use crate::att::{self, AttReq, AttRsp, ATT_HANDLE_VALUE_NTF};
Expand All @@ -18,29 +18,28 @@ use crate::{BleHostError, Error};
pub struct GattServer<
'reference,
'values,
'resources,
M: RawMutex,
T: Controller,
const MAX: usize,
// Including l2cap header
const MTU: usize = 27,
> {
pub(crate) server: AttributeServer<'reference, 'values, M, MAX>,
pub(crate) tx: DynamicSender<'reference, (ConnHandle, Pdu)>,
pub(crate) rx: DynamicReceiver<'reference, (ConnHandle, Pdu)>,
pub(crate) ble: &'reference BleHost<'resources, T>,
pub(crate) connections: &'reference dyn DynamicConnectionManager,
}

impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usize, const MTU: usize>
GattServer<'reference, 'values, 'resources, M, T, MAX, MTU>
impl<'reference, 'values, M: RawMutex, const MAX: usize, const MTU: usize>
GattServer<'reference, 'values, M, MAX, MTU>
{
/// Process GATT requests and update the attribute table accordingly.
///
/// If attributes are written or read, an event will be returned describing the handle
/// and the connection causing the event.
pub async fn next(&self) -> Result<GattEvent<'reference>, BleHostError<T::Error>> {
pub async fn next(&self) -> Result<GattEvent<'reference>, Error> {
loop {
let (handle, pdu) = self.rx.receive().await;
if let Some(connection) = self.ble.connections.get_connected_handle(handle) {
if let Some(connection) = self.connections.get_connected_handle(handle) {
match AttReq::decode(pdu.as_ref()) {
Ok(att) => {
let mut tx = [0; MTU];
Expand All @@ -49,45 +48,45 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi

match self.server.process(handle, &att, data.write_buf()) {
Ok(Some(written)) => {
let mtu = self.ble.connections.get_att_mtu(handle);
let mtu = self.connections.get_att_mtu(handle);
data.commit(written)?;
data.truncate(mtu as usize);
header.write(written as u16)?;
header.write(4_u16)?;
let len = header.len() + data.len();
self.ble.acl(handle, 1).await?.send(&tx[..len]).await?;

match att {
AttReq::Write { handle, data } => {
return Ok(GattEvent::Write {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
})
}

AttReq::Read { handle } => {
return Ok(GattEvent::Read {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
})
}

AttReq::ReadBlob { handle, offset } => {
return Ok(GattEvent::Read {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
})
}
_ => {}

let event = match att {
AttReq::Write { handle, data } => Some(GattEvent::Write {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
}),

AttReq::Read { handle } => Some(GattEvent::Read {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
}),

AttReq::ReadBlob { handle, offset } => Some(GattEvent::Read {
connection,
handle: Characteristic {
handle,
cccd_handle: None,
},
}),
_ => None,
};

let mut packet = pdu.packet;
packet.as_mut()[..len].copy_from_slice(&tx[..len]);
self.tx.send((handle, Pdu::new(packet, len))).await;
if let Some(event) = event {
return Ok(event);
}
}
Ok(None) => {
Expand All @@ -111,8 +110,9 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi
/// If the provided connection has not subscribed for this characteristic, it will not be notified.
///
/// If the characteristic for the handle cannot be found, an error is returned.
pub async fn notify(
pub async fn notify<T: Controller>(
&self,
ble: &BleHost<'_, T>,
handle: Characteristic,
connection: &Connection<'_>,
value: &[u8],
Expand All @@ -137,7 +137,7 @@ impl<'reference, 'values, 'resources, M: RawMutex, T: Controller, const MAX: usi
header.write(data.len() as u16)?;
header.write(4_u16)?;
let total = header.len() + data.len();
self.ble.acl(conn, 1).await?.send(&tx[..total]).await?;
ble.acl(conn, 1).await?.send(&tx[..total]).await?;
Ok(())
}
}
Expand Down
30 changes: 23 additions & 7 deletions host/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub struct BleHost<'d, T> {
#[cfg(feature = "gatt")]
pub(crate) att_inbound: Channel<NoopRawMutex, (ConnHandle, Pdu), { config::L2CAP_RX_QUEUE_SIZE }>,
pub(crate) rx_pool: &'static dyn GlobalPacketPool,
outbound: Channel<NoopRawMutex, (ConnHandle, Pdu), 4>,
outbound: Channel<NoopRawMutex, (ConnHandle, Pdu), { config::L2CAP_TX_QUEUE_SIZE }>,

#[cfg(feature = "scan")]
pub(crate) scanner: Channel<NoopRawMutex, Option<ScanReport>, 1>,
Expand Down Expand Up @@ -740,12 +740,13 @@ where
pub fn gatt_server<'reference, 'values, M: embassy_sync::blocking_mutex::raw::RawMutex, const MAX: usize>(
&'reference self,
table: &'reference AttributeTable<'values, M, MAX>,
) -> GattServer<'reference, 'values, 'd, M, T, MAX> {
) -> GattServer<'reference, 'values, M, MAX> {
use crate::attribute_server::AttributeServer;
GattServer {
server: AttributeServer::new(table),
rx: self.att_inbound.receiver().into(),
ble: self,
tx: self.outbound.sender().into(),
connections: &self.connections,
}
}

Expand Down Expand Up @@ -813,7 +814,7 @@ where
}

fn handle_acl(&self, acl: AclPacket<'_>) -> Result<(), Error> {
if !self.connections.is_handle_connected(acl.handle()) {
if self.connections.is_handle_disconnected(acl.handle()) {
return Err(Error::Disconnected);
}
let (header, mut packet) = match acl.boundary_flag() {
Expand Down Expand Up @@ -1121,12 +1122,23 @@ where
return Err(e.into());
}
}

warn!(
"[host] encountered error processing ACL data for {:?}: {:?}",
acl.handle(),
e
);

if let Error::Disconnected = e {
warn!("[host] requesting {:?} to be disconnected", acl.handle());
let _ = self
.command(Disconnect::new(
acl.handle(),
DisconnectReason::RemoteUserTerminatedConn,
))
.await;
}

let mut m = self.metrics.borrow_mut();
m.rx_errors = m.rx_errors.wrapping_add(1);
}
Expand Down Expand Up @@ -1180,10 +1192,14 @@ where
},
Event::DisconnectionComplete(e) => {
let handle = e.handle;
if let Err(e) = e.reason.to_result() {
info!("[host] disconnection event on handle {}, reason: {:?}", handle.raw(), e);
if let Err(e) = e.status.to_result() {
info!("[host] disconnection event on handle {}, status: {:?}", handle.raw(), e);
} else {
info!("[host] disconnection event on handle {}", handle.raw(),);
if let Err(e) = e.reason.to_result() {
info!("[host] disconnection event on handle {}, reason: {:?}", handle.raw(), e);
} else {
info!("[host] disconnection event on handle {}", handle.raw());
}
}
let _ = self.connections.disconnected(handle);
let _ = self.channels.disconnected(handle);
Expand Down
5 changes: 5 additions & 0 deletions host/tests/gatt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ async fn gatt_client_server() {
});
if writes == 2 {
println!("expected value written twice, test pass");
// NOTE: Ensure that adapter gets polled again
tokio::time::sleep(Duration::from_secs(2)).await;
break;
}
}
Expand Down Expand Up @@ -173,9 +175,12 @@ async fn gatt_client_server() {
client.read_characteristic(&c, &mut data[..]).await.unwrap();
println!("[central] read value: {}", data[0]);
data[0] = data[0].wrapping_add(1);
println!("[central] write value: {}", data[0]);
client.write_characteristic(&c, &data[..]).await.unwrap();
data[0] = data[0].wrapping_add(1);
println!("[central] write value: {}", data[0]);
client.write_characteristic(&c, &data[..]).await.unwrap();
println!("[central] write done");
Ok(())
} => {
r
Expand Down

0 comments on commit bb5002c

Please sign in to comment.