Skip to content

Commit

Permalink
Update gatt to allow for Write Without Response characteristics
Browse files Browse the repository at this point in the history
  • Loading branch information
Meigs2 committed Feb 26, 2025
1 parent 1b5b70b commit 4d11a11
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 9 deletions.
2 changes: 1 addition & 1 deletion host/src/att.rs
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ impl<'d> AttCmd<'d> {
let mut w = WriteCursor::new(dest);
match self {
Self::Write { handle, data } => {
w.write(ATT_WRITE_REQ)?;
w.write(ATT_WRITE_CMD)?;
w.write(*handle)?;
w.append(data)?;
}
Expand Down
53 changes: 45 additions & 8 deletions host/src/gatt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ impl<'reference> Drop for Response<'reference> {
pub(crate) trait Client<'d, E> {
/// Perform a gatt request and return the response.
fn request(&self, req: AttReq<'_>) -> impl Future<Output = Result<Response<'d>, BleHostError<E>>>;
fn command(&self, cmd: AttCmd<'_>) -> impl Future<Output = Result<(), BleHostError<E>>>;
}

impl<'reference, T: Controller, const MAX_SERVICES: usize, const L2CAP_MTU: usize> Client<'reference, T::Error>
Expand All @@ -430,6 +431,33 @@ impl<'reference, T: Controller, const MAX_SERVICES: usize, const L2CAP_MTU: usiz
async fn request(&self, req: AttReq<'_>) -> Result<Response<'reference>, BleHostError<T::Error>> {
let data = Att::Client(AttClient::Request(req));

self.send_att_data(data).await?;

let (h, pdu) = self.response_channel.receive().await;

assert_eq!(h, self.connection.handle());
Ok(Response {
handle: h,
pdu,
connections: &self.stack.host.connections,
})
}

async fn command(&self, cmd: AttCmd<'_>) -> Result<(), BleHostError<T::Error>> {
let data = Att::Client(AttClient::Command(cmd));

self.send_att_data(data).await?;

Ok(())
}
}

impl<'reference, T: Controller, const MAX_SERVICES: usize, const L2CAP_MTU: usize>
GattClient<'reference, T, MAX_SERVICES, L2CAP_MTU>
{
async fn send_att_data(&self, data: Att<'_>) -> Result<(), BleHostError<T::Error>> {
// Check the data type without consuming it

let header = L2capHeader {
channel: crate::types::l2cap::L2CAP_CID_ATT,
length: data.size() as u16,
Expand All @@ -447,14 +475,7 @@ impl<'reference, T: Controller, const MAX_SERVICES: usize, const L2CAP_MTU: usiz
.await?;
grant.send(w.finish()).await?;

let (h, pdu) = self.response_channel.receive().await;

assert_eq!(h, self.connection.handle());
Ok(Response {
handle: h,
pdu,
connections: &self.stack.host.connections,
})
Ok(())
}
}

Expand Down Expand Up @@ -706,6 +727,22 @@ impl<'reference, C: Controller, const MAX_SERVICES: usize, const L2CAP_MTU: usiz
}
}

/// Write without waiting for a response to a characteristic described by a handle.
pub async fn write_characteristic_without_response<T: FromGatt>(
&self,
handle: &Characteristic<T>,
buf: &[u8],
) -> Result<(), BleHostError<C::Error>> {
let data = att::AttCmd::Write {
handle: handle.handle,
data: buf,
};

self.command(data).await?;

Ok(())
}

/// Subscribe to indication/notification of a given Characteristic
///
/// A listener is returned, which has a `next()` method
Expand Down

0 comments on commit 4d11a11

Please sign in to comment.