torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 1 | //! Module to provide simple ble functions as scanning and advertising |
| 2 | |
Woyten | 30fc95b | 2019-01-10 21:09:46 +0100 | [diff] [blame] | 3 | use crate::ble_composer::BlePayload; |
| 4 | use crate::callback::CallbackSubscription; |
Woyten | d007bb9 | 2019-12-01 15:22:08 +0100 | [diff] [blame] | 5 | use crate::callback::Consumer; |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 6 | use crate::result::TockError; |
Woyten | 22bc254 | 2019-11-15 23:18:40 +0100 | [diff] [blame] | 7 | use crate::result::TockResult; |
Woyten | 30fc95b | 2019-01-10 21:09:46 +0100 | [diff] [blame] | 8 | use crate::shared_memory::SharedMemory; |
| 9 | use crate::syscalls; |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 10 | use core::cell::Cell; |
| 11 | use core::future::Future; |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 12 | |
Woyten | 9567d79 | 2018-02-04 00:11:39 +0100 | [diff] [blame] | 13 | const DRIVER_NUMBER: usize = 0x30000; |
Philipp Vollmer | 55570f2 | 2018-02-24 13:23:45 +0100 | [diff] [blame] | 14 | pub const MAX_PAYLOAD_SIZE: usize = 9; |
Philipp Vollmer | e057773 | 2018-04-19 17:36:49 +0200 | [diff] [blame] | 15 | pub const BUFFER_SIZE_ADVERTISE: usize = 39; |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 16 | pub(crate) const BUFFER_SIZE_SCAN: usize = 39; |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 17 | |
torfmaster | 9d7ff2a | 2019-12-28 13:45:55 +0100 | [diff] [blame] | 18 | mod command_nr { |
Woyten | 9567d79 | 2018-02-04 00:11:39 +0100 | [diff] [blame] | 19 | pub const START_ADVERTISING: usize = 0; |
Philipp Vollmer | 41b9135 | 2018-02-05 09:55:54 +0100 | [diff] [blame] | 20 | pub const PASSIVE_SCAN: usize = 5; |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 21 | } |
| 22 | |
torfmaster | 9d7ff2a | 2019-12-28 13:45:55 +0100 | [diff] [blame] | 23 | mod subscribe_nr { |
| 24 | pub const BLE_PASSIVE_SCAN_SUB: usize = 0; |
| 25 | } |
| 26 | |
| 27 | mod allow_nr { |
| 28 | pub const ALLOW_ADVERTISMENT_BUFFER: usize = 0; |
| 29 | pub const ALLOW_SCAN_BUFFER: usize = 1; |
| 30 | } |
| 31 | |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 32 | mod gap_flags { |
Philipp Vollmer | 090398c | 2018-06-29 15:14:54 +0200 | [diff] [blame] | 33 | pub const BLE_DISCOVERABLE: usize = 0x02; |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 34 | } |
| 35 | |
Philipp Vollmer | 349417d | 2018-02-24 17:29:19 +0100 | [diff] [blame] | 36 | pub mod gap_data { |
Woyten | 9567d79 | 2018-02-04 00:11:39 +0100 | [diff] [blame] | 37 | 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 Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 41 | } |
| 42 | |
torfmaster | 97c5e72 | 2020-01-02 21:30:16 +0100 | [diff] [blame] | 43 | #[non_exhaustive] |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 44 | pub struct BleAdvertisingDriverFactory; |
| 45 | |
| 46 | impl BleAdvertisingDriverFactory { |
torfmaster | dc326a4 | 2020-02-26 23:17:59 +0100 | [diff] [blame] | 47 | pub fn create_driver(&mut self) -> BleAdvertisingDriver { |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 48 | // Unfortunately, there is no way to check the availability of the ble advertising driver |
| 49 | BleAdvertisingDriver |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | #[non_exhaustive] |
torfmaster | 97c5e72 | 2020-01-02 21:30:16 +0100 | [diff] [blame] | 54 | pub struct BleAdvertisingDriver; |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 55 | |
Philipp Vollmer | 4519092 | 2018-03-09 19:48:58 +0100 | [diff] [blame] | 56 | impl BleAdvertisingDriver { |
Philipp Vollmer | e057773 | 2018-04-19 17:36:49 +0200 | [diff] [blame] | 57 | pub fn create_advertising_buffer() -> [u8; BUFFER_SIZE_ADVERTISE] { |
| 58 | [0; BUFFER_SIZE_ADVERTISE] |
Philipp Vollmer | a4ab659 | 2018-04-14 15:01:27 +0200 | [diff] [blame] | 59 | } |
Philipp Vollmer | e057773 | 2018-04-19 17:36:49 +0200 | [diff] [blame] | 60 | pub fn initialize<'a>( |
torfmaster | 1767981 | 2019-12-27 18:07:10 +0100 | [diff] [blame] | 61 | &'a mut self, |
Philipp Vollmer | 090398c | 2018-06-29 15:14:54 +0200 | [diff] [blame] | 62 | interval: usize, |
| 63 | service_payload: &BlePayload, |
Philipp Vollmer | e057773 | 2018-04-19 17:36:49 +0200 | [diff] [blame] | 64 | advertising_buffer: &'a mut [u8; BUFFER_SIZE_ADVERTISE], |
Woyten | 22bc254 | 2019-11-15 23:18:40 +0100 | [diff] [blame] | 65 | ) -> TockResult<SharedMemory<'a>> { |
Philipp Vollmer | 090398c | 2018-06-29 15:14:54 +0200 | [diff] [blame] | 66 | let mut shared_memory = syscalls::allow( |
Philipp Vollmer | a4ab659 | 2018-04-14 15:01:27 +0200 | [diff] [blame] | 67 | DRIVER_NUMBER, |
torfmaster | 9d7ff2a | 2019-12-28 13:45:55 +0100 | [diff] [blame] | 68 | allow_nr::ALLOW_ADVERTISMENT_BUFFER, |
Philipp Vollmer | a4ab659 | 2018-04-14 15:01:27 +0200 | [diff] [blame] | 69 | advertising_buffer, |
| 70 | )?; |
torfmaster | 906d297 | 2019-02-15 23:38:23 +0100 | [diff] [blame] | 71 | shared_memory.write_bytes(service_payload); |
Philipp Vollmer | 090398c | 2018-06-29 15:14:54 +0200 | [diff] [blame] | 72 | Self::start_advertising(gap_flags::BLE_DISCOVERABLE, interval)?; |
Philipp Vollmer | 4519092 | 2018-03-09 19:48:58 +0100 | [diff] [blame] | 73 | Ok(shared_memory) |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 74 | } |
| 75 | |
Woyten | 22bc254 | 2019-11-15 23:18:40 +0100 | [diff] [blame] | 76 | fn start_advertising(pdu_type: usize, interval: usize) -> TockResult<()> { |
| 77 | syscalls::command( |
Woyten | 4f5bc41 | 2019-11-21 23:36:58 +0100 | [diff] [blame] | 78 | DRIVER_NUMBER, |
torfmaster | 9d7ff2a | 2019-12-28 13:45:55 +0100 | [diff] [blame] | 79 | command_nr::START_ADVERTISING, |
Woyten | 4f5bc41 | 2019-11-21 23:36:58 +0100 | [diff] [blame] | 80 | pdu_type, |
| 81 | interval, |
Woyten | 22bc254 | 2019-11-15 23:18:40 +0100 | [diff] [blame] | 82 | )?; |
| 83 | Ok(()) |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 84 | } |
Philipp Vollmer | e04578a | 2018-01-09 21:18:10 +0100 | [diff] [blame] | 85 | } |
Philipp Vollmer | 41b9135 | 2018-02-05 09:55:54 +0100 | [diff] [blame] | 86 | |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 87 | struct BleCallback<'a> { |
| 88 | read_value: &'a Cell<Option<ScanBuffer>>, |
| 89 | shared_buffer: SharedMemory<'a>, |
Woyten | 0833a04 | 2018-04-03 19:29:34 +0200 | [diff] [blame] | 90 | } |
| 91 | |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 92 | pub(crate) type ScanBuffer = [u8; BUFFER_SIZE_SCAN]; |
Woyten | 0833a04 | 2018-04-03 19:29:34 +0200 | [diff] [blame] | 93 | |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 94 | const EMPTY_SCAN_BUFFER: ScanBuffer = [0; BUFFER_SIZE_SCAN]; |
Philipp Vollmer | 41b9135 | 2018-02-05 09:55:54 +0100 | [diff] [blame] | 95 | |
torfmaster | 97c5e72 | 2020-01-02 21:30:16 +0100 | [diff] [blame] | 96 | #[non_exhaustive] |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 97 | pub struct BleScanningDriverFactory; |
| 98 | |
| 99 | impl BleScanningDriverFactory { |
torfmaster | dc326a4 | 2020-02-26 23:17:59 +0100 | [diff] [blame] | 100 | pub fn create_driver(&mut self) -> BleScanningDriver { |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 101 | 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()?; |
torfmaster | dc326a4 | 2020-02-26 23:17:59 +0100 | [diff] [blame] | 119 | /// let mut ble_scanning_driver_factory = drivers.ble_scanning; |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 120 | /// 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 | /// ``` |
| 128 | pub struct BleScanningDriver { |
| 129 | shared_buffer: ScanBuffer, |
| 130 | read_value: Cell<Option<ScanBuffer>>, |
| 131 | } |
Philipp Vollmer | c7eec1f | 2018-02-10 18:06:04 +0100 | [diff] [blame] | 132 | |
torfmaster | 595d9c6 | 2019-12-27 18:15:31 +0100 | [diff] [blame] | 133 | impl BleScanningDriver { |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 134 | /// 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 Vollmer | a4ab659 | 2018-04-14 15:01:27 +0200 | [diff] [blame] | 149 | } |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 150 | } |
Philipp Vollmer | a4ab659 | 2018-04-14 15:01:27 +0200 | [diff] [blame] | 151 | |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 152 | /// Ble Scanning Driver in "shared buffer" state |
| 153 | pub struct BleScanningDriverShared<'a> { |
| 154 | callback: BleCallback<'a>, |
| 155 | read_value: &'a Cell<Option<ScanBuffer>>, |
| 156 | } |
Philipp Vollmer | 4519092 | 2018-03-09 19:48:58 +0100 | [diff] [blame] | 157 | |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 158 | impl<'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>>( |
Woyten | d007bb9 | 2019-12-01 15:22:08 +0100 | [diff] [blame] | 162 | DRIVER_NUMBER, |
| 163 | subscribe_nr::BLE_PASSIVE_SCAN_SUB, |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 164 | &mut self.callback, |
Woyten | d007bb9 | 2019-12-01 15:22:08 +0100 | [diff] [blame] | 165 | )?; |
torfmaster | 9d7ff2a | 2019-12-28 13:45:55 +0100 | [diff] [blame] | 166 | syscalls::command(DRIVER_NUMBER, command_nr::PASSIVE_SCAN, 1, 0)?; |
torfmaster | 76c8194 | 2020-02-23 17:31:59 +0100 | [diff] [blame] | 167 | Ok(BleScanningDriverScanning { |
| 168 | _subscription: subscription, |
| 169 | read_value: self.read_value, |
| 170 | }) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | /// Ble Scanning Driver in "scanning" state |
| 175 | pub struct BleScanningDriverScanning<'a> { |
| 176 | _subscription: CallbackSubscription<'a>, |
| 177 | read_value: &'a Cell<Option<ScanBuffer>>, |
| 178 | } |
| 179 | |
| 180 | impl<'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 | |
| 194 | impl<'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 Vollmer | 41b9135 | 2018-02-05 09:55:54 +0100 | [diff] [blame] | 200 | } |
| 201 | } |