esp32_nimble/server/
ble_service.rs1use alloc::{sync::Arc, vec::Vec};
2use esp_idf_svc::sys as esp_idf_sys;
3use esp_idf_sys::ble_uuid_any_t;
4
5use crate::{
6 BLECharacteristic, BLEError, ble,
7 utilities::{BleUuid, mutex::Mutex},
8};
9
10use super::ble_characteristic::NimbleProperties;
11
12const NULL_HANDLE: u16 = 0xFFFF;
13
14pub struct BLEService {
15 pub(crate) uuid: ble_uuid_any_t,
16 pub(crate) handle: u16,
17 pub(crate) characteristics: Vec<Arc<Mutex<BLECharacteristic>>>,
18 svc_def: Option<[esp_idf_sys::ble_gatt_svc_def; 2]>,
19 svc_def_characteristics: Vec<esp_idf_sys::ble_gatt_chr_def>,
20}
21
22impl BLEService {
23 pub(crate) fn new(uuid: BleUuid) -> Self {
24 Self {
25 uuid: ble_uuid_any_t::from(uuid),
26 handle: NULL_HANDLE,
27 characteristics: Vec::new(),
28 svc_def: None,
29 svc_def_characteristics: Vec::new(),
30 }
31 }
32
33 pub fn uuid(&self) -> BleUuid {
34 BleUuid::from(self.uuid)
35 }
36
37 pub(crate) fn start(&mut self) -> Result<(), BLEError> {
38 let svc_def = self.svc_def.get_or_insert_with(|| {
39 let mut svc = [esp_idf_sys::ble_gatt_svc_def::default(); 2];
40 svc[0].type_ = esp_idf_sys::BLE_GATT_SVC_TYPE_PRIMARY as _;
41 svc[0].uuid = unsafe { &self.uuid.u };
42 svc[0].includes = core::ptr::null_mut();
43
44 if self.characteristics.is_empty() {
45 } else {
46 for chr in &mut self.characteristics {
47 let arg =
48 unsafe { Arc::get_mut_unchecked(chr) } as *mut Mutex<BLECharacteristic>;
49 let mut chr = chr.lock();
50 self.svc_def_characteristics
51 .push(esp_idf_sys::ble_gatt_chr_def {
52 uuid: unsafe { &chr.uuid.u },
53 access_cb: Some(BLECharacteristic::handle_gap_event),
54 arg: arg as _,
55 descriptors: chr.construct_svc_def_descriptors(),
56 flags: chr.properties.bits(),
57 min_key_size: 0,
58 val_handle: &mut chr.handle,
59 #[cfg(cpfd)]
60 cpfd: chr.cpfd.as_mut_ptr(),
61 });
62 }
63 self.svc_def_characteristics
64 .push(esp_idf_sys::ble_gatt_chr_def::default());
65 svc[0].characteristics = self.svc_def_characteristics.as_ptr();
66 }
67
68 svc[1].type_ = 0;
69 svc
70 });
71
72 unsafe {
73 ble!(esp_idf_sys::ble_gatts_count_cfg(svc_def.as_ptr()))?;
74 ble!(esp_idf_sys::ble_gatts_add_svcs(svc_def.as_ptr()))?;
75 }
76 Ok(())
77 }
78
79 pub fn create_characteristic(
80 &mut self,
81 uuid: BleUuid,
82 properties: NimbleProperties,
83 ) -> Arc<Mutex<BLECharacteristic>> {
84 let characteristic = Arc::new(Mutex::new(BLECharacteristic::new(uuid, properties)));
85 self.characteristics.push(characteristic.clone());
86 characteristic
87 }
88
89 pub async fn get_characteristic(
91 &self,
92 uuid: BleUuid,
93 ) -> Option<&Arc<Mutex<BLECharacteristic>>> {
94 self.characteristics
95 .iter()
96 .find(|x| unsafe { x.raw() }.uuid() == uuid)
97 }
98}
99
100unsafe impl Send for BLEService {}