| // Copyright 2018 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_service_winrt.h" |
| |
| #include <windows.foundation.collections.h> |
| |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "device/bluetooth/bluetooth_device.h" |
| #include "device/bluetooth/bluetooth_gatt_discoverer_winrt.h" |
| |
| namespace device { |
| |
| namespace { |
| |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| IGattDeviceService; |
| using Microsoft::WRL::ComPtr; |
| |
| } // namespace |
| |
| // static |
| std::unique_ptr<BluetoothRemoteGattServiceWinrt> |
| BluetoothRemoteGattServiceWinrt::Create( |
| BluetoothDevice* device, |
| ComPtr<IGattDeviceService> gatt_service) { |
| DCHECK(gatt_service); |
| GUID guid; |
| HRESULT hr = gatt_service->get_Uuid(&guid); |
| if (FAILED(hr)) { |
| VLOG(2) << "Getting UUID failed: " << logging::SystemErrorCodeToString(hr); |
| return nullptr; |
| } |
| |
| uint16_t attribute_handle; |
| hr = gatt_service->get_AttributeHandle(&attribute_handle); |
| if (FAILED(hr)) { |
| VLOG(2) << "Getting AttributeHandle failed: " |
| << logging::SystemErrorCodeToString(hr); |
| return nullptr; |
| } |
| |
| return base::WrapUnique(new BluetoothRemoteGattServiceWinrt( |
| device, std::move(gatt_service), BluetoothUUID(guid), attribute_handle)); |
| } |
| |
| BluetoothRemoteGattServiceWinrt::~BluetoothRemoteGattServiceWinrt() = default; |
| |
| std::string BluetoothRemoteGattServiceWinrt::GetIdentifier() const { |
| return identifier_; |
| } |
| |
| BluetoothUUID BluetoothRemoteGattServiceWinrt::GetUUID() const { |
| return uuid_; |
| } |
| |
| bool BluetoothRemoteGattServiceWinrt::IsPrimary() const { |
| return true; |
| } |
| |
| BluetoothDevice* BluetoothRemoteGattServiceWinrt::GetDevice() const { |
| return device_; |
| } |
| |
| std::vector<BluetoothRemoteGattService*> |
| BluetoothRemoteGattServiceWinrt::GetIncludedServices() const { |
| NOTIMPLEMENTED(); |
| return {}; |
| } |
| |
| void BluetoothRemoteGattServiceWinrt::UpdateCharacteristics( |
| BluetoothGattDiscovererWinrt* gatt_discoverer) { |
| const auto* gatt_characteristics = |
| gatt_discoverer->GetCharacteristics(attribute_handle_); |
| DCHECK(gatt_characteristics); |
| |
| // Instead of clearing out |characteristics_| and creating each characteristic |
| // from scratch, we create a new map and move already existing characteristics |
| // into it in order to preserve pointer stability. |
| CharacteristicMap characteristics; |
| for (const auto& gatt_characteristic : *gatt_characteristics) { |
| auto characteristic = BluetoothRemoteGattCharacteristicWinrt::Create( |
| this, gatt_characteristic.Get()); |
| if (!characteristic) |
| continue; |
| |
| std::string identifier = characteristic->GetIdentifier(); |
| auto iter = characteristics_.find(identifier); |
| if (iter != characteristics_.end()) { |
| iter = characteristics.emplace(std::move(*iter)).first; |
| } else { |
| iter = characteristics |
| .emplace(std::move(identifier), std::move(characteristic)) |
| .first; |
| } |
| |
| static_cast<BluetoothRemoteGattCharacteristicWinrt*>(iter->second.get()) |
| ->UpdateDescriptors(gatt_discoverer); |
| } |
| |
| std::swap(characteristics, characteristics_); |
| SetDiscoveryComplete(true); |
| } |
| |
| IGattDeviceService* |
| BluetoothRemoteGattServiceWinrt::GetDeviceServiceForTesting() { |
| return gatt_service_.Get(); |
| } |
| |
| // static |
| uint8_t BluetoothRemoteGattServiceWinrt::ToProtocolError( |
| GattErrorCode error_code) { |
| switch (error_code) { |
| case GATT_ERROR_UNKNOWN: |
| return 0xF0; |
| case GATT_ERROR_FAILED: |
| return 0x01; |
| case GATT_ERROR_IN_PROGRESS: |
| return 0x09; |
| case GATT_ERROR_INVALID_LENGTH: |
| return 0x0D; |
| case GATT_ERROR_NOT_PERMITTED: |
| return 0x02; |
| case GATT_ERROR_NOT_AUTHORIZED: |
| return 0x08; |
| case GATT_ERROR_NOT_PAIRED: |
| return 0x0F; |
| case GATT_ERROR_NOT_SUPPORTED: |
| return 0x06; |
| } |
| |
| NOTREACHED(); |
| return 0x00; |
| } |
| |
| BluetoothRemoteGattServiceWinrt::BluetoothRemoteGattServiceWinrt( |
| BluetoothDevice* device, |
| ComPtr<IGattDeviceService> gatt_service, |
| BluetoothUUID uuid, |
| uint16_t attribute_handle) |
| : device_(device), |
| gatt_service_(std::move(gatt_service)), |
| uuid_(std::move(uuid)), |
| attribute_handle_(attribute_handle), |
| identifier_(base::StringPrintf("%s/%s_%04x", |
| device_->GetIdentifier().c_str(), |
| uuid_.value().c_str(), |
| attribute_handle)) {} |
| } // namespace device |