blob: e2d8c7d419367befdcdad2b73c96da6db1975bca [file] [log] [blame]
// Copyright 2013 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_device_mac.h"
#include <string>
#include "base/basictypes.h"
#include "base/hash.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
#include "device/bluetooth/bluetooth_profile_mac.h"
#include "device/bluetooth/bluetooth_service_record_mac.h"
#include "device/bluetooth/bluetooth_socket_mac.h"
#include "device/bluetooth/bluetooth_uuid.h"
// Replicate specific 10.7 SDK declarations for building with prior SDKs.
#if !defined(MAC_OS_X_VERSION_10_7) || \
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
@interface IOBluetoothDevice (LionSDKDeclarations)
- (NSString*)addressString;
- (unsigned int)classOfDevice;
- (BluetoothConnectionHandle)connectionHandle;
- (BluetoothHCIRSSIValue)rawRSSI;
- (NSArray*)services;
@end
#endif // MAC_OS_X_VERSION_10_7
// Undocumented API for accessing the Bluetooth transmit power level.
// Similar to the API defined here [ http://goo.gl/20Q5vE ].
@interface IOBluetoothHostController (UndocumentedAPI)
- (IOReturn)
BluetoothHCIReadTransmitPowerLevel:(BluetoothConnectionHandle)connection
inType:(BluetoothHCITransmitPowerLevelType)type
outTransmitPowerLevel:(BluetoothHCITransmitPowerLevel*)level;
@end
namespace device {
BluetoothDeviceMac::BluetoothDeviceMac(IOBluetoothDevice* device)
: device_([device retain]) {
}
BluetoothDeviceMac::~BluetoothDeviceMac() {
}
void BluetoothDeviceMac::AddObserver(
device::BluetoothDevice::Observer* observer) {
DCHECK(observer);
observers_.AddObserver(observer);
}
void BluetoothDeviceMac::RemoveObserver(
device::BluetoothDevice::Observer* observer) {
DCHECK(observer);
observers_.RemoveObserver(observer);
}
uint32 BluetoothDeviceMac::GetBluetoothClass() const {
return [device_ classOfDevice];
}
std::string BluetoothDeviceMac::GetDeviceName() const {
return base::SysNSStringToUTF8([device_ name]);
}
std::string BluetoothDeviceMac::GetAddress() const {
return GetDeviceAddress(device_);
}
BluetoothDevice::VendorIDSource BluetoothDeviceMac::GetVendorIDSource() const {
return VENDOR_ID_UNKNOWN;
}
uint16 BluetoothDeviceMac::GetVendorID() const {
return 0;
}
uint16 BluetoothDeviceMac::GetProductID() const {
return 0;
}
uint16 BluetoothDeviceMac::GetDeviceID() const {
return 0;
}
int BluetoothDeviceMac::GetRSSI() const {
if (![device_ isConnected]) {
NOTIMPLEMENTED();
return kUnknownPower;
}
int rssi = [device_ rawRSSI];
// The API guarantees that +127 is returned in case the RSSI is not readable:
// http://goo.gl/bpURYv
if (rssi == 127)
return kUnknownPower;
return rssi;
}
int BluetoothDeviceMac::GetCurrentHostTransmitPower() const {
return GetHostTransmitPower(kReadCurrentTransmitPowerLevel);
}
int BluetoothDeviceMac::GetMaximumHostTransmitPower() const {
return GetHostTransmitPower(kReadMaximumTransmitPowerLevel);
}
bool BluetoothDeviceMac::IsPaired() const {
return [device_ isPaired];
}
bool BluetoothDeviceMac::IsConnected() const {
return [device_ isConnected];
}
bool BluetoothDeviceMac::IsConnectable() const {
return false;
}
bool BluetoothDeviceMac::IsConnecting() const {
return false;
}
// TODO(keybuk): BluetoothServiceRecord is deprecated; implement this method
// without using BluetoothServiceRecord.
BluetoothDevice::UUIDList BluetoothDeviceMac::GetUUIDs() const {
UUIDList uuids;
for (IOBluetoothSDPServiceRecord* service in [device_ services]) {
BluetoothServiceRecordMac service_record(service);
uuids.push_back(service_record.uuid());
}
return uuids;
}
bool BluetoothDeviceMac::ExpectingPinCode() const {
NOTIMPLEMENTED();
return false;
}
bool BluetoothDeviceMac::ExpectingPasskey() const {
NOTIMPLEMENTED();
return false;
}
bool BluetoothDeviceMac::ExpectingConfirmation() const {
NOTIMPLEMENTED();
return false;
}
void BluetoothDeviceMac::Connect(
PairingDelegate* pairing_delegate,
const base::Closure& callback,
const ConnectErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::SetPinCode(const std::string& pincode) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::SetPasskey(uint32 passkey) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::ConfirmPairing() {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::RejectPairing() {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::CancelPairing() {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::Disconnect(const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::Forget(const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::ConnectToProfile(
BluetoothProfile* profile,
const base::Closure& callback,
const ConnectToProfileErrorCallback& error_callback) {
static_cast<BluetoothProfileMac*>(profile)
->Connect(device_, callback, error_callback);
}
void BluetoothDeviceMac::ConnectToService(
const BluetoothUUID& uuid,
const ConnectToServiceCallback& callback,
const ConnectToServiceErrorCallback& error_callback) {
// TODO(keybuk): implement
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::SetOutOfBandPairingData(
const BluetoothOutOfBandPairingData& data,
const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void BluetoothDeviceMac::ClearOutOfBandPairingData(
const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
int BluetoothDeviceMac::GetHostTransmitPower(
BluetoothHCITransmitPowerLevelType power_level_type) const {
IOBluetoothHostController* controller =
[IOBluetoothHostController defaultController];
// Bail if the undocumented API is unavailable on this machine.
SEL selector = @selector(
BluetoothHCIReadTransmitPowerLevel:inType:outTransmitPowerLevel:);
if (![controller respondsToSelector:selector])
return kUnknownPower;
BluetoothHCITransmitPowerLevel power_level;
IOReturn result =
[controller BluetoothHCIReadTransmitPowerLevel:[device_ connectionHandle]
inType:power_level_type
outTransmitPowerLevel:&power_level];
if (result != kIOReturnSuccess)
return kUnknownPower;
return power_level;
}
// static
std::string BluetoothDeviceMac::GetDeviceAddress(IOBluetoothDevice* device) {
return NormalizeAddress(base::SysNSStringToUTF8([device addressString]));
}
// static
std::string BluetoothDeviceMac::NormalizeAddress(const std::string& address) {
std::string normalized;
base::ReplaceChars(address, "-", ":", &normalized);
// TODO(isherman): Restore StringToUpperASCII(&normalized) call for M37.
// http://crbug.com/371014
return normalized;
}
} // namespace device