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
77impl crate::BluetoothSocketTrait for &mut BluetoothRfcommSocket {
78 fn is_connected(&self) -> Result<bool, std::io::Error> {
79 todo!()
80 }
81
82 fn connect(&mut self) -> Result<(), std::io::Error> {
83 todo!()
84 }
85}
86
87pub struct BluetoothDiscovery {}
89
90impl BluetoothDiscovery {
91 fn new() -> Self {
93 Self {}
94 }
95}
96
97impl super::BluetoothDiscoveryTrait for BluetoothDiscovery {}
98
99impl Drop for BluetoothDiscovery {
100 fn drop(&mut self) {}
101}
102
103pub struct BluetoothHandler {
105 session: bluer::Session,
107 adapters: Vec<bluer::Adapter>,
109 _blue_agent_handle: bluer::agent::AgentHandle,
111}
112
113impl TryFrom<super::BluetoothRfcommProfileSettings> for bluer::rfcomm::Profile {
114 type Error = String;
115 fn try_from(value: super::BluetoothRfcommProfileSettings) -> Result<Self, Self::Error> {
116 let service = if let Some(v) = value.service_uuid {
117 Some(bluer::Uuid::parse_str(&v).map_err(|e| e.to_string())?)
118 } else {
119 None
120 };
121 Ok(Self {
122 uuid: bluer::Uuid::parse_str(&value.uuid).map_err(|e| e.to_string())?,
123 name: value.name,
124 service,
125 role: None,
126 channel: value.channel,
127 psm: value.psm,
128 require_authentication: value.authenticate,
129 require_authorization: value.authorize,
130 auto_connect: value.auto_connect,
131 service_record: value.sdp_record,
132 version: value.sdp_version,
133 features: value.sdp_features,
134 ..Default::default()
135 })
136 }
137}
138
139impl super::BluetoothAdapterTrait for BluetoothHandler {
140 fn supports_async(&mut self) -> Option<&mut dyn super::AsyncBluetoothAdapterTrait> {
141 Some(self)
142 }
143
144 fn supports_sync(&mut self) -> Option<&mut dyn super::SyncBluetoothAdapterTrait> {
145 None
146 }
147}
148
149#[async_trait::async_trait]
150impl super::AsyncBluetoothAdapterTrait for BluetoothHandler {
151 async fn register_l2cap_profile(
152 &self,
153 settings: super::BluetoothL2capProfileSettings,
154 ) -> Result<crate::BluetoothL2capProfileAsync, String> {
155 todo!()
156 }
157
158 async fn register_rfcomm_profile(
159 &self,
160 settings: super::BluetoothRfcommProfileSettings,
161 ) -> Result<crate::BluetoothRfcommProfileAsync, String> {
162 self.session
163 .register_profile(settings.try_into()?)
164 .await
165 .map(|a| super::BluetoothRfcommProfileAsync::Bluez(a.into()))
166 .map_err(|e| e.to_string())
167 }
168
169 fn start_discovery(&self) -> crate::BluetoothDiscovery {
170 BluetoothDiscovery::new().into()
171 }
172
173 fn get_paired_devices(&self) -> Option<Vec<crate::BluetoothDevice>> {
174 let list = Vec::new();
175 for adapter in &self.adapters {
176 todo!();
177 }
178 Some(list)
179 }
180
181 async fn addresses(&self) -> Vec<super::BluetoothAdapterAddress> {
182 let mut a = Vec::new();
183 for adapter in &self.adapters {
184 if let Ok(adr) = adapter.address().await {
185 a.push(super::BluetoothAdapterAddress::Byte(adr.0));
186 }
187 }
188 a
189 }
190
191 async fn set_discoverable(&self, d: bool) -> Result<(), ()> {
192 for adapter in &self.adapters {
193 adapter.set_discoverable(d).await.map_err(|_| ())?;
194 }
195 Ok(())
196 }
197}
198
199impl BluetoothHandler {
200 pub async fn addresses(&self) -> Vec<bluer::Address> {
202 let mut addrs = Vec::new();
203 for a in &self.adapters {
204 if let Ok(addr) = a.address().await {
205 addrs.push(addr);
206 }
207 }
208 addrs
209 }
210
211 pub async fn new(
213 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
214 ) -> Result<Self, String> {
215 let session = bluer::Session::new().await.map_err(|e| e.to_string())?;
216
217 let adapter_names = session.adapter_names().await.map_err(|e| e.to_string())?;
218 let adapters: Vec<bluer::Adapter> = adapter_names
219 .iter()
220 .filter_map(|n| session.adapter(n).ok())
221 .collect();
222
223 let blue_agent = Self::build_agent(s);
224 let blue_agent_handle = session.register_agent(blue_agent).await;
225 println!("Registered a bluetooth agent {}", blue_agent_handle.is_ok());
226 Ok(Self {
227 session,
228 adapters,
229 _blue_agent_handle: blue_agent_handle.map_err(|e| e.to_string())?,
230 })
231 }
232
233 async fn enable(&mut self) {
235 for adapter in &self.adapters {
236 adapter.set_powered(true).await.unwrap();
237 adapter.set_pairable(true).await.unwrap();
238 }
239 }
240
241 async fn disable(&mut self) {
243 self.set_discoverable(false).await;
244 for adapter in &self.adapters {
245 adapter.set_powered(false).await.unwrap();
246 adapter.set_pairable(false).await.unwrap();
247 }
248 }
249
250 pub async fn set_discoverable(&mut self, d: bool) {
252 for adapter in &self.adapters {
253 adapter.set_discoverable(d).await.unwrap();
254 }
255 }
256
257 pub async fn register_rfcomm_profile(
259 &mut self,
260 profile: bluer::rfcomm::Profile,
261 ) -> Result<bluer::rfcomm::ProfileHandle, bluer::Error> {
262 self.session.register_profile(profile).await
263 }
264
265 fn build_agent(
267 s: tokio::sync::mpsc::Sender<super::MessageToBluetoothHost>,
268 ) -> bluer::agent::Agent {
269 let mut blue_agent = bluer::agent::Agent::default();
270 blue_agent.request_default = true;
271 blue_agent.request_pin_code = None;
272 blue_agent.request_passkey = None;
273 let s2 = s.clone();
274 blue_agent.display_passkey = Some(Box::new(move |mut a| {
275 println!("Running process for display_passkey: {:?}", a);
276 let s3 = s2.clone();
277 async move {
278 let mut chan = tokio::sync::mpsc::channel(5);
279 let _ = s3.send(super::MessageToBluetoothHost::DisplayPasskey(a.passkey, chan.0)).await;
280 loop {
281 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
282 tokio::select! {
283 asdf = f => {
284 match asdf {
285 Ok(Some(m)) => {
286 match m {
287 super::ResponseToPasskey::Yes => {
288 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
289 return Ok(());
290 }
291 super::ResponseToPasskey::No => {
292 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
293 return Err(bluer::agent::ReqError::Rejected);
294 }
295 super::ResponseToPasskey::Cancel => {
296 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
297 return Err(bluer::agent::ReqError::Canceled);
298 }
299 super::ResponseToPasskey::Waiting => {}
300 }
301 }
302 Ok(None) => {}
303 _ => {
304 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
305 return Err(bluer::agent::ReqError::Canceled);
306 }
307 }
308 }
309 _ = &mut a.cancel => {
310 let _ = s3.send(super::MessageToBluetoothHost::CancelDisplayPasskey).await;
311 break Err(bluer::agent::ReqError::Canceled);
312 }
313 }
314 }
315 }
316 .boxed()
317 }));
318 blue_agent.display_pin_code = Some(Box::new(|a| {
319 async move {
320 println!("Need to display pin code {:?}", a);
321 a.cancel.await.unwrap();
322 Ok(())
323 }
324 .boxed()
325 }));
326 let s2 = s.clone();
327 blue_agent.request_confirmation = Some(Box::new(move |a| {
328 println!("Need to confirm {:?}", a);
329 let s3 = s2.clone();
330 async move {
331 let mut chan = tokio::sync::mpsc::channel(5);
332 let _ = s3
333 .send(super::MessageToBluetoothHost::ConfirmPasskey(
334 a.passkey, chan.0,
335 ))
336 .await;
337 loop {
338 let f = tokio::time::timeout(std::time::Duration::from_secs(5), chan.1.recv());
339 let asdf = f.await;
340 match asdf {
341 Ok(Some(m)) => match m {
342 super::ResponseToPasskey::Yes => {
343 let _ = s3
344 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
345 .await;
346 return Ok(());
347 }
348 super::ResponseToPasskey::No => {
349 let _ = s3
350 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
351 .await;
352 return Err(bluer::agent::ReqError::Rejected);
353 }
354 super::ResponseToPasskey::Cancel => {
355 let _ = s3
356 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
357 .await;
358 return Err(bluer::agent::ReqError::Canceled);
359 }
360 super::ResponseToPasskey::Waiting => {}
361 },
362 Ok(None) => {}
363 _ => {
364 let _ = s3
365 .send(super::MessageToBluetoothHost::CancelDisplayPasskey)
366 .await;
367 return Err(bluer::agent::ReqError::Canceled);
368 }
369 }
370 }
371 }
372 .boxed()
373 }));
374 blue_agent.request_authorization = Some(Box::new(|a| {
375 async move {
376 println!("Need to authorize {:?}", a);
377 Ok(())
378 }
379 .boxed()
380 }));
381 blue_agent.authorize_service = Some(Box::new(|a| {
382 async move {
383 println!("Need to authorize service {:?}", a);
384 Ok(())
385 }
386 .boxed()
387 }));
388 blue_agent
389 }
390
391 pub async fn issue_command(
393 &mut self,
394 cmd: super::BluetoothCommand,
395 ) -> Option<super::BluetoothResponse> {
396 match cmd {
397 super::BluetoothCommand::QueryNumAdapters => {
398 Some(super::BluetoothResponse::Adapters(0))
399 }
400 _ => None,
401 }
402 }
403
404 pub async fn scan<'a>(
406 &'a mut self,
407 bluetooth_devices: &mut HashMap<
408 bluer::Address,
409 (&'a bluer::Adapter, Option<bluer::Device>),
410 >,
411 ) {
412 let mut adapter_scanner = Vec::new();
413 for a in &self.adapters {
414 let da = a.discover_devices_with_changes().await.unwrap();
415 adapter_scanner.push((a, da));
416 }
417
418 for (adapt, da) in &mut adapter_scanner {
419 if let Some(e) = da.next().await {
420 match e {
421 AdapterEvent::DeviceAdded(addr) => {
422 println!("Device added {:?}", addr);
423 bluetooth_devices.insert(addr, (adapt, None));
424 }
425 AdapterEvent::DeviceRemoved(addr) => {
426 println!("Device removed {:?}", addr);
427 bluetooth_devices.remove_entry(&addr);
428 }
429 AdapterEvent::PropertyChanged(prop) => {
430 println!("Property changed {:?}", prop);
431 }
432 }
433 }
434 }
435 for (addr, (adapter, dev)) in bluetooth_devices {
436 if dev.is_none() {
437 if let Ok(d) = adapter.device(*addr) {
438 if let Ok(ps) = d.all_properties().await {
439 for p in ps {}
440 }
441 *dev = Some(d);
442 }
443 }
444 }
445 }
446}