1 // Copyright 2015 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.
5 #include "device/bluetooth/bluetooth_low_energy_device_mac.h"
7 #import <CoreFoundation/CoreFoundation.h>
9 #include "base/mac/mac_util.h"
10 #include "base/mac/scoped_cftyperef.h"
11 #include "base/mac/sdk_forward_declarations.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/sys_string_conversions.h"
14 #include "device/bluetooth/bluetooth_adapter_mac.h"
15 #include "device/bluetooth/bluetooth_device.h"
17 using device::BluetoothDevice;
18 using device::BluetoothLowEnergyDeviceMac;
22 // Converts a CBUUID to a BluetoothUUID.
23 device::BluetoothUUID BluetoothUUIDWithCBUUID(CBUUID* uuid) {
24 // UUIDString only available OS X >= 10.8.
25 DCHECK(base::mac::IsOSMountainLionOrLater());
26 std::string uuid_c_string = base::SysNSStringToUTF8([uuid UUIDString]);
27 return device::BluetoothUUID(uuid_c_string);
32 BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac(
33 CBPeripheral* peripheral,
34 NSDictionary* advertisement_data,
36 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
37 identifier_ = GetPeripheralIdentifier(peripheral);
38 hash_address_ = GetPeripheralHashAddress(peripheral);
39 Update(peripheral, advertisement_data, rssi);
42 BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() {
45 void BluetoothLowEnergyDeviceMac::Update(CBPeripheral* peripheral,
46 NSDictionary* advertisement_data,
48 last_update_time_.reset([[NSDate date] retain]);
49 peripheral_.reset([peripheral retain]);
51 NSNumber* connectable =
52 [advertisement_data objectForKey:CBAdvertisementDataIsConnectable];
53 connectable_ = [connectable boolValue];
55 NSDictionary* service_data =
56 [advertisement_data objectForKey:CBAdvertisementDataServiceDataKey];
57 for (CBUUID* uuid in service_data) {
58 NSData* data = [service_data objectForKey:uuid];
59 BluetoothUUID service_uuid = BluetoothUUIDWithCBUUID(uuid);
60 SetServiceData(service_uuid, static_cast<const char*>([data bytes]),
63 NSArray* service_uuids =
64 [advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey];
65 for (CBUUID* uuid in service_uuids) {
66 advertised_uuids_.insert(
67 BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
69 NSArray* overflow_service_uuids = [advertisement_data
70 objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
71 for (CBUUID* uuid in overflow_service_uuids) {
72 advertised_uuids_.insert(
73 BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
77 std::string BluetoothLowEnergyDeviceMac::GetIdentifier() const {
81 uint32 BluetoothLowEnergyDeviceMac::GetBluetoothClass() const {
82 return 0x1F00; // Unspecified Device Class
85 std::string BluetoothLowEnergyDeviceMac::GetAddress() const {
89 BluetoothDevice::VendorIDSource BluetoothLowEnergyDeviceMac::GetVendorIDSource()
91 return VENDOR_ID_UNKNOWN;
94 uint16 BluetoothLowEnergyDeviceMac::GetVendorID() const {
98 uint16 BluetoothLowEnergyDeviceMac::GetProductID() const {
102 uint16 BluetoothLowEnergyDeviceMac::GetDeviceID() const {
106 int BluetoothLowEnergyDeviceMac::GetRSSI() const {
110 bool BluetoothLowEnergyDeviceMac::IsPaired() const {
114 bool BluetoothLowEnergyDeviceMac::IsConnected() const {
115 return (GetPeripheralState() == CBPeripheralStateConnected);
118 bool BluetoothLowEnergyDeviceMac::IsConnectable() const {
122 bool BluetoothLowEnergyDeviceMac::IsConnecting() const {
126 BluetoothDevice::UUIDList BluetoothLowEnergyDeviceMac::GetUUIDs() const {
127 return BluetoothDevice::UUIDList(advertised_uuids_.begin(),
128 advertised_uuids_.end());
131 int16 BluetoothLowEnergyDeviceMac::GetInquiryRSSI() const {
132 return kUnknownPower;
135 int16 BluetoothLowEnergyDeviceMac::GetInquiryTxPower() const {
137 return kUnknownPower;
140 bool BluetoothLowEnergyDeviceMac::ExpectingPinCode() const {
144 bool BluetoothLowEnergyDeviceMac::ExpectingPasskey() const {
148 bool BluetoothLowEnergyDeviceMac::ExpectingConfirmation() const {
152 void BluetoothLowEnergyDeviceMac::GetConnectionInfo(
153 const ConnectionInfoCallback& callback) {
157 void BluetoothLowEnergyDeviceMac::Connect(
158 PairingDelegate* pairing_delegate,
159 const base::Closure& callback,
160 const ConnectErrorCallback& error_callback) {
164 void BluetoothLowEnergyDeviceMac::SetPinCode(const std::string& pincode) {
168 void BluetoothLowEnergyDeviceMac::SetPasskey(uint32 passkey) {
172 void BluetoothLowEnergyDeviceMac::ConfirmPairing() {
176 void BluetoothLowEnergyDeviceMac::RejectPairing() {
180 void BluetoothLowEnergyDeviceMac::CancelPairing() {
184 void BluetoothLowEnergyDeviceMac::Disconnect(
185 const base::Closure& callback,
186 const ErrorCallback& error_callback) {
190 void BluetoothLowEnergyDeviceMac::Forget(const ErrorCallback& error_callback) {
194 void BluetoothLowEnergyDeviceMac::ConnectToService(
195 const BluetoothUUID& uuid,
196 const ConnectToServiceCallback& callback,
197 const ConnectToServiceErrorCallback& error_callback) {
201 void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely(
202 const device::BluetoothUUID& uuid,
203 const ConnectToServiceCallback& callback,
204 const ConnectToServiceErrorCallback& error_callback) {
208 void BluetoothLowEnergyDeviceMac::CreateGattConnection(
209 const GattConnectionCallback& callback,
210 const ConnectErrorCallback& error_callback) {
214 NSDate* BluetoothLowEnergyDeviceMac::GetLastUpdateTime() const {
215 return last_update_time_.get();
218 std::string BluetoothLowEnergyDeviceMac::GetDeviceName() const {
219 return base::SysNSStringToUTF8([peripheral_ name]);
223 std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(
224 CBPeripheral* peripheral) {
225 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
226 NSUUID* uuid = [peripheral identifier];
227 NSString* uuidString = [uuid UUIDString];
228 return base::SysNSStringToUTF8(uuidString);
232 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(
233 CBPeripheral* peripheral) {
234 const size_t kCanonicalAddressNumberOfBytes = 6;
235 char raw[kCanonicalAddressNumberOfBytes];
236 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw,
238 std::string hash = base::HexEncode(raw, sizeof(raw));
239 return BluetoothDevice::CanonicalizeAddress(hash);
242 CBPeripheralState BluetoothLowEnergyDeviceMac::GetPeripheralState() const {
243 Class peripheral_class = NSClassFromString(@"CBPeripheral");
244 base::scoped_nsobject<NSMethodSignature> signature([[peripheral_class
245 instanceMethodSignatureForSelector:@selector(state)] retain]);
246 base::scoped_nsobject<NSInvocation> invocation(
247 [[NSInvocation invocationWithMethodSignature:signature] retain]);
248 [invocation setTarget:peripheral_];
249 [invocation setSelector:@selector(state)];
251 CBPeripheralState state = CBPeripheralStateDisconnected;
252 [invocation getReturnValue:&state];