Skip to content

Commit

Permalink
feat(LE command): add Number of Completed Packets command
Browse files Browse the repository at this point in the history
  • Loading branch information
OueslatiGhaith committed Jan 2, 2024
1 parent 90d31c0 commit 1d099fc
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,15 +596,15 @@ fn to_hardware_error(payload: &[u8]) -> Result<HardwareError, Error> {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct NumberOfCompletedPackets {
/// Number of connection handles whose data is sent in this event.
num_handles: usize,
pub(crate) num_handles: usize,

/// Data buffer for the event.
data_buf: [u8; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN],
pub(crate) data_buf: [u8; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN],
}

// The maximum number of bytes in the buffer is the max HCI packet size (255) less the other data in
// the packet.
const NUMBER_OF_COMPLETED_PACKETS_MAX_LEN: usize = 254;
pub(crate) const NUMBER_OF_COMPLETED_PACKETS_MAX_LEN: usize = 254;

impl Debug for NumberOfCompletedPackets {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
Expand All @@ -617,6 +617,28 @@ impl Debug for NumberOfCompletedPackets {
}

impl NumberOfCompletedPackets {
pub fn new(items: impl Iterator<Item = NumberOfCompletedPacketsPair>) -> Self {
let mut data_buf = [0; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN];

// let num_handles = &items.count();
let mut index = 0;
let mut num_handles = 0;
for item in items {
LittleEndian::write_u16(&mut data_buf[index..], item.conn_handle.0);
LittleEndian::write_u16(
&mut data_buf[index + 2..],
item.num_completed_packets as u16,
);
index += 4;
num_handles += 1;
}

Self {
num_handles,
data_buf,
}
}

/// Returns an iterator over the connection handle-number of completed packet pairs.
pub fn iter(&self) -> NumberOfCompletedPacketsIterator {
NumberOfCompletedPacketsIterator {
Expand Down
40 changes: 40 additions & 0 deletions src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//! support sending the packet ID, as `uart` does. In that case, it would make sense to also remove
//! `uart` and move its contents up one level.
use crate::event::{NumberOfCompletedPackets, NUMBER_OF_COMPLETED_PACKETS_MAX_LEN};
use crate::ConnectionHandle;
use byteorder::{ByteOrder, LittleEndian};
use core::convert::Into;
Expand Down Expand Up @@ -230,6 +231,37 @@ pub trait HostHci {
/// is used to turn flow control on or off.
async fn host_buffer_size(&mut self, params: HostBufferSize);

/// This command is used by the Host to indicate to the Controller the number of HCI Data Packets
/// that have been completed for each [Connection Handle](ConnectionHandle) since the previous
/// [Number of Completed Packets](HostHci::number_of_completed_packets) command was sent to
/// the Controller. This means that the corresponding buffer space has been freed in the Host.
///
/// Based on this information, and the
/// [Total Number of ACL Data Packets](HostBufferSize::total_acl_data_packets) and
/// [Total Number of Synchronous Data Packets](HostBufferSize::total_sync_data_packets)
/// parameters of the [Host Buffer Size](HostHci::host_buffer_size) command, the Controller can
/// determine for which [Connection Handles](ConnectionHandle) the following HCI Data Packets
/// should be sent to the Host.
///
/// The command should only be issued by the Host if flow control in the direction from the Controller
/// to the host is on and there is at least one connection, or if the Controller is in local loopback
/// mode. Otherwise, the command will will be ignored by the Controller.
///
/// When the Host has completed one or more HCI Data Packet(s) it shall send a
/// [Number of Completed Packets](HostHci::number_of_completed_packets) command to the Controller,
/// unitl it finally reports that all pending HCI Data Packets have been completed. The frequency
/// at which this command is sent.
///
/// # Note:
/// This command is a special command in the sense that no event is normally generated after the
/// command has completed. The command may be sent at any time by the Host when there is at leat
/// one connection, or if the Controller is in local loopback mode independent of other commands.
/// The normal flow control for commands is not used for the
/// [Number of Complete Packets](HostHci::number_of_completed_packets) command.
///
/// See Bluetooth spec. v.5.4 [Vol 4, Part E, 7.3.40].
async fn number_of_completed_packets(&mut self, params: NumberOfCompletedPackets);

/// This command reads the values for the version information for the local Controller.
///
/// Defined in Bluetooth Specification Vol 2, Part E, Section 7.4.1.
Expand Down Expand Up @@ -1213,6 +1245,14 @@ where
.await;
}

async fn number_of_completed_packets(&mut self, params: NumberOfCompletedPackets) {
let mut bytes = [0; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN];
bytes[0] = params.num_handles as u8;
bytes[1..].copy_from_slice(&params.data_buf);
self.controller_write(crate::opcode::NUMBER_OF_COMPLETED_PACKETS, &bytes)
.await;
}

async fn read_local_version_information(&mut self) {
self.controller_write(crate::opcode::READ_LOCAL_VERSION_INFO, &[])
.await;
Expand Down
1 change: 1 addition & 0 deletions src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ opcodes! {
pub const READ_TX_POWER_LEVEL = 0x002D;
pub const SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 0x031;
pub const HOST_BUFFER_SIZE = 0x033;
pub const NUMBER_OF_COMPLETED_PACKETS = 0x035;
}

InfoParam = 0x0004;
Expand Down

0 comments on commit 1d099fc

Please sign in to comment.