| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 | |
| 5 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/strings/stringprintf.h" | |
| 9 #include "device/bluetooth/bluetooth_adapter_chromeos.h" | |
| 10 #include "device/bluetooth/bluetooth_device_chromeos.h" | |
| 11 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" | |
| 12 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h" | |
| 13 #include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" | |
| 14 #include "device/bluetooth/dbus/bluez_dbus_manager.h" | |
| 15 | |
| 16 namespace chromeos { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // TODO(jamuraa) move these to cros_system_api later | |
| 21 const char kErrorFailed[] = "org.bluez.Error.Failed"; | |
| 22 const char kErrorInProgress[] = "org.bluez.Error.InProgress"; | |
| 23 const char kErrorInvalidValueLength[] = "org.bluez.Error.InvalidValueLength"; | |
| 24 const char kErrorNotAuthorized[] = "org.bluez.Error.NotAuthorized"; | |
| 25 const char kErrorNotPaired[] = "org.bluez.Error.NotPaired"; | |
| 26 const char kErrorNotSupported[] = "org.bluez.Error.NotSupported"; | |
| 27 const char kErrorNotPermitted[] = "org.bluez.Error.NotPermitted"; | |
| 28 | |
| 29 } // namespace | |
| 30 | |
| 31 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS( | |
| 32 BluetoothAdapterChromeOS* adapter, | |
| 33 BluetoothDeviceChromeOS* device, | |
| 34 const dbus::ObjectPath& object_path) | |
| 35 : object_path_(object_path), | |
| 36 adapter_(adapter), | |
| 37 device_(device), | |
| 38 discovery_complete_(false), | |
| 39 weak_ptr_factory_(this) { | |
| 40 VLOG(1) << "Creating remote GATT service with identifier: " | |
| 41 << object_path.value() << ", UUID: " << GetUUID().canonical_value(); | |
| 42 DCHECK(adapter_); | |
| 43 | |
| 44 bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver( | |
| 45 this); | |
| 46 bluez::BluezDBusManager::Get() | |
| 47 ->GetBluetoothGattCharacteristicClient() | |
| 48 ->AddObserver(this); | |
| 49 | |
| 50 // Add all known GATT characteristics. | |
| 51 const std::vector<dbus::ObjectPath>& gatt_chars = | |
| 52 bluez::BluezDBusManager::Get() | |
| 53 ->GetBluetoothGattCharacteristicClient() | |
| 54 ->GetCharacteristics(); | |
| 55 for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin(); | |
| 56 iter != gatt_chars.end(); ++iter) | |
| 57 GattCharacteristicAdded(*iter); | |
| 58 } | |
| 59 | |
| 60 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() { | |
| 61 bluez::BluezDBusManager::Get() | |
| 62 ->GetBluetoothGattServiceClient() | |
| 63 ->RemoveObserver(this); | |
| 64 bluez::BluezDBusManager::Get() | |
| 65 ->GetBluetoothGattCharacteristicClient() | |
| 66 ->RemoveObserver(this); | |
| 67 | |
| 68 // Clean up all the characteristics. Copy the characteristics list here and | |
| 69 // clear the original so that when we send GattCharacteristicRemoved(), | |
| 70 // GetCharacteristics() returns no characteristics. | |
| 71 CharacteristicMap characteristics = characteristics_; | |
| 72 characteristics_.clear(); | |
| 73 for (CharacteristicMap::iterator iter = characteristics.begin(); | |
| 74 iter != characteristics.end(); ++iter) { | |
| 75 DCHECK(adapter_); | |
| 76 adapter_->NotifyGattCharacteristicRemoved(iter->second); | |
| 77 | |
| 78 delete iter->second; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const { | |
| 83 return object_path_.value(); | |
| 84 } | |
| 85 | |
| 86 device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const { | |
| 87 bluez::BluetoothGattServiceClient::Properties* properties = | |
| 88 bluez::BluezDBusManager::Get() | |
| 89 ->GetBluetoothGattServiceClient() | |
| 90 ->GetProperties(object_path_); | |
| 91 DCHECK(properties); | |
| 92 return device::BluetoothUUID(properties->uuid.value()); | |
| 93 } | |
| 94 | |
| 95 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const { | |
| 96 return false; | |
| 97 } | |
| 98 | |
| 99 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const { | |
| 100 bluez::BluetoothGattServiceClient::Properties* properties = | |
| 101 bluez::BluezDBusManager::Get() | |
| 102 ->GetBluetoothGattServiceClient() | |
| 103 ->GetProperties(object_path_); | |
| 104 DCHECK(properties); | |
| 105 return properties->primary.value(); | |
| 106 } | |
| 107 | |
| 108 device::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const { | |
| 109 return device_; | |
| 110 } | |
| 111 | |
| 112 std::vector<device::BluetoothGattCharacteristic*> | |
| 113 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const { | |
| 114 std::vector<device::BluetoothGattCharacteristic*> characteristics; | |
| 115 for (CharacteristicMap::const_iterator iter = characteristics_.begin(); | |
| 116 iter != characteristics_.end(); ++iter) { | |
| 117 characteristics.push_back(iter->second); | |
| 118 } | |
| 119 return characteristics; | |
| 120 } | |
| 121 | |
| 122 std::vector<device::BluetoothGattService*> | |
| 123 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const { | |
| 124 // TODO(armansito): Return the actual included services here. | |
| 125 return std::vector<device::BluetoothGattService*>(); | |
| 126 } | |
| 127 | |
| 128 device::BluetoothGattCharacteristic* | |
| 129 BluetoothRemoteGattServiceChromeOS::GetCharacteristic( | |
| 130 const std::string& identifier) const { | |
| 131 CharacteristicMap::const_iterator iter = | |
| 132 characteristics_.find(dbus::ObjectPath(identifier)); | |
| 133 if (iter == characteristics_.end()) | |
| 134 return NULL; | |
| 135 return iter->second; | |
| 136 } | |
| 137 | |
| 138 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic( | |
| 139 device::BluetoothGattCharacteristic* characteristic) { | |
| 140 VLOG(1) << "Characteristics cannot be added to a remote GATT service."; | |
| 141 return false; | |
| 142 } | |
| 143 | |
| 144 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService( | |
| 145 device::BluetoothGattService* service) { | |
| 146 VLOG(1) << "Included services cannot be added to a remote GATT service."; | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 void BluetoothRemoteGattServiceChromeOS::Register( | |
| 151 const base::Closure& callback, | |
| 152 const ErrorCallback& error_callback) { | |
| 153 VLOG(1) << "A remote GATT service cannot be registered."; | |
| 154 error_callback.Run(); | |
| 155 } | |
| 156 | |
| 157 void BluetoothRemoteGattServiceChromeOS::Unregister( | |
| 158 const base::Closure& callback, | |
| 159 const ErrorCallback& error_callback) { | |
| 160 VLOG(1) << "A remote GATT service cannot be unregistered."; | |
| 161 error_callback.Run(); | |
| 162 } | |
| 163 | |
| 164 // static | |
| 165 device::BluetoothGattService::GattErrorCode | |
| 166 BluetoothRemoteGattServiceChromeOS::DBusErrorToServiceError( | |
| 167 std::string error_name) { | |
| 168 device::BluetoothGattService::GattErrorCode code = GATT_ERROR_UNKNOWN; | |
| 169 if (error_name == kErrorFailed) { | |
| 170 code = GATT_ERROR_FAILED; | |
| 171 } else if (error_name == kErrorInProgress) { | |
| 172 code = GATT_ERROR_IN_PROGRESS; | |
| 173 } else if (error_name == kErrorInvalidValueLength) { | |
| 174 code = GATT_ERROR_INVALID_LENGTH; | |
| 175 } else if (error_name == kErrorNotPermitted) { | |
| 176 code = GATT_ERROR_NOT_PERMITTED; | |
| 177 } else if (error_name == kErrorNotAuthorized) { | |
| 178 code = GATT_ERROR_NOT_AUTHORIZED; | |
| 179 } else if (error_name == kErrorNotPaired) { | |
| 180 code = GATT_ERROR_NOT_PAIRED; | |
| 181 } else if (error_name == kErrorNotSupported) { | |
| 182 code = GATT_ERROR_NOT_SUPPORTED; | |
| 183 } | |
| 184 return code; | |
| 185 } | |
| 186 | |
| 187 BluetoothAdapterChromeOS* | |
| 188 BluetoothRemoteGattServiceChromeOS::GetAdapter() const { | |
| 189 return adapter_; | |
| 190 } | |
| 191 | |
| 192 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() { | |
| 193 // Don't send service changed unless we know that all characteristics have | |
| 194 // already been discovered. This is to prevent spammy events before sending | |
| 195 // out the first Gatt | |
| 196 if (!discovery_complete_) | |
| 197 return; | |
| 198 | |
| 199 DCHECK(adapter_); | |
| 200 adapter_->NotifyGattServiceChanged(this); | |
| 201 } | |
| 202 | |
| 203 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved( | |
| 204 BluetoothRemoteGattCharacteristicChromeOS* characteristic, | |
| 205 BluetoothRemoteGattDescriptorChromeOS* descriptor, | |
| 206 bool added) { | |
| 207 DCHECK(characteristic->GetService() == this); | |
| 208 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
| 209 DCHECK(adapter_); | |
| 210 | |
| 211 if (added) { | |
| 212 adapter_->NotifyGattDescriptorAdded(descriptor); | |
| 213 return; | |
| 214 } | |
| 215 | |
| 216 adapter_->NotifyGattDescriptorRemoved(descriptor); | |
| 217 } | |
| 218 | |
| 219 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged( | |
| 220 BluetoothRemoteGattCharacteristicChromeOS* characteristic, | |
| 221 BluetoothRemoteGattDescriptorChromeOS* descriptor, | |
| 222 const std::vector<uint8>& value) { | |
| 223 DCHECK(characteristic->GetService() == this); | |
| 224 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
| 225 DCHECK(adapter_); | |
| 226 adapter_->NotifyGattDescriptorValueChanged(descriptor, value); | |
| 227 } | |
| 228 | |
| 229 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged( | |
| 230 const dbus::ObjectPath& object_path, | |
| 231 const std::string& property_name){ | |
| 232 if (object_path != object_path_) | |
| 233 return; | |
| 234 | |
| 235 VLOG(1) << "Service property changed: \"" << property_name << "\", " | |
| 236 << object_path.value(); | |
| 237 bluez::BluetoothGattServiceClient::Properties* properties = | |
| 238 bluez::BluezDBusManager::Get() | |
| 239 ->GetBluetoothGattServiceClient() | |
| 240 ->GetProperties(object_path); | |
| 241 DCHECK(properties); | |
| 242 | |
| 243 if (property_name != properties->characteristics.name()) { | |
| 244 NotifyServiceChanged(); | |
| 245 return; | |
| 246 } | |
| 247 | |
| 248 if (discovery_complete_) | |
| 249 return; | |
| 250 | |
| 251 VLOG(1) << "All characteristics were discovered for service: " | |
| 252 << object_path.value(); | |
| 253 discovery_complete_ = true; | |
| 254 DCHECK(adapter_); | |
| 255 adapter_->NotifyGattDiscoveryComplete(this); | |
| 256 } | |
| 257 | |
| 258 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded( | |
| 259 const dbus::ObjectPath& object_path) { | |
| 260 if (characteristics_.find(object_path) != characteristics_.end()) { | |
| 261 VLOG(1) << "Remote GATT characteristic already exists: " | |
| 262 << object_path.value(); | |
| 263 return; | |
| 264 } | |
| 265 | |
| 266 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
| 267 bluez::BluezDBusManager::Get() | |
| 268 ->GetBluetoothGattCharacteristicClient() | |
| 269 ->GetProperties(object_path); | |
| 270 DCHECK(properties); | |
| 271 if (properties->service.value() != object_path_) { | |
| 272 VLOG(2) << "Remote GATT characteristic does not belong to this service."; | |
| 273 return; | |
| 274 } | |
| 275 | |
| 276 VLOG(1) << "Adding new remote GATT characteristic for GATT service: " | |
| 277 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
| 278 | |
| 279 BluetoothRemoteGattCharacteristicChromeOS* characteristic = | |
| 280 new BluetoothRemoteGattCharacteristicChromeOS(this, object_path); | |
| 281 characteristics_[object_path] = characteristic; | |
| 282 DCHECK(characteristic->GetIdentifier() == object_path.value()); | |
| 283 DCHECK(characteristic->GetUUID().IsValid()); | |
| 284 | |
| 285 DCHECK(adapter_); | |
| 286 adapter_->NotifyGattCharacteristicAdded(characteristic); | |
| 287 } | |
| 288 | |
| 289 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved( | |
| 290 const dbus::ObjectPath& object_path) { | |
| 291 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
| 292 if (iter == characteristics_.end()) { | |
| 293 VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value(); | |
| 294 return; | |
| 295 } | |
| 296 | |
| 297 VLOG(1) << "Removing remote GATT characteristic from service: " | |
| 298 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
| 299 | |
| 300 BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second; | |
| 301 DCHECK(characteristic->object_path() == object_path); | |
| 302 characteristics_.erase(iter); | |
| 303 | |
| 304 DCHECK(adapter_); | |
| 305 adapter_->NotifyGattCharacteristicRemoved(characteristic); | |
| 306 | |
| 307 delete characteristic; | |
| 308 } | |
| 309 | |
| 310 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged( | |
| 311 const dbus::ObjectPath& object_path, | |
| 312 const std::string& property_name) { | |
| 313 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
| 314 if (iter == characteristics_.end()) { | |
| 315 VLOG(3) << "Properties of unknown characteristic changed"; | |
| 316 return; | |
| 317 } | |
| 318 | |
| 319 // We may receive a property changed event in certain cases, e.g. when the | |
| 320 // characteristic "Flags" property has been updated with values from the | |
| 321 // "Characteristic Extended Properties" descriptor. In this case, kick off | |
| 322 // a service changed observer event to let observers refresh the | |
| 323 // characteristics. | |
| 324 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
| 325 bluez::BluezDBusManager::Get() | |
| 326 ->GetBluetoothGattCharacteristicClient() | |
| 327 ->GetProperties(object_path); | |
| 328 | |
| 329 DCHECK(properties); | |
| 330 DCHECK(adapter_); | |
| 331 | |
| 332 if (property_name == properties->flags.name()) | |
| 333 NotifyServiceChanged(); | |
| 334 else if (property_name == properties->value.name()) | |
| 335 adapter_->NotifyGattCharacteristicValueChanged(iter->second, | |
| 336 properties->value.value()); | |
| 337 } | |
| 338 | |
| 339 } // namespace chromeos | |
| OLD | NEW |