Commit 9c9b3611 authored by rpaquay@chromium.org's avatar rpaquay@chromium.org

Retrieve "connected" property from BLE devices.

We have to use the SetupDIGetDeviceProperty API to retrieve this specific property, as the "connected" status is something common to many PnP devices.

BUG=388016

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=282212

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282633 0039d316-1c4b-4281-b951-d872f2087c98
parent 907f235f
......@@ -4,6 +4,10 @@
#include "device/bluetooth/bluetooth_low_energy_win.h"
#include <cfg.h>
#define INITGUID // For DEVPKEY_Xxxx guid/pid pairs
#include <devpkey.h>
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/windows_version.h"
......@@ -11,6 +15,7 @@
namespace {
using device::win::DeviceRegistryPropertyValue;
using device::win::DevicePropertyValue;
const char kPlatformNotSupported[] =
"Bluetooth Low energy is only supported on Windows 8 and later.";
......@@ -125,6 +130,47 @@ bool CheckExpectedLength(size_t actual_length,
return true;
}
bool CollectBluetoothLowEnergyDeviceProperty(
const ScopedDeviceInfoSetHandle& device_info_handle,
PSP_DEVINFO_DATA device_info_data,
const DEVPROPKEY& key,
scoped_ptr<DevicePropertyValue>* value,
std::string* error) {
DWORD required_length;
DEVPROPTYPE prop_type;
BOOL success = SetupDiGetDeviceProperty(device_info_handle,
device_info_data,
&key,
&prop_type,
NULL,
0,
&required_length,
0);
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
return false;
scoped_ptr<uint8_t[]> prop_value(new uint8_t[required_length]);
DWORD actual_length = required_length;
success = SetupDiGetDeviceProperty(device_info_handle,
device_info_data,
&key,
&prop_type,
prop_value.get(),
actual_length,
&required_length,
0);
if (!CheckSuccess(!!success, kDeviceInfoError, error))
return false;
if (!CheckExpectedLength(
actual_length, required_length, kDeviceInfoError, error)) {
return false;
}
(*value) = scoped_ptr<DevicePropertyValue>(
new DevicePropertyValue(prop_type, prop_value.Pass(), actual_length));
return true;
}
bool CollectBluetoothLowEnergyDeviceRegistryProperty(
const ScopedDeviceInfoSetHandle& device_info_handle,
PSP_DEVINFO_DATA device_info_data,
......@@ -142,7 +188,7 @@ bool CollectBluetoothLowEnergyDeviceRegistryProperty(
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
return false;
scoped_ptr<UINT8[]> property_value(new UINT8[required_length]);
scoped_ptr<uint8_t[]> property_value(new uint8_t[required_length]);
ULONG actual_length = required_length;
DWORD property_type;
success = SetupDiGetDeviceRegistryProperty(device_info_handle,
......@@ -155,8 +201,9 @@ bool CollectBluetoothLowEnergyDeviceRegistryProperty(
if (!CheckSuccess(!!success, kDeviceInfoError, error))
return false;
if (!CheckExpectedLength(
actual_length, required_length, kDeviceInfoError, error))
actual_length, required_length, kDeviceInfoError, error)) {
return false;
}
(*value) = DeviceRegistryPropertyValue::Create(
property_type, property_value.Pass(), actual_length).Pass();
......@@ -255,6 +302,29 @@ bool CollectBluetoothLowEnergyDeviceAddress(
device_info->id, &device_info->address, error);
}
bool CollectBluetoothLowEnergyDeviceStatus(
const ScopedDeviceInfoSetHandle& device_info_handle,
PSP_DEVINFO_DATA device_info_data,
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>& device_info,
std::string* error) {
scoped_ptr<DevicePropertyValue> value;
if (!CollectBluetoothLowEnergyDeviceProperty(device_info_handle,
device_info_data,
DEVPKEY_Device_DevNodeStatus,
&value,
error)) {
return false;
}
if (value->property_type() != DEVPROP_TYPE_UINT32) {
*error = kDeviceInfoError;
return false;
}
device_info->connected = !(value->AsUint32() & DN_DEVICE_DISCONNECTED);
return true;
}
bool CollectBluetoothLowEnergyDeviceInfo(
const ScopedDeviceInfoSetHandle& device_info_handle,
PSP_DEVICE_INTERFACE_DATA device_interface_data,
......@@ -271,7 +341,7 @@ bool CollectBluetoothLowEnergyDeviceInfo(
if (!CheckInsufficientBuffer(!!success, kDeviceInfoError, error))
return false;
scoped_ptr<UINT8[]> interface_data(new UINT8[required_length]);
scoped_ptr<uint8_t[]> interface_data(new uint8_t[required_length]);
ZeroMemory(interface_data.get(), required_length);
PSP_DEVICE_INTERFACE_DETAIL_DATA device_interface_detail_data =
......@@ -292,8 +362,9 @@ bool CollectBluetoothLowEnergyDeviceInfo(
if (!CheckSuccess(!!success, kDeviceInfoError, error))
return false;
if (!CheckExpectedLength(
actual_length, required_length, kDeviceInfoError, error))
actual_length, required_length, kDeviceInfoError, error)) {
return false;
}
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo> result(
new device::win::BluetoothLowEnergyDeviceInfo());
......@@ -311,6 +382,10 @@ bool CollectBluetoothLowEnergyDeviceInfo(
device_info_handle, &device_info_data, result, error)) {
return false;
}
if (!CollectBluetoothLowEnergyDeviceStatus(
device_info_handle, &device_info_data, result, error)) {
return false;
}
(*device_info) = result.Pass();
return true;
}
......@@ -322,7 +397,7 @@ DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
DWORD device_index,
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
std::string* error) {
// Enumerate device of LE_DEVICE interface class
// Enumerate device of BLUETOOTHLE_DEVICE interface class
GUID BluetoothInterfaceGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
......@@ -341,8 +416,9 @@ DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
}
if (!CollectBluetoothLowEnergyDeviceInfo(
device_info_handle, &device_interface_data, device_info, error))
device_info_handle, &device_interface_data, device_info, error)) {
return kError;
}
return kOk;
}
......@@ -428,6 +504,28 @@ DWORD DeviceRegistryPropertyValue::AsDWORD() const {
return *value;
}
DevicePropertyValue::DevicePropertyValue(DEVPROPTYPE property_type,
scoped_ptr<uint8_t[]> value,
size_t value_size)
: property_type_(property_type),
value_(value.Pass()),
value_size_(value_size) {
}
uint32_t DevicePropertyValue::AsUint32() const {
CHECK_EQ(property_type_, static_cast<DEVPROPTYPE>(DEVPROP_TYPE_UINT32));
CHECK_EQ(value_size_, sizeof(uint32_t));
return *reinterpret_cast<uint32_t*>(value_.get());
}
BluetoothLowEnergyDeviceInfo::BluetoothLowEnergyDeviceInfo()
: connected(false) {
address.ullLong = BLUETOOTH_NULL_ADDRESS;
}
BluetoothLowEnergyDeviceInfo::~BluetoothLowEnergyDeviceInfo() {
}
bool IsBluetoothLowEnergySupported() {
return base::win::GetVersion() >= base::win::VERSION_WIN8;
}
......
......@@ -53,7 +53,8 @@ class DeviceRegistryPropertyValue {
// Creates a property value instance, where |property_type| is one of REG_xxx
// registry value type (e.g. REG_SZ, REG_DWORD), |value| is a byte array
// containing the propery value and |value_size| is the number of bytes in
// |value|. Note the returned instance takes ownership of |value| array.
// |value|. Note the returned instance takes ownership of the bytes in
// |value|.
static scoped_ptr<DeviceRegistryPropertyValue> Create(
DWORD property_type,
scoped_ptr<uint8_t[]> value,
......@@ -78,16 +79,41 @@ class DeviceRegistryPropertyValue {
DISALLOW_COPY_AND_ASSIGN(DeviceRegistryPropertyValue);
};
// Represents the value associated to a DEVPROPKEY.
class DevicePropertyValue {
public:
// Creates a property value instance, where |property_type| is one of
// DEVPROP_TYPE_xxx value type , |value| is a byte array containing the
// propery value and |value_size| is the number of bytes in |value|. Note the
// returned instance takes ownership of the bytes in |value|.
DevicePropertyValue(DEVPROPTYPE property_type,
scoped_ptr<uint8_t[]> value,
size_t value_size);
DEVPROPTYPE property_type() const { return property_type_; }
uint32_t AsUint32() const;
private:
DEVPROPTYPE property_type_;
scoped_ptr<uint8_t[]> value_;
size_t value_size_;
DISALLOW_COPY_AND_ASSIGN(DevicePropertyValue);
};
// Returns true only on Windows platforms supporting Bluetooth Low Energy.
bool IsBluetoothLowEnergySupported();
struct BluetoothLowEnergyDeviceInfo {
BluetoothLowEnergyDeviceInfo() { address.ullLong = BLUETOOTH_NULL_ADDRESS; }
BluetoothLowEnergyDeviceInfo();
~BluetoothLowEnergyDeviceInfo();
base::FilePath path;
std::string id;
std::string friendly_name;
BLUETOOTH_ADDRESS address;
bool connected;
};
// Enumerates the list of known (i.e. already paired) Bluetooth LE devices on
......
......@@ -71,4 +71,15 @@ TEST_F(BluetoothLowEnergyWinTest, DeviceRegistryPropertyValueAsDWORD) {
EXPECT_EQ(test_value, value->AsDWORD());
}
TEST_F(BluetoothLowEnergyWinTest, DevicePropertyValueAsUint32) {
uint32_t test_value = 5u;
size_t buffer_size = sizeof(uint32_t);
scoped_ptr<uint8_t[]> buffer(new uint8_t[buffer_size]);
memcpy(buffer.get(), &test_value, buffer_size);
scoped_ptr<device::win::DevicePropertyValue> value(
new device::win::DevicePropertyValue(
DEVPROP_TYPE_UINT32, buffer.Pass(), buffer_size));
EXPECT_EQ(test_value, value->AsUint32());
}
} // namespace device
......@@ -406,6 +406,7 @@ void BluetoothTaskManagerWin::GetKnownDevices() {
DeviceState* device_state = new DeviceState();
device_state->name = device_info->friendly_name;
device_state->address = BluetoothAddressToString(device_info->address);
device_state->connected = device_info->connected;
device_list->push_back(device_state);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment