summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorarmansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-07 20:26:45 +0000
committerarmansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-07 20:26:45 +0000
commitd62d70e49f7a7096175a8d071d1b930d9ca2f0a9 (patch)
tree8455a87fb5b9bd25b961e1af9563c292359614a4 /chromeos
parent0fc48a16950329a84ce8cda23646b82052ace2ef (diff)
downloadchromium_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')
-rw-r--r--chromeos/dbus/bluetooth_gatt_characteristic_client.cc150
-rw-r--r--chromeos/dbus/bluetooth_gatt_characteristic_client.h36
-rw-r--r--chromeos/dbus/bluetooth_gatt_service_client.cc13
-rw-r--r--chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc129
-rw-r--r--chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h7
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|.