Skip to content
52 changes: 44 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions abstracted/src/abstracted/abstract_bluetooth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,17 @@ pub trait AbstractBluetoothChannel {
let cbor = envelope.to_cbor_data();

for chunk in chunk(&cbor) {
self.send(chunk).await.expect("couldn't send");
self.send(chunk).await?;
}

Ok(())
}

async fn receive_envelope(&self, timeout: Duration) -> Result<Envelope> {
let mut unchunker = Dechunker::new();
loop {
while !unchunker.is_complete() {
let bytes = self.receive(timeout).await?;
println!("Received {} bytes over BLE", bytes.len());
unchunker.receive(&bytes)?;

if unchunker.is_complete() {
break;
}
}

let message = unchunker.data().expect("data is complete");
Expand Down
6 changes: 5 additions & 1 deletion btp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ edition = "2021"
homepage.workspace = true

[dependencies]
consts = { git = "https://github.com/Foundation-Devices/prime-ble-firmware.git", features = ["dle"] }
bytemuck = { version = "1", features = ["derive"] }
consts = { git = "https://github.com/Foundation-Devices/prime-ble-firmware.git", features = [
"dle",
] }
rand = { workspace = true }
thiserror = "2"
51 changes: 51 additions & 0 deletions btp/src/chunk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use consts::APP_MTU;

use crate::{Header, CHUNK_DATA_SIZE, HEADER_SIZE};

pub struct Chunker<'a> {
data: &'a [u8],
message_id: u16,
current_index: u16,
total_chunks: u16,
}

impl<'a> Iterator for Chunker<'a> {
type Item = [u8; APP_MTU];

fn next(&mut self) -> Option<Self::Item> {
let start_idx = self.current_index as usize * CHUNK_DATA_SIZE;
if start_idx >= self.data.len() {
return None;
}

let end_idx = (start_idx + CHUNK_DATA_SIZE).min(self.data.len());
let chunk_data = &self.data[start_idx..end_idx];

let header = Header::new(
self.message_id,
self.current_index,
self.total_chunks,
chunk_data.len() as u8,
);

let mut buffer = [0u8; APP_MTU];
buffer[..HEADER_SIZE].copy_from_slice(header.as_bytes());
buffer[HEADER_SIZE..HEADER_SIZE + chunk_data.len()].copy_from_slice(chunk_data);
self.current_index += 1;

Some(buffer)
}
}

/// Splits data into chunks for transmission
pub fn chunk(data: &[u8]) -> Chunker<'_> {
let message_id = rand::Rng::random::<u16>(&mut rand::rng());
let total_chunks = data.len().div_ceil(CHUNK_DATA_SIZE) as u16;

Chunker {
data,
message_id,
current_index: 0,
total_chunks,
}
}
Loading