blob: 102b36052f245e378b8c06bf5338a79ca61d65fe [file] [log] [blame]
torfmaster76c81942020-02-23 17:31:59 +01001//! Module to provide simple ble functions as scanning and advertising
2
Woyten30fc95b2019-01-10 21:09:46 +01003use crate::ble_composer::BlePayload;
4use crate::callback::CallbackSubscription;
Woytend007bb92019-12-01 15:22:08 +01005use crate::callback::Consumer;
torfmaster76c81942020-02-23 17:31:59 +01006use crate::result::TockError;
Woyten22bc2542019-11-15 23:18:40 +01007use crate::result::TockResult;
Woyten30fc95b2019-01-10 21:09:46 +01008use crate::shared_memory::SharedMemory;
9use crate::syscalls;
torfmaster76c81942020-02-23 17:31:59 +010010use core::cell::Cell;
11use core::future::Future;
Philipp Vollmere04578a2018-01-09 21:18:10 +010012
Woyten9567d792018-02-04 00:11:39 +010013const DRIVER_NUMBER: usize = 0x30000;
Philipp Vollmer55570f22018-02-24 13:23:45 +010014pub const MAX_PAYLOAD_SIZE: usize = 9;
Philipp Vollmere0577732018-04-19 17:36:49 +020015pub const BUFFER_SIZE_ADVERTISE: usize = 39;
torfmaster76c81942020-02-23 17:31:59 +010016pub(crate) const BUFFER_SIZE_SCAN: usize = 39;
Philipp Vollmere04578a2018-01-09 21:18:10 +010017
torfmaster9d7ff2a2019-12-28 13:45:55 +010018mod command_nr {
Woyten9567d792018-02-04 00:11:39 +010019 pub const START_ADVERTISING: usize = 0;
Philipp Vollmer41b91352018-02-05 09:55:54 +010020 pub const PASSIVE_SCAN: usize = 5;
Philipp Vollmere04578a2018-01-09 21:18:10 +010021}
22
torfmaster9d7ff2a2019-12-28 13:45:55 +010023mod subscribe_nr {
24 pub const BLE_PASSIVE_SCAN_SUB: usize = 0;
25}
26
27mod allow_nr {
28 pub const ALLOW_ADVERTISMENT_BUFFER: usize = 0;
29 pub const ALLOW_SCAN_BUFFER: usize = 1;
30}
31
Philipp Vollmere04578a2018-01-09 21:18:10 +010032mod gap_flags {
Philipp Vollmer090398c2018-06-29 15:14:54 +020033 pub const BLE_DISCOVERABLE: usize = 0x02;
Philipp Vollmere04578a2018-01-09 21:18:10 +010034}
35
Philipp Vollmer349417d2018-02-24 17:29:19 +010036pub mod gap_data {
Woyten9567d792018-02-04 00:11:39 +010037 pub const COMPLETE_LIST_16BIT_SERVICE_IDS: usize = 0x03;
38 pub const COMPLETE_LOCAL_NAME: usize = 0x09;
39 pub const SET_FLAGS: usize = 1;
40 pub const SERVICE_DATA: usize = 0x16;
Philipp Vollmere04578a2018-01-09 21:18:10 +010041}
42
torfmaster97c5e722020-01-02 21:30:16 +010043#[non_exhaustive]
torfmaster76c81942020-02-23 17:31:59 +010044pub struct BleAdvertisingDriverFactory;
45
46impl BleAdvertisingDriverFactory {
torfmasterdc326a42020-02-26 23:17:59 +010047 pub fn create_driver(&mut self) -> BleAdvertisingDriver {
torfmaster76c81942020-02-23 17:31:59 +010048 // Unfortunately, there is no way to check the availability of the ble advertising driver
49 BleAdvertisingDriver
50 }
51}
52
53#[non_exhaustive]
torfmaster97c5e722020-01-02 21:30:16 +010054pub struct BleAdvertisingDriver;
Philipp Vollmere04578a2018-01-09 21:18:10 +010055
Philipp Vollmer45190922018-03-09 19:48:58 +010056impl BleAdvertisingDriver {
Philipp Vollmere0577732018-04-19 17:36:49 +020057 pub fn create_advertising_buffer() -> [u8; BUFFER_SIZE_ADVERTISE] {
58 [0; BUFFER_SIZE_ADVERTISE]
Philipp Vollmera4ab6592018-04-14 15:01:27 +020059 }
Philipp Vollmere0577732018-04-19 17:36:49 +020060 pub fn initialize<'a>(
torfmaster17679812019-12-27 18:07:10 +010061 &'a mut self,
Philipp Vollmer090398c2018-06-29 15:14:54 +020062 interval: usize,
63 service_payload: &BlePayload,
Philipp Vollmere0577732018-04-19 17:36:49 +020064 advertising_buffer: &'a mut [u8; BUFFER_SIZE_ADVERTISE],
Woyten22bc2542019-11-15 23:18:40 +010065 ) -> TockResult<SharedMemory<'a>> {
Philipp Vollmer090398c2018-06-29 15:14:54 +020066 let mut shared_memory = syscalls::allow(
Philipp Vollmera4ab6592018-04-14 15:01:27 +020067 DRIVER_NUMBER,
torfmaster9d7ff2a2019-12-28 13:45:55 +010068 allow_nr::ALLOW_ADVERTISMENT_BUFFER,
Philipp Vollmera4ab6592018-04-14 15:01:27 +020069 advertising_buffer,
70 )?;
torfmaster906d2972019-02-15 23:38:23 +010071 shared_memory.write_bytes(service_payload);
Philipp Vollmer090398c2018-06-29 15:14:54 +020072 Self::start_advertising(gap_flags::BLE_DISCOVERABLE, interval)?;
Philipp Vollmer45190922018-03-09 19:48:58 +010073 Ok(shared_memory)
Philipp Vollmere04578a2018-01-09 21:18:10 +010074 }
75
Woyten22bc2542019-11-15 23:18:40 +010076 fn start_advertising(pdu_type: usize, interval: usize) -> TockResult<()> {
77 syscalls::command(
Woyten4f5bc412019-11-21 23:36:58 +010078 DRIVER_NUMBER,
torfmaster9d7ff2a2019-12-28 13:45:55 +010079 command_nr::START_ADVERTISING,
Woyten4f5bc412019-11-21 23:36:58 +010080 pdu_type,
81 interval,
Woyten22bc2542019-11-15 23:18:40 +010082 )?;
83 Ok(())
Philipp Vollmere04578a2018-01-09 21:18:10 +010084 }
Philipp Vollmere04578a2018-01-09 21:18:10 +010085}
Philipp Vollmer41b91352018-02-05 09:55:54 +010086
torfmaster76c81942020-02-23 17:31:59 +010087struct BleCallback<'a> {
88 read_value: &'a Cell<Option<ScanBuffer>>,
89 shared_buffer: SharedMemory<'a>,
Woyten0833a042018-04-03 19:29:34 +020090}
91
torfmaster76c81942020-02-23 17:31:59 +010092pub(crate) type ScanBuffer = [u8; BUFFER_SIZE_SCAN];
Woyten0833a042018-04-03 19:29:34 +020093
torfmaster76c81942020-02-23 17:31:59 +010094const EMPTY_SCAN_BUFFER: ScanBuffer = [0; BUFFER_SIZE_SCAN];
Philipp Vollmer41b91352018-02-05 09:55:54 +010095
torfmaster97c5e722020-01-02 21:30:16 +010096#[non_exhaustive]
torfmaster76c81942020-02-23 17:31:59 +010097pub struct BleScanningDriverFactory;
98
99impl BleScanningDriverFactory {
torfmasterdc326a42020-02-26 23:17:59 +0100100 pub fn create_driver(&mut self) -> BleScanningDriver {
torfmaster76c81942020-02-23 17:31:59 +0100101 BleScanningDriver {
102 shared_buffer: EMPTY_SCAN_BUFFER,
103 read_value: Cell::new(None),
104 }
105 }
106}
107
108/// Uninitialized Ble Scanning Driver
109///
110/// Usage:
111/// ```no_run
112/// # use futures::stream::StreamExt;
113/// # use libtock::ble_parser;
114/// # use libtock::result::TockResult;
115/// # use libtock::simple_ble;
116/// # async fn doc() -> TockResult<()> {
117/// let mut drivers = libtock::retrieve_drivers()?;
118/// let led_driver = drivers.leds.init_driver()?;
torfmasterdc326a42020-02-26 23:17:59 +0100119/// let mut ble_scanning_driver_factory = drivers.ble_scanning;
torfmaster76c81942020-02-23 17:31:59 +0100120/// let mut ble_scanning_driver = ble_scanning_driver_factory.create_driver();
121/// let mut ble_scanning_driver_sharing = ble_scanning_driver.share_memory()?;
122/// let ble_scanning_driver_scanning = ble_scanning_driver_sharing.start()?;
123///
124/// let value = ble_scanning_driver_scanning.stream_values().await;
125/// # Ok(())
126/// # }
127/// ```
128pub struct BleScanningDriver {
129 shared_buffer: ScanBuffer,
130 read_value: Cell<Option<ScanBuffer>>,
131}
Philipp Vollmerc7eec1f2018-02-10 18:06:04 +0100132
torfmaster595d9c62019-12-27 18:15:31 +0100133impl BleScanningDriver {
torfmaster76c81942020-02-23 17:31:59 +0100134 /// Prepare Ble Scanning Driver to share memory with the ble capsule
135 pub fn share_memory(&mut self) -> TockResult<BleScanningDriverShared> {
136 let shared_buffer: SharedMemory = syscalls::allow(
137 DRIVER_NUMBER,
138 allow_nr::ALLOW_SCAN_BUFFER,
139 &mut self.shared_buffer,
140 )
141 .map_err(Into::<TockError>::into)?;
142 Ok(BleScanningDriverShared {
143 read_value: &self.read_value,
144 callback: BleCallback {
145 read_value: &self.read_value,
146 shared_buffer,
147 },
148 })
Philipp Vollmera4ab6592018-04-14 15:01:27 +0200149 }
torfmaster76c81942020-02-23 17:31:59 +0100150}
Philipp Vollmera4ab6592018-04-14 15:01:27 +0200151
torfmaster76c81942020-02-23 17:31:59 +0100152/// Ble Scanning Driver in "shared buffer" state
153pub struct BleScanningDriverShared<'a> {
154 callback: BleCallback<'a>,
155 read_value: &'a Cell<Option<ScanBuffer>>,
156}
Philipp Vollmer45190922018-03-09 19:48:58 +0100157
torfmaster76c81942020-02-23 17:31:59 +0100158impl<'a> BleScanningDriverShared<'a> {
159 /// Start scanning for ble advertising events
160 pub fn start(&mut self) -> TockResult<BleScanningDriverScanning> {
161 let subscription = syscalls::subscribe::<BleCallback<'a>, BleCallback<'a>>(
Woytend007bb92019-12-01 15:22:08 +0100162 DRIVER_NUMBER,
163 subscribe_nr::BLE_PASSIVE_SCAN_SUB,
torfmaster76c81942020-02-23 17:31:59 +0100164 &mut self.callback,
Woytend007bb92019-12-01 15:22:08 +0100165 )?;
torfmaster9d7ff2a2019-12-28 13:45:55 +0100166 syscalls::command(DRIVER_NUMBER, command_nr::PASSIVE_SCAN, 1, 0)?;
torfmaster76c81942020-02-23 17:31:59 +0100167 Ok(BleScanningDriverScanning {
168 _subscription: subscription,
169 read_value: self.read_value,
170 })
171 }
172}
173
174/// Ble Scanning Driver in "scanning" state
175pub struct BleScanningDriverScanning<'a> {
176 _subscription: CallbackSubscription<'a>,
177 read_value: &'a Cell<Option<ScanBuffer>>,
178}
179
180impl<'a> BleScanningDriverScanning<'a> {
181 /// Create stream of ble scanning packets
182 pub fn stream_values(&'a self) -> impl Future<Output = ScanBuffer> + 'a {
183 crate::futures::wait_for_value(move || {
184 if let Some(temp_buffer) = self.read_value.get() {
185 self.read_value.set(None);
186 Some(temp_buffer)
187 } else {
188 None
189 }
190 })
191 }
192}
193
194impl<'a> Consumer<Self> for BleCallback<'a> {
195 fn consume(callback: &mut Self, _: usize, _: usize, _: usize) {
196 let mut temporary_buffer: ScanBuffer = EMPTY_SCAN_BUFFER;
197
198 callback.shared_buffer.read_bytes(&mut temporary_buffer[..]);
199 callback.read_value.set(Some(temporary_buffer));
Philipp Vollmer41b91352018-02-05 09:55:54 +0100200 }
201}