1use std::error::Error;
6use std::sync::Arc;
7
8#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
9use blurdroid::bluetooth_adapter::Adapter as BluetoothAdapterAndroid;
10#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
11use blurdroid::bluetooth_device::Device as BluetoothDeviceAndroid;
12#[cfg(all(target_os = "android", feature = "native-bluetooth"))]
13use blurdroid::bluetooth_discovery_session::DiscoverySession as BluetoothDiscoverySessionAndroid;
14#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
15use blurmac::BluetoothAdapter as BluetoothAdapterMac;
16#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
17use blurmac::BluetoothDevice as BluetoothDeviceMac;
18#[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
19use blurmac::BluetoothDiscoverySession as BluetoothDiscoverySessionMac;
20#[cfg(feature = "bluetooth-test")]
21use blurmock::fake_adapter::FakeBluetoothAdapter;
22#[cfg(feature = "bluetooth-test")]
23use blurmock::fake_device::FakeBluetoothDevice;
24#[cfg(feature = "bluetooth-test")]
25use blurmock::fake_discovery_session::FakeBluetoothDiscoverySession;
26#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
27use blurz::bluetooth_adapter::BluetoothAdapter as BluetoothAdapterBluez;
28#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
29use blurz::bluetooth_device::BluetoothDevice as BluetoothDeviceBluez;
30#[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
31use blurz::bluetooth_discovery_session::BluetoothDiscoverySession as BluetoothDiscoverySessionBluez;
32
33use super::bluetooth::{BluetoothDevice, BluetoothDiscoverySession};
34#[cfg(not(any(
35 all(target_os = "linux", feature = "native-bluetooth"),
36 all(target_os = "android", feature = "native-bluetooth"),
37 all(target_os = "macos", feature = "native-bluetooth")
38)))]
39use super::empty::BluetoothDevice as BluetoothDeviceEmpty;
40#[cfg(not(any(
41 all(target_os = "linux", feature = "native-bluetooth"),
42 all(target_os = "android", feature = "native-bluetooth"),
43 all(target_os = "macos", feature = "native-bluetooth")
44)))]
45use super::empty::BluetoothDiscoverySession as BluetoothDiscoverySessionEmpty;
46#[cfg(not(any(
47 all(target_os = "linux", feature = "native-bluetooth"),
48 all(target_os = "android", feature = "native-bluetooth"),
49 all(target_os = "macos", feature = "native-bluetooth")
50)))]
51use super::empty::EmptyAdapter as BluetoothAdapterEmpty;
52use super::macros::get_inner_and_call;
53#[cfg(feature = "bluetooth-test")]
54use super::macros::get_inner_and_call_test_func;
55
56#[derive(Clone, Debug)]
57pub enum BluetoothAdapter {
58 #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
59 Bluez(Arc<BluetoothAdapterBluez>),
60 #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
61 Android(Arc<BluetoothAdapterAndroid>),
62 #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
63 Mac(Arc<BluetoothAdapterMac>),
64 #[cfg(not(any(
65 all(target_os = "linux", feature = "native-bluetooth"),
66 all(target_os = "android", feature = "native-bluetooth"),
67 all(target_os = "macos", feature = "native-bluetooth")
68 )))]
69 Empty(Arc<BluetoothAdapterEmpty>),
70 #[cfg(feature = "bluetooth-test")]
71 Mock(Arc<FakeBluetoothAdapter>),
72}
73
74impl BluetoothAdapter {
75 #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
76 pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
77 let bluez_adapter = BluetoothAdapterBluez::init()?;
78 Ok(Self::Bluez(Arc::new(bluez_adapter)))
79 }
80
81 #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
82 pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
83 let blurdroid_adapter = BluetoothAdapterAndroid::get_adapter()?;
84 Ok(Self::Android(Arc::new(blurdroid_adapter)))
85 }
86
87 #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
88 pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
89 let mac_adapter = BluetoothAdapterMac::init()?;
90 Ok(Self::Mac(Arc::new(mac_adapter)))
91 }
92
93 #[cfg(not(any(
94 all(target_os = "linux", feature = "native-bluetooth"),
95 all(target_os = "android", feature = "native-bluetooth"),
96 all(target_os = "macos", feature = "native-bluetooth")
97 )))]
98 pub fn new() -> Result<BluetoothAdapter, Box<dyn Error>> {
99 let adapter = BluetoothAdapterEmpty::init()?;
100 Ok(Self::Empty(Arc::new(adapter)))
101 }
102
103 #[cfg(feature = "bluetooth-test")]
104 pub fn new_mock() -> Result<BluetoothAdapter, Box<dyn Error>> {
105 Ok(Self::Mock(FakeBluetoothAdapter::new_empty()))
106 }
107
108 pub fn get_id(&self) -> String {
109 get_inner_and_call!(self, BluetoothAdapter, get_id)
110 }
111
112 pub fn get_devices(&self) -> Result<Vec<BluetoothDevice>, Box<dyn Error>> {
113 match self {
114 #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
115 BluetoothAdapter::Bluez(inner) => {
116 let device_list = inner.get_device_list()?;
117 Ok(device_list
118 .into_iter()
119 .map(|device| BluetoothDevice::Bluez(BluetoothDeviceBluez::new(device).into()))
120 .collect())
121 },
122 #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
123 BluetoothAdapter::Android(inner) => {
124 let device_list = inner.get_device_list()?;
125 Ok(device_list
126 .into_iter()
127 .map(|device| {
128 BluetoothDevice::Android(BluetoothDeviceAndroid::new_empty(
129 self.0.clone(),
130 device,
131 ))
132 })
133 .collect())
134 },
135 #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
136 BluetoothAdapter::Mac(inner) => {
137 let device_list = inner.get_device_list()?;
138 Ok(device_list
139 .into_iter()
140 .map(|device| {
141 BluetoothDevice::Mac(Arc::new(BluetoothDeviceMac::new(
142 inner.clone(),
143 device,
144 )))
145 })
146 .collect())
147 },
148 #[cfg(not(any(
149 all(target_os = "linux", feature = "native-bluetooth"),
150 all(target_os = "android", feature = "native-bluetooth"),
151 all(target_os = "macos", feature = "native-bluetooth")
152 )))]
153 BluetoothAdapter::Empty(inner) => {
154 let device_list = inner.get_device_list()?;
155 Ok(device_list
156 .into_iter()
157 .map(|device| {
158 BluetoothDevice::Empty(Arc::new(BluetoothDeviceEmpty::new(device)))
159 })
160 .collect())
161 },
162 #[cfg(feature = "bluetooth-test")]
163 BluetoothAdapter::Mock(inner) => {
164 let device_list = inner.get_device_list()?;
165 Ok(device_list
166 .into_iter()
167 .map(|device| {
168 BluetoothDevice::Mock(FakeBluetoothDevice::new_empty(inner.clone(), device))
169 })
170 .collect())
171 },
172 }
173 }
174
175 pub fn get_device(&self, address: String) -> Result<Option<BluetoothDevice>, Box<dyn Error>> {
176 let devices = self.get_devices()?;
177 for device in devices {
178 if device.get_address()? == address {
179 return Ok(Some(device));
180 }
181 }
182 Ok(None)
183 }
184
185 pub fn create_mock_device(&self, _device: String) -> Result<BluetoothDevice, Box<dyn Error>> {
186 match self {
187 #[cfg(feature = "bluetooth-test")]
188 BluetoothAdapter::Mock(inner) => Ok(BluetoothDevice::Mock(
189 FakeBluetoothDevice::new_empty(inner.clone(), _device),
190 )),
191 _ => Err(Box::from(
192 "Error! Test functions are not supported on real devices!",
193 )),
194 }
195 }
196
197 pub fn create_discovery_session(&self) -> Result<BluetoothDiscoverySession, Box<dyn Error>> {
198 let discovery_session = match self {
199 #[cfg(all(target_os = "linux", feature = "native-bluetooth"))]
200 #[allow(clippy::arc_with_non_send_sync)] BluetoothAdapter::Bluez(inner) => BluetoothDiscoverySession::Bluez(Arc::new(
202 BluetoothDiscoverySessionBluez::create_session(inner.get_id())?,
203 )),
204 #[cfg(all(target_os = "android", feature = "native-bluetooth"))]
205 BluetoothAdapter::Android(inner) => BluetoothDiscoverySession::Android(Arc::new(
206 BluetoothDiscoverySessionAndroid::create_session(inner.clone())?,
207 )),
208 #[cfg(all(target_os = "macos", feature = "native-bluetooth"))]
209 BluetoothAdapter::Mac(_) => {
210 BluetoothDiscoverySession::Mac(Arc::new(BluetoothDiscoverySessionMac {}))
211 },
212 #[cfg(not(any(
213 all(target_os = "linux", feature = "native-bluetooth"),
214 all(target_os = "android", feature = "native-bluetooth"),
215 all(target_os = "macos", feature = "native-bluetooth")
216 )))]
217 BluetoothAdapter::Empty(_) => {
218 BluetoothDiscoverySession::Empty(Arc::new(BluetoothDiscoverySessionEmpty {}))
219 },
220 #[cfg(feature = "bluetooth-test")]
221 BluetoothAdapter::Mock(inner) => BluetoothDiscoverySession::Mock(Arc::new(
222 FakeBluetoothDiscoverySession::create_session(inner.clone())?,
223 )),
224 };
225 Ok(discovery_session)
226 }
227
228 pub fn get_address(&self) -> Result<String, Box<dyn Error>> {
229 get_inner_and_call!(self, BluetoothAdapter, get_address)
230 }
231
232 pub fn get_name(&self) -> Result<String, Box<dyn Error>> {
233 get_inner_and_call!(self, BluetoothAdapter, get_name)
234 }
235
236 pub fn get_alias(&self) -> Result<String, Box<dyn Error>> {
237 get_inner_and_call!(self, BluetoothAdapter, get_alias)
238 }
239
240 pub fn get_class(&self) -> Result<u32, Box<dyn Error>> {
241 get_inner_and_call!(self, BluetoothAdapter, get_class)
242 }
243
244 pub fn is_powered(&self) -> Result<bool, Box<dyn Error>> {
245 get_inner_and_call!(self, BluetoothAdapter, is_powered)
246 }
247
248 pub fn is_discoverable(&self) -> Result<bool, Box<dyn Error>> {
249 get_inner_and_call!(self, BluetoothAdapter, is_discoverable)
250 }
251
252 pub fn is_pairable(&self) -> Result<bool, Box<dyn Error>> {
253 get_inner_and_call!(self, BluetoothAdapter, is_pairable)
254 }
255
256 pub fn get_pairable_timeout(&self) -> Result<u32, Box<dyn Error>> {
257 get_inner_and_call!(self, BluetoothAdapter, get_pairable_timeout)
258 }
259
260 pub fn get_discoverable_timeout(&self) -> Result<u32, Box<dyn Error>> {
261 get_inner_and_call!(self, BluetoothAdapter, get_discoverable_timeout)
262 }
263
264 pub fn is_discovering(&self) -> Result<bool, Box<dyn Error>> {
265 get_inner_and_call!(self, BluetoothAdapter, is_discovering)
266 }
267
268 pub fn get_uuids(&self) -> Result<Vec<String>, Box<dyn Error>> {
269 get_inner_and_call!(self, BluetoothAdapter, get_uuids)
270 }
271
272 pub fn get_vendor_id_source(&self) -> Result<String, Box<dyn Error>> {
273 get_inner_and_call!(self, BluetoothAdapter, get_vendor_id_source)
274 }
275
276 pub fn get_vendor_id(&self) -> Result<u32, Box<dyn Error>> {
277 get_inner_and_call!(self, BluetoothAdapter, get_vendor_id)
278 }
279
280 pub fn get_product_id(&self) -> Result<u32, Box<dyn Error>> {
281 get_inner_and_call!(self, BluetoothAdapter, get_product_id)
282 }
283
284 pub fn get_device_id(&self) -> Result<u32, Box<dyn Error>> {
285 get_inner_and_call!(self, BluetoothAdapter, get_device_id)
286 }
287
288 pub fn get_modalias(&self) -> Result<(String, u32, u32, u32), Box<dyn Error>> {
289 get_inner_and_call!(self, BluetoothAdapter, get_modalias)
290 }
291
292 #[cfg(feature = "bluetooth-test")]
293 pub fn set_id(&self, id: String) -> Result<(), Box<dyn Error>> {
294 match self {
295 #[cfg(feature = "bluetooth-test")]
296 BluetoothAdapter::Mock(inner) => {
297 inner.set_id(id);
298 Ok(())
299 },
300 _ => Err(Box::from(
301 "Error! Test functions are not supported on real devices!",
302 )),
303 }
304 }
305
306 #[cfg(feature = "bluetooth-test")]
307 pub fn set_address(&self, address: String) -> Result<(), Box<dyn Error>> {
308 get_inner_and_call_test_func!(self, BluetoothAdapter, set_address, address)
309 }
310
311 #[cfg(feature = "bluetooth-test")]
312 pub fn set_name(&self, name: String) -> Result<(), Box<dyn Error>> {
313 get_inner_and_call_test_func!(self, BluetoothAdapter, set_name, name)
314 }
315
316 #[cfg(feature = "bluetooth-test")]
317 pub fn set_alias(&self, alias: String) -> Result<(), Box<dyn Error>> {
318 get_inner_and_call_test_func!(self, BluetoothAdapter, set_alias, alias)
319 }
320
321 #[cfg(feature = "bluetooth-test")]
322 pub fn set_class(&self, class: u32) -> Result<(), Box<dyn Error>> {
323 get_inner_and_call_test_func!(self, BluetoothAdapter, set_class, class)
324 }
325
326 #[cfg(feature = "bluetooth-test")]
327 pub fn set_powered(&self, powered: bool) -> Result<(), Box<dyn Error>> {
328 get_inner_and_call_test_func!(self, BluetoothAdapter, set_powered, powered)
329 }
330
331 #[cfg(feature = "bluetooth-test")]
332 pub fn is_present(&self) -> Result<bool, Box<dyn Error>> {
333 get_inner_and_call_test_func!(self, BluetoothAdapter, is_present)
334 }
335
336 #[cfg(feature = "bluetooth-test")]
337 pub fn set_present(&self, present: bool) -> Result<(), Box<dyn Error>> {
338 get_inner_and_call_test_func!(self, BluetoothAdapter, set_present, present)
339 }
340
341 #[cfg(feature = "bluetooth-test")]
342 pub fn set_discoverable(&self, discoverable: bool) -> Result<(), Box<dyn Error>> {
343 get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable, discoverable)
344 }
345
346 #[cfg(feature = "bluetooth-test")]
347 pub fn set_pairable(&self, pairable: bool) -> Result<(), Box<dyn Error>> {
348 get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable, pairable)
349 }
350
351 #[cfg(feature = "bluetooth-test")]
352 pub fn set_pairable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
353 get_inner_and_call_test_func!(self, BluetoothAdapter, set_pairable_timeout, timeout)
354 }
355
356 #[cfg(feature = "bluetooth-test")]
357 pub fn set_can_start_discovery(&self, can_start_discovery: bool) -> Result<(), Box<dyn Error>> {
358 get_inner_and_call_test_func!(
359 self,
360 BluetoothAdapter,
361 set_can_start_discovery,
362 can_start_discovery
363 )
364 }
365
366 #[cfg(feature = "bluetooth-test")]
367 pub fn set_discoverable_timeout(&self, timeout: u32) -> Result<(), Box<dyn Error>> {
368 get_inner_and_call_test_func!(self, BluetoothAdapter, set_discoverable_timeout, timeout)
369 }
370
371 #[cfg(feature = "bluetooth-test")]
372 pub fn set_discovering(&self, discovering: bool) -> Result<(), Box<dyn Error>> {
373 get_inner_and_call_test_func!(self, BluetoothAdapter, set_discovering, discovering)
374 }
375
376 #[cfg(feature = "bluetooth-test")]
377 pub fn set_can_stop_discovery(&self, can_stop_discovery: bool) -> Result<(), Box<dyn Error>> {
378 get_inner_and_call_test_func!(
379 self,
380 BluetoothAdapter,
381 set_can_stop_discovery,
382 can_stop_discovery
383 )
384 }
385
386 #[cfg(feature = "bluetooth-test")]
387 pub fn set_uuids(&self, uuids: Vec<String>) -> Result<(), Box<dyn Error>> {
388 get_inner_and_call_test_func!(self, BluetoothAdapter, set_uuids, uuids)
389 }
390
391 #[cfg(feature = "bluetooth-test")]
392 pub fn set_modalias(&self, modalias: String) -> Result<(), Box<dyn Error>> {
393 get_inner_and_call_test_func!(self, BluetoothAdapter, set_modalias, modalias)
394 }
395
396 #[cfg(feature = "bluetooth-test")]
397 pub fn get_ad_datas(&self) -> Result<Vec<String>, Box<dyn Error>> {
398 get_inner_and_call_test_func!(self, BluetoothAdapter, get_ad_datas)
399 }
400
401 #[cfg(feature = "bluetooth-test")]
402 pub fn set_ad_datas(&self, ad_datas: Vec<String>) -> Result<(), Box<dyn Error>> {
403 get_inner_and_call_test_func!(self, BluetoothAdapter, set_ad_datas, ad_datas)
404 }
405}