bluetooth_remote_gatt_characteristic_win.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. // Copyright 2016 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_remote_gatt_characteristic_win.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/memory/ptr_util.h"
  8. #include "base/threading/thread_task_runner_handle.h"
  9. #include "device/bluetooth/bluetooth_adapter_win.h"
  10. #include "device/bluetooth/bluetooth_gatt_notify_session.h"
  11. #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h"
  12. #include "device/bluetooth/bluetooth_remote_gatt_service_win.h"
  13. #include "device/bluetooth/bluetooth_task_manager_win.h"
  14. namespace device {
  15. BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
  16. BluetoothRemoteGattServiceWin* parent_service,
  17. BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
  18. scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
  19. : parent_service_(parent_service),
  20. characteristic_info_(characteristic_info),
  21. ui_task_runner_(std::move(ui_task_runner)),
  22. characteristic_added_notified_(false),
  23. characteristic_value_read_or_write_in_progress_(false),
  24. gatt_event_handle_(nullptr),
  25. discovery_pending_count_(0) {
  26. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  27. DCHECK(parent_service_);
  28. DCHECK(characteristic_info_);
  29. task_manager_ =
  30. parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager();
  31. DCHECK(task_manager_);
  32. characteristic_uuid_ =
  33. BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
  34. characteristic_info_->CharacteristicUuid);
  35. characteristic_identifier_ =
  36. parent_service_->GetIdentifier() + "_" +
  37. std::to_string(characteristic_info_->AttributeHandle);
  38. Update();
  39. }
  40. BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() {
  41. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  42. ClearIncludedDescriptors();
  43. if (gatt_event_handle_ != nullptr) {
  44. task_manager_->PostUnregisterGattCharacteristicValueChangedEvent(
  45. gatt_event_handle_);
  46. gatt_event_handle_ = nullptr;
  47. }
  48. parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this);
  49. if (read_characteristic_value_callback_) {
  50. std::move(read_characteristic_value_callback_)
  51. .Run(BluetoothGattService::GATT_ERROR_FAILED,
  52. /*value=*/std::vector<uint8_t>());
  53. }
  54. if (!write_characteristic_value_callbacks_.first.is_null()) {
  55. DCHECK(!write_characteristic_value_callbacks_.second.is_null());
  56. std::move(write_characteristic_value_callbacks_.second)
  57. .Run(BluetoothGattService::GATT_ERROR_FAILED);
  58. }
  59. }
  60. std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const {
  61. return characteristic_identifier_;
  62. }
  63. BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const {
  64. return characteristic_uuid_;
  65. }
  66. std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
  67. return const_cast<std::vector<uint8_t>&>(characteristic_value_);
  68. }
  69. BluetoothRemoteGattService* BluetoothRemoteGattCharacteristicWin::GetService()
  70. const {
  71. return parent_service_;
  72. }
  73. BluetoothRemoteGattCharacteristic::Properties
  74. BluetoothRemoteGattCharacteristicWin::GetProperties() const {
  75. BluetoothRemoteGattCharacteristic::Properties properties = PROPERTY_NONE;
  76. if (characteristic_info_->IsBroadcastable)
  77. properties = properties | PROPERTY_BROADCAST;
  78. if (characteristic_info_->IsReadable)
  79. properties = properties | PROPERTY_READ;
  80. if (characteristic_info_->IsWritableWithoutResponse)
  81. properties = properties | PROPERTY_WRITE_WITHOUT_RESPONSE;
  82. if (characteristic_info_->IsWritable)
  83. properties = properties | PROPERTY_WRITE;
  84. if (characteristic_info_->IsNotifiable)
  85. properties = properties | PROPERTY_NOTIFY;
  86. if (characteristic_info_->IsIndicatable)
  87. properties = properties | PROPERTY_INDICATE;
  88. if (characteristic_info_->IsSignedWritable)
  89. properties = properties | PROPERTY_AUTHENTICATED_SIGNED_WRITES;
  90. if (characteristic_info_->HasExtendedProperties)
  91. properties = properties | PROPERTY_EXTENDED_PROPERTIES;
  92. // TODO(crbug.com/589304): Information about PROPERTY_RELIABLE_WRITE and
  93. // PROPERTY_WRITABLE_AUXILIARIES is not available in characteristic_info_
  94. // (BTH_LE_GATT_CHARACTERISTIC).
  95. return properties;
  96. }
  97. BluetoothRemoteGattCharacteristic::Permissions
  98. BluetoothRemoteGattCharacteristicWin::GetPermissions() const {
  99. BluetoothRemoteGattCharacteristic::Permissions permissions = PERMISSION_NONE;
  100. if (characteristic_info_->IsReadable)
  101. permissions = permissions | PERMISSION_READ;
  102. if (characteristic_info_->IsWritable)
  103. permissions = permissions | PERMISSION_WRITE;
  104. return permissions;
  105. }
  106. bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const {
  107. return gatt_event_handle_ != nullptr;
  108. }
  109. void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
  110. ValueCallback callback) {
  111. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  112. if (!characteristic_info_.get()->IsReadable) {
  113. std::move(callback).Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED,
  114. std::vector<uint8_t>());
  115. return;
  116. }
  117. if (characteristic_value_read_or_write_in_progress_) {
  118. std::move(callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS,
  119. std::vector<uint8_t>());
  120. return;
  121. }
  122. characteristic_value_read_or_write_in_progress_ = true;
  123. read_characteristic_value_callback_ = std::move(callback);
  124. task_manager_->PostReadGattCharacteristicValue(
  125. parent_service_->GetServicePath(), characteristic_info_.get(),
  126. base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
  127. OnReadRemoteCharacteristicValueCallback,
  128. weak_ptr_factory_.GetWeakPtr()));
  129. }
  130. void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
  131. const std::vector<uint8_t>& value,
  132. WriteType write_type,
  133. base::OnceClosure callback,
  134. ErrorCallback error_callback) {
  135. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  136. if (characteristic_value_read_or_write_in_progress_) {
  137. std::move(error_callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
  138. return;
  139. }
  140. ULONG flags;
  141. switch (write_type) {
  142. case WriteType::kWithResponse:
  143. flags = BLUETOOTH_GATT_FLAG_NONE;
  144. break;
  145. case WriteType::kWithoutResponse:
  146. flags = BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
  147. break;
  148. }
  149. characteristic_value_read_or_write_in_progress_ = true;
  150. write_characteristic_value_callbacks_ =
  151. std::make_pair(std::move(callback), std::move(error_callback));
  152. task_manager_->PostWriteGattCharacteristicValue(
  153. parent_service_->GetServicePath(), characteristic_info_.get(), value,
  154. flags,
  155. base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
  156. OnWriteRemoteCharacteristicValueCallback,
  157. weak_ptr_factory_.GetWeakPtr()));
  158. }
  159. void BluetoothRemoteGattCharacteristicWin::DeprecatedWriteRemoteCharacteristic(
  160. const std::vector<uint8_t>& value,
  161. base::OnceClosure callback,
  162. ErrorCallback error_callback) {
  163. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  164. if (!characteristic_info_->IsWritable &&
  165. !characteristic_info_->IsWritableWithoutResponse) {
  166. std::move(error_callback)
  167. .Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
  168. return;
  169. }
  170. if (characteristic_value_read_or_write_in_progress_) {
  171. std::move(error_callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
  172. return;
  173. }
  174. ULONG flags = BLUETOOTH_GATT_FLAG_NONE;
  175. if (!characteristic_info_->IsWritable) {
  176. flags |= BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
  177. }
  178. characteristic_value_read_or_write_in_progress_ = true;
  179. write_characteristic_value_callbacks_ =
  180. std::make_pair(std::move(callback), std::move(error_callback));
  181. task_manager_->PostWriteGattCharacteristicValue(
  182. parent_service_->GetServicePath(), characteristic_info_.get(), value,
  183. flags,
  184. base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
  185. OnWriteRemoteCharacteristicValueCallback,
  186. weak_ptr_factory_.GetWeakPtr()));
  187. }
  188. void BluetoothRemoteGattCharacteristicWin::Update() {
  189. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  190. ++discovery_pending_count_;
  191. task_manager_->PostGetGattIncludedDescriptors(
  192. parent_service_->GetServicePath(), characteristic_info_.get(),
  193. base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
  194. OnGetIncludedDescriptorsCallback,
  195. weak_ptr_factory_.GetWeakPtr()));
  196. }
  197. uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const {
  198. return characteristic_info_->AttributeHandle;
  199. }
  200. void BluetoothRemoteGattCharacteristicWin::SubscribeToNotifications(
  201. BluetoothRemoteGattDescriptor* ccc_descriptor,
  202. base::OnceClosure callback,
  203. ErrorCallback error_callback) {
  204. task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
  205. parent_service_->GetServicePath(), characteristic_info_.get(),
  206. static_cast<BluetoothRemoteGattDescriptorWin*>(ccc_descriptor)
  207. ->GetWinDescriptorInfo(),
  208. base::BindOnce(
  209. &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
  210. weak_ptr_factory_.GetWeakPtr(), std::move(callback),
  211. std::move(error_callback)),
  212. base::BindRepeating(&BluetoothRemoteGattCharacteristicWin::
  213. OnGattCharacteristicValueChanged,
  214. weak_ptr_factory_.GetWeakPtr()));
  215. }
  216. void BluetoothRemoteGattCharacteristicWin::UnsubscribeFromNotifications(
  217. BluetoothRemoteGattDescriptor* ccc_descriptor,
  218. base::OnceClosure callback,
  219. ErrorCallback error_callback) {
  220. // TODO(crbug.com/735828): Implement this method.
  221. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
  222. }
  223. void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback(
  224. std::unique_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors,
  225. uint16_t num,
  226. HRESULT hr) {
  227. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  228. UpdateIncludedDescriptors(descriptors.get(), num);
  229. if (!characteristic_added_notified_) {
  230. characteristic_added_notified_ = true;
  231. parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this);
  232. }
  233. // Report discovery complete.
  234. if (--discovery_pending_count_ == 0)
  235. parent_service_->GattCharacteristicDiscoveryComplete(this);
  236. }
  237. void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors(
  238. PBTH_LE_GATT_DESCRIPTOR descriptors,
  239. uint16_t num) {
  240. if (num == 0) {
  241. descriptors_.clear();
  242. return;
  243. }
  244. // First, remove descriptors that no longer exist.
  245. std::vector<std::string> to_be_removed;
  246. for (const auto& d : descriptors_) {
  247. if (!DoesDescriptorExist(
  248. descriptors, num,
  249. static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())))
  250. to_be_removed.push_back(d.second->GetIdentifier());
  251. }
  252. for (const auto& id : to_be_removed) {
  253. auto iter = descriptors_.find(id);
  254. auto pair = std::move(*iter);
  255. descriptors_.erase(iter);
  256. }
  257. // Return if no new descriptors have been added.
  258. if (descriptors_.size() == num)
  259. return;
  260. // Add new descriptors.
  261. for (uint16_t i = 0; i < num; i++) {
  262. if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid,
  263. descriptors[i].AttributeHandle)) {
  264. PBTH_LE_GATT_DESCRIPTOR win_descriptor_info =
  265. new BTH_LE_GATT_DESCRIPTOR();
  266. *win_descriptor_info = descriptors[i];
  267. BluetoothRemoteGattDescriptorWin* descriptor =
  268. new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info,
  269. ui_task_runner_);
  270. AddDescriptor(base::WrapUnique(descriptor));
  271. }
  272. }
  273. }
  274. bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered(
  275. const BTH_LE_UUID& uuid,
  276. uint16_t attribute_handle) {
  277. BluetoothUUID bt_uuid =
  278. BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
  279. for (const auto& d : descriptors_) {
  280. if (bt_uuid == d.second->GetUUID() &&
  281. attribute_handle ==
  282. static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())
  283. ->GetAttributeHandle()) {
  284. return true;
  285. }
  286. }
  287. return false;
  288. }
  289. bool BluetoothRemoteGattCharacteristicWin::DoesDescriptorExist(
  290. PBTH_LE_GATT_DESCRIPTOR descriptors,
  291. uint16_t num,
  292. BluetoothRemoteGattDescriptorWin* descriptor) {
  293. for (uint16_t i = 0; i < num; i++) {
  294. BluetoothUUID uuid =
  295. BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
  296. descriptors[i].DescriptorUuid);
  297. if (descriptor->GetUUID() == uuid &&
  298. descriptor->GetAttributeHandle() == descriptors[i].AttributeHandle) {
  299. return true;
  300. }
  301. }
  302. return false;
  303. }
  304. void BluetoothRemoteGattCharacteristicWin::
  305. OnReadRemoteCharacteristicValueCallback(
  306. std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value,
  307. HRESULT hr) {
  308. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  309. characteristic_value_read_or_write_in_progress_ = false;
  310. ValueCallback callback = std::move(read_characteristic_value_callback_);
  311. if (FAILED(hr)) {
  312. std::move(callback).Run(HRESULTToGattErrorCode(hr), std::vector<uint8_t>());
  313. } else {
  314. characteristic_value_.clear();
  315. for (ULONG i = 0; i < value->DataSize; i++)
  316. characteristic_value_.push_back(value->Data[i]);
  317. std::move(callback).Run(absl::nullopt, characteristic_value_);
  318. }
  319. }
  320. void BluetoothRemoteGattCharacteristicWin::
  321. OnWriteRemoteCharacteristicValueCallback(HRESULT hr) {
  322. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  323. characteristic_value_read_or_write_in_progress_ = false;
  324. std::pair<base::OnceClosure, ErrorCallback> callbacks;
  325. callbacks.swap(write_characteristic_value_callbacks_);
  326. if (FAILED(hr)) {
  327. std::move(callbacks.second).Run(HRESULTToGattErrorCode(hr));
  328. } else {
  329. std::move(callbacks.first).Run();
  330. }
  331. }
  332. BluetoothGattService::GattErrorCode
  333. BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) {
  334. if (HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER) == hr)
  335. return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
  336. switch (hr) {
  337. case E_BLUETOOTH_ATT_READ_NOT_PERMITTED:
  338. case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED:
  339. return BluetoothGattService::GATT_ERROR_NOT_PERMITTED;
  340. case E_BLUETOOTH_ATT_UNKNOWN_ERROR:
  341. return BluetoothGattService::GATT_ERROR_UNKNOWN;
  342. case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
  343. return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
  344. case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED:
  345. return BluetoothGattService::GATT_ERROR_NOT_SUPPORTED;
  346. default:
  347. return BluetoothGattService::GATT_ERROR_FAILED;
  348. }
  349. }
  350. void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged(
  351. std::unique_ptr<std::vector<uint8_t>> new_value) {
  352. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  353. characteristic_value_.assign(new_value->begin(), new_value->end());
  354. parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged(
  355. this, characteristic_value_);
  356. }
  357. void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
  358. base::OnceClosure callback,
  359. ErrorCallback error_callback,
  360. BLUETOOTH_GATT_EVENT_HANDLE event_handle,
  361. HRESULT hr) {
  362. DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
  363. if (SUCCEEDED(hr)) {
  364. gatt_event_handle_ = event_handle;
  365. std::move(callback).Run();
  366. } else {
  367. std::move(error_callback).Run(HRESULTToGattErrorCode(hr));
  368. }
  369. }
  370. void BluetoothRemoteGattCharacteristicWin::ClearIncludedDescriptors() {
  371. // Explicitly reset to null to ensure that calling GetDescriptor() on the
  372. // removed descriptor in GattDescriptorRemoved() returns null.
  373. std::exchange(descriptors_, {});
  374. }
  375. } // namespace device.