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

Unified Diff: device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc

Issue 1606013002: BLE GATT service implementation in Chrome for Windows 8 and later (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update Build.gn Created 4 years, 11 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
Index: device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4df856d8cad10507b3ff5d2cd462e7a40198b2b3
--- /dev/null
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -0,0 +1,424 @@
+// Copyright 2015 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 "base/bind.h"
+#include "base/thread_task_runner_handle.h"
+#include "device/bluetooth/bluetooth_gatt_notify_session_win.h"
+
+namespace device {
+
+void WinOnRemoteCharacteristicValueChanged(BTH_LE_GATT_EVENT_TYPE type,
+ PVOID event_parameter,
+ PVOID context) {
+ BluetoothRemoteGattCharacteristicWin* characteristic =
+ (BluetoothRemoteGattCharacteristicWin*)context;
+ characteristic->OnRemoteCharacteristicValueChanged(type, event_parameter);
+}
+
+void BluetoothRemoteGattCharacteristicWin::
+ NotifyCharacteristicDiscComplIfNecessary() {
+ if (descriptor_discovered_ &&
+ completed_descriptors_.size() == included_descriptor_objects_.size() &&
+ (characteristic_value_initialized_ ||
+ !characteristic_info_->IsReadable) &&
+ !complete_notified_) {
+ parent_service_->NotifyGattCharacteristicAdded(this);
+ complete_notified_ = true;
+ }
+}
+
+void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors(
+ PBTH_LE_GATT_DESCRIPTOR descriptors,
+ uint16_t num) {
+ if (num == 0) {
+ completed_descriptors_.clear();
+ included_descriptor_objects_.clear();
+ return;
+ }
+ // Map of retrieved descriptor uuid value to its index in |descriptors|.
+ std::map<std::string, uint16_t> current_descriptors;
+ for (uint16_t i = 0; i < num; i++) {
+ current_descriptors[task_manager_->BluetoothLowEnergyUuidToBluetoothUuid(
+ descriptors[i].DescriptorUuid)
+ .value()] = i;
+ }
+ // Map of known descriptor uuid value to its identifier.
+ std::map<std::string, std::string> known_descriptors;
+ if (included_descriptor_objects_.size() != 0) {
+ for (auto e : included_descriptor_objects_) {
+ known_descriptors[e.second->GetUUID().value()] = e.first;
+ }
+ std::vector<std::string> removed_descriptors;
+ for (auto e : known_descriptors) {
+ if (current_descriptors.find(e.first) == current_descriptors.end()) {
+ removed_descriptors.push_back(e.second);
+ }
+ }
+ for (auto e : removed_descriptors) {
+ completed_descriptors_.erase(e);
+ included_descriptor_objects_.erase(e);
+ }
+ // Update previously known descriptors.
+ for (auto e : included_descriptor_objects_)
+ e.second->Update();
+ }
+
+ // Return if no new descriptors have been added.
+ if (included_descriptor_objects_.size() == num)
+ return;
+
+ // Add new descriptors.
+ for (auto e : current_descriptors) {
+ if (known_descriptors.find(e.first) == known_descriptors.end()) {
+ PBTH_LE_GATT_DESCRIPTOR win_descriptor_info =
+ new BTH_LE_GATT_DESCRIPTOR();
+ *win_descriptor_info = descriptors[e.second];
+ BluetoothRemoteGattDescriptorWin* descriptor_object =
+ new BluetoothRemoteGattDescriptorWin(
+ adapter_, parent_service_->GetServicePath(), this,
+ win_descriptor_info, ui_task_runner_);
+ included_descriptor_objects_.add(
+ descriptor_object->GetIdentifier(),
+ scoped_ptr<BluetoothRemoteGattDescriptorWin>(descriptor_object));
+ }
+ }
+}
+
+void BluetoothRemoteGattCharacteristicWin::GetIncludedDescriptorsCallback(
+ PBTH_LE_GATT_DESCRIPTOR descriptors,
+ uint16_t num,
+ HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
+ return;
+ descriptor_discovered_ = true;
+ UpdateIncludedDescriptors(descriptors, num);
+ NotifyCharacteristicDiscComplIfNecessary();
+}
+
+// Called by included descriptors.
+void BluetoothRemoteGattCharacteristicWin::NotifyGattDescriptorAdded(
+ BluetoothRemoteGattDescriptorWin* descriptor) {
+ completed_descriptors_.insert(descriptor->GetIdentifier());
+ adapter_->NotifyGattDescriptorAdded(descriptor);
+ NotifyCharacteristicDiscComplIfNecessary();
+}
+
+void BluetoothRemoteGattCharacteristicWin::NotifyGattCharacteristicValueChanged(
+ uint8_t* new_value,
+ ULONG size) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ characteristic_value_.clear();
+ for (ULONG i = 0; i < size; i++)
+ characteristic_value_.push_back(new_value[i]);
+ adapter_->NotifyGattCharacteristicValueChanged(this, characteristic_value_);
+}
+
+void BluetoothRemoteGattCharacteristicWin::OnRemoteCharacteristicValueChanged(
+ BTH_LE_GATT_EVENT_TYPE type,
+ PVOID event_parameter) {
+ if (type == CharacteristicValueChangedEvent) {
+ BLUETOOTH_GATT_VALUE_CHANGED_EVENT* event =
+ (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)event_parameter;
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value_win =
+ event->CharacteristicValue;
+
+ uint8_t* new_value = new uint8_t[new_value_win->DataSize];
+ memcpy(new_value, &(new_value_win->Data[0]), new_value_win->DataSize);
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ NotifyGattCharacteristicValueChanged,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(new_value), new_value_win->DataSize));
+ }
+}
+
+void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
+ BLUETOOTH_GATT_EVENT_HANDLE event_handle,
+ HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (FAILED(hr)) {
+ for (auto callback : start_notifying_callback_)
+ callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
+ start_notifying_callback_.clear();
+ return;
+ }
+
+ for (auto callback : start_notifying_callback_) {
+ scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
+ new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
+ callback.first.Run(std::move(notify_session));
+ number_of_active_notify_sessions_++;
+ }
+ start_notifying_callback_.clear();
+ registered_event_handle_ = event_handle;
+ is_notifying_ = true;
+}
+
+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_(ui_task_runner),
+ characteristic_value_initialized_(false),
+ registered_event_handle_(NULL),
+ weak_ptr_factory_(this),
+ complete_notified_(false),
+ is_notifying_(false),
+ number_of_active_notify_sessions_(0) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ characteristic_value_.clear();
+ included_descriptor_objects_.clear();
+ completed_descriptors_.clear();
+ read_remote_characteristic_value_callbacks_.clear();
+ write_remote_characteristic_value_callback_.clear();
+ start_notifying_callback_.clear();
+
+ adapter_ = parent_service_->GetAdapter();
+ task_manager_ = adapter_->GetWinBluetoothTaskManager();
+ DCHECK(parent_service_);
+ DCHECK(characteristic_info_);
+ DCHECK(adapter_);
+ DCHECK(task_manager_);
+
+ characteristic_uuid_ = task_manager_->BluetoothLowEnergyUuidToBluetoothUuid(
+ characteristic_info_->CharacteristicUuid);
+ Update();
+}
+
+BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (registered_event_handle_ != NULL) {
+ task_manager_->UnregisterCharacteristicValueChangedEvent(
+ registered_event_handle_);
+ }
+
+ completed_descriptors_.clear();
+ included_descriptor_objects_.clear();
+ adapter_->NotifyGattCharacteristicRemoved(this);
+}
+
+std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const {
+ return parent_service_->GetIdentifier() + "_" + characteristic_uuid_.value();
+}
+
+BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const {
+ return characteristic_uuid_;
+}
+
+bool BluetoothRemoteGattCharacteristicWin::IsLocal() const {
+ return false;
+}
+
+std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
+ return const_cast<std::vector<uint8_t>&>(characteristic_value_);
+}
+
+BluetoothGattService* BluetoothRemoteGattCharacteristicWin::GetService() const {
+ return parent_service_;
+}
+
+BluetoothGattCharacteristic::Properties
+BluetoothRemoteGattCharacteristicWin::GetProperties() const {
+ BluetoothGattCharacteristic::Properties properties = PROPERTY_NONE;
+
+ if (characteristic_info_.get()->IsBroadcastable)
+ properties = properties | PROPERTY_BROADCAST;
+ if (characteristic_info_.get()->IsReadable)
+ properties = properties | PROPERTY_READ;
+ if (characteristic_info_.get()->IsWritableWithoutResponse)
+ properties = properties | PROPERTY_WRITE_WITHOUT_RESPONSE;
+ if (characteristic_info_.get()->IsWritable)
+ properties = properties | PROPERTY_WRITE;
+ if (characteristic_info_.get()->IsNotifiable)
+ properties = properties | PROPERTY_NOTIFY;
+ if (characteristic_info_.get()->IsIndicatable)
+ properties = properties | PROPERTY_INDICATE;
+ if (characteristic_info_.get()->IsSignedWritable)
+ properties = properties | PROPERTY_AUTHENTICATED_SIGNED_WRITES;
+ if (characteristic_info_.get()->HasExtendedProperties)
+ properties = properties | PROPERTY_EXTENDED_PROPERTIES;
+
+ return properties;
+}
+
+BluetoothGattCharacteristic::Permissions
+BluetoothRemoteGattCharacteristicWin::GetPermissions() const {
+ BluetoothGattCharacteristic::Permissions permissions = PERMISSION_NONE;
+
+ if (characteristic_info_.get()->IsReadable)
+ permissions = permissions | PERMISSION_READ;
+ if (characteristic_info_.get()->IsWritable)
+ permissions = permissions | PERMISSION_WRITE;
+
+ return permissions;
+}
+
+bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const {
+ return is_notifying_;
+}
+
+std::vector<BluetoothGattDescriptor*>
+BluetoothRemoteGattCharacteristicWin::GetDescriptors() const {
+ std::vector<BluetoothGattDescriptor*> descriptors;
+ for (auto descriptor : included_descriptor_objects_)
+ descriptors.push_back(descriptor.second);
+ return descriptors;
+}
+
+BluetoothGattDescriptor* BluetoothRemoteGattCharacteristicWin::GetDescriptor(
+ const std::string& identifier) const {
+ GattDescriptorMap::const_iterator it =
+ included_descriptor_objects_.find(identifier);
+ if (it != included_descriptor_objects_.end())
+ return it->second;
+ return nullptr;
+}
+
+bool BluetoothRemoteGattCharacteristicWin::AddDescriptor(
+ BluetoothGattDescriptor* descriptor) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool BluetoothRemoteGattCharacteristicWin::UpdateValue(
+ const std::vector<uint8_t>& value) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void BluetoothRemoteGattCharacteristicWin::StartNotifySession(
+ const NotifySessionCallback& callback,
+ const ErrorCallback& error_callback) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (is_notifying_) {
+ scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
+ new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
+ callback.Run(std::move(notify_session));
+ number_of_active_notify_sessions_++;
+ return;
+ }
+
+ if (characteristic_info_->IsNotifiable ||
+ characteristic_info_->IsIndicatable) {
+ start_notifying_callback_.push_back(
+ std::make_pair(callback, error_callback));
+ task_manager_->PostRegisterCharacteristicValueChangedEvent(
+ parent_service_->GetServicePath(), characteristic_info_.get(),
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ GattEventRegistrationCallback,
+ weak_ptr_factory_.GetWeakPtr()),
+ &WinOnRemoteCharacteristicValueChanged, (PVOID) this);
+ } else {
+ error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED);
+ }
+}
+
+void BluetoothRemoteGattCharacteristicWin::StopNotifySession() {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (!is_notifying_)
+ return;
+
+ number_of_active_notify_sessions_--;
+ if (number_of_active_notify_sessions_ > 0)
+ return;
+ task_manager_->UnregisterCharacteristicValueChangedEvent(
+ registered_event_handle_);
+ registered_event_handle_ = NULL;
+ is_notifying_ = false;
+ number_of_active_notify_sessions_ = 0;
+ start_notifying_callback_.clear();
+}
+
+void BluetoothRemoteGattCharacteristicWin::ReadCharacteristicValueCallback(
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE value,
+ HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (FAILED(hr)) {
+ LOG(ERROR) << "Failed at reading characteristic value with error ";
+ for (const auto callback : read_remote_characteristic_value_callbacks_)
+ callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
+ } else {
+ characteristic_value_.clear();
+ for (ULONG i = 0; i < value->DataSize; i++)
+ characteristic_value_.push_back(value->Data[i]);
+ for (const auto callback : read_remote_characteristic_value_callbacks_)
+ callback.first.Run(characteristic_value_);
+ }
+
+ if (!characteristic_value_initialized_) {
+ characteristic_value_initialized_ = true;
+ NotifyCharacteristicDiscComplIfNecessary();
+ }
+ read_remote_characteristic_value_callbacks_.clear();
+}
+
+void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
+ const ValueCallback& callback,
+ const ErrorCallback& error_callback) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (!characteristic_info_.get()->IsReadable)
+ error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
+
+ read_remote_characteristic_value_callbacks_.push_back(
+ std::make_pair(callback, error_callback));
+ task_manager_->PostReadCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(),
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ ReadCharacteristicValueCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristicCallback(
+ HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (FAILED(hr)) {
+ for (const auto callback : write_remote_characteristic_value_callback_)
+ callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
+ } else {
+ for (const auto callback : write_remote_characteristic_value_callback_)
+ callback.first.Run();
+ }
+ write_remote_characteristic_value_callback_.clear();
+}
+
+void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
+ const std::vector<uint8_t>& new_value,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ if (!characteristic_info_.get()->IsWritable)
+ error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
+
+ write_remote_characteristic_value_callback_.push_back(
+ std::make_pair(callback, error_callback));
+ task_manager_->PostWriteCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(), new_value,
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ WriteRemoteCharacteristicCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothRemoteGattCharacteristicWin::Update() {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ task_manager_->PostGetGattIncludedDescriptors(
+ parent_service_->GetServicePath(), characteristic_info_.get(),
+ base::Bind(
+ &BluetoothRemoteGattCharacteristicWin::GetIncludedDescriptorsCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ if (characteristic_info_->IsReadable) {
+ task_manager_->PostReadCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(),
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ ReadCharacteristicValueCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+} // namespace device.

Powered by Google App Engine
This is Rietveld 408576698