summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
authorgogerald <gogerald@chromium.org>2016-02-02 13:16:09 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-02 21:18:01 +0000
commit6d6e034f20421ee76fc70b4124370e7c8d600b7e (patch)
tree321ac90d76e64857467a4ffd9b782f80b3e09fc4 /device
parente14afa03e4594eb6aeafe7ccd093d354d03c1709 (diff)
downloadchromium_src-6d6e034f20421ee76fc70b4124370e7c8d600b7e.zip
chromium_src-6d6e034f20421ee76fc70b4124370e7c8d600b7e.tar.gz
chromium_src-6d6e034f20421ee76fc70b4124370e7c8d600b7e.tar.bz2
Add service attribute handle and service device path to BLE Gatt service info
Attribute handle uniquely identified a service on a device. Operation of included characteristics and descriptors of a service needs service device path instead of resident device device path. BUG=579202 Review URL: https://codereview.chromium.org/1655593002 Cr-Commit-Position: refs/heads/master@{#373039}
Diffstat (limited to 'device')
-rw-r--r--device/bluetooth/bluetooth_low_energy_win.cc81
-rw-r--r--device/bluetooth/bluetooth_low_energy_win.h13
-rw-r--r--device/bluetooth/bluetooth_task_manager_win.cc60
-rw-r--r--device/bluetooth/bluetooth_task_manager_win.h12
4 files changed, 142 insertions, 24 deletions
diff --git a/device/bluetooth/bluetooth_low_energy_win.cc b/device/bluetooth/bluetooth_low_energy_win.cc
index 6e1cb81..54af750 100644
--- a/device/bluetooth/bluetooth_low_energy_win.cc
+++ b/device/bluetooth/bluetooth_low_energy_win.cc
@@ -405,6 +405,7 @@ bool CollectBluetoothLowEnergyDeviceServices(
BluetoothLowEnergyServiceInfo* service_info =
new BluetoothLowEnergyServiceInfo();
service_info->uuid = gatt_service.ServiceUuid;
+ service_info->attribute_handle = gatt_service.AttributeHandle;
services->push_back(service_info);
}
@@ -462,7 +463,11 @@ bool CollectBluetoothLowEnergyDeviceInfo(
}
if (!CollectBluetoothLowEnergyDeviceFriendlyName(
device_info_handle, &device_info_data, result, error)) {
- return false;
+ // Only fail if not the GATT service device interface, which doesn't have a
+ // friendly name.
+ if (device_info_data.ClassGuid !=
+ GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE)
+ return false;
}
if (!CollectBluetoothLowEnergyDeviceAddress(
device_info_handle, &device_info_data, result, error)) {
@@ -478,13 +483,15 @@ bool CollectBluetoothLowEnergyDeviceInfo(
enum DeviceInfoResult { kOk, kError, kNoMoreDevices };
+// For |device_interface_guid| see the Note of below
+// EnumerateKnownBLEOrBLEGattServiceDevices interface.
DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
+ GUID device_interface_guid,
const ScopedDeviceInfoSetHandle& device_info_handle,
DWORD device_index,
scoped_ptr<device::win::BluetoothLowEnergyDeviceInfo>* device_info,
std::string* error) {
- // Enumerate device of BLUETOOTHLE_DEVICE interface class
- GUID BluetoothInterfaceGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
+ GUID BluetoothInterfaceGUID = device_interface_guid;
SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
BOOL success = ::SetupDiEnumDeviceInterfaces(device_info_handle.Get(),
@@ -510,9 +517,11 @@ DeviceInfoResult EnumerateSingleBluetoothLowEnergyDevice(
}
// Opens a Device Info Set that can be used to enumerate Bluetooth LE devices
-// present on the machine.
-HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle) {
- GUID BluetoothClassGUID = GUID_BLUETOOTHLE_DEVICE_INTERFACE;
+// present on the machine. For |device_interface_guid| see the Note of below
+// EnumerateKnownBLEOrBLEGattServiceDevices interface.
+HRESULT OpenBluetoothLowEnergyDevices(GUID device_interface_guid,
+ ScopedDeviceInfoSetHandle* handle) {
+ GUID BluetoothClassGUID = device_interface_guid;
ScopedDeviceInfoSetHandle result(SetupDiGetClassDevs(
&BluetoothClassGUID, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
if (!result.IsValid()) {
@@ -523,6 +532,38 @@ HRESULT OpenBluetoothLowEnergyDevices(ScopedDeviceInfoSetHandle* handle) {
return S_OK;
}
+// Enumerate known Bluetooth low energy devices or Bluetooth low energy GATT
+// service devices according to |device_interface_guid|.
+// Note: |device_interface_guid| = GUID_BLUETOOTHLE_DEVICE_INTERFACE corresponds
+// Bluetooth low energy devices. |device_interface_guid| =
+// GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE corresponds Bluetooth low energy
+// Gatt service devices.
+bool EnumerateKnownBLEOrBLEGattServiceDevices(
+ GUID guid,
+ ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
+ std::string* error) {
+ ScopedDeviceInfoSetHandle info_set_handle;
+ HRESULT hr = OpenBluetoothLowEnergyDevices(guid, &info_set_handle);
+ if (FAILED(hr)) {
+ *error = FormatBluetoothError(kDeviceEnumError, hr);
+ return false;
+ }
+
+ for (DWORD i = 0;; ++i) {
+ scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info;
+ DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice(
+ guid, info_set_handle, i, &device_info, error);
+ switch (result) {
+ case kNoMoreDevices:
+ return true;
+ case kError:
+ return false;
+ case kOk:
+ devices->push_back(std::move(device_info));
+ }
+ }
+}
+
} // namespace
namespace device {
@@ -619,26 +660,20 @@ bool EnumerateKnownBluetoothLowEnergyDevices(
return false;
}
- ScopedDeviceInfoSetHandle info_set_handle;
- HRESULT hr = OpenBluetoothLowEnergyDevices(&info_set_handle);
- if (FAILED(hr)) {
- *error = FormatBluetoothError(kDeviceEnumError, hr);
+ return EnumerateKnownBLEOrBLEGattServiceDevices(
+ GUID_BLUETOOTHLE_DEVICE_INTERFACE, devices, error);
+}
+
+bool EnumerateKnownBluetoothLowEnergyGattServiceDevices(
+ ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
+ std::string* error) {
+ if (!IsBluetoothLowEnergySupported()) {
+ *error = kPlatformNotSupported;
return false;
}
- for (DWORD i = 0;; ++i) {
- scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info;
- DeviceInfoResult result = EnumerateSingleBluetoothLowEnergyDevice(
- info_set_handle, i, &device_info, error);
- switch (result) {
- case kNoMoreDevices:
- return true;
- case kError:
- return false;
- case kOk:
- devices->push_back(device_info.Pass());
- }
- }
+ return EnumerateKnownBLEOrBLEGattServiceDevices(
+ GUID_BLUETOOTH_GATT_SERVICE_DEVICE_INTERFACE, devices, error);
}
bool EnumerateKnownBluetoothLowEnergyServices(
diff --git a/device/bluetooth/bluetooth_low_energy_win.h b/device/bluetooth/bluetooth_low_energy_win.h
index fd73b2c..52347ce 100644
--- a/device/bluetooth/bluetooth_low_energy_win.h
+++ b/device/bluetooth/bluetooth_low_energy_win.h
@@ -83,6 +83,8 @@ struct BluetoothLowEnergyServiceInfo {
~BluetoothLowEnergyServiceInfo();
BTH_LE_UUID uuid;
+ // Attribute handle uniquely identifies this service on the device.
+ USHORT attribute_handle = 0;
};
struct BluetoothLowEnergyDeviceInfo {
@@ -107,6 +109,17 @@ bool EnumerateKnownBluetoothLowEnergyDevices(
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
std::string* error);
+// Enumerates the list of known Bluetooth LE GATT service devices on this
+// machine (a Bluetooth LE device usually has more than one GATT
+// services that each of them has a device interface on the machine). In case
+// of error, returns false and sets |error| with an error message describing the
+// problem.
+// Note: This function returns an error if Bluetooth Low Energy is not supported
+// on this Windows platform.
+bool EnumerateKnownBluetoothLowEnergyGattServiceDevices(
+ ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
+ std::string* error);
+
// Enumerates the list of known (i.e. cached) GATT services for a given
// Bluetooth LE device |device_path| into |services|. In case of error, returns
// false and sets |error| with an error message describing the problem. Note:
diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc
index a3c75b6..b34718f 100644
--- a/device/bluetooth/bluetooth_task_manager_win.cc
+++ b/device/bluetooth/bluetooth_task_manager_win.cc
@@ -526,7 +526,8 @@ bool BluetoothTaskManagerWin::DiscoverServices(
} else {
if (!DiscoverLowEnergyDeviceServices(device->path,
service_record_states)) {
- return false;
+ return SearchForGattServiceDevicePaths(device->address,
+ service_record_states);
}
}
}
@@ -650,9 +651,66 @@ bool BluetoothTaskManagerWin::DiscoverLowEnergyDeviceServices(
ServiceRecordState* service_state = new ServiceRecordState();
service_state->gatt_uuid =
BluetoothLowEnergyUuidToBluetoothUuid((*iter2)->uuid);
+ service_state->attribute_handle = (*iter2)->attribute_handle;
service_record_states->push_back(service_state);
}
return true;
}
+// Each GATT service of a BLE device will be listed on the machine as a BLE
+// device interface with a matching service attribute handle. This interface
+// lists all GATT service devices and matches them back to correspond GATT
+// service of the BLE device according to their address and included service
+// attribute handles, as we did not find a more neat way to bond them.
+bool BluetoothTaskManagerWin::SearchForGattServiceDevicePaths(
+ const std::string device_address,
+ ScopedVector<ServiceRecordState>* service_record_states) {
+ std::string error;
+
+ // List all known GATT service devices on the machine.
+ ScopedVector<win::BluetoothLowEnergyDeviceInfo> gatt_service_devices;
+ bool success = win::EnumerateKnownBluetoothLowEnergyGattServiceDevices(
+ &gatt_service_devices, &error);
+ if (!success) {
+ LogPollingError(error.c_str(), 0);
+ return false;
+ }
+
+ for (auto gatt_service_device : gatt_service_devices) {
+ // Only care about the service devices with |device_address|.
+ if (BluetoothAddressToCanonicalString(gatt_service_device->address) !=
+ device_address) {
+ continue;
+ }
+
+ // Discover this service device's contained services.
+ ScopedVector<win::BluetoothLowEnergyServiceInfo> gatt_services;
+ if (!win::EnumerateKnownBluetoothLowEnergyServices(
+ gatt_service_device->path, &gatt_services, &error)) {
+ LogPollingError(error.c_str(), 0);
+ continue;
+ }
+
+ // Usually each service device correspond to one Gatt service.
+ if (gatt_services.size() > 1) {
+ LOG(WARNING) << "This GATT service device contains more than one ("
+ << gatt_services.size() << ") services";
+ }
+
+ // Associate service device to corresponding service record. Attribute
+ // handle is unique on one device.
+ for (auto gatt_service : gatt_services) {
+ for (auto service_record_state : *service_record_states) {
+ if (service_record_state->attribute_handle ==
+ gatt_service->attribute_handle) {
+ service_record_state->path = gatt_service_device->path;
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
} // namespace device
diff --git a/device/bluetooth/bluetooth_task_manager_win.h b/device/bluetooth/bluetooth_task_manager_win.h
index 8882d42..4cde9e6 100644
--- a/device/bluetooth/bluetooth_task_manager_win.h
+++ b/device/bluetooth/bluetooth_task_manager_win.h
@@ -56,6 +56,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
std::vector<uint8_t> sdp_bytes;
// Properties specific to Bluetooth LE devices.
BluetoothUUID gatt_uuid;
+ uint16_t attribute_handle;
+ // GATT service device path.
+ // Note: Operation of the included characteristics and descriptors of this
+ // service must use service device path instead of resident device device
+ // path.
+ base::FilePath path;
};
struct DEVICE_BLUETOOTH_EXPORT DeviceState {
@@ -196,6 +202,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
const base::FilePath& device_path,
ScopedVector<ServiceRecordState>* service_record_states);
+ // Search for device paths of the GATT services in |*service_record_states|
+ // from |device_address|.
+ bool SearchForGattServiceDevicePaths(
+ const std::string device_address,
+ ScopedVector<ServiceRecordState>* service_record_states);
+
// UI task runner reference.
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;