1use std::collections::{HashMap, HashSet};
4use std::marker::PhantomData;
5
6use bluer::{AdapterEvent, DeviceProperty};
7use futures::FutureExt;
8use futures::StreamExt;
9
10impl super::BluetoothRfcommConnectableAsyncTrait for bluer::rfcomm::ConnectRequest {
11 async fn accept(self) -> Result<crate::BluetoothStream, String> {
12 bluer::rfcomm::ConnectRequest::accept(self)
13 .map(|a| crate::BluetoothStream::Bluez(Box::pin(a)))
14 .map_err(|e| e.to_string())
15 }
16}
17
18impl super::BluetoothRfcommProfileAsyncTrait for bluer::rfcomm::ProfileHandle {
19 async fn connectable(&mut self) -> Result<crate::BluetoothRfcommConnectableAsync, String> {
20 self.next()
21 .await
22 .map(|a| crate::BluetoothRfcommConnectableAsync::Bluez(a))
23 .ok_or("Failed to get bluetooth connection".to_string())
24 }
25}
26
27impl super::BluetoothDeviceTrait for bluer::Device {
28 fn run_sdp(&mut self) {
29 todo!()
30 }
31
32 #[doc = " Get all known uuids for this device"]
33 fn get_uuids(&mut self) -> Result<Vec<crate::BluetoothUuid>, std::io::Error> {
34 todo!()
35 }
36
37 #[doc = " Retrieve the device name"]
38 fn get_name(&self) -> Result<String, std::io::Error> {
39 todo!()
40 }
41
42 #[doc = " Retrieve the device address"]
43 fn get_address(&mut self) -> Result<String, std::io::Error> {
44 todo!()
45 }
46
47 #[doc = " Retrieve the device pairing (bonding) status"]
48 fn get_pair_state(&self) -> Result<crate::PairingStatus, std::io::Error> {
49 todo!()
50 }
51
52 #[doc = " Attempt to get an rfcomm socket for the given uuid and seciruty setting"]
53 fn get_l2cap_socket(
54 &mut self,
55 uuid: crate::BluetoothUuid,
56 is_secure: bool,
57 ) -> Result<crate::BluetoothSocket, String> {
58 todo!()
59 }
60
61 #[doc = " Attempt to get an rfcomm socket for the given uuid and seciruty setting"]
62 fn get_rfcomm_socket(
63 &mut self,
64 uuid: crate::BluetoothUuid,
65 is_secure: bool,
66 ) -> Result<crate::BluetoothSocket, String> {
67 todo!()
68 }
69}
70
71pub struct BluetoothRfcommSocket {
73 inner: u32,
75}
76
77pub struct BluetoothDiscovery {}
79
80impl BluetoothDiscovery {
81 fn new() -> Self {
83 Self {}
84 }
85}
86
87impl super::BluetoothDiscoveryTrait for BluetoothDiscovery {}
88
89impl Drop for BluetoothDiscovery {
90 fn drop(&mut self) {}
91}
92
93pub struct BluetoothHandler {
95 session: bluer::Session,
97 adapters: Vec<bluer::Adapter>,
99 _blue_agent_handle: bluer::agent::AgentHandle,
101}
102
103impl TryFrom<super::BluetoothRfcommProfileSettings> for bluer::rfcomm::Profile {
104 type Error = String;
105 fn try_from(value: super::BluetoothRfcommProfileSettings) -> Result<Self, Self::Error> {
106 let service = if let Some(v) = value.service_uuid {
107 Some(bluer::Uuid::parse_str(&v).map_err(|e| e.to_string())?)
108 } else {
109 None
110 };
111 Ok(Self {
112 uuid: bluer::Uuid::parse_str(&value.uuid).map_err(|e| e.to_string())?,
113 name: value.name,
114 service,
115 role: None,
116 channel: value.channel,
117 psm: value.psm,
118 require_authentication: value.authenticate,
119 require_authorization: value.authorize,
120 auto_connect: value.auto_connect,
121 service_record: value.sdp_record,
122 version: value.sdp_version,
123 features: value.sdp_features,
124 ..Default::default()
125 })
126 }
127}
128
129impl super::BluetoothAdapterTrait for BluetoothHandler {
130 fn supports_async(&mut self) -> Option<&mut dyn super::AsyncBluetoothAdapterTrait> {
131 Some(self)
132 }
133
134 fn supports_sync(&mut self) -> Option<&mut dyn super::SyncBluetoothAdapterTrait> {
135 None
136 }
137}
138
139#[async_trait::async_trait]
140impl super::AsyncBluetoothAdapterTrait for BluetoothHandler {
141 async fn register_l2cap_profile(
142 &self,
143 settings: super::BluetoothL2capProfileSettings,
144 ) -> Result<crate::BluetoothL2capProfileAsync, String> {
145 todo!()
146 }
147
148 async fn register_rfcomm_profile(
149 &self,
150 settings: super::BluetoothRfcommProfileSettings,
151 ) -> Result<crate::BluetoothRfcommProfileAsync, String> {
152 self.session
153 .register_profile(settings.try_into()?)
154 .await
155 .map(|a| super::BluetoothRfcommProfileAsync::Bluez(a.into()))
156 .map_err(|e| e.to_string())
157 }
158
159 fn start_discovery(&self) -> crate::BluetoothDiscovery {
160 BluetoothDiscovery::new().into()
161 }
162
163 fn get_paired_devices(&self) -> Option<Vec<crate::BluetoothDevice>> {
164 let list = Vec::new();
165 for adapter in &self.adapters {
166 todo!();
167 }
168 Some(list)
169 }
170
171 async fn addresses(&self) -> Vec<super::BluetoothAdapterAddress> {
172 let mut a = Vec::new();
173 for adapter in &self.adapters {
174 if let Ok(adr) = adapter.address().await {
175 a.push(super::BluetoothAdapterAddress::Byte(adr.0));
176 }
177 }
178 a
179 }
180
181 async fn set_discoverable(&self, d: bool) -> Result<(), ()> {
182 for adapter in &self.adapters {
183 adapter.set_discoverable(d).await.map_err(|_| ())?;
184 }
185 Ok(())
186 }
187}
188
189impl BluetoothHandler {
190 pub async fn addresses(&self) -> Vec<bluer::Address> {
192 let mut addrs = Vec::new();
193 for a in &self.adapters {
194 if let Ok(addr) = a.address().await {
195 addrs.push(addr);
196 }
197 }
198 addrs
199 }
200
201 pub async fn new(
203 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
204 ) -> Result<Self, String> {
205 let session = bluer::Session::new().await.map_err(|e| e.to_string())?;
206
207 let adapter_names = session.adapter_names().await.map_err(|e| e.to_string())?;
208 let adapters: Vec<bluer::Adapter> = adapter_names
209 .iter()
210 .filter_map(|n| session.adapter(n).ok())
211 .collect();
212
213 let blue_agent = Self::build_agent(s);
214 let blue_agent_handle = session.register_agent(blue_agent).await;
215 println!("Registered a bluetooth agent {}", blue_agent_handle.is_ok());
216 Ok(Self {
217 session,
218 adapters,
219 _blue_agent_handle: blue_agent_handle.map_err(|e| e.to_string())?,
220 })
221 }
222
223 async fn enable(&mut self) {
225 for adapter in &self.adapters {
226 adapter.set_powered(true).await.unwrap();
227 adapter.set_pairable(true).await.unwrap();
228 }
229 }
230
231 async fn disable(&mut self) {
233 self.set_discoverable(false).await;
234 for adapter in &self.adapters {
235 adapter.set_powered(false).await.unwrap();
236 adapter.set_pairable(false).await.unwrap();
237 }
238 }
239
240 pub async fn set_discoverable(&mut self, d: bool) {
242 for adapter in &self.adapters {
243 adapter.set_discoverable(d).await.unwrap();
244 }
245 }
246
247 pub async fn register_rfcomm_profile(
249 &mut self,
250 profile: bluer::rfcomm::Profile,
251 ) -> Result<bluer::rfcomm::ProfileHandle, bluer::Error> {
252 self.session.register_profile(profile).await
253 }
254
255 fn build_agent(
257 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
258 ) -> bluer::agent::Agent {
259 let mut blue_agent = bluer::agent::Agent::default();
260 blue_agent.request_default = true;
261 blue_agent.request_pin_code = None;
262 blue_agent.request_passkey = None;
263 let s2 = s.clone();
264 blue_agent.display_passkey = Some(Box::new(move |mut a| {
265 println!("Running process for display_passkey: {:?}", a);
266 let s3 = s2.clone();
267 async move {
268 let mut chan = tokio::sync::mpsc::channel(5);
269 let _ = s3.send(super::MessageToBluetoothHost::DisplayPasskey(a.passkey, chan.0)).await;
270 loop {
271 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
272 tokio::select! {
273 asdf = f => {
274 match asdf {
275 Ok(Some(m)) => {
276 match m {
277 super::ResponseToPasskey::Yes => {
278 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
279 return Ok(());
280 }
281 super::ResponseToPasskey::No => {
282 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
283 return Err(bluer::agent::ReqError::Rejected);
284 }
285 super::ResponseToPasskey::Cancel => {
286 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
287 return Err(bluer::agent::ReqError::Canceled);
288 }
289 super::ResponseToPasskey::Waiting => {}
290 }
291 }
292 Ok(None) => {}
293 _ => {
294 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
295 return Err(bluer::agent::ReqError::Canceled);
296 }
297 }
298 }
299 _ = &mut a.cancel => {
300 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
301 break Err(bluer::agent::ReqError::Canceled);
302 }
303 }
304 }
305 }
306 .boxed()
307 }));
308 blue_agent.display_pin_code = Some(Box::new(|a| {
309 async move {
310 println!("Need to display pin code {:?}", a);
311 a.cancel.await.unwrap();
312 Ok(())
313 }
314 .boxed()
315 }));
316 let s2 = s.clone();
317 blue_agent.request_confirmation = Some(Box::new(move |a| {
318 println!("Need to confirm {:?}", a);
319 let s3 = s2.clone();
320 async move {
321 let mut chan = tokio::sync::mpsc::channel(5);
322 let _ = s3
323 .send(super::MessageToBluetoothHost::ConfirmPasskey(
324 a.passkey, chan.0,
325 ))
326 .await;
327 loop {
328 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
329 let asdf = f.await;
330 match asdf {
331 Ok(Some(m)) => match m {
332 super::ResponseToPasskey::Yes => {
333 let _ = s3
334 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
335 .await;
336 return Ok(());
337 }
338 super::ResponseToPasskey::No => {
339 let _ = s3
340 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
341 .await;
342 return Err(bluer::agent::ReqError::Rejected);
343 }
344 super::ResponseToPasskey::Cancel => {
345 let _ = s3
346 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
347 .await;
348 return Err(bluer::agent::ReqError::Canceled);
349 }
350 super::ResponseToPasskey::Waiting => {}
351 },
352 Ok(None) => {}
353 _ => {
354 let _ = s3
355 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
356 .await;
357 return Err(bluer::agent::ReqError::Canceled);
358 }
359 }
360 }
361 }
362 .boxed()
363 }));
364 blue_agent.request_authorization = Some(Box::new(|a| {
365 async move {
366 println!("Need to authorize {:?}", a);
367 Ok(())
368 }
369 .boxed()
370 }));
371 blue_agent.authorize_service = Some(Box::new(|a| {
372 async move {
373 println!("Need to authorize service {:?}", a);
374 Ok(())
375 }
376 .boxed()
377 }));
378 blue_agent
379 }
380
381 pub async fn issue_command(
383 &mut self,
384 cmd: super::BluetoothCommand,
385 ) -> Option<super::BluetoothResponse> {
386 match cmd {
387 super::BluetoothCommand::QueryNumAdapters => {
388 Some(super::BluetoothResponse::Adapters(0))
389 }
390 _ => None,
391 }
392 }
393
394 pub async fn scan<'a>(
396 &'a mut self,
397 bluetooth_devices: &mut HashMap<
398 bluer::Address,
399 (&'a bluer::Adapter, Option<bluer::Device>),
400 >,
401 ) {
402 let mut adapter_scanner = Vec::new();
403 for a in &self.adapters {
404 let da = a.discover_devices_with_changes().await.unwrap();
405 adapter_scanner.push((a, da));
406 }
407
408 for (adapt, da) in &mut adapter_scanner {
409 if let Some(e) = da.next().await {
410 match e {
411 AdapterEvent::DeviceAdded(addr) => {
412 println!("Device added {:?}", addr);
413 bluetooth_devices.insert(addr, (adapt, None));
414 }
415 AdapterEvent::DeviceRemoved(addr) => {
416 println!("Device removed {:?}", addr);
417 bluetooth_devices.remove_entry(&addr);
418 }
419 AdapterEvent::PropertyChanged(prop) => {
420 println!("Property changed {:?}", prop);
421 }
422 }
423 }
424 }
425 for (addr, (adapter, dev)) in bluetooth_devices {
426 if dev.is_none() {
427 if let Ok(d) = adapter.device(*addr) {
428 if let Ok(ps) = d.all_properties().await {
429 for p in ps {}
430 }
431 *dev = Some(d);
432 }
433 }
434 }
435 }
436}