use embassy_sync::blocking_mutex::raw::RawMutex;
use crate::prelude::*;
const DEVICE_NAME_MAX_LENGTH: usize = 22;
#[cfg(not(feature = "security"))]
pub const GAP_SERVICE_ATTRIBUTE_COUNT: usize = 6;
#[cfg(all(feature = "security", not(feature = "central")))]
pub const GAP_SERVICE_ATTRIBUTE_COUNT: usize = 6;
#[cfg(all(feature = "security", feature = "central"))]
pub const GAP_SERVICE_ATTRIBUTE_COUNT: usize = 8;
pub enum GapConfig<'a> {
Peripheral(PeripheralConfig<'a>),
Central(CentralConfig<'a>),
}
pub struct PeripheralConfig<'a> {
pub name: &'a str,
pub appearance: &'a BluetoothUuid16,
}
pub struct CentralConfig<'a> {
pub name: &'a str,
pub appearance: &'a BluetoothUuid16,
}
impl<'a> GapConfig<'a> {
pub fn default(name: &'a str) -> Self {
GapConfig::Peripheral(PeripheralConfig {
name,
appearance: &appearance::UNKNOWN,
})
}
pub fn build<M: RawMutex, const MAX: usize>(
self,
table: &mut AttributeTable<'a, M, MAX>,
) -> Result<(), &'static str> {
match self {
GapConfig::Peripheral(config) => config.build(table),
GapConfig::Central(config) => config.build(table),
}
}
}
impl<'a> PeripheralConfig<'a> {
fn build<M: RawMutex, const MAX: usize>(self, table: &mut AttributeTable<'a, M, MAX>) -> Result<(), &'static str> {
if self.name.len() > DEVICE_NAME_MAX_LENGTH {
return Err("Device name is too long. Max length is 22 bytes");
}
let mut gap_builder = table.add_service(Service::new(service::GAP));
gap_builder.add_characteristic_ro(characteristic::DEVICE_NAME, self.name);
gap_builder.add_characteristic_ro(characteristic::APPEARANCE, self.appearance);
#[cfg(all(feature = "security", feature = "central"))]
gap_builder.add_characteristic_ro(characteristic::CENTRAL_ADDRESS_RESOLUTION, &1u8);
gap_builder.build();
table.add_service(Service::new(service::GATT));
Ok(())
}
}
impl<'a> CentralConfig<'a> {
fn build<M: RawMutex, const MAX: usize>(self, table: &mut AttributeTable<'a, M, MAX>) -> Result<(), &'static str> {
if self.name.len() > DEVICE_NAME_MAX_LENGTH {
return Err("Device name is too long. Max length is 22 bytes");
}
let mut gap_builder = table.add_service(Service::new(service::GAP));
gap_builder.add_characteristic_ro(characteristic::DEVICE_NAME, self.name);
gap_builder.add_characteristic_ro(characteristic::APPEARANCE, self.appearance);
#[cfg(all(feature = "security", feature = "central"))]
gap_builder.add_characteristic_ro(characteristic::CENTRAL_ADDRESS_RESOLUTION, &1u8);
gap_builder.build();
table.add_service(Service::new(service::GATT));
Ok(())
}
}
#[cfg(test)]
mod tests {
extern crate std;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use super::*;
#[test]
fn gap_config_can_be_built_twice() {
for _ in 0..2 {
let mut table: AttributeTable<'_, NoopRawMutex, 16> = AttributeTable::new();
GapConfig::Peripheral(PeripheralConfig {
name: "trouble",
appearance: &appearance::UNKNOWN,
})
.build(&mut table)
.unwrap();
}
}
}