@@ -11,17 +11,17 @@ extern crate rand;
1111#[ cfg( target_os = "linux" ) ]
1212extern crate tinyfiledialogs;
1313extern crate util;
14+ extern crate uuid;
15+
16+ pub mod test;
1417
1518use bluetooth_traits:: { BluetoothCharacteristicMsg , BluetoothCharacteristicsMsg } ;
1619use bluetooth_traits:: { BluetoothDescriptorMsg , BluetoothDescriptorsMsg } ;
1720use bluetooth_traits:: { BluetoothDeviceMsg , BluetoothError , BluetoothMethodMsg } ;
1821use bluetooth_traits:: { BluetoothResult , BluetoothServiceMsg , BluetoothServicesMsg } ;
1922use bluetooth_traits:: scanfilter:: { BluetoothScanfilter , BluetoothScanfilterSequence , RequestDeviceoptions } ;
20- use device:: bluetooth:: BluetoothAdapter ;
21- use device:: bluetooth:: BluetoothDevice ;
22- use device:: bluetooth:: BluetoothGATTCharacteristic ;
23- use device:: bluetooth:: BluetoothGATTDescriptor ;
24- use device:: bluetooth:: BluetoothGATTService ;
23+ use device:: bluetooth:: { BluetoothAdapter , BluetoothDevice , BluetoothGATTCharacteristic } ;
24+ use device:: bluetooth:: { BluetoothGATTDescriptor , BluetoothGATTService } ;
2525use ipc_channel:: ipc:: { self , IpcReceiver , IpcSender } ;
2626use rand:: Rng ;
2727use std:: borrow:: ToOwned ;
@@ -33,6 +33,8 @@ use util::thread::spawn_named;
3333
3434const ADAPTER_ERROR : & ' static str = "No adapter found" ;
3535
36+ const ADAPTER_NOT_POWERED_ERROR : & ' static str = "Bluetooth adapter not powered" ;
37+
3638// A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed.
3739// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480)
3840const MAXIMUM_TRANSACTION_TIME : u8 = 30 ;
@@ -71,7 +73,12 @@ macro_rules! return_if_cached(
7173macro_rules! get_adapter_or_return_error(
7274 ( $bl_manager: expr, $sender: expr) => (
7375 match $bl_manager. get_or_create_adapter( ) {
74- Some ( adapter) => adapter,
76+ Some ( adapter) => {
77+ if !adapter. is_powered( ) . unwrap_or( false ) {
78+ return drop( $sender. send( Err ( BluetoothError :: Type ( ADAPTER_NOT_POWERED_ERROR . to_string( ) ) ) ) )
79+ }
80+ adapter
81+ } ,
7582 None => return drop( $sender. send( Err ( BluetoothError :: Type ( ADAPTER_ERROR . to_string( ) ) ) ) ) ,
7683 }
7784 ) ;
@@ -155,6 +162,13 @@ fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequen
155162 return filters. iter ( ) . any ( |f| matches_filter ( device, f) )
156163}
157164
165+ fn is_mock_adapter ( adapter : & BluetoothAdapter ) -> bool {
166+ match adapter {
167+ & BluetoothAdapter :: Mock ( _) => true ,
168+ _ => false ,
169+ }
170+ }
171+
158172pub struct BluetoothManager {
159173 receiver : IpcReceiver < BluetoothMethodMsg > ,
160174 adapter : Option < BluetoothAdapter > ,
@@ -228,20 +242,56 @@ impl BluetoothManager {
228242 BluetoothMethodMsg :: WriteValue ( id, value, sender) => {
229243 self . write_value ( id, value, sender)
230244 } ,
245+ BluetoothMethodMsg :: Test ( data_set_name, sender) => {
246+ self . test ( data_set_name, sender)
247+ }
231248 BluetoothMethodMsg :: Exit => {
232249 break
233250 } ,
234251 }
235252 }
236253 }
237254
255+ // Test
256+
257+ fn test ( & mut self , data_set_name : String , sender : IpcSender < BluetoothResult < ( ) > > ) {
258+ self . address_to_id . clear ( ) ;
259+ self . service_to_device . clear ( ) ;
260+ self . characteristic_to_service . clear ( ) ;
261+ self . descriptor_to_characteristic . clear ( ) ;
262+ self . cached_devices . clear ( ) ;
263+ self . cached_services . clear ( ) ;
264+ self . cached_characteristics . clear ( ) ;
265+ self . cached_descriptors . clear ( ) ;
266+ self . allowed_services . clear ( ) ;
267+ self . adapter = BluetoothAdapter :: init_mock ( ) . ok ( ) ;
268+ match test:: test ( self , data_set_name) {
269+ Ok ( _) => {
270+ let _ = sender. send ( Ok ( ( ) ) ) ;
271+ } ,
272+ Err ( error) => {
273+ let _ = sender. send ( Err ( BluetoothError :: Type ( error. description ( ) . to_owned ( ) ) ) ) ;
274+ } ,
275+ }
276+ }
277+
238278 // Adapter
239279
240- fn get_or_create_adapter ( & mut self ) -> Option < BluetoothAdapter > {
280+ pub fn get_or_create_adapter ( & mut self ) -> Option < BluetoothAdapter > {
241281 let adapter_valid = self . adapter . as_ref ( ) . map_or ( false , |a| a. get_address ( ) . is_ok ( ) ) ;
242282 if !adapter_valid {
243283 self . adapter = BluetoothAdapter :: init ( ) . ok ( ) ;
244284 }
285+
286+ let adapter = match self . adapter . as_ref ( ) {
287+ Some ( adapter) => adapter,
288+ None => return None ,
289+ } ;
290+
291+ if is_mock_adapter ( adapter) && !adapter. is_present ( ) . unwrap_or ( false ) {
292+ return None ;
293+ }
294+
245295 self . adapter . clone ( )
246296 }
247297
@@ -270,7 +320,16 @@ impl BluetoothManager {
270320 }
271321
272322 #[ cfg( target_os = "linux" ) ]
273- fn select_device ( & mut self , devices : Vec < BluetoothDevice > ) -> Option < String > {
323+ fn select_device ( & mut self , devices : Vec < BluetoothDevice > , adapter : & BluetoothAdapter ) -> Option < String > {
324+ if is_mock_adapter ( adapter) {
325+ for device in devices {
326+ if let Ok ( address) = device. get_address ( ) {
327+ return Some ( address) ;
328+ }
329+ }
330+ return None ;
331+ }
332+
274333 let mut dialog_rows: Vec < String > = vec ! ( ) ;
275334 for device in devices {
276335 dialog_rows. extend_from_slice ( & [ device. get_address ( ) . unwrap_or ( "" . to_string ( ) ) ,
@@ -291,7 +350,7 @@ impl BluetoothManager {
291350 }
292351
293352 #[ cfg( not( target_os = "linux" ) ) ]
294- fn select_device ( & mut self , devices : Vec < BluetoothDevice > ) -> Option < String > {
353+ fn select_device ( & mut self , devices : Vec < BluetoothDevice > , _adapter : & BluetoothAdapter ) -> Option < String > {
295354 for device in devices {
296355 if let Ok ( address) = device. get_address ( ) {
297356 return Some ( address) ;
@@ -312,6 +371,17 @@ impl BluetoothManager {
312371 device_id
313372 }
314373
374+ fn device_from_service_id ( & self , service_id : & str ) -> Option < BluetoothDevice > {
375+ let device_id = match self . service_to_device . get ( service_id) {
376+ Some ( id) => id,
377+ None => return None ,
378+ } ;
379+ match self . cached_devices . get ( device_id) {
380+ Some ( d) => Some ( d. clone ( ) ) ,
381+ None => None ,
382+ }
383+ }
384+
315385 // Service
316386
317387 fn get_and_cache_gatt_services ( & mut self ,
@@ -464,7 +534,9 @@ impl BluetoothManager {
464534 let mut adapter = get_adapter_or_return_error ! ( self , sender) ;
465535 if let Ok ( ref session) = adapter. create_discovery_session ( ) {
466536 if session. start_discovery ( ) . is_ok ( ) {
467- thread:: sleep ( Duration :: from_millis ( DISCOVERY_TIMEOUT_MS ) ) ;
537+ if !is_mock_adapter ( & adapter) {
538+ thread:: sleep ( Duration :: from_millis ( DISCOVERY_TIMEOUT_MS ) ) ;
539+ }
468540 }
469541 let _ = session. stop_discovery ( ) ;
470542 }
@@ -481,7 +553,7 @@ impl BluetoothManager {
481553 }
482554
483555 // Step 8.
484- if let Some ( address) = self . select_device ( matched_devices) {
556+ if let Some ( address) = self . select_device ( matched_devices, & adapter ) {
485557 let device_id = match self . address_to_id . get ( & address) {
486558 Some ( id) => id. clone ( ) ,
487559 None => return drop ( sender. send ( Err ( BluetoothError :: NotFound ) ) ) ,
@@ -517,7 +589,12 @@ impl BluetoothManager {
517589 for _ in 0 ..MAXIMUM_TRANSACTION_TIME {
518590 match d. is_connected ( ) . unwrap_or ( false ) {
519591 true => return drop ( sender. send ( Ok ( true ) ) ) ,
520- false => thread:: sleep ( Duration :: from_millis ( CONNECTION_TIMEOUT_MS ) ) ,
592+ false => {
593+ if is_mock_adapter ( & adapter) {
594+ break ;
595+ }
596+ thread:: sleep ( Duration :: from_millis ( CONNECTION_TIMEOUT_MS ) ) ;
597+ } ,
521598 }
522599 }
523600 return drop ( sender. send ( Err ( BluetoothError :: Network ) ) ) ;
@@ -617,11 +694,15 @@ impl BluetoothManager {
617694 Some ( a) => a,
618695 None => return drop ( sender. send ( Err ( BluetoothError :: Type ( ADAPTER_ERROR . to_string ( ) ) ) ) ) ,
619696 } ;
697+ let device = match self . device_from_service_id ( & service_id) {
698+ Some ( device) => device,
699+ None => return drop ( sender. send ( Err ( BluetoothError :: NotFound ) ) ) ,
700+ } ;
620701 let primary_service = match self . get_gatt_service ( & mut adapter, & service_id) {
621702 Some ( s) => s,
622703 None => return drop ( sender. send ( Err ( BluetoothError :: NotFound ) ) ) ,
623704 } ;
624- let services = primary_service. get_includes ( ) . unwrap_or ( vec ! ( ) ) ;
705+ let services = primary_service. get_includes ( device ) . unwrap_or ( vec ! ( ) ) ;
625706 for service in services {
626707 if let Ok ( service_uuid) = service. get_uuid ( ) {
627708 if uuid == service_uuid {
@@ -644,11 +725,15 @@ impl BluetoothManager {
644725 Some ( a) => a,
645726 None => return drop ( sender. send ( Err ( BluetoothError :: Type ( ADAPTER_ERROR . to_string ( ) ) ) ) ) ,
646727 } ;
728+ let device = match self . device_from_service_id ( & service_id) {
729+ Some ( device) => device,
730+ None => return drop ( sender. send ( Err ( BluetoothError :: NotFound ) ) ) ,
731+ } ;
647732 let primary_service = match self . get_gatt_service ( & mut adapter, & service_id) {
648733 Some ( s) => s,
649734 None => return drop ( sender. send ( Err ( BluetoothError :: NotFound ) ) ) ,
650735 } ;
651- let services = primary_service. get_includes ( ) . unwrap_or ( vec ! ( ) ) ;
736+ let services = primary_service. get_includes ( device ) . unwrap_or ( vec ! ( ) ) ;
652737 let mut services_vec = vec ! ( ) ;
653738 for service in services {
654739 if let Ok ( service_uuid) = service. get_uuid ( ) {
0 commit comments