Skip to content

Commit

Permalink
Merge pull request embassy-rs#170 from embassy-rs/connection-events
Browse files Browse the repository at this point in the history
Add ability to receive connection events
  • Loading branch information
lulf authored Nov 18, 2024
2 parents a257ab4 + 1926ab9 commit 8e2d1b6
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 170 deletions.
48 changes: 21 additions & 27 deletions examples/apps/src/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use embassy_futures::join::join3;
use embassy_futures::{
join::join3,
select::{select, Either},
};
use embassy_time::{Duration, Timer};
use trouble_host::prelude::*;

Expand Down Expand Up @@ -71,26 +74,8 @@ async fn ble_task<C: Controller>(mut runner: Runner<'_, C>) -> Result<(), BleHos
runner.run().await
}

async fn gatt_task<C: Controller>(server: &Server<'_, '_, C>) {
loop {
match server.next().await {
Ok(GattEvent::Write {
value_handle,
connection: _,
}) => {
info!("[gatt] Write event on {:?}", value_handle);
}
Ok(GattEvent::Read {
value_handle,
connection: _,
}) => {
info!("[gatt] Read event on {:?}", value_handle);
}
Err(e) => {
error!("[gatt] Error processing GATT events: {:?}", e);
}
}
}
async fn gatt_task<C: Controller>(server: &Server<'_, '_, C>) -> Result<(), BleHostError<C::Error>> {
server.run().await
}

async fn advertise_task<C: Controller>(
Expand Down Expand Up @@ -119,13 +104,22 @@ async fn advertise_task<C: Controller>(
.await?;
let conn = advertiser.accept().await?;
info!("[adv] connection established");
// Keep connection alive
let mut tick: u8 = 0;
while conn.is_connected() {
Timer::after(Duration::from_secs(2)).await;
tick = tick.wrapping_add(1);
info!("[adv] notifying connection of tick {}", tick);
let _ = server.notify(&server.battery_service.level, &conn, &tick).await;
loop {
match select(conn.next(), Timer::after(Duration::from_secs(2))).await {
Either::First(event) => match event {
ConnectionEvent::Disconnected { reason } => {
info!("[adv] disconnected: {:?}", reason);
break;
}
_ => {}
},
Either::Second(_) => {
tick = tick.wrapping_add(1);
info!("[adv] notifying connection of tick {}", tick);
let _ = server.notify(&server.battery_service.level, &conn, &tick).await;
}
}
}
}
}
18 changes: 13 additions & 5 deletions host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,34 +55,42 @@ connection-metrics = []

# BEGIN AUTOGENERATED CONFIG FEATURES
# Generated by gen_config.py. DO NOT EDIT.
connection-event-queue-size-1 = []
connection-event-queue-size-2 = [] # Default
connection-event-queue-size-4 = []
connection-event-queue-size-8 = []
connection-event-queue-size-16 = []
connection-event-queue-size-32 = []
connection-event-queue-size-64 = []

l2cap-rx-queue-size-1 = []
l2cap-rx-queue-size-2 = []
l2cap-rx-queue-size-4 = []
l2cap-rx-queue-size-8 = [] # Default
l2cap-rx-queue-size-8 = [] # Default
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-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 = []
l2cap-rx-packet-pool-size-8 = [] # Default
l2cap-rx-packet-pool-size-8 = [] # Default
l2cap-rx-packet-pool-size-16 = []
l2cap-rx-packet-pool-size-32 = []
l2cap-rx-packet-pool-size-64 = []
l2cap-rx-packet-pool-size-128 = []
l2cap-rx-packet-pool-size-256 = []
l2cap-rx-packet-pool-size-512 = []

gatt-client-notification-max-subscribers-1 = [] # Default
gatt-client-notification-max-subscribers-1 = [] # Default
gatt-client-notification-max-subscribers-2 = []
gatt-client-notification-max-subscribers-4 = []
gatt-client-notification-max-subscribers-8 = []
Expand All @@ -93,7 +101,7 @@ gatt-client-notification-max-subscribers-128 = []
gatt-client-notification-max-subscribers-256 = []
gatt-client-notification-max-subscribers-512 = []

gatt-client-notification-queue-size-1 = [] # Default
gatt-client-notification-queue-size-1 = [] # Default
gatt-client-notification-queue-size-2 = []
gatt-client-notification-queue-size-4 = []
gatt-client-notification-queue-size-8 = []
Expand Down
1 change: 1 addition & 0 deletions host/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{env, fs};
static CONFIGS: &[(&str, usize)] = &[
// BEGIN AUTOGENERATED CONFIG FEATURES
// Generated by gen_config.py. DO NOT EDIT.
("CONNECTION_EVENT_QUEUE_SIZE", 2),
("L2CAP_RX_QUEUE_SIZE", 8),
("L2CAP_TX_QUEUE_SIZE", 8),
("L2CAP_RX_PACKET_POOL_SIZE", 8),
Expand Down
1 change: 1 addition & 0 deletions host/gen_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def feature(name, default, min=None, max=None, pow2=None, vals=None, factors=[])
)


feature("connection_event_queue_size", default=2, min=1, max=64, pow2=True)
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)
Expand Down
1 change: 1 addition & 0 deletions host/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use core::cell::RefCell;
use core::fmt;
use core::marker::PhantomData;

use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;

Expand Down
4 changes: 2 additions & 2 deletions host/src/channel_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,7 @@ impl<'reference, 'state> Drop for CreditGrant<'reference, 'state> {
mod tests {
extern crate std;

use bt_hci::param::{AddrKind, BdAddr, LeConnRole};
use bt_hci::param::{AddrKind, BdAddr, LeConnRole, Status};

use super::*;
use crate::mock_controller::MockController;
Expand Down Expand Up @@ -1035,7 +1035,7 @@ mod tests {
let chan = ble.channels.poll_created(conn, idx, &ble, None);
assert!(matches!(chan, Poll::Pending));

ble.connections.disconnected(conn).unwrap();
ble.connections.disconnected(conn, Status::UNSPECIFIED).unwrap();
ble.channels.disconnected(conn).unwrap();

let chan = ble.channels.poll_created(conn, idx, &ble, None);
Expand Down
7 changes: 7 additions & 0 deletions host/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ mod raw {
include!(concat!(env!("OUT_DIR"), "/config.rs"));
}

/// Connection event queue size
///
/// This is the connection event queue size for every connection.
///
/// Default: 2.
pub const CONNECTION_EVENT_QUEUE_SIZE: usize = raw::CONNECTION_EVENT_QUEUE_SIZE;

// ======== L2CAP parameters
//
/// L2CAP TX queue size
Expand Down
30 changes: 29 additions & 1 deletion host/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use bt_hci::cmd::le::LeConnUpdate;
use bt_hci::cmd::status::ReadRssi;
use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync};
use bt_hci::param::{BdAddr, ConnHandle, DisconnectReason, LeConnRole};
use bt_hci::param::{BdAddr, ConnHandle, DisconnectReason, LeConnRole, Status};
use embassy_time::Duration;

use crate::connection_manager::ConnectionManager;
Expand Down Expand Up @@ -31,6 +31,25 @@ pub struct ConnectParams {
pub supervision_timeout: Duration,
}

/// An event
#[derive(Clone)]
pub enum ConnectionEvent<'d> {
/// Connection disconnected.
Disconnected {
/// The reason (status code) for the disconnect.
reason: Status,
},
/// GATT event.
Gatt {
/// Connection that caused the event.
// TODO: Can probably be removed, but keeping around for lifetime
connection: Connection<'d>,
/// The event that was returned,
#[cfg(feature = "gatt")]
event: crate::gatt::GattEvent,
},
}

impl Default for ConnectParams {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -73,6 +92,15 @@ impl<'d> Connection<'d> {
self.manager.set_att_mtu(self.index, mtu);
}

pub(crate) async fn post_event(&self, event: ConnectionEvent<'d>) {
self.manager.post_event(self.index, event).await
}

/// Wait for next connection event.
pub async fn next(&self) -> ConnectionEvent<'d> {
self.manager.next(self.index).await
}

/// Check if still connected
pub fn is_connected(&self) -> bool {
self.manager.is_connected(self.index)
Expand Down
Loading

0 comments on commit 8e2d1b6

Please sign in to comment.