Skip to content

Commit

Permalink
Expose device RSSI and Tx power via the chrome.bluetooth API.
Browse files Browse the repository at this point in the history
This CL only implements the fetching of these values on Mac.

BUG=365966
TEST=browser_tests
R=kalman@chromium.org, keybuk@chromium.org

Review URL: https://codereview.chromium.org/246603008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267458 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
isherman@chromium.org committed May 1, 2014
1 parent ea0c7a8 commit eb6725f
Show file tree
Hide file tree
Showing 12 changed files with 172 additions and 6 deletions.
13 changes: 13 additions & 0 deletions chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ void BluetoothDeviceToApiDevice(const device::BluetoothDevice& device,
out->paired.reset(new bool(device.IsPaired()));
out->connected.reset(new bool(device.IsConnected()));

int rssi = device.GetRSSI();
if (rssi != BluetoothDevice::kUnknownPower)
out->rssi.reset(new int(rssi));

if (*out->connected) {
int current_transmit_power = device.GetCurrentHostTransmitPower();
if (current_transmit_power != BluetoothDevice::kUnknownPower)
out->current_host_transmit_power.reset(new int(current_transmit_power));
int maximum_transmit_power = device.GetMaximumHostTransmitPower();
if (maximum_transmit_power != BluetoothDevice::kUnknownPower)
out->maximum_host_transmit_power.reset(new int(maximum_transmit_power));
}

std::vector<std::string>* string_uuids = new std::vector<std::string>();
const device::BluetoothDevice::UUIDList& uuids = device.GetUUIDs();
for (device::BluetoothDevice::UUIDList::const_iterator iter = uuids.begin();
Expand Down
5 changes: 5 additions & 0 deletions chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,11 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, DeviceInfo) {
.WillRepeatedly(testing::Return(0x240A));
EXPECT_CALL(*device1_.get(), GetDeviceID())
.WillRepeatedly(testing::Return(0x0400));
EXPECT_CALL(*device1_, GetRSSI()).WillRepeatedly(testing::Return(-42));
EXPECT_CALL(*device1_, GetCurrentHostTransmitPower())
.WillRepeatedly(testing::Return(-16));
EXPECT_CALL(*device1_, GetMaximumHostTransmitPower())
.WillRepeatedly(testing::Return(10));

BluetoothDevice::UUIDList uuids;
uuids.push_back(BluetoothUUID("1105"));
Expand Down
17 changes: 17 additions & 0 deletions chrome/common/extensions/api/bluetooth.idl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ namespace bluetooth {
// Indicates whether the device is currently connected to the system.
boolean? connected;

// Indicates the RSSI ("received signal strength indication") of the
// connection to the device, measured in dBm, to a resolution of 1dBm.
// If the device is currently connected, then measures the RSSI of the
// connection signal. Otherwise, measures the RSSI of the last inquiry sent
// to the device, where available. Absent if unavailable.
long? rssi;

// Indicates the host's current transmit power ("Tx power") for the
// connection to the device, measured in dBm, to a resolution of 1dBm.
// This value is only available if the device is currently connected.
long? currentHostTransmitPower;

// Indicates the host's maximum transmit power ("Tx power") for the
// connection to the device, measured in dBm, to a resolution of 1dBm.
// This value is only available if the device is currently connected.
long? maximumHostTransmitPower;

// UUIDs of protocols, profiles and services advertised by the device.
// For classic Bluetooth devices, this list is obtained from EIR data and
// SDP tables. For Low Energy devices, this list is obtained from AD and
Expand Down
25 changes: 25 additions & 0 deletions device/bluetooth/bluetooth_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class BluetoothDevice {
DEVICE_KEYBOARD_MOUSE_COMBO
};

// The value returned if the RSSI or transmit power cannot be read.
static const int kUnknownPower = 127;

// Possible errors passed back to an error callback function in case of a
// failed call to Connect().
enum ConnectErrorCode {
Expand Down Expand Up @@ -227,6 +230,28 @@ class BluetoothDevice {
// DEVICE_PERIPHERAL.
DeviceType GetDeviceType() const;

// Gets the "received signal strength indication" (RSSI) of the current
// connection to the device. The RSSI indicates the power present in the
// received radio signal, measured in dBm, to a resolution of 1dBm. Larger
// (typically, less negative) values indicate a stronger signal.
// If the device is not currently connected, then returns the RSSI read from
// the last inquiry that returned the device, where available. In case of an
// error, returns |kUnknownPower|. Otherwise, returns the connection's RSSI.
virtual int GetRSSI() const = 0;

// These two methods are used to read the current or maximum transmit power
// ("Tx power") of the current connection to the device. The transmit power
// indicates the strength of the signal broadcast from the host's Bluetooth
// antenna when communicating with the device, measured in dBm, to a
// resolution of 1dBm. Larger (typically, less negative) values
// indicate a stronger signal.
// It is only meaningful to call this method when there is a connection
// established to the device. If there is no connection, or in case of an
// error, returns |kUnknownPower|. Otherwise, returns the connection's
// transmit power.
virtual int GetCurrentHostTransmitPower() const = 0;
virtual int GetMaximumHostTransmitPower() const = 0;

// Indicates whether the device is known to support pairing based on its
// device class and address.
bool IsPairable() const;
Expand Down
15 changes: 15 additions & 0 deletions device/bluetooth/bluetooth_device_chromeos.cc
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,21 @@ uint16 BluetoothDeviceChromeOS::GetDeviceID() const {
return device_id;
}

int BluetoothDeviceChromeOS::GetRSSI() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

int BluetoothDeviceChromeOS::GetCurrentHostTransmitPower() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

int BluetoothDeviceChromeOS::GetMaximumHostTransmitPower() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

bool BluetoothDeviceChromeOS::IsPaired() const {
BluetoothDeviceClient::Properties* properties =
DBusThreadManager::Get()->GetBluetoothDeviceClient()->
Expand Down
3 changes: 3 additions & 0 deletions device/bluetooth/bluetooth_device_chromeos.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class BluetoothDeviceChromeOS
virtual uint16 GetVendorID() const OVERRIDE;
virtual uint16 GetProductID() const OVERRIDE;
virtual uint16 GetDeviceID() const OVERRIDE;
virtual int GetRSSI() const OVERRIDE;
virtual int GetCurrentHostTransmitPower() const OVERRIDE;
virtual int GetMaximumHostTransmitPower() const OVERRIDE;
virtual bool IsPaired() const OVERRIDE;
virtual bool IsConnected() const OVERRIDE;
virtual bool IsConnectable() const OVERRIDE;
Expand Down
10 changes: 10 additions & 0 deletions device/bluetooth/bluetooth_device_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_MAC_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_MAC_H_

#import <IOBluetooth/IOBluetooth.h>

#include <string>

#include "base/basictypes.h"
Expand Down Expand Up @@ -32,6 +34,9 @@ class BluetoothDeviceMac : public BluetoothDevice {
virtual uint16 GetVendorID() const OVERRIDE;
virtual uint16 GetProductID() const OVERRIDE;
virtual uint16 GetDeviceID() const OVERRIDE;
virtual int GetRSSI() const OVERRIDE;
virtual int GetCurrentHostTransmitPower() const OVERRIDE;
virtual int GetMaximumHostTransmitPower() const OVERRIDE;
virtual bool IsPaired() const OVERRIDE;
virtual bool IsConnected() const OVERRIDE;
virtual bool IsConnectable() const OVERRIDE;
Expand Down Expand Up @@ -72,6 +77,11 @@ class BluetoothDeviceMac : public BluetoothDevice {
private:
friend class BluetoothAdapterMac;

// Implementation to read the host's transmit power level of type
// |power_level_type|.
int GetHostTransmitPower(
BluetoothHCITransmitPowerLevelType power_level_type) const;

// List of observers interested in event notifications from us.
ObserverList<Observer> observers_;

Expand Down
63 changes: 57 additions & 6 deletions device/bluetooth/bluetooth_device_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@

#include "device/bluetooth/bluetooth_device_mac.h"

#include <IOBluetooth/Bluetooth.h>
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothSDPServiceRecord.h>
#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>

#include <string>

#include "base/basictypes.h"
Expand All @@ -28,13 +23,23 @@

@interface IOBluetoothDevice (LionSDKDeclarations)
- (NSString*)addressString;
- (NSString*)name;
- (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)
Expand Down Expand Up @@ -84,6 +89,30 @@ - (NSArray*)services;
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];
}
Expand Down Expand Up @@ -183,4 +212,26 @@ - (NSArray*)services;
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;
}

} // namespace device
15 changes: 15 additions & 0 deletions device/bluetooth/bluetooth_device_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,21 @@ uint16 BluetoothDeviceWin::GetDeviceID() const {
return 0;
}

int BluetoothDeviceWin::GetRSSI() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

int BluetoothDeviceWin::GetCurrentHostTransmitPower() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

int BluetoothDeviceWin::GetMaximumHostTransmitPower() const {
NOTIMPLEMENTED();
return kUnknownPower;
}

bool BluetoothDeviceWin::IsPaired() const {
return paired_;
}
Expand Down
3 changes: 3 additions & 0 deletions device/bluetooth/bluetooth_device_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class BluetoothDeviceWin : public BluetoothDevice {
virtual uint16 GetVendorID() const OVERRIDE;
virtual uint16 GetProductID() const OVERRIDE;
virtual uint16 GetDeviceID() const OVERRIDE;
virtual int GetRSSI() const OVERRIDE;
virtual int GetCurrentHostTransmitPower() const OVERRIDE;
virtual int GetMaximumHostTransmitPower() const OVERRIDE;
virtual bool IsPaired() const OVERRIDE;
virtual bool IsConnected() const OVERRIDE;
virtual bool IsConnectable() const OVERRIDE;
Expand Down
6 changes: 6 additions & 0 deletions device/bluetooth/test/mock_bluetooth_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ MockBluetoothDevice::MockBluetoothDevice(MockBluetoothAdapter* adapter,
.WillByDefault(testing::Return(address_));
ON_CALL(*this, GetDeviceType())
.WillByDefault(testing::Return(DEVICE_UNKNOWN));
ON_CALL(*this, GetRSSI())
.WillByDefault(testing::Return(kUnknownPower));
ON_CALL(*this, GetCurrentHostTransmitPower())
.WillByDefault(testing::Return(kUnknownPower));
ON_CALL(*this, GetMaximumHostTransmitPower())
.WillByDefault(testing::Return(kUnknownPower));
ON_CALL(*this, GetVendorIDSource())
.WillByDefault(testing::Return(VENDOR_ID_UNKNOWN));
ON_CALL(*this, GetVendorID())
Expand Down
3 changes: 3 additions & 0 deletions device/bluetooth/test/mock_bluetooth_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class MockBluetoothDevice : public BluetoothDevice {
MOCK_CONST_METHOD0(GetDeviceID, uint16());
MOCK_CONST_METHOD0(GetName, base::string16());
MOCK_CONST_METHOD0(GetDeviceType, BluetoothDevice::DeviceType());
MOCK_CONST_METHOD0(GetRSSI, int());
MOCK_CONST_METHOD0(GetCurrentHostTransmitPower, int());
MOCK_CONST_METHOD0(GetMaximumHostTransmitPower, int());
MOCK_CONST_METHOD0(IsPaired, bool());
MOCK_CONST_METHOD0(IsConnected, bool());
MOCK_CONST_METHOD0(IsConnectable, bool());
Expand Down

0 comments on commit eb6725f

Please sign in to comment.