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