Skip to content

Commit

Permalink
Merge pull request #25 from jneem/perf
Browse files Browse the repository at this point in the history
Add mtu and write cmd support
  • Loading branch information
bjoernQ authored Dec 2, 2023
2 parents 0db8fcb + 80b612b commit 7074555
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 13 deletions.
2 changes: 2 additions & 0 deletions bleps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@ env_logger = "0.10.0"
async = [ "dep:embedded-io-async", "dep:futures", "dep:critical-section" ]
macros = [ "bleps-macros" ]
defmt = [ "dep:defmt" ]
mtu128 = []
mtu256 = []
23 changes: 21 additions & 2 deletions bleps/src/async_attribute_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ where
self.handle_read_req(src_handle, handle).await;
}

Att::WriteCmd { handle, data } => {
self.src_handle = handle;
self.handle_write_cmd(src_handle, handle, data).await;
}

Att::WriteReq { handle, data } => {
self.src_handle = src_handle;
self.handle_write_req(src_handle, handle, data).await;
Expand Down Expand Up @@ -395,6 +400,21 @@ where
self.write_att(src_handle, response).await;
}

async fn handle_write_cmd(&mut self, _src_handle: u16, handle: u16, data: Data) {
for att in self.attributes.iter_mut() {
if att.handle == handle {
if att.data.writable() {
// Write commands can't respond with an error.
let err = att.data.write(0, data.as_slice());
if let Err(e) = err {
log::debug!("write error: {e:?}");
}
}
break;
}
}
}

