bluetooth_task_manager_win.cc 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/bluetooth/bluetooth_task_manager_win.h"
  5. #include <stddef.h>
  6. #include <winsock2.h>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/logging.h"
  12. #include "base/memory/ptr_util.h"
  13. #include "base/memory/ref_counted.h"
  14. #include "base/no_destructor.h"
  15. #include "base/strings/stringprintf.h"
  16. #include "base/strings/sys_string_conversions.h"
  17. #include "base/task/sequenced_task_runner.h"
  18. #include "base/task/thread_pool.h"
  19. #include "base/threading/scoped_thread_priority.h"
  20. #include "device/bluetooth/bluetooth_classic_win.h"
  21. #include "device/bluetooth/bluetooth_device.h"
  22. #include "device/bluetooth/bluetooth_init_win.h"
  23. #include "device/bluetooth/bluetooth_service_record_win.h"
  24. #include "device/bluetooth/public/cpp/bluetooth_address.h"
  25. #include "net/base/winsock_init.h"
  26. namespace {
  27. const int kMaxNumDeviceAddressChar = 127;
  28. const int kServiceDiscoveryResultBufferSize = 5000;
  29. // See http://goo.gl/iNTRQe: cTimeoutMultiplier: A value that indicates the time
  30. // out for the inquiry, expressed in increments of 1.28 seconds. For example, an
  31. // inquiry of 12.8 seconds has a cTimeoutMultiplier value of 10. The maximum
  32. // value for this member is 48. When a value greater than 48 is used, the
  33. // calling function immediately fails and returns
  34. const int kMaxDeviceDiscoveryTimeoutMultiplier = 48;
  35. typedef device::BluetoothTaskManagerWin::ServiceRecordState ServiceRecordState;
  36. // Note: The string returned here must have the same format as
  37. // CanonicalizeBluetoothAddress.
  38. std::string BluetoothAddressToCanonicalString(const BLUETOOTH_ADDRESS& btha) {
  39. std::string result = base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X",
  40. btha.rgBytes[5],
  41. btha.rgBytes[4],
  42. btha.rgBytes[3],
  43. btha.rgBytes[2],
  44. btha.rgBytes[1],
  45. btha.rgBytes[0]);
  46. DCHECK_EQ(result, device::CanonicalizeBluetoothAddress(result));
  47. return result;
  48. }
  49. bool BluetoothUUIDToWinBLEUUID(const device::BluetoothUUID& uuid,
  50. BTH_LE_UUID* out_win_uuid) {
  51. if (!uuid.IsValid())
  52. return false;
  53. if (uuid.format() == device::BluetoothUUID::kFormat16Bit) {
  54. out_win_uuid->IsShortUuid = TRUE;
  55. unsigned int data = 0;
  56. int result = sscanf_s(uuid.value().c_str(), "%04x", &data);
  57. if (result != 1)
  58. return false;
  59. out_win_uuid->Value.ShortUuid = data;
  60. } else {
  61. out_win_uuid->IsShortUuid = FALSE;
  62. unsigned int data[11];
  63. int result =
  64. sscanf_s(uuid.value().c_str(),
  65. "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &data[0],
  66. &data[1], &data[2], &data[3], &data[4], &data[5], &data[6],
  67. &data[7], &data[8], &data[9], &data[10]);
  68. if (result != 11)
  69. return false;
  70. out_win_uuid->Value.LongUuid.Data1 = data[0];
  71. out_win_uuid->Value.LongUuid.Data2 = data[1];
  72. out_win_uuid->Value.LongUuid.Data3 = data[2];
  73. out_win_uuid->Value.LongUuid.Data4[0] = data[3];
  74. out_win_uuid->Value.LongUuid.Data4[1] = data[4];
  75. out_win_uuid->Value.LongUuid.Data4[2] = data[5];
  76. out_win_uuid->Value.LongUuid.Data4[3] = data[6];
  77. out_win_uuid->Value.LongUuid.Data4[4] = data[7];
  78. out_win_uuid->Value.LongUuid.Data4[5] = data[8];
  79. out_win_uuid->Value.LongUuid.Data4[6] = data[9];
  80. out_win_uuid->Value.LongUuid.Data4[7] = data[10];
  81. }
  82. return true;
  83. }
  84. // Populates bluetooth adapter state from the currently open adapter.
  85. void GetAdapterState(device::win::BluetoothClassicWrapper* classic_wrapper,
  86. device::BluetoothTaskManagerWin::AdapterState* state) {
  87. std::string name;
  88. std::string address;
  89. bool powered = false;
  90. BLUETOOTH_RADIO_INFO adapter_info = {sizeof(BLUETOOTH_RADIO_INFO)};
  91. if (classic_wrapper->HasHandle() &&
  92. ERROR_SUCCESS == classic_wrapper->GetRadioInfo(&adapter_info)) {
  93. name = base::SysWideToUTF8(adapter_info.szName);
  94. address = BluetoothAddressToCanonicalString(adapter_info.address);
  95. powered = !!classic_wrapper->IsConnectable();
  96. }
  97. state->name = name;
  98. state->address = address;
  99. state->powered = powered;
  100. }
  101. void GetDeviceState(const BLUETOOTH_DEVICE_INFO& device_info,
  102. device::BluetoothTaskManagerWin::DeviceState* state) {
  103. state->name = base::SysWideToUTF8(device_info.szName);
  104. state->address = BluetoothAddressToCanonicalString(device_info.Address);
  105. state->bluetooth_class = device_info.ulClassofDevice;
  106. state->visible = true;
  107. state->connected = !!device_info.fConnected;
  108. state->authenticated = !!device_info.fAuthenticated;
  109. }
  110. struct CharacteristicValueChangedRegistration {
  111. CharacteristicValueChangedRegistration();
  112. ~CharacteristicValueChangedRegistration();
  113. BLUETOOTH_GATT_EVENT_HANDLE win_event_handle;
  114. device::BluetoothTaskManagerWin::GattCharacteristicValueChangedCallback
  115. callback;
  116. // The task runner the callback should run on.
  117. scoped_refptr<base::SequencedTaskRunner> callback_task_runner;
  118. };
  119. CharacteristicValueChangedRegistration::
  120. CharacteristicValueChangedRegistration() {}
  121. CharacteristicValueChangedRegistration::
  122. ~CharacteristicValueChangedRegistration() {}
  123. // The key of CharacteristicValueChangedRegistrationMap is a
  124. // GattCharacteristicValueChangedCallback pointer (cast to PVOID) to make it
  125. // unique for different callbacks. It is also the context value passed into OS
  126. // when registering event.
  127. typedef std::unordered_map<
  128. PVOID,
  129. std::unique_ptr<CharacteristicValueChangedRegistration>>
  130. CharacteristicValueChangedRegistrationMap;
  131. CharacteristicValueChangedRegistrationMap&
  132. GetCharacteristicValueChangedRegistrations() {
  133. static base::NoDestructor<CharacteristicValueChangedRegistrationMap>
  134. registrations;
  135. return *registrations;
  136. }
  137. base::Lock& GetCharacteristicValueChangedRegistrationsLock() {
  138. static base::NoDestructor<base::Lock> lock;
  139. return *lock;
  140. }
  141. // Function to be registered to OS to monitor Bluetooth LE GATT event. It is
  142. // invoked in BluetoothApis.dll thread.
  143. void CALLBACK OnGetGattEventWin(BTH_LE_GATT_EVENT_TYPE type,
  144. PVOID event_parameter,
  145. PVOID context) {
  146. if (type != CharacteristicValueChangedEvent) {
  147. // Right now, only characteristic value changed event is supported.
  148. NOTREACHED();
  149. return;
  150. }
  151. BLUETOOTH_GATT_VALUE_CHANGED_EVENT* event =
  152. (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)event_parameter;
  153. PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value_win = event->CharacteristicValue;
  154. std::unique_ptr<std::vector<uint8_t>> new_value(
  155. new std::vector<uint8_t>(new_value_win->DataSize));
  156. for (ULONG i = 0; i < new_value_win->DataSize; i++)
  157. (*new_value)[i] = new_value_win->Data[i];
  158. base::AutoLock auto_lock(GetCharacteristicValueChangedRegistrationsLock());
  159. CharacteristicValueChangedRegistrationMap::const_iterator it =
  160. GetCharacteristicValueChangedRegistrations().find(context);
  161. if (it == GetCharacteristicValueChangedRegistrations().end())
  162. return;
  163. it->second->callback_task_runner->PostTask(
  164. FROM_HERE, base::BindOnce(it->second->callback, std::move(new_value)));
  165. }
  166. } // namespace
  167. namespace device {
  168. // static
  169. const int BluetoothTaskManagerWin::kPollIntervalMs = 500;
  170. BluetoothTaskManagerWin::AdapterState::AdapterState() : powered(false) {
  171. }
  172. BluetoothTaskManagerWin::AdapterState::~AdapterState() {
  173. }
  174. BluetoothTaskManagerWin::ServiceRecordState::ServiceRecordState() {
  175. }
  176. BluetoothTaskManagerWin::ServiceRecordState::~ServiceRecordState() {
  177. }
  178. BluetoothTaskManagerWin::DeviceState::DeviceState()
  179. : visible(false),
  180. connected(false),
  181. authenticated(false),
  182. bluetooth_class(0) {
  183. }
  184. BluetoothTaskManagerWin::DeviceState::~DeviceState() {
  185. }
  186. BluetoothTaskManagerWin::BluetoothTaskManagerWin(
  187. scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
  188. : ui_task_runner_(std::move(ui_task_runner)),
  189. classic_wrapper_(std::make_unique<win::BluetoothClassicWrapper>()),
  190. le_wrapper_(std::make_unique<win::BluetoothLowEnergyWrapper>()) {}
  191. BluetoothTaskManagerWin::BluetoothTaskManagerWin(
  192. std::unique_ptr<win::BluetoothClassicWrapper> classic_wrapper,
  193. std::unique_ptr<win::BluetoothLowEnergyWrapper> le_wrapper,
  194. scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
  195. : ui_task_runner_(std::move(ui_task_runner)),
  196. classic_wrapper_(std::move(classic_wrapper)),
  197. le_wrapper_(std::move(le_wrapper)) {}
  198. BluetoothTaskManagerWin::~BluetoothTaskManagerWin() = default;
  199. // static
  200. scoped_refptr<BluetoothTaskManagerWin>
  201. BluetoothTaskManagerWin::CreateForTesting(
  202. std::unique_ptr<win::BluetoothClassicWrapper> classic_wrapper,
  203. std::unique_ptr<win::BluetoothLowEnergyWrapper> le_wrapper,
  204. scoped_refptr<base::SequencedTaskRunner> ui_task_runner) {
  205. return new BluetoothTaskManagerWin(std::move(classic_wrapper),
  206. std::move(le_wrapper),
  207. std::move(ui_task_runner));
  208. }
  209. // static
  210. BluetoothUUID BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
  211. const BTH_LE_UUID& bth_le_uuid) {
  212. if (bth_le_uuid.IsShortUuid) {
  213. std::string uuid_hex =
  214. base::StringPrintf("%04x", bth_le_uuid.Value.ShortUuid);
  215. return BluetoothUUID(uuid_hex);
  216. } else {
  217. return BluetoothUUID(base::StringPrintf(
  218. "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  219. bth_le_uuid.Value.LongUuid.Data1, bth_le_uuid.Value.LongUuid.Data2,
  220. bth_le_uuid.Value.LongUuid.Data3, bth_le_uuid.Value.LongUuid.Data4[0],
  221. bth_le_uuid.Value.LongUuid.Data4[1],
  222. bth_le_uuid.Value.LongUuid.Data4[2],
  223. bth_le_uuid.Value.LongUuid.Data4[3],
  224. bth_le_uuid.Value.LongUuid.Data4[4],
  225. bth_le_uuid.Value.LongUuid.Data4[5],
  226. bth_le_uuid.Value.LongUuid.Data4[6],
  227. bth_le_uuid.Value.LongUuid.Data4[7]));
  228. }
  229. }
  230. void BluetoothTaskManagerWin::AddObserver(Observer* observer) {
  231. DCHECK(observer);
  232. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  233. observers_.AddObserver(observer);
  234. }
  235. void BluetoothTaskManagerWin::RemoveObserver(Observer* observer) {
  236. DCHECK(observer);
  237. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  238. observers_.RemoveObserver(observer);
  239. }
  240. void BluetoothTaskManagerWin::Initialize() {
  241. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  242. InitializeWithBluetoothTaskRunner(base::ThreadPool::CreateSequencedTaskRunner(
  243. {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
  244. base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}));
  245. }
  246. void BluetoothTaskManagerWin::InitializeWithBluetoothTaskRunner(
  247. scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) {
  248. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  249. bluetooth_task_runner_ = bluetooth_task_runner;
  250. bluetooth_task_runner_->PostTask(
  251. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::StartPolling, this));
  252. }
  253. void BluetoothTaskManagerWin::StartPolling() {
  254. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  255. if (device::bluetooth_init_win::HasBluetoothStack()) {
  256. PollAdapter();
  257. } else {
  258. // IF the bluetooth stack is not available, we still send an empty state
  259. // to BluetoothAdapter so that it is marked initialized, but the adapter
  260. // will not be present.
  261. AdapterState* state = new AdapterState();
  262. ui_task_runner_->PostTask(
  263. FROM_HERE,
  264. base::BindOnce(&BluetoothTaskManagerWin::OnAdapterStateChanged, this,
  265. base::Owned(state)));
  266. }
  267. }
  268. void BluetoothTaskManagerWin::PostSetPoweredBluetoothTask(
  269. bool powered,
  270. base::OnceClosure callback,
  271. BluetoothAdapter::ErrorCallback error_callback) {
  272. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  273. bluetooth_task_runner_->PostTask(
  274. FROM_HERE,
  275. base::BindOnce(&BluetoothTaskManagerWin::SetPowered, this, powered,
  276. std::move(callback), std::move(error_callback)));
  277. }
  278. void BluetoothTaskManagerWin::PostStartDiscoveryTask() {
  279. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  280. bluetooth_task_runner_->PostTask(
  281. FROM_HERE,
  282. base::BindOnce(&BluetoothTaskManagerWin::StartDiscovery, this));
  283. }
  284. void BluetoothTaskManagerWin::PostStopDiscoveryTask() {
  285. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  286. bluetooth_task_runner_->PostTask(
  287. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::StopDiscovery, this));
  288. }
  289. void BluetoothTaskManagerWin::LogPollingError(const char* message,
  290. int win32_error) {
  291. const int kLogPeriodInMilliseconds = 60 * 1000;
  292. const int kMaxMessagesPerLogPeriod = 10;
  293. // Check if we need to discard this message
  294. if (!current_logging_batch_ticks_.is_null()) {
  295. if (base::TimeTicks::Now() - current_logging_batch_ticks_ <=
  296. base::Milliseconds(kLogPeriodInMilliseconds)) {
  297. if (current_logging_batch_count_ >= kMaxMessagesPerLogPeriod)
  298. return;
  299. } else {
  300. // The batch expired, reset it to "null".
  301. current_logging_batch_ticks_ = base::TimeTicks();
  302. }
  303. }
  304. // Keep track of this batch of messages
  305. if (current_logging_batch_ticks_.is_null()) {
  306. current_logging_batch_ticks_ = base::TimeTicks::Now();
  307. current_logging_batch_count_ = 0;
  308. }
  309. ++current_logging_batch_count_;
  310. // Log the message
  311. if (win32_error == 0)
  312. LOG(WARNING) << message;
  313. else
  314. LOG(WARNING) << message << ": "
  315. << logging::SystemErrorCodeToString(win32_error);
  316. }
  317. void BluetoothTaskManagerWin::OnAdapterStateChanged(const AdapterState* state) {
  318. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  319. for (auto& observer : observers_)
  320. observer.AdapterStateChanged(*state);
  321. }
  322. void BluetoothTaskManagerWin::OnDiscoveryStarted(bool success) {
  323. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  324. for (auto& observer : observers_)
  325. observer.DiscoveryStarted(success);
  326. }
  327. void BluetoothTaskManagerWin::OnDiscoveryStopped() {
  328. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  329. for (auto& observer : observers_)
  330. observer.DiscoveryStopped();
  331. }
  332. void BluetoothTaskManagerWin::OnDevicesPolled(
  333. std::vector<std::unique_ptr<DeviceState>> devices) {
  334. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  335. for (auto& observer : observers_)
  336. observer.DevicesPolled(devices);
  337. }
  338. void BluetoothTaskManagerWin::PollAdapter() {
  339. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  340. // Skips updating the adapter info if the adapter is in discovery mode.
  341. if (!discovering_) {
  342. const BLUETOOTH_FIND_RADIO_PARAMS adapter_param =
  343. { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
  344. HBLUETOOTH_RADIO_FIND handle =
  345. classic_wrapper_->FindFirstRadio(&adapter_param);
  346. if (handle) {
  347. GetKnownDevices();
  348. classic_wrapper_->FindRadioClose(handle);
  349. }
  350. PostAdapterStateToUi();
  351. }
  352. // Re-poll.
  353. bluetooth_task_runner_->PostDelayedTask(
  354. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::PollAdapter, this),
  355. base::Milliseconds(kPollIntervalMs));
  356. }
  357. void BluetoothTaskManagerWin::PostAdapterStateToUi() {
  358. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  359. AdapterState* state = new AdapterState();
  360. GetAdapterState(classic_wrapper_.get(), state);
  361. ui_task_runner_->PostTask(
  362. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::OnAdapterStateChanged,
  363. this, base::Owned(state)));
  364. }
  365. void BluetoothTaskManagerWin::SetPowered(
  366. bool powered,
  367. base::OnceClosure callback,
  368. BluetoothAdapter::ErrorCallback error_callback) {
  369. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  370. bool success = false;
  371. if (classic_wrapper_->HasHandle()) {
  372. if (!powered)
  373. classic_wrapper_->EnableDiscovery(false);
  374. success = !!classic_wrapper_->EnableIncomingConnections(powered);
  375. }
  376. if (success) {
  377. PostAdapterStateToUi();
  378. ui_task_runner_->PostTask(FROM_HERE, std::move(callback));
  379. } else {
  380. ui_task_runner_->PostTask(FROM_HERE, std::move(error_callback));
  381. }
  382. }
  383. void BluetoothTaskManagerWin::StartDiscovery() {
  384. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  385. bool adapter_opened = classic_wrapper_->HasHandle();
  386. ui_task_runner_->PostTask(
  387. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::OnDiscoveryStarted,
  388. this, adapter_opened));
  389. if (!adapter_opened)
  390. return;
  391. discovering_ = true;
  392. DiscoverDevices(1);
  393. }
  394. void BluetoothTaskManagerWin::StopDiscovery() {
  395. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  396. discovering_ = false;
  397. ui_task_runner_->PostTask(
  398. FROM_HERE,
  399. base::BindOnce(&BluetoothTaskManagerWin::OnDiscoveryStopped, this));
  400. }
  401. void BluetoothTaskManagerWin::DiscoverDevices(int timeout_multiplier) {
  402. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  403. if (!discovering_ || !classic_wrapper_->HasHandle())
  404. return;
  405. std::vector<std::unique_ptr<DeviceState>> device_list;
  406. if (SearchDevices(timeout_multiplier, false, &device_list)) {
  407. ui_task_runner_->PostTask(
  408. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::OnDevicesPolled,
  409. this, std::move(device_list)));
  410. }
  411. if (timeout_multiplier < kMaxDeviceDiscoveryTimeoutMultiplier)
  412. ++timeout_multiplier;
  413. bluetooth_task_runner_->PostTask(
  414. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::DiscoverDevices, this,
  415. timeout_multiplier));
  416. }
  417. void BluetoothTaskManagerWin::GetKnownDevices() {
  418. std::vector<std::unique_ptr<DeviceState>> device_list;
  419. if (SearchDevices(1, true, &device_list)) {
  420. ui_task_runner_->PostTask(
  421. FROM_HERE, base::BindOnce(&BluetoothTaskManagerWin::OnDevicesPolled,
  422. this, std::move(device_list)));
  423. }
  424. }
  425. bool BluetoothTaskManagerWin::SearchDevices(
  426. int timeout_multiplier,
  427. bool search_cached_devices_only,
  428. std::vector<std::unique_ptr<DeviceState>>* device_list) {
  429. return SearchClassicDevices(
  430. timeout_multiplier, search_cached_devices_only, device_list) &&
  431. SearchLowEnergyDevices(device_list) &&
  432. DiscoverServices(device_list, search_cached_devices_only);
  433. }
  434. bool BluetoothTaskManagerWin::SearchClassicDevices(
  435. int timeout_multiplier,
  436. bool search_cached_devices_only,
  437. std::vector<std::unique_ptr<DeviceState>>* device_list) {
  438. // Issues a device inquiry and waits for |timeout_multiplier| * 1.28 seconds.
  439. BLUETOOTH_DEVICE_SEARCH_PARAMS device_search_params;
  440. ZeroMemory(&device_search_params, sizeof(device_search_params));
  441. device_search_params.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
  442. device_search_params.fReturnAuthenticated = 1;
  443. device_search_params.fReturnRemembered = 1;
  444. device_search_params.fReturnUnknown = (search_cached_devices_only ? 0 : 1);
  445. device_search_params.fReturnConnected = 1;
  446. device_search_params.fIssueInquiry = (search_cached_devices_only ? 0 : 1);
  447. device_search_params.cTimeoutMultiplier = timeout_multiplier;
  448. BLUETOOTH_DEVICE_INFO device_info;
  449. ZeroMemory(&device_info, sizeof(device_info));
  450. device_info.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
  451. HBLUETOOTH_DEVICE_FIND handle =
  452. classic_wrapper_->FindFirstDevice(&device_search_params, &device_info);
  453. if (!handle) {
  454. int last_error = classic_wrapper_->LastError();
  455. if (last_error == ERROR_NO_MORE_ITEMS) {
  456. return true; // No devices is not an error.
  457. }
  458. LogPollingError("Error calling BluetoothFindFirstDevice", last_error);
  459. return false;
  460. }
  461. while (true) {
  462. auto device_state = std::make_unique<DeviceState>();
  463. GetDeviceState(device_info, device_state.get());
  464. device_list->push_back(std::move(device_state));
  465. // Reset device info before next call (as a safety precaution).
  466. ZeroMemory(&device_info, sizeof(device_info));
  467. device_info.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
  468. if (!classic_wrapper_->FindNextDevice(handle, &device_info)) {
  469. int last_error = classic_wrapper_->LastError();
  470. if (last_error == ERROR_NO_MORE_ITEMS) {
  471. break; // No more items is expected error when done enumerating.
  472. }
  473. LogPollingError("Error calling BluetoothFindNextDevice", last_error);
  474. classic_wrapper_->FindDeviceClose(handle);
  475. return false;
  476. }
  477. }
  478. if (!classic_wrapper_->FindDeviceClose(handle)) {
  479. LogPollingError("Error calling BluetoothFindDeviceClose",
  480. classic_wrapper_->LastError());
  481. return false;
  482. }
  483. return true;
  484. }
  485. bool BluetoothTaskManagerWin::SearchLowEnergyDevices(
  486. std::vector<std::unique_ptr<DeviceState>>* device_list) {
  487. if (!le_wrapper_->IsBluetoothLowEnergySupported()) {
  488. return true; // Bluetooth LE not supported is not an error.
  489. }
  490. std::vector<std::unique_ptr<win::BluetoothLowEnergyDeviceInfo>> btle_devices;
  491. std::string error;
  492. bool success = le_wrapper_->EnumerateKnownBluetoothLowEnergyDevices(
  493. &btle_devices, &error);
  494. if (!success) {
  495. error.insert(0, "Error calling EnumerateKnownBluetoothLowEnergyDevices: ");
  496. LogPollingError(error.c_str(), 0);
  497. return false;
  498. }
  499. for (const auto& device_info : btle_devices) {
  500. auto device_state = std::make_unique<DeviceState>();
  501. device_state->name = device_info->friendly_name;
  502. device_state->address =
  503. BluetoothAddressToCanonicalString(device_info->address);
  504. device_state->visible = device_info->visible;
  505. device_state->authenticated = device_info->authenticated;
  506. device_state->connected = device_info->connected;
  507. device_state->path = device_info->path;
  508. device_list->push_back(std::move(device_state));
  509. }
  510. return true;
  511. }
  512. bool BluetoothTaskManagerWin::DiscoverServices(
  513. std::vector<std::unique_ptr<DeviceState>>* device_list,
  514. bool search_cached_services_only) {
  515. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  516. net::EnsureWinsockInit();
  517. for (const auto& device : *device_list) {
  518. std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states =
  519. &device->service_record_states;
  520. if (device->is_bluetooth_classic()) {
  521. if (!DiscoverClassicDeviceServices(device->address,
  522. L2CAP_PROTOCOL_UUID,
  523. search_cached_services_only,
  524. service_record_states)) {
  525. return false;
  526. }
  527. } else {
  528. if (!DiscoverLowEnergyDeviceServices(device->path,
  529. service_record_states)) {
  530. return false;
  531. }
  532. if (!SearchForGattServiceDevicePaths(device->address,
  533. service_record_states)) {
  534. return false;
  535. }
  536. }
  537. }
  538. return true;
  539. }
  540. bool BluetoothTaskManagerWin::DiscoverClassicDeviceServices(
  541. const std::string& device_address,
  542. const GUID& protocol_uuid,
  543. bool search_cached_services_only,
  544. std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states) {
  545. int error_code =
  546. DiscoverClassicDeviceServicesWorker(device_address,
  547. protocol_uuid,
  548. search_cached_services_only,
  549. service_record_states);
  550. // If the device is "offline", no services are returned when specifying
  551. // "LUP_FLUSHCACHE". Try again without flushing the cache so that the list
  552. // of previously known services is returned.
  553. if (!search_cached_services_only &&
  554. (error_code == WSASERVICE_NOT_FOUND || error_code == WSANO_DATA)) {
  555. error_code = DiscoverClassicDeviceServicesWorker(
  556. device_address, protocol_uuid, true, service_record_states);
  557. }
  558. return (error_code == ERROR_SUCCESS);
  559. }
  560. int BluetoothTaskManagerWin::DiscoverClassicDeviceServicesWorker(
  561. const std::string& device_address,
  562. const GUID& protocol_uuid,
  563. bool search_cached_services_only,
  564. std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states) {
  565. // Mitigate the issues caused by loading DLLs on a background thread
  566. // (http://crbug/973868).
  567. SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
  568. // Bluetooth and WSAQUERYSET for Service Inquiry. See http://goo.gl/2v9pyt.
  569. WSAQUERYSET sdp_query;
  570. ZeroMemory(&sdp_query, sizeof(sdp_query));
  571. sdp_query.dwSize = sizeof(sdp_query);
  572. GUID protocol = protocol_uuid;
  573. sdp_query.lpServiceClassId = &protocol;
  574. sdp_query.dwNameSpace = NS_BTH;
  575. wchar_t device_address_context[kMaxNumDeviceAddressChar];
  576. std::size_t length = base::SysUTF8ToWide("(" + device_address + ")").copy(
  577. device_address_context, kMaxNumDeviceAddressChar);
  578. device_address_context[length] = NULL;
  579. sdp_query.lpszContext = device_address_context;
  580. DWORD control_flags = LUP_RETURN_ALL;
  581. // See http://goo.gl/t1Hulo: "Applications should generally specify
  582. // LUP_FLUSHCACHE. This flag instructs the system to ignore any cached
  583. // information and establish an over-the-air SDP connection to the specified
  584. // device to perform the SDP search. This non-cached operation may take
  585. // several seconds (whereas a cached search returns quickly)."
  586. // In summary, we need to specify LUP_FLUSHCACHE if we want to obtain the list
  587. // of services for devices which have not been discovered before.
  588. if (!search_cached_services_only)
  589. control_flags |= LUP_FLUSHCACHE;
  590. HANDLE sdp_handle;
  591. if (ERROR_SUCCESS !=
  592. WSALookupServiceBegin(&sdp_query, control_flags, &sdp_handle)) {
  593. int last_error = WSAGetLastError();
  594. // If the device is "offline", no services are returned when specifying
  595. // "LUP_FLUSHCACHE". Don't log error in that case.
  596. if (!search_cached_services_only &&
  597. (last_error == WSASERVICE_NOT_FOUND || last_error == WSANO_DATA)) {
  598. return last_error;
  599. }
  600. LogPollingError("Error calling WSALookupServiceBegin", last_error);
  601. return last_error;
  602. }
  603. char sdp_buffer[kServiceDiscoveryResultBufferSize];
  604. LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer);
  605. while (true) {
  606. DWORD sdp_buffer_size = sizeof(sdp_buffer);
  607. if (ERROR_SUCCESS !=
  608. WSALookupServiceNext(
  609. sdp_handle, control_flags, &sdp_buffer_size, sdp_result_data)) {
  610. int last_error = WSAGetLastError();
  611. if (last_error == WSA_E_NO_MORE || last_error == WSAENOMORE) {
  612. break;
  613. }
  614. LogPollingError("Error calling WSALookupServiceNext", last_error);
  615. WSALookupServiceEnd(sdp_handle);
  616. return last_error;
  617. }
  618. auto service_record_state = std::make_unique<ServiceRecordState>();
  619. service_record_state->name =
  620. base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName);
  621. for (uint64_t i = 0; i < sdp_result_data->lpBlob->cbSize; i++) {
  622. service_record_state->sdp_bytes.push_back(
  623. sdp_result_data->lpBlob->pBlobData[i]);
  624. }
  625. service_record_states->push_back(std::move(service_record_state));
  626. }
  627. if (ERROR_SUCCESS != WSALookupServiceEnd(sdp_handle)) {
  628. int last_error = WSAGetLastError();
  629. LogPollingError("Error calling WSALookupServiceEnd", last_error);
  630. return last_error;
  631. }
  632. return ERROR_SUCCESS;
  633. }
  634. bool BluetoothTaskManagerWin::DiscoverLowEnergyDeviceServices(
  635. const base::FilePath& device_path,
  636. std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states) {
  637. if (!le_wrapper_->IsBluetoothLowEnergySupported()) {
  638. return true; // Bluetooth LE not supported is not an error.
  639. }
  640. std::string error;
  641. std::vector<std::unique_ptr<win::BluetoothLowEnergyServiceInfo>> services;
  642. bool success = le_wrapper_->EnumerateKnownBluetoothLowEnergyServices(
  643. device_path, &services, &error);
  644. if (!success) {
  645. error.insert(0, "Error calling EnumerateKnownBluetoothLowEnergyServices: ");
  646. LogPollingError(error.c_str(), 0);
  647. return false;
  648. }
  649. for (const auto& service : services) {
  650. auto service_state = std::make_unique<ServiceRecordState>();
  651. service_state->gatt_uuid =
  652. BluetoothLowEnergyUuidToBluetoothUuid(service->uuid);
  653. service_state->attribute_handle = service->attribute_handle;
  654. service_record_states->push_back(std::move(service_state));
  655. }
  656. return true;
  657. }
  658. // Each GATT service of a BLE device will be listed on the machine as a BLE
  659. // device interface with a matching service attribute handle. This interface
  660. // lists all GATT service devices and matches them back to correspond GATT
  661. // service of the BLE device according to their address and included service
  662. // attribute handles, as we did not find a more neat way to bond them.
  663. bool BluetoothTaskManagerWin::SearchForGattServiceDevicePaths(
  664. const std::string device_address,
  665. std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states) {
  666. std::string error;
  667. // List all known GATT service devices on the machine.
  668. std::vector<std::unique_ptr<win::BluetoothLowEnergyDeviceInfo>>
  669. gatt_service_devices;
  670. bool success =
  671. le_wrapper_->EnumerateKnownBluetoothLowEnergyGattServiceDevices(
  672. &gatt_service_devices, &error);
  673. if (!success) {
  674. error.insert(
  675. 0,
  676. "Error calling EnumerateKnownBluetoothLowEnergyGattServiceDevices: ");
  677. LogPollingError(error.c_str(), 0);
  678. return false;
  679. }
  680. for (const auto& gatt_service_device : gatt_service_devices) {
  681. // Only care about the service devices with |device_address|.
  682. if (BluetoothAddressToCanonicalString(gatt_service_device->address) !=
  683. device_address) {
  684. continue;
  685. }
  686. // Discover this service device's contained services.
  687. std::vector<std::unique_ptr<win::BluetoothLowEnergyServiceInfo>>
  688. gatt_services;
  689. if (!le_wrapper_->EnumerateKnownBluetoothLowEnergyServices(
  690. gatt_service_device->path, &gatt_services, &error)) {
  691. error.insert(0,
  692. "Error calling EnumerateKnownBluetoothLowEnergyServices: ");
  693. LogPollingError(error.c_str(), 0);
  694. continue;
  695. }
  696. // Usually each service device correspond to one Gatt service.
  697. if (gatt_services.size() > 1) {
  698. LOG(WARNING) << "This GATT service device contains more than one ("
  699. << gatt_services.size() << ") services";
  700. }
  701. // Associate service device to corresponding service record. Attribute
  702. // handle is unique on one device.
  703. for (const auto& gatt_service : gatt_services) {
  704. for (const auto& service_record_state : *service_record_states) {
  705. if (service_record_state->attribute_handle ==
  706. gatt_service->attribute_handle) {
  707. service_record_state->path = gatt_service_device->path;
  708. break;
  709. }
  710. }
  711. }
  712. }
  713. // Service devices are known and available for enumeration shortly after a
  714. // a service is known. If we are searching for service device paths in that
  715. // short window, we won't have a service device path for every service.
  716. for (const auto& service_record_state : *service_record_states) {
  717. if (service_record_state->path.empty())
  718. return false;
  719. }
  720. return true;
  721. }
  722. void BluetoothTaskManagerWin::GetGattIncludedCharacteristics(
  723. base::FilePath service_path,
  724. BluetoothUUID uuid,
  725. uint16_t attribute_handle,
  726. GetGattIncludedCharacteristicsCallback callback) {
  727. HRESULT hr = S_OK;
  728. std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC> win_characteristics_info;
  729. uint16_t number_of_charateristics = 0;
  730. BTH_LE_GATT_SERVICE win_service;
  731. if (BluetoothUUIDToWinBLEUUID(uuid, &(win_service.ServiceUuid))) {
  732. win_service.AttributeHandle = attribute_handle;
  733. hr = le_wrapper_->ReadCharacteristicsOfAService(service_path, &win_service,
  734. &win_characteristics_info,
  735. &number_of_charateristics);
  736. } else {
  737. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  738. }
  739. ui_task_runner_->PostTask(
  740. FROM_HERE,
  741. base::BindOnce(std::move(callback), std::move(win_characteristics_info),
  742. number_of_charateristics, hr));
  743. }
  744. void BluetoothTaskManagerWin::GetGattIncludedDescriptors(
  745. base::FilePath service_path,
  746. BTH_LE_GATT_CHARACTERISTIC characteristic,
  747. GetGattIncludedDescriptorsCallback callback) {
  748. std::unique_ptr<BTH_LE_GATT_DESCRIPTOR> win_descriptors_info;
  749. uint16_t number_of_descriptors = 0;
  750. HRESULT hr = le_wrapper_->ReadDescriptorsOfACharacteristic(
  751. service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
  752. &win_descriptors_info, &number_of_descriptors);
  753. ui_task_runner_->PostTask(
  754. FROM_HERE,
  755. base::BindOnce(std::move(callback), std::move(win_descriptors_info),
  756. number_of_descriptors, hr));
  757. }
  758. void BluetoothTaskManagerWin::ReadGattCharacteristicValue(
  759. base::FilePath service_path,
  760. BTH_LE_GATT_CHARACTERISTIC characteristic,
  761. ReadGattCharacteristicValueCallback callback) {
  762. std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> win_characteristic_value;
  763. HRESULT hr = le_wrapper_->ReadCharacteristicValue(
  764. service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
  765. &win_characteristic_value);
  766. ui_task_runner_->PostTask(
  767. FROM_HERE, base::BindOnce(std::move(callback),
  768. std::move(win_characteristic_value), hr));
  769. }
  770. void BluetoothTaskManagerWin::WriteGattCharacteristicValue(
  771. base::FilePath service_path,
  772. BTH_LE_GATT_CHARACTERISTIC characteristic,
  773. std::vector<uint8_t> new_value,
  774. ULONG flags,
  775. HResultCallback callback) {
  776. ULONG length = (ULONG)(sizeof(ULONG) + new_value.size());
  777. std::vector<UCHAR> data(length);
  778. auto* win_new_value =
  779. reinterpret_cast<PBTH_LE_GATT_CHARACTERISTIC_VALUE>(&data[0]);
  780. win_new_value->DataSize = (ULONG)new_value.size();
  781. for (ULONG i = 0; i < new_value.size(); i++)
  782. win_new_value->Data[i] = new_value[i];
  783. HRESULT hr = le_wrapper_->WriteCharacteristicValue(
  784. service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
  785. win_new_value, flags);
  786. ui_task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), hr));
  787. }
  788. void BluetoothTaskManagerWin::RegisterGattCharacteristicValueChangedEvent(
  789. base::FilePath service_path,
  790. BTH_LE_GATT_CHARACTERISTIC characteristic,
  791. BTH_LE_GATT_DESCRIPTOR ccc_descriptor,
  792. GattEventRegistrationCallback callback,
  793. const GattCharacteristicValueChangedCallback& registered_callback) {
  794. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  795. BLUETOOTH_GATT_EVENT_HANDLE win_event_handle = NULL;
  796. BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION win_event_parameter;
  797. memcpy(&(win_event_parameter.Characteristics[0]), &characteristic,
  798. sizeof(BTH_LE_GATT_CHARACTERISTIC));
  799. win_event_parameter.NumCharacteristics = 1;
  800. PVOID user_event_handle = (PVOID)&registered_callback;
  801. HRESULT hr = le_wrapper_->RegisterGattEvents(
  802. service_path, CharacteristicValueChangedEvent, &win_event_parameter,
  803. &OnGetGattEventWin, user_event_handle, &win_event_handle);
  804. // Sets the Client Characteristic Configuration descriptor.
  805. if (SUCCEEDED(hr)) {
  806. BTH_LE_GATT_DESCRIPTOR_VALUE new_cccd_value;
  807. RtlZeroMemory(&new_cccd_value, sizeof(new_cccd_value));
  808. new_cccd_value.DescriptorType = ClientCharacteristicConfiguration;
  809. if (characteristic.IsNotifiable) {
  810. new_cccd_value.ClientCharacteristicConfiguration
  811. .IsSubscribeToNotification = TRUE;
  812. } else {
  813. new_cccd_value.ClientCharacteristicConfiguration.IsSubscribeToIndication =
  814. TRUE;
  815. }
  816. hr = le_wrapper_->WriteDescriptorValue(
  817. service_path, (PBTH_LE_GATT_DESCRIPTOR)(&ccc_descriptor),
  818. &new_cccd_value);
  819. }
  820. if (SUCCEEDED(hr)) {
  821. std::unique_ptr<CharacteristicValueChangedRegistration> registration(
  822. new CharacteristicValueChangedRegistration());
  823. registration->win_event_handle = win_event_handle;
  824. registration->callback = registered_callback;
  825. registration->callback_task_runner = ui_task_runner_;
  826. base::AutoLock auto_lock(GetCharacteristicValueChangedRegistrationsLock());
  827. GetCharacteristicValueChangedRegistrations()[user_event_handle] =
  828. std::move(registration);
  829. }
  830. ui_task_runner_->PostTask(
  831. FROM_HERE, base::BindOnce(std::move(callback), user_event_handle, hr));
  832. }
  833. void BluetoothTaskManagerWin::UnregisterGattCharacteristicValueChangedEvent(
  834. PVOID event_handle) {
  835. DCHECK(bluetooth_task_runner_->RunsTasksInCurrentSequence());
  836. base::AutoLock auto_lock(GetCharacteristicValueChangedRegistrationsLock());
  837. CharacteristicValueChangedRegistrationMap::const_iterator it =
  838. GetCharacteristicValueChangedRegistrations().find(event_handle);
  839. if (it != GetCharacteristicValueChangedRegistrations().end()) {
  840. le_wrapper_->UnregisterGattEvent(it->second->win_event_handle);
  841. GetCharacteristicValueChangedRegistrations().erase(event_handle);
  842. }
  843. }
  844. void BluetoothTaskManagerWin::PostGetGattIncludedCharacteristics(
  845. const base::FilePath& service_path,
  846. const BluetoothUUID& uuid,
  847. uint16_t attribute_handle,
  848. GetGattIncludedCharacteristicsCallback callback) {
  849. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  850. bluetooth_task_runner_->PostTask(
  851. FROM_HERE,
  852. base::BindOnce(&BluetoothTaskManagerWin::GetGattIncludedCharacteristics,
  853. this, service_path, uuid, attribute_handle,
  854. std::move(callback)));
  855. }
  856. void BluetoothTaskManagerWin::PostGetGattIncludedDescriptors(
  857. const base::FilePath& service_path,
  858. const PBTH_LE_GATT_CHARACTERISTIC characteristic,
  859. GetGattIncludedDescriptorsCallback callback) {
  860. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  861. bluetooth_task_runner_->PostTask(
  862. FROM_HERE,
  863. base::BindOnce(&BluetoothTaskManagerWin::GetGattIncludedDescriptors, this,
  864. service_path, *characteristic, std::move(callback)));
  865. }
  866. void BluetoothTaskManagerWin::PostReadGattCharacteristicValue(
  867. const base::FilePath& service_path,
  868. const PBTH_LE_GATT_CHARACTERISTIC characteristic,
  869. ReadGattCharacteristicValueCallback callback) {
  870. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  871. bluetooth_task_runner_->PostTask(
  872. FROM_HERE,
  873. base::BindOnce(&BluetoothTaskManagerWin::ReadGattCharacteristicValue,
  874. this, service_path, *characteristic, std::move(callback)));
  875. }
  876. void BluetoothTaskManagerWin::PostWriteGattCharacteristicValue(
  877. const base::FilePath& service_path,
  878. const PBTH_LE_GATT_CHARACTERISTIC characteristic,
  879. const std::vector<uint8_t>& new_value,
  880. ULONG flags,
  881. HResultCallback callback) {
  882. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  883. bluetooth_task_runner_->PostTask(
  884. FROM_HERE,
  885. base::BindOnce(&BluetoothTaskManagerWin::WriteGattCharacteristicValue,
  886. this, service_path, *characteristic, new_value, flags,
  887. std::move(callback)));
  888. }
  889. void BluetoothTaskManagerWin::PostRegisterGattCharacteristicValueChangedEvent(
  890. const base::FilePath& service_path,
  891. const PBTH_LE_GATT_CHARACTERISTIC characteristic,
  892. const PBTH_LE_GATT_DESCRIPTOR ccc_descriptor,
  893. GattEventRegistrationCallback callback,
  894. const GattCharacteristicValueChangedCallback& registered_callback) {
  895. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  896. bluetooth_task_runner_->PostTask(
  897. FROM_HERE,
  898. base::BindOnce(
  899. &BluetoothTaskManagerWin::RegisterGattCharacteristicValueChangedEvent,
  900. this, service_path, *characteristic, *ccc_descriptor,
  901. std::move(callback), registered_callback));
  902. }
  903. void BluetoothTaskManagerWin::PostUnregisterGattCharacteristicValueChangedEvent(
  904. PVOID event_handle) {
  905. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  906. bluetooth_task_runner_->PostTask(
  907. FROM_HERE,
  908. base::BindOnce(&BluetoothTaskManagerWin::
  909. UnregisterGattCharacteristicValueChangedEvent,
  910. this, event_handle));
  911. }
  912. } // namespace device