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 "chromeos/dbus/bluetooth_gatt_characteristic_client.h" 6 7 #include "base/bind.h" 8 #include "base/memory/weak_ptr.h" 9 #include "base/observer_list.h" 10 #include "dbus/bus.h" 11 #include "dbus/object_manager.h" 12 #include "third_party/cros_system_api/dbus/service_constants.h" 13 14 namespace chromeos { 15 16 // static 17 const char BluetoothGattCharacteristicClient::kNoResponseError[] = 18 "org.chromium.Error.NoResponse"; 19 // static 20 const char BluetoothGattCharacteristicClient::kUnknownCharacteristicError[] = 21 "org.chromium.Error.UnknownCharacteristic"; 22 23 BluetoothGattCharacteristicClient::Properties::Properties( 24 dbus::ObjectProxy* object_proxy, 25 const std::string& interface_name, 26 const PropertyChangedCallback& callback) 27 : dbus::PropertySet(object_proxy, interface_name, callback) { 28 RegisterProperty(bluetooth_gatt_characteristic::kUUIDProperty, &uuid); 29 RegisterProperty(bluetooth_gatt_characteristic::kServiceProperty, &service); 30 RegisterProperty(bluetooth_gatt_characteristic::kNotifyingProperty, 31 ¬ifying); 32 RegisterProperty(bluetooth_gatt_characteristic::kFlagsProperty, &flags); 33 RegisterProperty(bluetooth_gatt_characteristic::kDescriptorsProperty, 34 &descriptors); 35 } 36 37 BluetoothGattCharacteristicClient::Properties::~Properties() { 38 } 39 40 // The BluetoothGattCharacteristicClient implementation used in production. 41 class BluetoothGattCharacteristicClientImpl 42 : public BluetoothGattCharacteristicClient, 43 public dbus::ObjectManager::Interface { 44 public: 45 BluetoothGattCharacteristicClientImpl() 46 : object_manager_(NULL), 47 weak_ptr_factory_(this) { 48 } 49 50 virtual ~BluetoothGattCharacteristicClientImpl() { 51 object_manager_->UnregisterInterface( 52 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); 53 } 54 55 // BluetoothGattCharacteristicClient override. 56 virtual void AddObserver( 57 BluetoothGattCharacteristicClient::Observer* observer) OVERRIDE { 58 DCHECK(observer); 59 observers_.AddObserver(observer); 60 } 61 62 // BluetoothGattCharacteristicClient override. 63 virtual void RemoveObserver( 64 BluetoothGattCharacteristicClient::Observer* observer) OVERRIDE { 65 DCHECK(observer); 66 observers_.RemoveObserver(observer); 67 } 68 69 // BluetoothGattCharacteristicClient override. 70 virtual std::vector<dbus::ObjectPath> GetCharacteristics() OVERRIDE { 71 DCHECK(object_manager_); 72 return object_manager_->GetObjectsWithInterface( 73 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface); 74 } 75 76 // BluetoothGattCharacteristicClient override. 77 virtual Properties* GetProperties( 78 const dbus::ObjectPath& object_path) OVERRIDE { 79 DCHECK(object_manager_); 80 return static_cast<Properties*>( 81 object_manager_->GetProperties( 82 object_path, 83 bluetooth_gatt_characteristic:: 84 kBluetoothGattCharacteristicInterface)); 85 } 86 87 // BluetoothGattCharacteristicClient override. 88 virtual void ReadValue(const dbus::ObjectPath& object_path, 89 const ValueCallback& callback, 90 const ErrorCallback& error_callback) OVERRIDE { 91 dbus::ObjectProxy* object_proxy = 92 object_manager_->GetObjectProxy(object_path); 93 if (!object_proxy) { 94 error_callback.Run(kUnknownCharacteristicError, ""); 95 return; 96 } 97 98 dbus::MethodCall method_call( 99 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 100 bluetooth_gatt_characteristic::kReadValue); 101 102 object_proxy->CallMethodWithErrorCallback( 103 &method_call, 104 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 105 base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess, 106 weak_ptr_factory_.GetWeakPtr(), 107 callback), 108 base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, 109 weak_ptr_factory_.GetWeakPtr(), 110 error_callback)); 111 } 112 113 // BluetoothGattCharacteristicClient override. 114 virtual void WriteValue(const dbus::ObjectPath& object_path, 115 const std::vector<uint8>& value, 116 const base::Closure& callback, 117 const ErrorCallback& error_callback) OVERRIDE { 118 dbus::ObjectProxy* object_proxy = 119 object_manager_->GetObjectProxy(object_path); 120 if (!object_proxy) { 121 error_callback.Run(kUnknownCharacteristicError, ""); 122 return; 123 } 124 125 dbus::MethodCall method_call( 126 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 127 bluetooth_gatt_characteristic::kWriteValue); 128 dbus::MessageWriter writer(&method_call); 129 writer.AppendArrayOfBytes(value.data(), value.size()); 130 131 object_proxy->CallMethodWithErrorCallback( 132 &method_call, 133 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 134 base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, 135 weak_ptr_factory_.GetWeakPtr(), 136 callback), 137 base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, 138 weak_ptr_factory_.GetWeakPtr(), 139 error_callback)); 140 } 141 142 // BluetoothGattCharacteristicClient override. 143 virtual void StartNotify(const dbus::ObjectPath& object_path, 144 const base::Closure& callback, 145 const ErrorCallback& error_callback) OVERRIDE { 146 dbus::ObjectProxy* object_proxy = 147 object_manager_->GetObjectProxy(object_path); 148 if (!object_proxy) { 149 error_callback.Run(kUnknownCharacteristicError, ""); 150 return; 151 } 152 153 dbus::MethodCall method_call( 154 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 155 bluetooth_gatt_characteristic::kStartNotify); 156 157 object_proxy->CallMethodWithErrorCallback( 158 &method_call, 159 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 160 base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, 161 weak_ptr_factory_.GetWeakPtr(), 162 callback), 163 base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, 164 weak_ptr_factory_.GetWeakPtr(), 165 error_callback)); 166 } 167 168 // BluetoothGattCharacteristicClient override. 169 virtual void StopNotify(const dbus::ObjectPath& object_path, 170 const base::Closure& callback, 171 const ErrorCallback& error_callback) OVERRIDE { 172 dbus::ObjectProxy* object_proxy = 173 object_manager_->GetObjectProxy(object_path); 174 if (!object_proxy) { 175 error_callback.Run(kUnknownCharacteristicError, ""); 176 return; 177 } 178 179 dbus::MethodCall method_call( 180 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 181 bluetooth_gatt_characteristic::kStopNotify); 182 183 object_proxy->CallMethodWithErrorCallback( 184 &method_call, 185 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 186 base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, 187 weak_ptr_factory_.GetWeakPtr(), 188 callback), 189 base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, 190 weak_ptr_factory_.GetWeakPtr(), 191 error_callback)); 192 } 193 194 // dbus::ObjectManager::Interface override. 195 virtual dbus::PropertySet* CreateProperties( 196 dbus::ObjectProxy *object_proxy, 197 const dbus::ObjectPath& object_path, 198 const std::string& interface_name) OVERRIDE { 199 Properties* properties = new Properties( 200 object_proxy, 201 interface_name, 202 base::Bind(&BluetoothGattCharacteristicClientImpl::OnPropertyChanged, 203 weak_ptr_factory_.GetWeakPtr(), 204 object_path)); 205 return static_cast<dbus::PropertySet*>(properties); 206 } 207 208 // dbus::ObjectManager::Interface override. 209 virtual void ObjectAdded(const dbus::ObjectPath& object_path, 210 const std::string& interface_name) OVERRIDE { 211 VLOG(2) << "Remote GATT characteristic added: " << object_path.value(); 212 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, 213 GattCharacteristicAdded(object_path)); 214 215 // Connect the "ValueUpdated" signal. 216 dbus::ObjectProxy* object_proxy = 217 object_manager_->GetObjectProxy(object_path); 218 DCHECK(object_proxy); 219 220 object_proxy->ConnectToSignal( 221 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 222 bluetooth_gatt_characteristic::kValueUpdatedSignal, 223 base::Bind(&BluetoothGattCharacteristicClientImpl::ValueUpdatedReceived, 224 weak_ptr_factory_.GetWeakPtr(), 225 object_path), 226 base::Bind( 227 &BluetoothGattCharacteristicClientImpl::ValueUpdatedConnected, 228 weak_ptr_factory_.GetWeakPtr())); 229 } 230 231 // dbus::ObjectManager::Interface override. 232 virtual void ObjectRemoved(const dbus::ObjectPath& object_path, 233 const std::string& interface_name) OVERRIDE { 234 VLOG(2) << "Remote GATT characteristic removed: " << object_path.value(); 235 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, 236 GattCharacteristicRemoved(object_path)); 237 } 238 239 protected: 240 // chromeos::DBusClient override. 241 virtual void Init(dbus::Bus* bus) OVERRIDE { 242 object_manager_ = bus->GetObjectManager( 243 bluetooth_object_manager::kBluetoothObjectManagerServiceName, 244 dbus::ObjectPath( 245 bluetooth_object_manager::kBluetoothObjectManagerServicePath)); 246 object_manager_->RegisterInterface( 247 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, 248 this); 249 } 250 251 private: 252 // Called by dbus::PropertySet when a property value is changed, either by 253 // result of a signal or response to a GetAll() or Get() call. Informs 254 // observers. 255 virtual void OnPropertyChanged(const dbus::ObjectPath& object_path, 256 const std::string& property_name) { 257 VLOG(2) << "Remote GATT characteristic property changed: " 258 << object_path.value() << ": " << property_name; 259 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, 260 GattCharacteristicPropertyChanged(object_path, 261 property_name)); 262 } 263 264 // Called by dbus:: when a "ValueUpdated" signal is received. 265 void ValueUpdatedReceived(const dbus::ObjectPath& object_path, 266 dbus::Signal* signal) { 267 DCHECK(signal); 268 const uint8* bytes = NULL; 269 size_t length = 0; 270 dbus::MessageReader reader(signal); 271 if (!reader.PopArrayOfBytes(&bytes, &length)) { 272 LOG(WARNING) << "ValueUpdated signal has incorrect parameters: " 273 << signal->ToString(); 274 return; 275 } 276 277 std::vector<uint8> value; 278 if (bytes) 279 value.assign(bytes, bytes + length); 280 281 FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, 282 observers_, 283 GattCharacteristicValueUpdated(object_path, value)); 284 } 285 286 // Called by dbus:: when the "ValueUpdated" signal is initially connected. 287 void ValueUpdatedConnected(const std::string& interface_name, 288 const std::string& signal_name, 289 bool success) { 290 LOG_IF(WARNING, !success) << "Failed to connect to the ValueUpdated signal"; 291 } 292 293 // Called when a response for successful method call is received. 294 void OnSuccess(const base::Closure& callback, dbus::Response* response) { 295 DCHECK(response); 296 callback.Run(); 297 } 298 299 // Called when a characteristic value response for a successful method call 300 // is received. 301 void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { 302 DCHECK(response); 303 dbus::MessageReader reader(response); 304 305 const uint8* bytes = NULL; 306 size_t length = 0; 307 308 if (!reader.PopArrayOfBytes(&bytes, &length)) 309 VLOG(2) << "Error reading array of bytes in ValueCallback"; 310 311 std::vector<uint8> value; 312 313 if (bytes) 314 value.assign(bytes, bytes + length); 315 316 callback.Run(value); 317 } 318 319 // Called when a response for a failed method call is received. 320 void OnError(const ErrorCallback& error_callback, 321 dbus::ErrorResponse* response) { 322 // Error response has optional error message argument. 323 std::string error_name; 324 std::string error_message; 325 if (response) { 326 dbus::MessageReader reader(response); 327 error_name = response->GetErrorName(); 328 reader.PopString(&error_message); 329 } else { 330 error_name = kNoResponseError; 331 error_message = ""; 332 } 333 error_callback.Run(error_name, error_message); 334 } 335 336 dbus::ObjectManager* object_manager_; 337 338 // List of observers interested in event notifications from us. 339 ObserverList<BluetoothGattCharacteristicClient::Observer> observers_; 340 341 // Weak pointer factory for generating 'this' pointers that might live longer 342 // than we do. 343 // Note: This should remain the last member so it'll be destroyed and 344 // invalidate its weak pointers before any other members are destroyed. 345 base::WeakPtrFactory<BluetoothGattCharacteristicClientImpl> 346 weak_ptr_factory_; 347 348 DISALLOW_COPY_AND_ASSIGN(BluetoothGattCharacteristicClientImpl); 349 }; 350 351 BluetoothGattCharacteristicClient::BluetoothGattCharacteristicClient() { 352 } 353 354 BluetoothGattCharacteristicClient::~BluetoothGattCharacteristicClient() { 355 } 356 357 // static 358 BluetoothGattCharacteristicClient* BluetoothGattCharacteristicClient::Create() { 359 return new BluetoothGattCharacteristicClientImpl(); 360 } 361 362 } // namespace chromeos 363