diff options
author | gogerald <gogerald@chromium.org> | 2016-02-02 13:16:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-02 21:18:01 +0000 |
commit | 6d6e034f20421ee76fc70b4124370e7c8d600b7e (patch) | |
tree | 321ac90d76e64857467a4ffd9b782f80b3e09fc4 /device | |
parent | e14afa03e4594eb6aeafe7ccd093d354d03c1709 (diff) | |
download | chromium_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.cc | 81 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_low_energy_win.h | 13 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_task_manager_win.cc | 60 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_task_manager_win.h | 12 |
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_; |