Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 19 additions & 23 deletions rmk/src/split/ble/central.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use embassy_time::{Duration, Timer, with_timeout};
use heapless::VecView;
use trouble_host::prelude::*;

use super::GattSplitMessage;
use crate::ble::sleep::report_activity;
use crate::ble::{update_ble_phy, update_conn_params};
use crate::channel::FLASH_CHANNEL;
Expand Down Expand Up @@ -364,7 +365,7 @@ async fn run_peripheral_manager<
info!("Services found");
if let Some(service) = services.first() {
let message_to_central = client
.characteristic_by_uuid::<[u8; SPLIT_MESSAGE_MAX_SIZE]>(
.characteristic_by_uuid::<GattSplitMessage>(
service,
// uuid: 0e6313e3-bd0b-45c2-8d2e-37a2e8128bc3
&Uuid::Uuid128([
Expand All @@ -375,7 +376,7 @@ async fn run_peripheral_manager<
.await?;
info!("Message to central found");
let message_to_peripheral = client
.characteristic_by_uuid::<[u8; SPLIT_MESSAGE_MAX_SIZE]>(
.characteristic_by_uuid::<GattSplitMessage>(
service,
// uuid: 4b3514fb-cae4-4d38-a097-3a2a3d1c3b9c
&Uuid::Uuid128([
Expand Down Expand Up @@ -404,15 +405,15 @@ pub(crate) struct BleSplitCentralDriver<'a, 'b, 'c, C: Controller + ControllerCm
// Listener for split message from peripheral
listener: NotificationListener<'b, 512>,
// Characteristic to send split message to peripheral
message_to_peripheral: Characteristic<[u8; SPLIT_MESSAGE_MAX_SIZE]>,
message_to_peripheral: Characteristic<GattSplitMessage>,
// Client
client: &'c GattClient<'a, C, P, 10>,
}

impl<'a, 'b, 'c, C: Controller + ControllerCmdAsync<LeSetPhy>, P: PacketPool> BleSplitCentralDriver<'a, 'b, 'c, C, P> {
pub(crate) fn new(
listener: NotificationListener<'b, 512>,
message_to_peripheral: Characteristic<[u8; SPLIT_MESSAGE_MAX_SIZE]>,
message_to_peripheral: Characteristic<GattSplitMessage>,
client: &'c GattClient<'a, C, P, 10>,
) -> Self {
Self {
Expand Down Expand Up @@ -445,27 +446,22 @@ impl<'a, 'b, 'c, C: Controller + ControllerCmdAsync<LeSetPhy>, P: PacketPool> Sp
for BleSplitCentralDriver<'a, 'b, 'c, C, P>
{
async fn write(&mut self, message: &SplitMessage) -> Result<usize, SplitDriverError> {
let mut buf = [0_u8; SPLIT_MESSAGE_MAX_SIZE];
match postcard::to_slice(&message, &mut buf) {
Ok(_bytes) => {
if let Err(e) = self
.client
.write_characteristic_without_response(&self.message_to_peripheral, &buf)
.await
{
if let BleHostError::BleHost(Error::NotFound) = e {
error!("Peripheral disconnected");
return Err(SplitDriverError::Disconnected);
}
#[cfg(feature = "defmt")]
let e = defmt::Debug2Format(&e);
error!("BLE message_to_peripheral_write error: {:?}", e);
}
let gatt_msg = GattSplitMessage::try_from(message)?;
if let Err(e) = self
.client
.write_characteristic_without_response(&self.message_to_peripheral, gatt_msg.as_gatt())
.await
{
if let BleHostError::BleHost(Error::NotFound) = e {
error!("Peripheral disconnected");
return Err(SplitDriverError::Disconnected);
}
Err(e) => error!("Postcard serialize split message error: {}", e),
};
#[cfg(feature = "defmt")]
let e = defmt::Debug2Format(&e);
error!("BLE message_to_peripheral_write error: {:?}", e);
}

Ok(SPLIT_MESSAGE_MAX_SIZE)
Ok(gatt_msg.len)
}
}

Expand Down
42 changes: 42 additions & 0 deletions rmk/src/split/ble/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ pub mod peripheral;

use postcard::experimental::max_size::MaxSize;
use serde::{Deserialize, Serialize};
use trouble_host::types::gatt_traits::AsGatt;

use super::SplitMessage;
use super::driver::SplitDriverError;

#[derive(Clone, Debug, Serialize, Deserialize, MaxSize)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
Expand All @@ -21,3 +25,41 @@ impl PeerAddress {
}
}
}

#[derive(Default, Clone)]
pub(crate) struct GattSplitMessage {
buf: [u8; SplitMessage::POSTCARD_MAX_SIZE],
len: usize,
}

impl TryFrom<&SplitMessage> for GattSplitMessage {
type Error = SplitDriverError;

fn try_from(value: &SplitMessage) -> Result<Self, Self::Error> {
let mut buf = [0; SplitMessage::POSTCARD_MAX_SIZE];
let encoded = postcard::to_slice(value, &mut buf).map_err(|e| {
error!("Postcard serialize split message error: {}", e);
SplitDriverError::SerializeError
})?;

let len = encoded.len();

// Check if slice starts at the beginning of buffer
if encoded.as_ptr() != buf.as_ptr() {
error!("Postcard serialize split message did not use the buffer correctly!");
return Err(SplitDriverError::SerializeError);
}

Ok(Self { buf, len })
}
}

impl AsGatt for GattSplitMessage {
const MIN_SIZE: usize = 0;

const MAX_SIZE: usize = SplitMessage::POSTCARD_MAX_SIZE;

fn as_gatt(&self) -> &[u8] {
&self.buf[..self.len]
}
}
24 changes: 10 additions & 14 deletions rmk/src/split/ble/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ use trouble_host::prelude::*;

#[cfg(feature = "storage")]
use super::PeerAddress;
use super::{GattSplitMessage, SplitMessage};
use crate::event::{CentralConnectedEvent, KeyboardEvent, SubscribableEvent, publish_event};
use crate::split::driver::{SplitDriverError, SplitReader, SplitWriter};
use crate::split::peripheral::SplitPeripheral;
use crate::split::{SPLIT_MESSAGE_MAX_SIZE, SplitMessage};
use crate::state::update_status;

/// Gatt service used in split peripheral to send split message to central
#[gatt_service(uuid = "4dd5fbaa-18e5-4b07-bf0a-353698659946")]
pub(crate) struct SplitBleService {
#[characteristic(uuid = "0e6313e3-bd0b-45c2-8d2e-37a2e8128bc3", read, notify, indicate)]
pub(crate) message_to_central: [u8; SPLIT_MESSAGE_MAX_SIZE],
pub(crate) message_to_central: GattSplitMessage,

#[characteristic(uuid = "4b3514fb-cae4-4d38-a097-3a2a3d1c3b9c", write_without_response, read, notify)]
pub(crate) message_to_peripheral: [u8; SPLIT_MESSAGE_MAX_SIZE],
pub(crate) message_to_peripheral: GattSplitMessage,
}

/// Gatt server in split peripheral
Expand All @@ -31,16 +31,16 @@ pub(crate) struct BleSplitPeripheralServer {

/// BLE driver for split peripheral
pub(crate) struct BleSplitPeripheralDriver<'stack, 'server, 'c, P: PacketPool> {
message_to_peripheral: Characteristic<[u8; SPLIT_MESSAGE_MAX_SIZE]>,
message_to_central: Characteristic<[u8; SPLIT_MESSAGE_MAX_SIZE]>,
message_to_peripheral: Characteristic<GattSplitMessage>,
message_to_central: Characteristic<GattSplitMessage>,
conn: &'c GattConnection<'stack, 'server, P>,
}

impl<'stack, 'server, 'c, P: PacketPool> BleSplitPeripheralDriver<'stack, 'server, 'c, P> {
pub(crate) fn new(server: &'server BleSplitPeripheralServer, conn: &'c GattConnection<'stack, 'server, P>) -> Self {
Self {
message_to_central: server.service.message_to_central,
message_to_peripheral: server.service.message_to_peripheral,
message_to_central: server.service.message_to_central.clone(),
message_to_peripheral: server.service.message_to_peripheral.clone(),
conn,
}
}
Expand Down Expand Up @@ -109,20 +109,16 @@ impl<'stack, 'server, 'c, P: PacketPool> SplitReader for BleSplitPeripheralDrive

impl<'stack, 'server, 'c, P: PacketPool> SplitWriter for BleSplitPeripheralDriver<'stack, 'server, 'c, P> {
async fn write(&mut self, message: &SplitMessage) -> Result<usize, SplitDriverError> {
let mut buf = [0_u8; SPLIT_MESSAGE_MAX_SIZE];
postcard::to_slice(message, &mut buf).map_err(|e| {
error!("Postcard serialize split message error: {}", e);
SplitDriverError::SerializeError
})?;
let gatt_msg = GattSplitMessage::try_from(message)?;
info!("Writing split message to central: {:?}", message);
self.message_to_central
.notify(self.conn, &buf, true)
.notify(self.conn, &gatt_msg, true)
.await
.map_err(|e| {
error!("BLE notify error: {:?}", e);
SplitDriverError::BleError(1)
})?;
Ok(buf.len())
Ok(gatt_msg.len)
}
}

Expand Down