1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file. 4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" 6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/logging.h" 8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/strings/stringprintf.h" 9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/bluetooth_gatt_service_client.h" 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chromeos/dbus/dbus_thread_manager.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "device/bluetooth/bluetooth_adapter_chromeos.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "device/bluetooth/bluetooth_device_chromeos.h" 13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace chromeos { 17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS( 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BluetoothAdapterChromeOS* adapter, 20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BluetoothDeviceChromeOS* device, 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const dbus::ObjectPath& object_path) 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : object_path_(object_path), 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch adapter_(adapter), 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch device_(device), 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) discovery_complete_(false), 26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch weak_ptr_factory_(this) { 27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << "Creating remote GATT service with identifier: " 28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << object_path.value() << ", UUID: " << GetUUID().canonical_value(); 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(adapter_); 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); 32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()-> 33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch AddObserver(this); 34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Add all known GATT characteristics. 36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const std::vector<dbus::ObjectPath>& gatt_chars = 37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()-> 38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetCharacteristics(); 39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin(); 40a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter != gatt_chars.end(); ++iter) 41a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GattCharacteristicAdded(*iter); 42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() { 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch RemoveObserver(this); 47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()-> 48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch RemoveObserver(this); 49a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Clean up all the characteristics. Copy the characteristics list here and 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // clear the original so that when we send GattCharacteristicRemoved(), 52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // GetCharacteristics() returns no characteristics. 53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CharacteristicMap characteristics = characteristics_; 54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch characteristics_.clear(); 55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (CharacteristicMap::iterator iter = characteristics.begin(); 56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter != characteristics.end(); ++iter) { 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattCharacteristicRemoved(iter->second); 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch delete iter->second; 61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstd::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const { 65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return object_path_.value(); 66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochdevice::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const { 69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BluetoothGattServiceClient::Properties* properties = 70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetProperties(object_path_); 72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(properties); 73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return device::BluetoothUUID(properties->uuid.value()); 74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::IsLocal() const { 77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::IsPrimary() const { 81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BluetoothGattServiceClient::Properties* properties = 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetProperties(object_path_); 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(properties); 85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return properties->primary.value(); 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liudevice::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const { 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return device_; 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 92a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::vector<device::BluetoothGattCharacteristic*> 93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::GetCharacteristics() const { 94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::vector<device::BluetoothGattCharacteristic*> characteristics; 95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for (CharacteristicMap::const_iterator iter = characteristics_.begin(); 96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch iter != characteristics_.end(); ++iter) { 97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch characteristics.push_back(iter->second); 98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return characteristics; 100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::vector<device::BluetoothGattService*> 103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochBluetoothRemoteGattServiceChromeOS::GetIncludedServices() const { 104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // TODO(armansito): Return the actual included services here. 105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return std::vector<device::BluetoothGattService*>(); 106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochdevice::BluetoothGattCharacteristic* 109a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochBluetoothRemoteGattServiceChromeOS::GetCharacteristic( 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const std::string& identifier) const { 111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CharacteristicMap::const_iterator iter = 112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch characteristics_.find(dbus::ObjectPath(identifier)); 113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (iter == characteristics_.end()) 114a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return NULL; 115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return iter->second; 116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::AddCharacteristic( 119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch device::BluetoothGattCharacteristic* characteristic) { 120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << "Characteristics cannot be added to a remote GATT service."; 121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool BluetoothRemoteGattServiceChromeOS::AddIncludedService( 125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch device::BluetoothGattService* service) { 126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << "Included services cannot be added to a remote GATT service."; 127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::Register( 131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Closure& callback, 132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const ErrorCallback& error_callback) { 133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << "A remote GATT service cannot be registered."; 134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run(); 135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::Unregister( 138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const base::Closure& callback, 139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const ErrorCallback& error_callback) { 140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << "A remote GATT service cannot be unregistered."; 141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch error_callback.Run(); 142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BluetoothAdapterChromeOS* 145116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBluetoothRemoteGattServiceChromeOS::GetAdapter() const { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return adapter_; 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() { 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Don't send service changed unless we know that all characteristics have 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // already been discovered. This is to prevent spammy events before sending 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // out the first Gatt 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!discovery_complete_) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattServiceChanged(this); 158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyCharacteristicValueChanged( 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) BluetoothRemoteGattCharacteristicChromeOS* characteristic, 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<uint8>& value) { 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(characteristic->GetService() == this); 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattCharacteristicValueChanged(characteristic, value); 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved( 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BluetoothRemoteGattCharacteristicChromeOS* characteristic, 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BluetoothRemoteGattDescriptorChromeOS* descriptor, 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool added) { 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(characteristic->GetService() == this); 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(descriptor->GetCharacteristic() == characteristic); 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (added) { 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattDescriptorAdded(descriptor); 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return; 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattDescriptorRemoved(descriptor); 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged( 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BluetoothRemoteGattCharacteristicChromeOS* characteristic, 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BluetoothRemoteGattDescriptorChromeOS* descriptor, 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::vector<uint8>& value) { 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(characteristic->GetService() == this); 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(descriptor->GetCharacteristic() == characteristic); 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattDescriptorValueChanged(descriptor, value); 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged( 195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const dbus::ObjectPath& object_path, 196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const std::string& property_name){ 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (object_path != object_path_) 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Service property changed: \"" << property_name << "\", " 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << object_path.value(); 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BluetoothGattServiceClient::Properties* properties = 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties( 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) object_path); 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(properties); 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (property_name != properties->characteristics.name()) { 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NotifyServiceChanged(); 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (discovery_complete_) 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "All characteristics were discovered for service: " 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << object_path.value(); 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) discovery_complete_ = true; 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattDiscoveryComplete(this); 220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 221a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded( 223a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const dbus::ObjectPath& object_path) { 224a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (characteristics_.find(object_path) != characteristics_.end()) { 225a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch VLOG(1) << "Remote GATT characteristic already exists: " 226a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch << object_path.value(); 227a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return; 228a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch BluetoothGattCharacteristicClient::Properties* properties = 231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()-> 232a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GetProperties(object_path); 233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK(properties); 234a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (properties->service.value() != object_path_) { 235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch VLOG(2) << "Remote GATT characteristic does not belong to this service."; 236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return; 237a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 239a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch VLOG(1) << "Adding new remote GATT characteristic for GATT service: " 240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); 241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch BluetoothRemoteGattCharacteristicChromeOS* characteristic = 243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch new BluetoothRemoteGattCharacteristicChromeOS(this, object_path); 244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch characteristics_[object_path] = characteristic; 245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK(characteristic->GetIdentifier() == object_path.value()); 246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK(characteristic->GetUUID().IsValid()); 247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattCharacteristicAdded(characteristic); 250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 252a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved( 253a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const dbus::ObjectPath& object_path) { 254a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CharacteristicMap::iterator iter = characteristics_.find(object_path); 255a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (iter == characteristics_.end()) { 256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value(); 257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return; 258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch VLOG(1) << "Removing remote GATT characteristic from service: " 261a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); 262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second; 264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch DCHECK(characteristic->object_path() == object_path); 265a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch characteristics_.erase(iter); 266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(adapter_); 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) adapter_->NotifyGattCharacteristicRemoved(characteristic); 269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch delete characteristic; 271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 272a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 2736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged( 2746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const dbus::ObjectPath& object_path, 2756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::string& property_name) { 2766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (characteristics_.find(object_path) == characteristics_.end()) { 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(3) << "Properties of unknown characteristic changed"; 2786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 2796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 2806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // We may receive a property changed event in certain cases, e.g. when the 2826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // characteristic "Flags" property has been updated with values from the 2836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // "Characteristic Extended Properties" descriptor. In this case, kick off 2846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // a service changed observer event to let observers refresh the 2856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // characteristics. 2866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) BluetoothGattCharacteristicClient::Properties* properties = 2876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()-> 2886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) GetProperties(object_path); 2896d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK(properties); 2906d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (property_name != properties->flags.name()) 2916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return; 2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) NotifyServiceChanged(); 2946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 2956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} // namespace chromeos 297