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* advertisementData,
36 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
37 identifier_ = GetPeripheralIdentifier(peripheral);
38 hash_address_ = GetPeripheralHashAddress(peripheral);
39 Update(peripheral, advertisementData, rssi);
42 BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() {
45 void BluetoothLowEnergyDeviceMac::Update(CBPeripheral* peripheral,
46 NSDictionary* advertisementData,
48 last_update_time_.reset([[NSDate date] retain]);
49 peripheral_.reset([peripheral retain]);
52 NSNumber* nbConnectable =
53 [advertisementData objectForKey:CBAdvertisementDataIsConnectable];
54 connectable_ = [nbConnectable boolValue];
55 NSDictionary* serviceData =
56 [advertisementData objectForKey:CBAdvertisementDataServiceDataKey];
57 for (CBUUID* uuid in serviceData) {
58 NSData* data = [serviceData objectForKey:uuid];
59 BluetoothUUID serviceUUID = BluetoothUUIDWithCBUUID(uuid);
60 SetServiceData(serviceUUID, (const char*)[data bytes], [data length]);
64 std::string BluetoothLowEnergyDeviceMac::GetIdentifier() const {
68 uint32 BluetoothLowEnergyDeviceMac::GetBluetoothClass() const {
72 std::string BluetoothLowEnergyDeviceMac::GetAddress() const {
76 BluetoothDevice::VendorIDSource BluetoothLowEnergyDeviceMac::GetVendorIDSource()
78 return VENDOR_ID_UNKNOWN;
81 uint16 BluetoothLowEnergyDeviceMac::GetVendorID() const {
85 uint16 BluetoothLowEnergyDeviceMac::GetProductID() const {
89 uint16 BluetoothLowEnergyDeviceMac::GetDeviceID() const {
93 int BluetoothLowEnergyDeviceMac::GetRSSI() const {
97 bool BluetoothLowEnergyDeviceMac::IsPaired() const {
101 bool BluetoothLowEnergyDeviceMac::IsConnected() const {
102 return (GetPeripheralState() == CBPeripheralStateConnected);
105 bool BluetoothLowEnergyDeviceMac::IsConnectable() const {
109 bool BluetoothLowEnergyDeviceMac::IsConnecting() const {
113 BluetoothDevice::UUIDList BluetoothLowEnergyDeviceMac::GetUUIDs() const {
114 return std::vector<device::BluetoothUUID>();
117 int16 BluetoothLowEnergyDeviceMac::GetInquiryRSSI() const {
118 return kUnknownPower;
121 int16 BluetoothLowEnergyDeviceMac::GetInquiryTxPower() const {
123 return kUnknownPower;
126 bool BluetoothLowEnergyDeviceMac::ExpectingPinCode() const {
130 bool BluetoothLowEnergyDeviceMac::ExpectingPasskey() const {
134 bool BluetoothLowEnergyDeviceMac::ExpectingConfirmation() const {
138 void BluetoothLowEnergyDeviceMac::GetConnectionInfo(
139 const ConnectionInfoCallback& callback) {
143 void BluetoothLowEnergyDeviceMac::Connect(
144 PairingDelegate* pairing_delegate,
145 const base::Closure& callback,
146 const ConnectErrorCallback& error_callback) {
150 void BluetoothLowEnergyDeviceMac::SetPinCode(const std::string& pincode) {
154 void BluetoothLowEnergyDeviceMac::SetPasskey(uint32 passkey) {
158 void BluetoothLowEnergyDeviceMac::ConfirmPairing() {
162 void BluetoothLowEnergyDeviceMac::RejectPairing() {
166 void BluetoothLowEnergyDeviceMac::CancelPairing() {
170 void BluetoothLowEnergyDeviceMac::Disconnect(
171 const base::Closure& callback,
172 const ErrorCallback& error_callback) {
176 void BluetoothLowEnergyDeviceMac::Forget(const ErrorCallback& error_callback) {
180 void BluetoothLowEnergyDeviceMac::ConnectToService(
181 const BluetoothUUID& uuid,
182 const ConnectToServiceCallback& callback,
183 const ConnectToServiceErrorCallback& error_callback) {
187 void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely(
188 const device::BluetoothUUID& uuid,
189 const ConnectToServiceCallback& callback,
190 const ConnectToServiceErrorCallback& error_callback) {
194 void BluetoothLowEnergyDeviceMac::CreateGattConnection(
195 const GattConnectionCallback& callback,
196 const ConnectErrorCallback& error_callback) {
200 NSDate* BluetoothLowEnergyDeviceMac::GetLastUpdateTime() const {
201 return last_update_time_.get();
204 std::string BluetoothLowEnergyDeviceMac::GetDeviceName() const {
205 return base::SysNSStringToUTF8([peripheral_ name]);
209 std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(
210 CBPeripheral* peripheral) {
211 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
212 NSUUID* uuid = [peripheral identifier];
213 NSString* uuidString = [uuid UUIDString];
214 return base::SysNSStringToUTF8(uuidString);
218 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(
219 CBPeripheral* peripheral) {
220 const size_t kCanonicalAddressNumberOfBytes = 6;
221 char raw[kCanonicalAddressNumberOfBytes];
222 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw,
224 std::string hash = base::HexEncode(raw, sizeof(raw));
225 return BluetoothDevice::CanonicalizeAddress(hash);
228 CBPeripheralState BluetoothLowEnergyDeviceMac::GetPeripheralState() const {
229 Class peripheral_class = NSClassFromString(@"CBPeripheral");
230 base::scoped_nsobject<NSMethodSignature> signature([[peripheral_class
231 instanceMethodSignatureForSelector:@selector(state)] retain]);
232 base::scoped_nsobject<NSInvocation> invocation(
233 [[NSInvocation invocationWithMethodSignature:signature] retain]);
234 [invocation setTarget:peripheral_];
235 [invocation setSelector:@selector(state)];
237 CBPeripheralState state = CBPeripheralStateDisconnected;
238 [invocation getReturnValue:&state];