123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/memory/ptr_util.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "device/bluetooth/bluetooth_adapter_win.h"
- #include "device/bluetooth/bluetooth_gatt_notify_session.h"
- #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h"
- #include "device/bluetooth/bluetooth_remote_gatt_service_win.h"
- #include "device/bluetooth/bluetooth_task_manager_win.h"
- namespace device {
- BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
- BluetoothRemoteGattServiceWin* parent_service,
- BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
- : parent_service_(parent_service),
- characteristic_info_(characteristic_info),
- ui_task_runner_(std::move(ui_task_runner)),
- characteristic_added_notified_(false),
- characteristic_value_read_or_write_in_progress_(false),
- gatt_event_handle_(nullptr),
- discovery_pending_count_(0) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(parent_service_);
- DCHECK(characteristic_info_);
- task_manager_ =
- parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager();
- DCHECK(task_manager_);
- characteristic_uuid_ =
- BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
- characteristic_info_->CharacteristicUuid);
- characteristic_identifier_ =
- parent_service_->GetIdentifier() + "_" +
- std::to_string(characteristic_info_->AttributeHandle);
- Update();
- }
- BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- ClearIncludedDescriptors();
- if (gatt_event_handle_ != nullptr) {
- task_manager_->PostUnregisterGattCharacteristicValueChangedEvent(
- gatt_event_handle_);
- gatt_event_handle_ = nullptr;
- }
- parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this);
- if (read_characteristic_value_callback_) {
- std::move(read_characteristic_value_callback_)
- .Run(BluetoothGattService::GATT_ERROR_FAILED,
- /*value=*/std::vector<uint8_t>());
- }
- if (!write_characteristic_value_callbacks_.first.is_null()) {
- DCHECK(!write_characteristic_value_callbacks_.second.is_null());
- std::move(write_characteristic_value_callbacks_.second)
- .Run(BluetoothGattService::GATT_ERROR_FAILED);
- }
- }
- std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const {
- return characteristic_identifier_;
- }
- BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const {
- return characteristic_uuid_;
- }
- std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
- return const_cast<std::vector<uint8_t>&>(characteristic_value_);
- }
- BluetoothRemoteGattService* BluetoothRemoteGattCharacteristicWin::GetService()
- const {
- return parent_service_;
- }
- BluetoothRemoteGattCharacteristic::Properties
- BluetoothRemoteGattCharacteristicWin::GetProperties() const {
- BluetoothRemoteGattCharacteristic::Properties properties = PROPERTY_NONE;
- if (characteristic_info_->IsBroadcastable)
- properties = properties | PROPERTY_BROADCAST;
- if (characteristic_info_->IsReadable)
- properties = properties | PROPERTY_READ;
- if (characteristic_info_->IsWritableWithoutResponse)
- properties = properties | PROPERTY_WRITE_WITHOUT_RESPONSE;
- if (characteristic_info_->IsWritable)
- properties = properties | PROPERTY_WRITE;
- if (characteristic_info_->IsNotifiable)
- properties = properties | PROPERTY_NOTIFY;
- if (characteristic_info_->IsIndicatable)
- properties = properties | PROPERTY_INDICATE;
- if (characteristic_info_->IsSignedWritable)
- properties = properties | PROPERTY_AUTHENTICATED_SIGNED_WRITES;
- if (characteristic_info_->HasExtendedProperties)
- properties = properties | PROPERTY_EXTENDED_PROPERTIES;
- // TODO(crbug.com/589304): Information about PROPERTY_RELIABLE_WRITE and
- // PROPERTY_WRITABLE_AUXILIARIES is not available in characteristic_info_
- // (BTH_LE_GATT_CHARACTERISTIC).
- return properties;
- }
- BluetoothRemoteGattCharacteristic::Permissions
- BluetoothRemoteGattCharacteristicWin::GetPermissions() const {
- BluetoothRemoteGattCharacteristic::Permissions permissions = PERMISSION_NONE;
- if (characteristic_info_->IsReadable)
- permissions = permissions | PERMISSION_READ;
- if (characteristic_info_->IsWritable)
- permissions = permissions | PERMISSION_WRITE;
- return permissions;
- }
- bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const {
- return gatt_event_handle_ != nullptr;
- }
- void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
- ValueCallback callback) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- if (!characteristic_info_.get()->IsReadable) {
- std::move(callback).Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED,
- std::vector<uint8_t>());
- return;
- }
- if (characteristic_value_read_or_write_in_progress_) {
- std::move(callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS,
- std::vector<uint8_t>());
- return;
- }
- characteristic_value_read_or_write_in_progress_ = true;
- read_characteristic_value_callback_ = std::move(callback);
- task_manager_->PostReadGattCharacteristicValue(
- parent_service_->GetServicePath(), characteristic_info_.get(),
- base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
- OnReadRemoteCharacteristicValueCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
- const std::vector<uint8_t>& value,
- WriteType write_type,
- base::OnceClosure callback,
- ErrorCallback error_callback) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- if (characteristic_value_read_or_write_in_progress_) {
- std::move(error_callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
- return;
- }
- ULONG flags;
- switch (write_type) {
- case WriteType::kWithResponse:
- flags = BLUETOOTH_GATT_FLAG_NONE;
- break;
- case WriteType::kWithoutResponse:
- flags = BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
- break;
- }
- characteristic_value_read_or_write_in_progress_ = true;
- write_characteristic_value_callbacks_ =
- std::make_pair(std::move(callback), std::move(error_callback));
- task_manager_->PostWriteGattCharacteristicValue(
- parent_service_->GetServicePath(), characteristic_info_.get(), value,
- flags,
- base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
- OnWriteRemoteCharacteristicValueCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void BluetoothRemoteGattCharacteristicWin::DeprecatedWriteRemoteCharacteristic(
- const std::vector<uint8_t>& value,
- base::OnceClosure callback,
- ErrorCallback error_callback) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- if (!characteristic_info_->IsWritable &&
- !characteristic_info_->IsWritableWithoutResponse) {
- std::move(error_callback)
- .Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
- return;
- }
- if (characteristic_value_read_or_write_in_progress_) {
- std::move(error_callback).Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
- return;
- }
- ULONG flags = BLUETOOTH_GATT_FLAG_NONE;
- if (!characteristic_info_->IsWritable) {
- flags |= BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
- }
- characteristic_value_read_or_write_in_progress_ = true;
- write_characteristic_value_callbacks_ =
- std::make_pair(std::move(callback), std::move(error_callback));
- task_manager_->PostWriteGattCharacteristicValue(
- parent_service_->GetServicePath(), characteristic_info_.get(), value,
- flags,
- base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
- OnWriteRemoteCharacteristicValueCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void BluetoothRemoteGattCharacteristicWin::Update() {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- ++discovery_pending_count_;
- task_manager_->PostGetGattIncludedDescriptors(
- parent_service_->GetServicePath(), characteristic_info_.get(),
- base::BindOnce(&BluetoothRemoteGattCharacteristicWin::
- OnGetIncludedDescriptorsCallback,
- weak_ptr_factory_.GetWeakPtr()));
- }
- uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const {
- return characteristic_info_->AttributeHandle;
- }
- void BluetoothRemoteGattCharacteristicWin::SubscribeToNotifications(
- BluetoothRemoteGattDescriptor* ccc_descriptor,
- base::OnceClosure callback,
- ErrorCallback error_callback) {
- task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
- parent_service_->GetServicePath(), characteristic_info_.get(),
- static_cast<BluetoothRemoteGattDescriptorWin*>(ccc_descriptor)
- ->GetWinDescriptorInfo(),
- base::BindOnce(
- &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- std::move(error_callback)),
- base::BindRepeating(&BluetoothRemoteGattCharacteristicWin::
- OnGattCharacteristicValueChanged,
- weak_ptr_factory_.GetWeakPtr()));
- }
- void BluetoothRemoteGattCharacteristicWin::UnsubscribeFromNotifications(
- BluetoothRemoteGattDescriptor* ccc_descriptor,
- base::OnceClosure callback,
- ErrorCallback error_callback) {
- // TODO(crbug.com/735828): Implement this method.
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
- }
- void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback(
- std::unique_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors,
- uint16_t num,
- HRESULT hr) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- UpdateIncludedDescriptors(descriptors.get(), num);
- if (!characteristic_added_notified_) {
- characteristic_added_notified_ = true;
- parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this);
- }
- // Report discovery complete.
- if (--discovery_pending_count_ == 0)
- parent_service_->GattCharacteristicDiscoveryComplete(this);
- }
- void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors(
- PBTH_LE_GATT_DESCRIPTOR descriptors,
- uint16_t num) {
- if (num == 0) {
- descriptors_.clear();
- return;
- }
- // First, remove descriptors that no longer exist.
- std::vector<std::string> to_be_removed;
- for (const auto& d : descriptors_) {
- if (!DoesDescriptorExist(
- descriptors, num,
- static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())))
- to_be_removed.push_back(d.second->GetIdentifier());
- }
- for (const auto& id : to_be_removed) {
- auto iter = descriptors_.find(id);
- auto pair = std::move(*iter);
- descriptors_.erase(iter);
- }
- // Return if no new descriptors have been added.
- if (descriptors_.size() == num)
- return;
- // Add new descriptors.
- for (uint16_t i = 0; i < num; i++) {
- if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid,
- descriptors[i].AttributeHandle)) {
- PBTH_LE_GATT_DESCRIPTOR win_descriptor_info =
- new BTH_LE_GATT_DESCRIPTOR();
- *win_descriptor_info = descriptors[i];
- BluetoothRemoteGattDescriptorWin* descriptor =
- new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info,
- ui_task_runner_);
- AddDescriptor(base::WrapUnique(descriptor));
- }
- }
- }
- bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered(
- const BTH_LE_UUID& uuid,
- uint16_t attribute_handle) {
- BluetoothUUID bt_uuid =
- BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
- for (const auto& d : descriptors_) {
- if (bt_uuid == d.second->GetUUID() &&
- attribute_handle ==
- static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())
- ->GetAttributeHandle()) {
- return true;
- }
- }
- return false;
- }
- bool BluetoothRemoteGattCharacteristicWin::DoesDescriptorExist(
- PBTH_LE_GATT_DESCRIPTOR descriptors,
- uint16_t num,
- BluetoothRemoteGattDescriptorWin* descriptor) {
- for (uint16_t i = 0; i < num; i++) {
- BluetoothUUID uuid =
- BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
- descriptors[i].DescriptorUuid);
- if (descriptor->GetUUID() == uuid &&
- descriptor->GetAttributeHandle() == descriptors[i].AttributeHandle) {
- return true;
- }
- }
- return false;
- }
- void BluetoothRemoteGattCharacteristicWin::
- OnReadRemoteCharacteristicValueCallback(
- std::unique_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value,
- HRESULT hr) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- characteristic_value_read_or_write_in_progress_ = false;
- ValueCallback callback = std::move(read_characteristic_value_callback_);
- if (FAILED(hr)) {
- std::move(callback).Run(HRESULTToGattErrorCode(hr), std::vector<uint8_t>());
- } else {
- characteristic_value_.clear();
- for (ULONG i = 0; i < value->DataSize; i++)
- characteristic_value_.push_back(value->Data[i]);
- std::move(callback).Run(absl::nullopt, characteristic_value_);
- }
- }
- void BluetoothRemoteGattCharacteristicWin::
- OnWriteRemoteCharacteristicValueCallback(HRESULT hr) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- characteristic_value_read_or_write_in_progress_ = false;
- std::pair<base::OnceClosure, ErrorCallback> callbacks;
- callbacks.swap(write_characteristic_value_callbacks_);
- if (FAILED(hr)) {
- std::move(callbacks.second).Run(HRESULTToGattErrorCode(hr));
- } else {
- std::move(callbacks.first).Run();
- }
- }
- BluetoothGattService::GattErrorCode
- BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) {
- if (HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER) == hr)
- return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
- switch (hr) {
- case E_BLUETOOTH_ATT_READ_NOT_PERMITTED:
- case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED:
- return BluetoothGattService::GATT_ERROR_NOT_PERMITTED;
- case E_BLUETOOTH_ATT_UNKNOWN_ERROR:
- return BluetoothGattService::GATT_ERROR_UNKNOWN;
- case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
- return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
- case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED:
- return BluetoothGattService::GATT_ERROR_NOT_SUPPORTED;
- default:
- return BluetoothGattService::GATT_ERROR_FAILED;
- }
- }
- void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged(
- std::unique_ptr<std::vector<uint8_t>> new_value) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- characteristic_value_.assign(new_value->begin(), new_value->end());
- parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged(
- this, characteristic_value_);
- }
- void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
- base::OnceClosure callback,
- ErrorCallback error_callback,
- BLUETOOTH_GATT_EVENT_HANDLE event_handle,
- HRESULT hr) {
- DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
- if (SUCCEEDED(hr)) {
- gatt_event_handle_ = event_handle;
- std::move(callback).Run();
- } else {
- std::move(error_callback).Run(HRESULTToGattErrorCode(hr));
- }
- }
- void BluetoothRemoteGattCharacteristicWin::ClearIncludedDescriptors() {
- // Explicitly reset to null to ensure that calling GetDescriptor() on the
- // removed descriptor in GattDescriptorRemoved() returns null.
- std::exchange(descriptors_, {});
- }
- } // namespace device.
|