1use embassy_sync::blocking_mutex::raw::RawMutex;
11use heapless::String;
12use static_cell::StaticCell;
13
14use crate::prelude::*;
15
16const DEVICE_NAME_MAX_LENGTH: usize = 22;
18
19pub const GAP_SERVICE_ATTRIBUTE_COUNT: usize = 6;
27
28pub enum GapConfig<'a> {
30 Peripheral(PeripheralConfig<'a>),
32 Central(CentralConfig<'a>),
34}
35
36pub struct PeripheralConfig<'a> {
38 pub name: &'a str,
40 pub appearance: &'a BluetoothUuid16,
44 }
47
48pub struct CentralConfig<'a> {
50 pub name: &'a str,
52 pub appearance: &'a BluetoothUuid16,
56 }
58
59impl<'a> GapConfig<'a> {
60 pub fn default(name: &'a str) -> Self {
64 GapConfig::Peripheral(PeripheralConfig {
65 name,
66 appearance: &appearance::UNKNOWN,
67 })
68 }
69
70 pub fn build<M: RawMutex, const MAX: usize>(
72 self,
73 table: &mut AttributeTable<'a, M, MAX>,
74 ) -> Result<(), &'static str> {
75 match self {
76 GapConfig::Peripheral(config) => config.build(table),
77 GapConfig::Central(config) => config.build(table),
78 }
79 }
80}
81
82impl<'a> PeripheralConfig<'a> {
83 fn build<M: RawMutex, const MAX: usize>(self, table: &mut AttributeTable<'a, M, MAX>) -> Result<(), &'static str> {
85 static PERIPHERAL_NAME: StaticCell<String<DEVICE_NAME_MAX_LENGTH>> = StaticCell::new();
86 let peripheral_name = PERIPHERAL_NAME.init(String::new());
87 peripheral_name
88 .push_str(self.name)
89 .map_err(|_| "Device name is too long. Max length is 22 bytes")?;
90
91 let mut gap_builder = table.add_service(Service::new(service::GAP));
92 gap_builder.add_characteristic_ro(characteristic::DEVICE_NAME, peripheral_name);
93 gap_builder.add_characteristic_ro(characteristic::APPEARANCE, self.appearance);
94 gap_builder.build();
95
96 table.add_service(Service::new(service::GATT));
97
98 Ok(())
99 }
100}
101
102impl<'a> CentralConfig<'a> {
103 fn build<M: RawMutex, const MAX: usize>(self, table: &mut AttributeTable<'a, M, MAX>) -> Result<(), &'static str> {
105 static CENTRAL_NAME: StaticCell<String<DEVICE_NAME_MAX_LENGTH>> = StaticCell::new();
106 let central_name = CENTRAL_NAME.init(String::new());
107 central_name
108 .push_str(self.name)
109 .map_err(|_| "Device name is too long. Max length is 22 bytes")?;
110
111 let mut gap_builder = table.add_service(Service::new(service::GAP));
112 gap_builder.add_characteristic_ro(characteristic::DEVICE_NAME, central_name);
113 gap_builder.add_characteristic_ro(characteristic::APPEARANCE, self.appearance);
114 gap_builder.build();
115
116 table.add_service(Service::new(service::GATT));
117
118 Ok(())
119 }
120}