Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: device/bluetooth/bluetooth_task_manager_win.cc

Issue 424093004: Improve processing of Bluetooth device discovery on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address code review feedback (nits and memory leak). Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « device/bluetooth/bluetooth_task_manager_win.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: device/bluetooth/bluetooth_task_manager_win.cc
diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc
index 7bfc32b658eda1c961ce5e37e9f423031f114565..db2540b12e77ddf41d8132c8b1ab5a904e590c6a 100644
--- a/device/bluetooth/bluetooth_task_manager_win.cc
+++ b/device/bluetooth/bluetooth_task_manager_win.cc
@@ -17,6 +17,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/win/scoped_handle.h"
+#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_init_win.h"
#include "device/bluetooth/bluetooth_low_energy_win.h"
#include "device/bluetooth/bluetooth_service_record_win.h"
@@ -28,21 +29,31 @@ const int kNumThreadsInWorkerPool = 3;
const char kBluetoothThreadName[] = "BluetoothPollingThreadWin";
const int kMaxNumDeviceAddressChar = 127;
const int kServiceDiscoveryResultBufferSize = 5000;
-const int kMaxDeviceDiscoveryTimeout = 48;
-typedef device::BluetoothTaskManagerWin::ServiceRecordState ServiceRecordState;
+// See http://goo.gl/iNTRQe: cTimeoutMultiplier: A value that indicates the time
+// out for the inquiry, expressed in increments of 1.28 seconds. For example, an
+// inquiry of 12.8 seconds has a cTimeoutMultiplier value of 10. The maximum
+// value for this member is 48. When a value greater than 48 is used, the
+// calling function immediately fails and returns
+const int kMaxDeviceDiscoveryTimeoutMultiplier = 48;
-std::string BluetoothAddressToString(const BLUETOOTH_ADDRESS& btha) {
- return base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
- btha.rgBytes[5],
- btha.rgBytes[4],
- btha.rgBytes[3],
- btha.rgBytes[2],
- btha.rgBytes[1],
- btha.rgBytes[0]);
-}
+typedef device::BluetoothTaskManagerWin::ServiceRecordState ServiceRecordState;
-device::BluetoothUUID BluetoothLowEnergyUuidToUBluetoothUuid(
+// Note: The string returned here must have the same format as
+// BluetoothDevice::CanonicalizeAddress.
+std::string BluetoothAddressToCanonicalString(const BLUETOOTH_ADDRESS& btha) {
+ std::string result = base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
+ btha.rgBytes[5],
+ btha.rgBytes[4],
+ btha.rgBytes[3],
+ btha.rgBytes[2],
+ btha.rgBytes[1],
+ btha.rgBytes[0]);
+ DCHECK_EQ(result, device::BluetoothDevice::CanonicalizeAddress(result));
+ return result;
+}
+
+device::BluetoothUUID BluetoothLowEnergyUuidToBluetoothUuid(
const BTH_LE_UUID& bth_le_uuid) {
if (bth_le_uuid.IsShortUuid) {
std::string uuid_hex =
@@ -76,7 +87,7 @@ void GetAdapterState(HANDLE adapter_handle,
ERROR_SUCCESS == BluetoothGetRadioInfo(adapter_handle,
&adapter_info)) {
name = base::SysWideToUTF8(adapter_info.szName);
- address = BluetoothAddressToString(adapter_info.address);
+ address = BluetoothAddressToCanonicalString(adapter_info.address);
powered = !!BluetoothIsConnectable(adapter_handle);
}
state->name = name;
@@ -87,55 +98,13 @@ void GetAdapterState(HANDLE adapter_handle,
void GetDeviceState(const BLUETOOTH_DEVICE_INFO& device_info,
device::BluetoothTaskManagerWin::DeviceState* state) {
state->name = base::SysWideToUTF8(device_info.szName);
- state->address = BluetoothAddressToString(device_info.Address);
+ state->address = BluetoothAddressToCanonicalString(device_info.Address);
state->bluetooth_class = device_info.ulClassofDevice;
state->visible = true;
state->connected = !!device_info.fConnected;
state->authenticated = !!device_info.fAuthenticated;
}
-void DiscoverDeviceServices(
- const std::string& device_address,
- const GUID& protocol_uuid,
- ScopedVector<ServiceRecordState>* service_record_states) {
- // Bluetooth and WSAQUERYSET for Service Inquiry. See http://goo.gl/2v9pyt.
- WSAQUERYSET sdp_query;
- ZeroMemory(&sdp_query, sizeof(sdp_query));
- sdp_query.dwSize = sizeof(sdp_query);
- GUID protocol = protocol_uuid;
- sdp_query.lpServiceClassId = &protocol;
- sdp_query.dwNameSpace = NS_BTH;
- wchar_t device_address_context[kMaxNumDeviceAddressChar];
- std::size_t length = base::SysUTF8ToWide("(" + device_address + ")").copy(
- device_address_context, kMaxNumDeviceAddressChar);
- device_address_context[length] = NULL;
- sdp_query.lpszContext = device_address_context;
- HANDLE sdp_handle;
- if (ERROR_SUCCESS !=
- WSALookupServiceBegin(&sdp_query, LUP_RETURN_ALL, &sdp_handle)) {
- return;
- }
- char sdp_buffer[kServiceDiscoveryResultBufferSize];
- LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer);
- while (true) {
- DWORD sdp_buffer_size = sizeof(sdp_buffer);
- if (ERROR_SUCCESS !=
- WSALookupServiceNext(
- sdp_handle, LUP_RETURN_ALL, &sdp_buffer_size, sdp_result_data)) {
- break;
- }
- ServiceRecordState* service_record_state = new ServiceRecordState();
- service_record_state->name =
- base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName);
- for (uint64 i = 0; i < sdp_result_data->lpBlob->cbSize; i++) {
- service_record_state->sdp_bytes.push_back(
- sdp_result_data->lpBlob->pBlobData[i]);
- }
- service_record_states->push_back(service_record_state);
- }
- WSALookupServiceEnd(sdp_handle);
-}
-
} // namespace
namespace device {
@@ -168,7 +137,8 @@ BluetoothTaskManagerWin::DeviceState::~DeviceState() {
BluetoothTaskManagerWin::BluetoothTaskManagerWin(
scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
: ui_task_runner_(ui_task_runner),
- discovering_(false) {
+ discovering_(false),
+ current_logging_batch_count_(0) {
}
BluetoothTaskManagerWin::~BluetoothTaskManagerWin() {
@@ -257,6 +227,38 @@ void BluetoothTaskManagerWin::PostStopDiscoveryTask() {
base::Bind(&BluetoothTaskManagerWin::StopDiscovery, this));
}
+void BluetoothTaskManagerWin::LogPollingError(const char* message,
+ int win32_error) {
+ const int kLogPeriodInMilliseconds = 60 * 1000;
+ const int kMaxMessagesPerLogPeriod = 10;
+
+ // Check if we need to discard this message
+ if (!current_logging_batch_ticks_.is_null()) {
+ if (base::TimeTicks::Now() - current_logging_batch_ticks_ <=
+ base::TimeDelta::FromMilliseconds(kLogPeriodInMilliseconds)) {
+ if (current_logging_batch_count_ >= kMaxMessagesPerLogPeriod)
+ return;
+ } else {
+ // The batch expired, reset it to "null".
+ current_logging_batch_ticks_ = base::TimeTicks();
+ }
+ }
+
+ // Keep track of this batch of messages
+ if (current_logging_batch_ticks_.is_null()) {
+ current_logging_batch_ticks_ = base::TimeTicks::Now();
+ current_logging_batch_count_ = 0;
+ }
+ ++current_logging_batch_count_;
+
+ // Log the message
+ if (win32_error == 0)
+ LOG(WARNING) << message;
+ else
+ LOG(WARNING) << message << ": "
+ << logging::SystemErrorCodeToString(win32_error);
+}
+
void BluetoothTaskManagerWin::OnAdapterStateChanged(const AdapterState* state) {
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
@@ -275,18 +277,11 @@ void BluetoothTaskManagerWin::OnDiscoveryStopped() {
DiscoveryStopped());
}
-void BluetoothTaskManagerWin::OnDevicesUpdated(
- const ScopedVector<DeviceState>* devices) {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
- DevicesUpdated(*devices));
-}
-
-void BluetoothTaskManagerWin::OnDevicesDiscovered(
+void BluetoothTaskManagerWin::OnDevicesPolled(
const ScopedVector<DeviceState>* devices) {
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
- DevicesDiscovered(*devices));
+ FOR_EACH_OBSERVER(
+ BluetoothTaskManagerWin::Observer, observers_, DevicesPolled(*devices));
}
void BluetoothTaskManagerWin::PollAdapter() {
@@ -372,7 +367,7 @@ void BluetoothTaskManagerWin::StopDiscovery() {
base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
}
-void BluetoothTaskManagerWin::DiscoverDevices(int timeout) {
+void BluetoothTaskManagerWin::DiscoverDevices(int timeout_multiplier) {
DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
if (!discovering_ || !adapter_handle_) {
ui_task_runner_->PostTask(
@@ -381,133 +376,252 @@ void BluetoothTaskManagerWin::DiscoverDevices(int timeout) {
return;
}
- ScopedVector<DeviceState>* device_list = new ScopedVector<DeviceState>();
- SearchDevices(timeout, false, device_list);
- if (device_list->empty()) {
- delete device_list;
- } else {
- DiscoverServices(device_list);
+ scoped_ptr<ScopedVector<DeviceState> > device_list(
+ new ScopedVector<DeviceState>());
+ if (SearchDevices(timeout_multiplier, false, device_list.get())) {
ui_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&BluetoothTaskManagerWin::OnDevicesDiscovered,
+ base::Bind(&BluetoothTaskManagerWin::OnDevicesPolled,
this,
- base::Owned(device_list)));
+ base::Owned(device_list.release())));
}
- if (timeout < kMaxDeviceDiscoveryTimeout) {
- bluetooth_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&BluetoothTaskManagerWin::DiscoverDevices,
- this,
- timeout + 1));
- } else {
+ if (timeout_multiplier < kMaxDeviceDiscoveryTimeoutMultiplier)
+ ++timeout_multiplier;
+ bluetooth_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &BluetoothTaskManagerWin::DiscoverDevices, this, timeout_multiplier));
+}
+
+void BluetoothTaskManagerWin::GetKnownDevices() {
+ scoped_ptr<ScopedVector<DeviceState> > device_list(
+ new ScopedVector<DeviceState>());
+ if (SearchDevices(1, true, device_list.get())) {
ui_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
- discovering_ = false;
+ base::Bind(&BluetoothTaskManagerWin::OnDevicesPolled,
+ this,
+ base::Owned(device_list.release())));
}
}
-void BluetoothTaskManagerWin::GetKnownDevices() {
- ScopedVector<DeviceState>* device_list = new ScopedVector<DeviceState>();
- SearchDevices(1, true, device_list);
-
- // Search for Bluetooth Low Energy devices
- if (win::IsBluetoothLowEnergySupported()) {
- ScopedVector<win::BluetoothLowEnergyDeviceInfo> btle_devices;
- std::string error;
- bool success =
- win::EnumerateKnownBluetoothLowEnergyDevices(&btle_devices, &error);
- if (success) {
- for (ScopedVector<win::BluetoothLowEnergyDeviceInfo>::iterator iter =
- btle_devices.begin();
- iter != btle_devices.end();
- ++iter) {
- win::BluetoothLowEnergyDeviceInfo* device_info = (*iter);
-
- DeviceState* device_state = new DeviceState();
- device_state->name = device_info->friendly_name;
- device_state->address = BluetoothAddressToString(device_info->address);
- device_state->visible = device_info->visible;
- device_state->authenticated = device_info->authenticated;
- device_state->connected = device_info->connected;
- device_state->path = device_info->path;
-
- ScopedVector<win::BluetoothLowEnergyServiceInfo> services;
- success = win::EnumerateKnownBluetoothLowEnergyServices(
- device_info, &services, &error);
- if (success) {
- for (ScopedVector<win::BluetoothLowEnergyServiceInfo>::iterator
- iter2 = services.begin();
- iter2 != services.end();
- ++iter2) {
- ServiceRecordState* service_state = new ServiceRecordState();
- service_state->gatt_uuid =
- BluetoothLowEnergyUuidToUBluetoothUuid((*iter2)->uuid);
- device_state->service_record_states.push_back(service_state);
- }
- }
- device_list->push_back(device_state);
+bool BluetoothTaskManagerWin::SearchDevices(
+ int timeout_multiplier,
+ bool search_cached_devices_only,
+ ScopedVector<DeviceState>* device_list) {
+ return SearchClassicDevices(
+ timeout_multiplier, search_cached_devices_only, device_list) &&
+ SearchLowEnergyDevices(device_list) &&
+ DiscoverServices(device_list, search_cached_devices_only);
+}
+
+bool BluetoothTaskManagerWin::SearchClassicDevices(
+ int timeout_multiplier,
+ bool search_cached_devices_only,
+ ScopedVector<DeviceState>* device_list) {
+ // Issues a device inquiry and waits for |timeout_multiplier| * 1.28 seconds.
+ BLUETOOTH_DEVICE_SEARCH_PARAMS device_search_params;
+ ZeroMemory(&device_search_params, sizeof(device_search_params));
+ device_search_params.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
+ device_search_params.fReturnAuthenticated = 1;
+ device_search_params.fReturnRemembered = 1;
+ device_search_params.fReturnUnknown = (search_cached_devices_only ? 0 : 1);
+ device_search_params.fReturnConnected = 1;
+ device_search_params.fIssueInquiry = (search_cached_devices_only ? 0 : 1);
+ device_search_params.cTimeoutMultiplier = timeout_multiplier;
+
+ BLUETOOTH_DEVICE_INFO device_info;
+ ZeroMemory(&device_info, sizeof(device_info));
+ device_info.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
+ HBLUETOOTH_DEVICE_FIND handle =
+ BluetoothFindFirstDevice(&device_search_params, &device_info);
+ if (!handle) {
+ int last_error = GetLastError();
+ if (last_error == ERROR_NO_MORE_ITEMS) {
+ return true; // No devices is not an error.
+ }
+ LogPollingError("Error calling BluetoothFindFirstDevice", last_error);
+ return false;
+ }
+
+ while (true) {
+ DeviceState* device_state = new DeviceState();
+ GetDeviceState(device_info, device_state);
+ device_list->push_back(device_state);
+
+ // Reset device info before next call (as a safety precaution).
+ ZeroMemory(&device_info, sizeof(device_info));
+ device_info.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
+ if (!BluetoothFindNextDevice(handle, &device_info)) {
+ int last_error = GetLastError();
+ if (last_error == ERROR_NO_MORE_ITEMS) {
+ break; // No more items is expected error when done enumerating.
}
+ LogPollingError("Error calling BluetoothFindNextDevice", last_error);
+ BluetoothFindDeviceClose(handle);
+ return false;
}
}
- if (device_list->empty()) {
- delete device_list;
- return;
+ if (!BluetoothFindDeviceClose(handle)) {
+ LogPollingError("Error calling BluetoothFindDeviceClose", GetLastError());
+ return false;
}
- DiscoverServices(device_list);
- ui_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&BluetoothTaskManagerWin::OnDevicesUpdated,
- this,
- base::Owned(device_list)));
+ return true;
}
-void BluetoothTaskManagerWin::SearchDevices(
- int timeout,
- bool search_cached_devices_only,
+bool BluetoothTaskManagerWin::SearchLowEnergyDevices(
ScopedVector<DeviceState>* device_list) {
- BLUETOOTH_DEVICE_SEARCH_PARAMS device_search_params = {
- sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS),
- 1, // return authenticated devices
- 1, // return remembered devicess
- search_cached_devices_only ? 0 : 1, // return unknown devices
- 1, // return connected devices
- search_cached_devices_only ? 0 : 1, // issue a new inquiry
- timeout, // timeout for the inquiry in increments of 1.28 seconds
- adapter_handle_
- };
-
- BLUETOOTH_DEVICE_INFO device_info = { sizeof(BLUETOOTH_DEVICE_INFO), 0 };
- // Issues a device inquiry and waits for |timeout| * 1.28 seconds.
- HBLUETOOTH_DEVICE_FIND handle =
- BluetoothFindFirstDevice(&device_search_params, &device_info);
- if (handle) {
- do {
- DeviceState* device_state = new DeviceState();
- GetDeviceState(device_info, device_state);
- device_list->push_back(device_state);
- } while (BluetoothFindNextDevice(handle, &device_info));
-
- BluetoothFindDeviceClose(handle);
+ if (!win::IsBluetoothLowEnergySupported())
+ return true; // Bluetooth LE not supported is not an error.
+
+ ScopedVector<win::BluetoothLowEnergyDeviceInfo> btle_devices;
+ std::string error;
+ bool success =
+ win::EnumerateKnownBluetoothLowEnergyDevices(&btle_devices, &error);
+ if (!success) {
+ LogPollingError(error.c_str(), 0);
+ return false;
+ }
+
+ for (ScopedVector<win::BluetoothLowEnergyDeviceInfo>::iterator iter =
+ btle_devices.begin();
+ iter != btle_devices.end();
+ ++iter) {
+ win::BluetoothLowEnergyDeviceInfo* device_info = (*iter);
+ DeviceState* device_state = new DeviceState();
+ device_state->name = device_info->friendly_name;
+ device_state->address =
+ BluetoothAddressToCanonicalString(device_info->address);
+ device_state->visible = device_info->visible;
+ device_state->authenticated = device_info->authenticated;
+ device_state->connected = device_info->connected;
+ device_state->path = device_info->path;
+ device_list->push_back(device_state);
}
+ return true;
}
-void BluetoothTaskManagerWin::DiscoverServices(
- ScopedVector<DeviceState>* device_list) {
+bool BluetoothTaskManagerWin::DiscoverServices(
+ ScopedVector<DeviceState>* device_list,
+ bool search_cached_services_only) {
DCHECK(bluetooth_task_runner_->RunsTasksOnCurrentThread());
net::EnsureWinsockInit();
for (ScopedVector<DeviceState>::iterator iter = device_list->begin();
iter != device_list->end();
++iter) {
- const std::string device_address = (*iter)->address;
+ DeviceState* device = (*iter);
ScopedVector<ServiceRecordState>* service_record_states =
&(*iter)->service_record_states;
- DiscoverDeviceServices(
- device_address, L2CAP_PROTOCOL_UUID, service_record_states);
+ if ((*iter)->is_bluetooth_classic()) {
+ if (!DiscoverClassicDeviceServices(device->address,
+ L2CAP_PROTOCOL_UUID,
+ search_cached_services_only,
+ service_record_states)) {
+ return false;
+ }
+ } else {
+ if (!DiscoverLowEnergyDeviceServices(device->path,
+ service_record_states)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool BluetoothTaskManagerWin::DiscoverClassicDeviceServices(
+ const std::string& device_address,
+ const GUID& protocol_uuid,
+ bool search_cached_services_only,
+ ScopedVector<ServiceRecordState>* service_record_states) {
+ // Bluetooth and WSAQUERYSET for Service Inquiry. See http://goo.gl/2v9pyt.
+ WSAQUERYSET sdp_query;
+ ZeroMemory(&sdp_query, sizeof(sdp_query));
+ sdp_query.dwSize = sizeof(sdp_query);
+ GUID protocol = protocol_uuid;
+ sdp_query.lpServiceClassId = &protocol;
+ sdp_query.dwNameSpace = NS_BTH;
+ wchar_t device_address_context[kMaxNumDeviceAddressChar];
+ std::size_t length = base::SysUTF8ToWide("(" + device_address + ")").copy(
+ device_address_context, kMaxNumDeviceAddressChar);
+ device_address_context[length] = NULL;
+ sdp_query.lpszContext = device_address_context;
+ DWORD control_flags = LUP_RETURN_ALL;
+ // See http://goo.gl/t1Hulo: "Applications should generally specify
+ // LUP_FLUSHCACHE. This flag instructs the system to ignore any cached
+ // information and establish an over-the-air SDP connection to the specified
+ // device to perform the SDP search. This non-cached operation may take
+ // several seconds (whereas a cached search returns quickly)."
+ // In summary, we need to specify LUP_FLUSHCACHE if we want to obtain the list
+ // of services for devices which have not been discovered before.
+ if (!search_cached_services_only)
+ control_flags |= LUP_FLUSHCACHE;
+ HANDLE sdp_handle;
+ if (ERROR_SUCCESS !=
+ WSALookupServiceBegin(&sdp_query, control_flags, &sdp_handle)) {
+ LogPollingError("Error calling WSALookupServiceBegin", WSAGetLastError());
+ return false;
+ }
+ char sdp_buffer[kServiceDiscoveryResultBufferSize];
+ LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer);
+ while (true) {
+ DWORD sdp_buffer_size = sizeof(sdp_buffer);
+ if (ERROR_SUCCESS !=
+ WSALookupServiceNext(
+ sdp_handle, control_flags, &sdp_buffer_size, sdp_result_data)) {
+ int last_error = WSAGetLastError();
+ if (last_error == WSA_E_NO_MORE || last_error == WSAENOMORE) {
+ break;
+ }
+ LogPollingError("Error calling WSALookupServiceNext", last_error);
+ WSALookupServiceEnd(sdp_handle);
+ return false;
+ }
+ ServiceRecordState* service_record_state = new ServiceRecordState();
+ service_record_state->name =
+ base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName);
+ for (uint64 i = 0; i < sdp_result_data->lpBlob->cbSize; i++) {
+ service_record_state->sdp_bytes.push_back(
+ sdp_result_data->lpBlob->pBlobData[i]);
+ }
+ service_record_states->push_back(service_record_state);
+ }
+ if (ERROR_SUCCESS != WSALookupServiceEnd(sdp_handle)) {
+ LogPollingError("Error calling WSALookupServiceEnd", WSAGetLastError());
+ return false;
+ }
+
+ return true;
+}
+
+bool BluetoothTaskManagerWin::DiscoverLowEnergyDeviceServices(
+ const base::FilePath& device_path,
+ ScopedVector<ServiceRecordState>* service_record_states) {
+ if (!win::IsBluetoothLowEnergySupported())
+ return true; // Bluetooth LE not supported is not an error.
+
+ std::string error;
+ ScopedVector<win::BluetoothLowEnergyServiceInfo> services;
+ bool success = win::EnumerateKnownBluetoothLowEnergyServices(
+ device_path, &services, &error);
+ if (!success) {
+ LogPollingError(error.c_str(), 0);
+ return false;
+ }
+
+ for (ScopedVector<win::BluetoothLowEnergyServiceInfo>::iterator iter2 =
+ services.begin();
+ iter2 != services.end();
+ ++iter2) {
+ ServiceRecordState* service_state = new ServiceRecordState();
+ service_state->gatt_uuid =
+ BluetoothLowEnergyUuidToBluetoothUuid((*iter2)->uuid);
+ service_record_states->push_back(service_state);
}
+ return true;
}
} // namespace device
« no previous file with comments | « device/bluetooth/bluetooth_task_manager_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698