async fn handle_write_req(&mut self, src_handle: u16, handle: u16, data: Data) {
let mut err = Err(AttErrorCode::AttributeNotFound);
for att in self.attributes.iter_mut() {
Expand All @@ -414,10 +434,9 @@ where
}

async fn handle_exchange_mtu(&mut self, src_handle: u16, mtu: u16) {
log::debug!("Requested MTU {}, returning 23", mtu);
log::debug!("Requested MTU {mtu}, returning {MTU}");
self.write_att(src_handle, Data::new_att_exchange_mtu_response(MTU))
.await;
return;
}

async fn handle_find_type_value(
Expand Down
12 changes: 12 additions & 0 deletions bleps/src/att.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const ATT_READ_BY_TYPE_RESPONSE_OPCODE: u8 = 0x09;
pub const ATT_READ_REQUEST_OPCODE: u8 = 0x0a;
const ATT_READ_RESPONSE_OPCODE: u8 = 0x0b;
pub const ATT_WRITE_REQUEST_OPCODE: u8 = 0x12;
pub const ATT_WRITE_CMD_OPCODE: u8 = 0x52;
const ATT_WRITE_RESPONSE_OPCODE: u8 = 0x13;
pub const ATT_EXCHANGE_MTU_REQUEST_OPCODE: u8 = 0x02;
const ATT_EXCHANGE_MTU_RESPONSE_OPCODE: u8 = 0x03;
Expand Down Expand Up @@ -150,6 +151,10 @@ pub enum Att {
handle: u16,
data: Data,
},
WriteCmd {
handle: u16,
data: Data,
},
ExchangeMtu {
mtu: u16,
},
Expand Down Expand Up @@ -244,6 +249,13 @@ impl Att {

Ok(Self::WriteReq { handle, data })
}
ATT_WRITE_CMD_OPCODE => {
let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
let mut data = Data::default();
data.append(&payload[2..]);

Ok(Self::WriteCmd { handle, data })
}
ATT_EXCHANGE_MTU_REQUEST_OPCODE => {
let mtu = (payload[0] as u16) + ((payload[1] as u16) << 8);
Ok(Self::ExchangeMtu { mtu })
Expand Down
45 changes: 40 additions & 5 deletions bleps/src/attribute_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ pub const PRIMARY_SERVICE_UUID16: Uuid = Uuid::Uuid16(0x2800);
pub const CHARACTERISTIC_UUID16: Uuid = Uuid::Uuid16(0x2803);
pub const GENERIC_ATTRIBUTE_UUID16: Uuid = Uuid::Uuid16(0x1801);

/// The base MTU that is always supported. The MTU can be upgraded
/// per-connection. In the case of multiple connections, handling this
/// correctly would involve keeping track of which connection was configured
/// with which MTU. Instead of doing this, we always use the `BASE_MTU`
/// when transmitting but in the MTU exchange we support reporting a larger MTU.
/// This allows the client to use a larger MTU when transmitting to us, even
/// though we always respond with the smaller MTU.
pub const BASE_MTU: u16 = 23;

#[cfg(feature = "mtu128")]
pub const MTU: u16 = 128;

#[cfg(feature = "mtu256")]
pub const MTU: u16 = 256;

#[cfg(not(any(feature = "mtu128", feature = "mtu256")))]
pub const MTU: u16 = 23;

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -118,7 +134,7 @@ impl<'a> AttributeServer<'a> {
) -> Result<WorkResult, AttributeServerError> {
if let Some(notification_data) = notification_data {
let mut answer = notification_data.data;
answer.limit_len(MTU as usize - 3);
answer.limit_len(BASE_MTU as usize - 3);
let mut data = Data::new_att_value_ntf(notification_data.handle);
data.append(&answer.as_slice());
self.write_att(self.src_handle, data);
Expand Down Expand Up @@ -175,6 +191,11 @@ impl<'a> AttributeServer<'a> {
self.handle_write_req(src_handle, handle, data);
}

Att::WriteCmd { handle, data } => {
self.src_handle = src_handle;
self.handle_write_cmd(src_handle, handle, data);
}

Att::ExchangeMtu { mtu } => {
self.handle_exchange_mtu(src_handle, mtu);
}
Expand Down Expand Up @@ -316,7 +337,7 @@ impl<'a> AttributeServer<'a> {

let response = match err {
Ok(_) => {
data.limit_len(MTU as usize);
data.limit_len(BASE_MTU as usize);
data
}
Err(e) => Data::new_att_error_response(ATT_READ_REQUEST_OPCODE, handle, e),
Expand All @@ -325,6 +346,21 @@ impl<'a> AttributeServer<'a> {
self.write_att(src_handle, response);
}

fn handle_write_cmd(&mut self, _src_handle: u16, handle: u16, data: Data) {
for att in self.attributes.iter_mut() {
if att.handle == handle {
if att.data.writable() {
// Write commands can't respond with an error.
let err = att.data.write(0, data.as_slice());
if let Err(e) = err {
log::debug!("write error: {e:?}");
}
}
break;
}
}
}

fn handle_write_req(&mut self, src_handle: u16, handle: u16, data: Data) {
let mut err = Err(AttErrorCode::AttributeNotFound);
for att in self.attributes.iter_mut() {
Expand All @@ -344,9 +380,8 @@ impl<'a> AttributeServer<'a> {
}

fn handle_exchange_mtu(&mut self, src_handle: u16, mtu: u16) {
log::debug!("Requested MTU {}, returning 23", mtu);
log::debug!("Requested MTU {mtu}, returning {MTU}");
self.write_att(src_handle, Data::new_att_exchange_mtu_response(MTU));
return;
}

fn handle_find_type_value(
Expand Down Expand Up @@ -448,7 +483,7 @@ impl<'a> AttributeServer<'a> {

let response = match err {
Ok(_) => {
data.limit_len(MTU as usize - 1);
data.limit_len(BASE_MTU as usize - 1);
data
}
Err(e) => Data::new_att_error_response(ATT_READ_BLOB_REQ_OPCODE, handle, e),
Expand Down
12 changes: 6 additions & 6 deletions bleps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ pub enum PollResult {

#[derive(Clone, Copy)]
pub struct Data {
pub data: [u8; 128],
pub data: [u8; 256],
pub len: usize,
}

impl Data {
pub fn new(bytes: &[u8]) -> Data {
let mut data = [0u8; 128];
let mut data = [0u8; 256];
data[..bytes.len()].copy_from_slice(bytes);
Data {
data,
Expand Down Expand Up @@ -105,7 +105,7 @@ impl Data {
}

pub fn subdata_from(&self, from: usize) -> Data {
let mut data = [0u8; 128];
let mut data = [0u8; 256];
let new_len = self.len - from;
data[..new_len].copy_from_slice(&self.data[from..(from + new_len)]);
Data { data, len: new_len }
Expand Down Expand Up @@ -330,7 +330,7 @@ impl<'a> Ble<'a> {
return Some(PollResult::Event(event));
}
_ => {
// this is an serious error
// this is a serious error
panic!("Unknown packet type {}", packet_type);
}
},
Expand All @@ -349,7 +349,7 @@ impl<'a> Ble<'a> {

impl Data {
fn read(connector: &dyn HciConnection, len: usize) -> Self {
let mut data = [0u8; 128];
let mut data = [0u8; 256];
for i in 0..len {
loop {
match connector.read() {
Expand Down Expand Up @@ -591,7 +591,7 @@ pub mod asynch {
T: embedded_io_async::Read,
{
let mut idx = 0;
let mut data = [0u8; 128];
let mut data = [0u8; 256];
loop {
let l = connector.read(&mut data[idx..][..len]).await.unwrap();
idx += l;
Expand Down

0 comments on commit 7074555

Please sign in to comment.