OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/mac/bluetooth_utility.h" | |
6 | |
7 #import <Foundation/Foundation.h> | |
8 #include <IOKit/IOKitLib.h> | |
9 | |
10 #include "base/mac/foundation_util.h" | |
11 #include "base/mac/mac_util.h" | |
12 #include "base/mac/scoped_ioobject.h" | |
13 #include "base/mac/sdk_forward_declarations.h" | |
14 | |
15 namespace bluetooth_utility { | |
16 | |
17 BluetoothAvailability GetBluetoothAvailability() { | |
18 base::ScopedCFTypeRef<CFMutableDictionaryRef> matching_dict( | |
19 IOServiceMatching("IOBluetoothHCIController")); | |
20 if (!matching_dict) | |
21 return BLUETOOTH_AVAILABILITY_ERROR; | |
22 | |
23 // IOServiceGetMatchingServices takes ownership of matching_dict. | |
24 io_iterator_t iter; | |
25 int kr = IOServiceGetMatchingServices( | |
26 kIOMasterPortDefault, matching_dict.release(), &iter); | |
27 if (kr != KERN_SUCCESS) | |
28 return BLUETOOTH_NOT_AVAILABLE; | |
29 base::mac::ScopedIOObject<io_iterator_t> scoped_iter(iter); | |
30 | |
31 int bluetooth_available = false; | |
32 int le_unknown = false; | |
33 base::mac::ScopedIOObject<io_service_t> device; | |
34 while (device.reset(IOIteratorNext(scoped_iter.get())), device) { | |
35 bluetooth_available = true; | |
36 | |
37 CFMutableDictionaryRef dict; | |
38 kr = IORegistryEntryCreateCFProperties( | |
39 device, &dict, kCFAllocatorDefault, kNilOptions); | |
40 if (kr != KERN_SUCCESS) | |
41 continue; | |
42 base::ScopedCFTypeRef<CFMutableDictionaryRef> scoped_dict(dict); | |
43 | |
44 NSDictionary* objc_dict = base::mac::CFToNSCast(scoped_dict.get()); | |
45 NSNumber* lmp_version = | |
46 base::mac::ObjCCast<NSNumber>([objc_dict objectForKey:@"LMPVersion"]); | |
47 if (!lmp_version) | |
48 continue; | |
49 | |
50 // The LMP version is too low to support Bluetooth LE. | |
51 if ([lmp_version intValue] < 6) | |
52 continue; | |
53 | |
54 // Check the supported features registry entry for Bluetooth LE | |
55 // availability. The relevant bit has a different meaning on OSX 10.6, and | |
56 // could change again in the future. | |
57 if (base::mac::IsOSSnowLeopard()) { | |
58 le_unknown = true; | |
Mark Mentovai
2014/07/11 22:26:29
You can return BLUETOOTH_AVAILABLE_LE_UNKNOWN righ
erikchen
2014/07/11 22:39:59
Done.
| |
59 continue; | |
60 } | |
61 | |
62 NSData* data = base::mac::ObjCCast<NSData>( | |
63 [objc_dict objectForKey:@"HCISupportedFeatures"]); | |
64 | |
65 NSUInteger supported_features_index = 4; | |
66 NSUInteger length = [data length]; | |
67 if (length < supported_features_index + 1) | |
68 continue; | |
69 | |
70 // The bytes are indexed in reverse order. | |
71 NSUInteger index = length - supported_features_index - 1; | |
72 | |
73 const unsigned char* bytes = | |
74 static_cast<const unsigned char*>([data bytes]); | |
75 const unsigned char byte = bytes[index]; | |
76 bool le_supported = byte & kBluetoothFeatureLESupportedController; | |
77 if (le_supported) | |
78 return BLUETOOTH_AVAILABLE_WITH_LE; | |
79 } | |
80 | |
81 if (le_unknown) | |
82 return BLUETOOTH_AVAILABLE_LE_UNKNOWN; | |
83 return bluetooth_available ? BLUETOOTH_AVAILABLE_WITHOUT_LE | |
84 : BLUETOOTH_AVAILABILITY_ERROR; | |
85 } | |
86 | |
87 } // namespace bluetooth_utility | |
OLD | NEW |