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.
5 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
12 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
18 // Stream operator for logging vector<uint8>.
19 std::ostream
& operator<<(std::ostream
& out
, const std::vector
<uint8
> bytes
) {
21 for (std::vector
<uint8
>::const_iterator iter
= bytes
.begin();
22 iter
!= bytes
.end(); ++iter
) {
23 out
<< base::StringPrintf("%02X", *iter
);
30 BluetoothRemoteGattCharacteristicChromeOS::
31 BluetoothRemoteGattCharacteristicChromeOS(
32 BluetoothRemoteGattServiceChromeOS
* service
,
33 const dbus::ObjectPath
& object_path
)
34 : object_path_(object_path
),
36 weak_ptr_factory_(this) {
37 VLOG(1) << "Creating remote GATT characteristic with identifier: "
38 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
39 DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
42 // Add all known GATT characteristic descriptors.
43 const std::vector
<dbus::ObjectPath
>& gatt_descs
=
44 DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
46 for (std::vector
<dbus::ObjectPath
>::const_iterator iter
= gatt_descs
.begin();
47 iter
!= gatt_descs
.end(); ++iter
)
48 GattDescriptorAdded(*iter
);
51 BluetoothRemoteGattCharacteristicChromeOS::
52 ~BluetoothRemoteGattCharacteristicChromeOS() {
53 DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
56 // Clean up all the descriptors. There isn't much point in notifying service
57 // observers for each descriptor that gets removed, so just delete them.
58 for (DescriptorMap::iterator iter
= descriptors_
.begin();
59 iter
!= descriptors_
.end(); ++iter
)
63 std::string
BluetoothRemoteGattCharacteristicChromeOS::GetIdentifier() const {
64 return object_path_
.value();
68 BluetoothRemoteGattCharacteristicChromeOS::GetUUID() const {
69 BluetoothGattCharacteristicClient::Properties
* properties
=
70 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
71 GetProperties(object_path_
);
73 return device::BluetoothUUID(properties
->uuid
.value());
76 bool BluetoothRemoteGattCharacteristicChromeOS::IsLocal() const {
80 const std::vector
<uint8
>&
81 BluetoothRemoteGattCharacteristicChromeOS::GetValue() const {
82 BluetoothGattCharacteristicClient::Properties
* properties
=
83 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
84 GetProperties(object_path_
);
86 return properties
->value
.value();
89 device::BluetoothGattService
*
90 BluetoothRemoteGattCharacteristicChromeOS::GetService() const {
94 device::BluetoothGattCharacteristic::Properties
95 BluetoothRemoteGattCharacteristicChromeOS::GetProperties() const {
96 // TODO(armansito): Once BlueZ implements properties properly, return those
101 device::BluetoothGattCharacteristic::Permissions
102 BluetoothRemoteGattCharacteristicChromeOS::GetPermissions() const {
103 // TODO(armansito): Once BlueZ defines the permissions, return the correct
105 return kPermissionNone
;
108 std::vector
<device::BluetoothGattDescriptor
*>
109 BluetoothRemoteGattCharacteristicChromeOS::GetDescriptors() const {
110 std::vector
<device::BluetoothGattDescriptor
*> descriptors
;
111 for (DescriptorMap::const_iterator iter
= descriptors_
.begin();
112 iter
!= descriptors_
.end(); ++iter
)
113 descriptors
.push_back(iter
->second
);
117 device::BluetoothGattDescriptor
*
118 BluetoothRemoteGattCharacteristicChromeOS::GetDescriptor(
119 const std::string
& identifier
) const {
120 DescriptorMap::const_iterator iter
=
121 descriptors_
.find(dbus::ObjectPath(identifier
));
122 if (iter
== descriptors_
.end())
127 bool BluetoothRemoteGattCharacteristicChromeOS::AddDescriptor(
128 device::BluetoothGattDescriptor
* descriptor
) {
129 VLOG(1) << "Descriptors cannot be added to a remote GATT characteristic.";
133 bool BluetoothRemoteGattCharacteristicChromeOS::UpdateValue(
134 const std::vector
<uint8
>& value
) {
135 VLOG(1) << "Cannot update the value of a remote GATT characteristic.";
139 void BluetoothRemoteGattCharacteristicChromeOS::ReadRemoteCharacteristic(
140 const ValueCallback
& callback
,
141 const ErrorCallback
& error_callback
) {
142 VLOG(1) << "Sending GATT characteristic read request to characteristic: "
143 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
145 BluetoothGattCharacteristicClient::Properties
* properties
=
146 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
147 GetProperties(object_path_
);
149 properties
->value
.Get(
150 base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnGetValue
,
151 weak_ptr_factory_
.GetWeakPtr(),
152 callback
, error_callback
));
155 void BluetoothRemoteGattCharacteristicChromeOS::WriteRemoteCharacteristic(
156 const std::vector
<uint8
>& new_value
,
157 const base::Closure
& callback
,
158 const ErrorCallback
& error_callback
) {
159 VLOG(1) << "Sending GATT characteristic write request to characteristic: "
160 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
161 << ", with value: " << new_value
<< ".";
163 // Permission and bonding are handled by BlueZ so no need check it here.
164 if (new_value
.empty()) {
165 VLOG(1) << "Nothing to write.";
166 error_callback
.Run();
170 BluetoothGattCharacteristicClient::Properties
* properties
=
171 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
172 GetProperties(object_path_
);
174 properties
->value
.Set(
176 base::Bind(&BluetoothRemoteGattCharacteristicChromeOS::OnSetValue
,
177 weak_ptr_factory_
.GetWeakPtr(),
178 callback
, error_callback
));
181 void BluetoothRemoteGattCharacteristicChromeOS::GattDescriptorAdded(
182 const dbus::ObjectPath
& object_path
) {
183 if (descriptors_
.find(object_path
) != descriptors_
.end()) {
184 VLOG(1) << "Remote GATT characteristic descriptor already exists: "
185 << object_path
.value();
189 BluetoothGattDescriptorClient::Properties
* properties
=
190 DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
191 GetProperties(object_path
);
193 if (properties
->characteristic
.value() != object_path_
) {
194 VLOG(2) << "Remote GATT descriptor does not belong to this characteristic.";
198 VLOG(1) << "Adding new remote GATT descriptor for GATT characteristic: "
199 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
201 BluetoothRemoteGattDescriptorChromeOS
* descriptor
=
202 new BluetoothRemoteGattDescriptorChromeOS(this, object_path
);
203 descriptors_
[object_path
] = descriptor
;
204 DCHECK(descriptor
->GetIdentifier() == object_path
.value());
205 DCHECK(descriptor
->GetUUID().IsValid());
208 service_
->NotifyDescriptorAddedOrRemoved(this, descriptor
, true /* added */);
209 service_
->NotifyServiceChanged();
212 void BluetoothRemoteGattCharacteristicChromeOS::GattDescriptorRemoved(
213 const dbus::ObjectPath
& object_path
) {
214 DescriptorMap::iterator iter
= descriptors_
.find(object_path
);
215 if (iter
== descriptors_
.end()) {
216 VLOG(2) << "Unknown descriptor removed: " << object_path
.value();
220 VLOG(1) << "Removing remote GATT descriptor from characteristic: "
221 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
223 BluetoothRemoteGattDescriptorChromeOS
* descriptor
= iter
->second
;
224 DCHECK(descriptor
->object_path() == object_path
);
225 descriptors_
.erase(iter
);
227 service_
->NotifyDescriptorAddedOrRemoved(this, descriptor
, false /* added */);
232 service_
->NotifyServiceChanged();
235 void BluetoothRemoteGattCharacteristicChromeOS::GattDescriptorPropertyChanged(
236 const dbus::ObjectPath
& object_path
,
237 const std::string
& property_name
) {
238 DescriptorMap::const_iterator iter
= descriptors_
.find(object_path
);
239 if (iter
== descriptors_
.end())
242 // Ignore all property changes except for "Value".
243 BluetoothGattDescriptorClient::Properties
* properties
=
244 DBusThreadManager::Get()->GetBluetoothGattDescriptorClient()->
245 GetProperties(object_path
);
247 if (property_name
!= properties
->value
.name())
250 VLOG(1) << "GATT descriptor property changed: " << object_path
.value()
251 << ", property: " << property_name
;
255 service_
->NotifyDescriptorValueChanged(
256 this, iter
->second
, properties
->value
.value());
259 void BluetoothRemoteGattCharacteristicChromeOS::OnGetValue(
260 const ValueCallback
& callback
,
261 const ErrorCallback
& error_callback
,
264 VLOG(1) << "Failed to read the value from the remote characteristic.";
265 error_callback
.Run();
269 VLOG(1) << "Read value of remote characteristic.";
270 BluetoothGattCharacteristicClient::Properties
* properties
=
271 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
272 GetProperties(object_path_
);
274 callback
.Run(properties
->value
.value());
277 void BluetoothRemoteGattCharacteristicChromeOS::OnSetValue(
278 const base::Closure
& callback
,
279 const ErrorCallback
& error_callback
,
282 VLOG(1) << "Failed to write the value of remote characteristic.";
283 error_callback
.Run();
287 VLOG(1) << "Wrote value of remote characteristic.";
291 } // namespace chromeos