blob: 677c59557087bc8be0e1cb5f92a9d631ec910e7b [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/bluetooth/bluetooth_low_energy_device_mac.h"
#import <CoreFoundation/CoreFoundation.h>
#include <stddef.h>
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "device/bluetooth/bluetooth_adapter_mac.h"
#include "device/bluetooth/bluetooth_device.h"
using device::BluetoothDevice;
using device::BluetoothLowEnergyDeviceMac;
namespace {
// Converts a CBUUID to a BluetoothUUID.
device::BluetoothUUID BluetoothUUIDWithCBUUID(CBUUID* uuid) {
// UUIDString only available OS X >= 10.8.
DCHECK(base::mac::IsOSMountainLionOrLater());
std::string uuid_c_string = base::SysNSStringToUTF8([uuid UUIDString]);
return device::BluetoothUUID(uuid_c_string);
}
} // namespace
BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac(
BluetoothAdapterMac* adapter,
CBPeripheral* peripheral,
NSDictionary* advertisement_data,
int rssi)
: BluetoothDeviceMac(adapter) {
DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
identifier_ = GetPeripheralIdentifier(peripheral);
hash_address_ = GetPeripheralHashAddress(peripheral);
Update(peripheral, advertisement_data, rssi);
}
BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() {
}
void BluetoothLowEnergyDeviceMac::Update(CBPeripheral* peripheral,
NSDictionary* advertisement_data,
int rssi) {
last_update_time_.reset([[NSDate date] retain]);
peripheral_.reset([peripheral retain]);
rssi_ = rssi;
NSNumber* connectable =
[advertisement_data objectForKey:CBAdvertisementDataIsConnectable];
connectable_ = [connectable boolValue];
ClearServiceData();
NSDictionary* service_data =
[advertisement_data objectForKey:CBAdvertisementDataServiceDataKey];
for (CBUUID* uuid in service_data) {
NSData* data = [service_data objectForKey:uuid];
BluetoothUUID service_uuid = BluetoothUUIDWithCBUUID(uuid);
SetServiceData(service_uuid, static_cast<const char*>([data bytes]),
[data length]);
}
NSArray* service_uuids =
[advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey];
for (CBUUID* uuid in service_uuids) {
advertised_uuids_.insert(
BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
}
NSArray* overflow_service_uuids = [advertisement_data
objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
for (CBUUID* uuid in overflow_service_uuids) {
advertised_uuids_.insert(
BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
}
}
std::string BluetoothLowEnergyDeviceMac::GetIdentifier() const {
return identifier_;
}
uint32_t BluetoothLowEnergyDeviceMac::GetBluetoothClass() const {
return 0x1F00; // Unspecified Device Class
}
std::string BluetoothLowEnergyDeviceMac::GetAddress() const {
return hash_address_;
}
BluetoothDevice::VendorIDSource BluetoothLowEnergyDeviceMac::GetVendorIDSource()
const {
return VENDOR_ID_UNKNOWN;
}
uint16_t BluetoothLowEnergyDeviceMac::GetVendorID() const {
return 0;
}
uint16_t BluetoothLowEnergyDeviceMac::GetProductID() const {
return 0;
}
uint16_t BluetoothLowEnergyDeviceMac::GetDeviceID() const {
return 0;
}
int BluetoothLowEnergyDeviceMac::GetRSSI() const {
return rssi_;
}
bool BluetoothLowEnergyDeviceMac::IsPaired() const {
return false;
}
bool BluetoothLowEnergyDeviceMac::IsConnected() const {
return IsGattConnected();
}
bool BluetoothLowEnergyDeviceMac::IsGattConnected() const {
return (GetPeripheralState() == CBPeripheralStateConnected);
}
bool BluetoothLowEnergyDeviceMac::IsConnectable() const {
return connectable_;
}
bool BluetoothLowEnergyDeviceMac::IsConnecting() const {
return false;
}
BluetoothDevice::UUIDList BluetoothLowEnergyDeviceMac::GetUUIDs() const {
return BluetoothDevice::UUIDList(advertised_uuids_.begin(),
advertised_uuids_.end());
}
int16_t BluetoothLowEnergyDeviceMac::GetInquiryRSSI() const {
return kUnknownPower;
}
int16_t BluetoothLowEnergyDeviceMac::GetInquiryTxPower() const {
NOTIMPLEMENTED();
return kUnknownPower;
}
bool BluetoothLowEnergyDeviceMac::ExpectingPinCode() const {
return false;
}
bool BluetoothLowEnergyDeviceMac::ExpectingPasskey() const {
return false;
}
bool BluetoothLowEnergyDeviceMac::ExpectingConfirmation() const {
return false;
}
void BluetoothLowEnergyDeviceMac::GetConnectionInfo(
const ConnectionInfoCallback& callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::Connect(
PairingDelegate* pairing_delegate,
const base::Closure& callback,
const ConnectErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::SetPinCode(const std::string& pincode) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::SetPasskey(uint32_t passkey) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::ConfirmPairing() {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::RejectPairing() {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::CancelPairing() {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::Disconnect(
const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::Forget(const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::ConnectToService(
const BluetoothUUID& uuid,
const ConnectToServiceCallback& callback,
const ConnectToServiceErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely(
const device::BluetoothUUID& uuid,
const ConnectToServiceCallback& callback,
const ConnectToServiceErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::CreateGattConnection(
const GattConnectionCallback& callback,
const ConnectErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
NSDate* BluetoothLowEnergyDeviceMac::GetLastUpdateTime() const {
return last_update_time_.get();
}
std::string BluetoothLowEnergyDeviceMac::GetDeviceName() const {
return base::SysNSStringToUTF8([peripheral_ name]);
}
void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() {
// Mac implementation does not yet use the default CreateGattConnection
// implementation. http://crbug.com/520774
NOTIMPLEMENTED();
}
void BluetoothLowEnergyDeviceMac::DisconnectGatt() {
// Mac implementation does not yet use the default CreateGattConnection
// implementation. http://crbug.com/520774
NOTIMPLEMENTED();
}
// static
std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(
CBPeripheral* peripheral) {
DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable());
NSUUID* uuid = [peripheral identifier];
NSString* uuidString = [uuid UUIDString];
return base::SysNSStringToUTF8(uuidString);
}
// static
std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(
CBPeripheral* peripheral) {
const size_t kCanonicalAddressNumberOfBytes = 6;
char raw[kCanonicalAddressNumberOfBytes];
crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw,
sizeof(raw));
std::string hash = base::HexEncode(raw, sizeof(raw));
return BluetoothDevice::CanonicalizeAddress(hash);
}
CBPeripheralState BluetoothLowEnergyDeviceMac::GetPeripheralState() const {
Class peripheral_class = NSClassFromString(@"CBPeripheral");
base::scoped_nsobject<NSMethodSignature> signature([[peripheral_class
instanceMethodSignatureForSelector:@selector(state)] retain]);
base::scoped_nsobject<NSInvocation> invocation(
[[NSInvocation invocationWithMethodSignature:signature] retain]);
[invocation setTarget:peripheral_];
[invocation setSelector:@selector(state)];
[invocation invoke];
CBPeripheralState state = CBPeripheralStateDisconnected;
[invocation getReturnValue:&state];
return state;
}