diff options
author | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-07 20:26:45 +0000 |
---|---|---|
committer | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-07 20:26:45 +0000 |
commit | d62d70e49f7a7096175a8d071d1b930d9ca2f0a9 (patch) | |
tree | 8455a87fb5b9bd25b961e1af9563c292359614a4 /chromeos/dbus | |
parent | 0fc48a16950329a84ce8cda23646b82052ace2ef (diff) | |
download | chromium_src-d62d70e49f7a7096175a8d071d1b930d9ca2f0a9.zip chromium_src-d62d70e49f7a7096175a8d071d1b930d9ca2f0a9.tar.gz chromium_src-d62d70e49f7a7096175a8d071d1b930d9ca2f0a9.tar.bz2 |
device/bluetooth: Update characteristic value D-Bus bindings.
The original BlueZ GATT API doc spec used DBus.Properties interface for
characteristic value access. Since we are modifying this API for Chrome OS,
this CL updates the Chrome D-Bus bindings and modifies the device/bluetooth
GATT code to use the new bindings for characteristic value reads, writes, and
updates.
BUG=378182
TEST=Tested against my custom bluetoothd build; device_unittests
Review URL: https://codereview.chromium.org/301093003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275693 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/dbus')
5 files changed, 252 insertions, 83 deletions
diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/bluetooth_gatt_characteristic_client.cc index e2e7c74..a510b91 100644 --- a/chromeos/dbus/bluetooth_gatt_characteristic_client.cc +++ b/chromeos/dbus/bluetooth_gatt_characteristic_client.cc @@ -13,6 +13,13 @@ namespace chromeos { +// static +const char BluetoothGattCharacteristicClient::kNoResponseError[] = + "org.chromium.Error.NoResponse"; +// static +const char BluetoothGattCharacteristicClient::kUnknownCharacteristicError[] = + "org.chromium.Error.UnknownCharacteristic"; + BluetoothGattCharacteristicClient::Properties::Properties( dbus::ObjectProxy* object_proxy, const std::string& interface_name, @@ -20,7 +27,6 @@ BluetoothGattCharacteristicClient::Properties::Properties( : dbus::PropertySet(object_proxy, interface_name, callback) { RegisterProperty(bluetooth_gatt_characteristic::kUUIDProperty, &uuid); RegisterProperty(bluetooth_gatt_characteristic::kServiceProperty, &service); - RegisterProperty(bluetooth_gatt_characteristic::kValueProperty, &value); RegisterProperty(bluetooth_gatt_characteristic::kFlagsProperty, &flags); } @@ -74,6 +80,61 @@ class BluetoothGattCharacteristicClientImpl kBluetoothGattCharacteristicInterface)); } + // BluetoothGattCharacteristicClient override. + virtual void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kReadValue); + + object_proxy->CallMethodWithErrorCallback( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnValueSuccess, + weak_ptr_factory_.GetWeakPtr(), + callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), + error_callback)); + } + + // BluetoothGattCharacteristicClient override. + virtual void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE { + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + if (!object_proxy) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + dbus::MethodCall method_call( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kWriteValue); + dbus::MessageWriter writer(&method_call); + writer.AppendArrayOfBytes(value.data(), value.size()); + + object_proxy->CallMethodWithErrorCallback( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothGattCharacteristicClientImpl::OnSuccess, + weak_ptr_factory_.GetWeakPtr(), + callback), + base::Bind(&BluetoothGattCharacteristicClientImpl::OnError, + weak_ptr_factory_.GetWeakPtr(), + error_callback)); + } + // dbus::ObjectManager::Interface override. virtual dbus::PropertySet* CreateProperties( dbus::ObjectProxy *object_proxy, @@ -94,6 +155,21 @@ class BluetoothGattCharacteristicClientImpl VLOG(2) << "Remote GATT characteristic added: " << object_path.value(); FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, GattCharacteristicAdded(object_path)); + + // Connect the "ValueUpdated" signal. + dbus::ObjectProxy* object_proxy = + object_manager_->GetObjectProxy(object_path); + DCHECK(object_proxy); + + object_proxy->ConnectToSignal( + bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface, + bluetooth_gatt_characteristic::kValueUpdatedSignal, + base::Bind(&BluetoothGattCharacteristicClientImpl::ValueUpdatedReceived, + weak_ptr_factory_.GetWeakPtr(), + object_path), + base::Bind( + &BluetoothGattCharacteristicClientImpl::ValueUpdatedConnected, + weak_ptr_factory_.GetWeakPtr())); } // dbus::ObjectManager::Interface override. @@ -129,6 +205,78 @@ class BluetoothGattCharacteristicClientImpl property_name)); } + // Called by dbus:: when a "ValueUpdated" signal is received. + void ValueUpdatedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + const uint8* bytes = NULL; + size_t length = 0; + dbus::MessageReader reader(signal); + if (!reader.PopArrayOfBytes(&bytes, &length)) { + LOG(WARNING) << "ValueUpdated signal has incorrect parameters: " + << signal->ToString(); + return; + } + + std::vector<uint8> value; + if (bytes) + value.assign(bytes, bytes + length); + + FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, + observers_, + GattCharacteristicValueUpdated(object_path, value)); + } + + // Called by dbus:: when the "ValueUpdated" signal is initially connected. + void ValueUpdatedConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to connect to the ValueUpdated signal"; + } + + // Called when a response for successful method call is received. + void OnSuccess(const base::Closure& callback, dbus::Response* response) { + DCHECK(response); + callback.Run(); + } + + // Called when a characteristic value response for a successful method call + // is received. + void OnValueSuccess(const ValueCallback& callback, dbus::Response* response) { + DCHECK(response); + dbus::MessageReader reader(response); + + const uint8* bytes = NULL; + size_t length = 0; + + if (!reader.PopArrayOfBytes(&bytes, &length)) + VLOG(2) << "Error reading array of bytes in ValueCallback"; + + std::vector<uint8> value; + + if (bytes) + value.assign(bytes, bytes + length); + + callback.Run(value); + } + + // Called when a response for a failed method call is received. + void OnError(const ErrorCallback& error_callback, + dbus::ErrorResponse* response) { + // Error response has optional error message argument. + std::string error_name; + std::string error_message; + if (response) { + dbus::MessageReader reader(response); + error_name = response->GetErrorName(); + reader.PopString(&error_message); + } else { + error_name = kNoResponseError; + error_message = ""; + } + error_callback.Run(error_name, error_message); + } + dbus::ObjectManager* object_manager_; // List of observers interested in event notifications from us. diff --git a/chromeos/dbus/bluetooth_gatt_characteristic_client.h b/chromeos/dbus/bluetooth_gatt_characteristic_client.h index 2935e4a..e5d48ad 100644 --- a/chromeos/dbus/bluetooth_gatt_characteristic_client.h +++ b/chromeos/dbus/bluetooth_gatt_characteristic_client.h @@ -8,6 +8,7 @@ #include <string> #include "base/basictypes.h" +#include "base/callback.h" #include "chromeos/chromeos_export.h" #include "chromeos/dbus/dbus_client.h" #include "dbus/object_path.h" @@ -28,10 +29,6 @@ class CHROMEOS_EXPORT BluetoothGattCharacteristicClient : public DBusClient { // [read-only] dbus::Property<dbus::ObjectPath> service; - // Characteristic value read from the remote Bluetooth device. Setting the - // value sends a write request to the remote device. [read-write] - dbus::Property<std::vector<uint8> > value; - // List of flags representing the GATT "Characteristic Properties bit field" // and properties read from the GATT "Characteristic Extended Properties" // descriptor bit field. [read-only, optional] @@ -62,8 +59,20 @@ class CHROMEOS_EXPORT BluetoothGattCharacteristicClient : public DBusClient { virtual void GattCharacteristicPropertyChanged( const dbus::ObjectPath& object_path, const std::string& property_name) {} + + // Called when a "ValueUpdated" signal is received from the remote GATT + // characteristic with object path |object_path| with characteristic value + // |value|. + virtual void GattCharacteristicValueUpdated( + const dbus::ObjectPath& object_path, + const std::vector<uint8>& value) {} }; + // Callbacks used to report the result of asynchronous methods. + typedef base::Callback<void(const std::string& error_name, + const std::string& error_message)> ErrorCallback; + typedef base::Callback<void(const std::vector<uint8>& value)> ValueCallback; + virtual ~BluetoothGattCharacteristicClient(); // Adds and removes observers for events on all remote GATT characteristics. @@ -79,9 +88,28 @@ class CHROMEOS_EXPORT BluetoothGattCharacteristicClient : public DBusClient { // |object_path|. Values should be copied if needed. virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + // Issues a request to read the value of GATT characteristic with object path + // |object_path| and returns the value in |callback| on success. On error, + // invokes |error_callback|. + virtual void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) = 0; + + // Issues a request to write the value of GATT characteristic with object path + // |object_path| with value |value|. Invokes |callback| on success and + // |error_callback| on failure. + virtual void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + // Creates the instance. static BluetoothGattCharacteristicClient* Create(); + // Constants used to indicate exceptional error conditions. + static const char kNoResponseError[]; + static const char kUnknownCharacteristicError[]; + protected: BluetoothGattCharacteristicClient(); diff --git a/chromeos/dbus/bluetooth_gatt_service_client.cc b/chromeos/dbus/bluetooth_gatt_service_client.cc index 1888e51..83ce29a 100644 --- a/chromeos/dbus/bluetooth_gatt_service_client.cc +++ b/chromeos/dbus/bluetooth_gatt_service_client.cc @@ -13,15 +13,6 @@ namespace chromeos { -namespace { - -// TODO(armansito): Add these to service_constants.h when they are defined -// in the BlueZ doc. -const char kDeviceProperty[] = "Device"; -const char kPrimaryProperty[] = "Primary"; - -} // namespace - BluetoothGattServiceClient::Properties::Properties( dbus::ObjectProxy* object_proxy, const std::string& interface_name, @@ -29,8 +20,8 @@ BluetoothGattServiceClient::Properties::Properties( : dbus::PropertySet(object_proxy, interface_name, callback) { RegisterProperty(bluetooth_gatt_service::kUUIDProperty, &uuid); RegisterProperty(bluetooth_gatt_service::kIncludesProperty, &includes); - RegisterProperty(kDeviceProperty, &device); - RegisterProperty(kPrimaryProperty, &primary); + RegisterProperty(bluetooth_gatt_service::kDeviceProperty, &device); + RegisterProperty(bluetooth_gatt_service::kPrimaryProperty, &primary); } BluetoothGattServiceClient::Properties::~Properties() { diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc index c822f95..0010ace 100644 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc +++ b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc @@ -51,9 +51,6 @@ void FakeBluetoothGattCharacteristicClient::Properties::Get( dbus::PropertyBase* property, dbus::PropertySet::GetCallback callback) { VLOG(1) << "Get " << property->name(); - - // TODO(armansito): Return success or failure here based on characteristic - // read permission. callback.Run(true); } @@ -65,34 +62,7 @@ void FakeBluetoothGattCharacteristicClient::Properties::Set( dbus::PropertyBase* property, dbus::PropertySet::SetCallback callback) { VLOG(1) << "Set " << property->name(); - if (property->name() != value.name()) { - callback.Run(false); - return; - } - - // Allow writing to only certain characteristics that are defined with the - // write permission. - bool write = false; - for (std::vector<std::string>::const_iterator iter = flags.value().begin(); - iter != flags.value().end(); - ++iter) { - if (*iter == bluetooth_gatt_characteristic::kFlagWrite || - *iter == bluetooth_gatt_characteristic::kFlagWriteWithoutResponse || - *iter == - bluetooth_gatt_characteristic::kFlagAuthenticatedSignedWrites || - *iter == bluetooth_gatt_characteristic::kFlagReliableWrite) { - write = true; - break; - } - } - - if (!write) { - callback.Run(false); - return; - } - - callback.Run(true); - property->ReplaceValueWithSetValue(); + callback.Run(false); } FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient() @@ -145,6 +115,61 @@ FakeBluetoothGattCharacteristicClient::GetProperties( return NULL; } +void FakeBluetoothGattCharacteristicClient::ReadValue( + const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) { + if (!IsHeartRateVisible()) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (object_path.value() == heart_rate_measurement_path_ || + object_path.value() == heart_rate_control_point_path_) { + error_callback.Run("org.bluez.Error.ReadNotPermitted", + "Reads of this value are not allowed"); + return; + } + + if (object_path.value() != body_sensor_location_path_) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + std::vector<uint8> value; + value.push_back(0x06); // Location is "foot". + callback.Run(value); +} + +void FakeBluetoothGattCharacteristicClient::WriteValue( + const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + if (!IsHeartRateVisible()) { + error_callback.Run(kUnknownCharacteristicError, ""); + return; + } + + if (object_path.value() != heart_rate_control_point_path_) { + error_callback.Run("org.bluez.Error.WriteNotPermitted", + "Writes of this value are not allowed"); + return; + } + + DCHECK(heart_rate_control_point_properties_.get()); + if (value.size() != 1 || value[0] > 1) { + error_callback.Run("org.bluez.Error.Failed", + "Invalid value given for write"); + return; + } + + if (value[0] == 1) + calories_burned_ = 0; + + callback.Run(); +} + void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( const dbus::ObjectPath& service_path) { if (IsHeartRateVisible()) { @@ -169,9 +194,6 @@ void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( flags.push_back(bluetooth_gatt_characteristic::kFlagNotify); heart_rate_measurement_properties_->flags.ReplaceValue(flags); - std::vector<uint8> measurement_value = GetHeartRateMeasurementValue(); - heart_rate_measurement_properties_->value.ReplaceValue(measurement_value); - // ==== Body Sensor Location Characteristic ==== body_sensor_location_path_ = service_path.value() + "/" + kBodySensorLocationPathComponent; @@ -185,12 +207,6 @@ void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( flags.push_back(bluetooth_gatt_characteristic::kFlagRead); body_sensor_location_properties_->flags.ReplaceValue(flags); - // The sensor is in the "Other" location. - std::vector<uint8> body_sensor_location_value; - body_sensor_location_value.push_back(0); - body_sensor_location_properties_->value.ReplaceValue( - body_sensor_location_value); - // ==== Heart Rate Control Point Characteristic ==== heart_rate_control_point_path_ = service_path.value() + "/" + kHeartRateControlPointPathComponent; @@ -205,13 +221,6 @@ void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( flags.push_back(bluetooth_gatt_characteristic::kFlagWrite); heart_rate_control_point_properties_->flags.ReplaceValue(flags); - // Set the initial value to 0. Whenever this gets set to 1, we will reset the - // total calories burned and change the value back to 0. - std::vector<uint8> heart_rate_control_point_value; - heart_rate_control_point_value.push_back(0); - heart_rate_control_point_properties_->value.ReplaceValue( - heart_rate_control_point_value); - heart_rate_visible_ = true; NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_)); @@ -286,25 +295,6 @@ void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_, GattCharacteristicPropertyChanged( object_path, property_name)); - - // If the heart rate control point was set, reset the calories burned. - if (object_path.value() != heart_rate_control_point_path_) - return; - DCHECK(heart_rate_control_point_properties_.get()); - dbus::Property<std::vector<uint8> >* value_prop = - &heart_rate_control_point_properties_->value; - if (property_name != value_prop->name()) - return; - - std::vector<uint8> value = value_prop->value(); - DCHECK(value.size() == 1); - if (value[0] == 0) - return; - - DCHECK(value[0] == 1); - calories_burned_ = 0; - value[0] = 0; - value_prop->ReplaceValue(value); } void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded( @@ -327,7 +317,12 @@ void FakeBluetoothGattCharacteristicClient:: return; VLOG(2) << "Updating heart rate value."; std::vector<uint8> measurement = GetHeartRateMeasurementValue(); - heart_rate_measurement_properties_->value.ReplaceValue(measurement); + + FOR_EACH_OBSERVER( + BluetoothGattCharacteristicClient::Observer, + observers_, + GattCharacteristicValueUpdated( + dbus::ObjectPath(heart_rate_measurement_path_), measurement)); base::MessageLoop::current()->PostDelayedTask( FROM_HERE, diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h index 1ae77cb..2f23586 100644 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h +++ b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h @@ -49,6 +49,13 @@ class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicClient virtual std::vector<dbus::ObjectPath> GetCharacteristics() OVERRIDE; virtual Properties* GetProperties(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void ReadValue(const dbus::ObjectPath& object_path, + const ValueCallback& callback, + const ErrorCallback& error_callback) OVERRIDE; + virtual void WriteValue(const dbus::ObjectPath& object_path, + const std::vector<uint8>& value, + const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; // Makes the group of characteristics belonging to a particular GATT based // profile available under the GATT service with object path |service_path|. |