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_service_chromeos.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "chromeos/dbus/bluetooth_gatt_service_client.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
12 #include "device/bluetooth/bluetooth_device_chromeos.h"
13 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
14 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
20 // TODO(jamuraa) move these to cros_system_api later
21 const char kErrorFailed
[] = "org.bluez.Error.Failed";
22 const char kErrorInProgress
[] = "org.bluez.Error.InProgress";
23 const char kErrorInvalidValueLength
[] = "org.bluez.Error.InvalidValueLength";
24 const char kErrorNotAuthorized
[] = "org.bluez.Error.NotAuthorized";
25 const char kErrorNotPaired
[] = "org.bluez.Error.NotPaired";
26 const char kErrorNotSupported
[] = "org.bluez.Error.NotSupported";
27 const char kErrorNotPermitted
[] = "org.bluez.Error.NotPermitted";
31 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
32 BluetoothAdapterChromeOS
* adapter
,
33 BluetoothDeviceChromeOS
* device
,
34 const dbus::ObjectPath
& object_path
)
35 : object_path_(object_path
),
38 discovery_complete_(false),
39 weak_ptr_factory_(this) {
40 VLOG(1) << "Creating remote GATT service with identifier: "
41 << object_path
.value() << ", UUID: " << GetUUID().canonical_value();
44 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
45 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
48 // Add all known GATT characteristics.
49 const std::vector
<dbus::ObjectPath
>& gatt_chars
=
50 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
52 for (std::vector
<dbus::ObjectPath
>::const_iterator iter
= gatt_chars
.begin();
53 iter
!= gatt_chars
.end(); ++iter
)
54 GattCharacteristicAdded(*iter
);
57 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
58 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
60 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
63 // Clean up all the characteristics. Copy the characteristics list here and
64 // clear the original so that when we send GattCharacteristicRemoved(),
65 // GetCharacteristics() returns no characteristics.
66 CharacteristicMap characteristics
= characteristics_
;
67 characteristics_
.clear();
68 for (CharacteristicMap::iterator iter
= characteristics
.begin();
69 iter
!= characteristics
.end(); ++iter
) {
71 adapter_
->NotifyGattCharacteristicRemoved(iter
->second
);
77 std::string
BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
78 return object_path_
.value();
81 device::BluetoothUUID
BluetoothRemoteGattServiceChromeOS::GetUUID() const {
82 BluetoothGattServiceClient::Properties
* properties
=
83 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
84 GetProperties(object_path_
);
86 return device::BluetoothUUID(properties
->uuid
.value());
89 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const {
93 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
94 BluetoothGattServiceClient::Properties
* properties
=
95 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
96 GetProperties(object_path_
);
98 return properties
->primary
.value();
101 device::BluetoothDevice
* BluetoothRemoteGattServiceChromeOS::GetDevice() const {
105 std::vector
<device::BluetoothGattCharacteristic
*>
106 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const {
107 std::vector
<device::BluetoothGattCharacteristic
*> characteristics
;
108 for (CharacteristicMap::const_iterator iter
= characteristics_
.begin();
109 iter
!= characteristics_
.end(); ++iter
) {
110 characteristics
.push_back(iter
->second
);
112 return characteristics
;
115 std::vector
<device::BluetoothGattService
*>
116 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const {
117 // TODO(armansito): Return the actual included services here.
118 return std::vector
<device::BluetoothGattService
*>();
121 device::BluetoothGattCharacteristic
*
122 BluetoothRemoteGattServiceChromeOS::GetCharacteristic(
123 const std::string
& identifier
) const {
124 CharacteristicMap::const_iterator iter
=
125 characteristics_
.find(dbus::ObjectPath(identifier
));
126 if (iter
== characteristics_
.end())
131 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic(
132 device::BluetoothGattCharacteristic
* characteristic
) {
133 VLOG(1) << "Characteristics cannot be added to a remote GATT service.";
137 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService(
138 device::BluetoothGattService
* service
) {
139 VLOG(1) << "Included services cannot be added to a remote GATT service.";
143 void BluetoothRemoteGattServiceChromeOS::Register(
144 const base::Closure
& callback
,
145 const ErrorCallback
& error_callback
) {
146 VLOG(1) << "A remote GATT service cannot be registered.";
147 error_callback
.Run();
150 void BluetoothRemoteGattServiceChromeOS::Unregister(
151 const base::Closure
& callback
,
152 const ErrorCallback
& error_callback
) {
153 VLOG(1) << "A remote GATT service cannot be unregistered.";
154 error_callback
.Run();
158 device::BluetoothGattService::GattErrorCode
159 BluetoothRemoteGattServiceChromeOS::DBusErrorToServiceError(
160 std::string error_name
) {
161 device::BluetoothGattService::GattErrorCode code
= GATT_ERROR_UNKNOWN
;
162 if (error_name
== kErrorFailed
) {
163 code
= GATT_ERROR_FAILED
;
164 } else if (error_name
== kErrorInProgress
) {
165 code
= GATT_ERROR_IN_PROGRESS
;
166 } else if (error_name
== kErrorInvalidValueLength
) {
167 code
= GATT_ERROR_INVALID_LENGTH
;
168 } else if (error_name
== kErrorNotPermitted
) {
169 code
= GATT_ERROR_NOT_PERMITTED
;
170 } else if (error_name
== kErrorNotAuthorized
) {
171 code
= GATT_ERROR_NOT_AUTHORIZED
;
172 } else if (error_name
== kErrorNotPaired
) {
173 code
= GATT_ERROR_NOT_PAIRED
;
174 } else if (error_name
== kErrorNotSupported
) {
175 code
= GATT_ERROR_NOT_SUPPORTED
;
180 BluetoothAdapterChromeOS
*
181 BluetoothRemoteGattServiceChromeOS::GetAdapter() const {
185 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
186 // Don't send service changed unless we know that all characteristics have
187 // already been discovered. This is to prevent spammy events before sending
188 // out the first Gatt
189 if (!discovery_complete_
)
193 adapter_
->NotifyGattServiceChanged(this);
196 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
197 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
198 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
200 DCHECK(characteristic
->GetService() == this);
201 DCHECK(descriptor
->GetCharacteristic() == characteristic
);
205 adapter_
->NotifyGattDescriptorAdded(descriptor
);
209 adapter_
->NotifyGattDescriptorRemoved(descriptor
);
212 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
213 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
214 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
215 const std::vector
<uint8
>& value
) {
216 DCHECK(characteristic
->GetService() == this);
217 DCHECK(descriptor
->GetCharacteristic() == characteristic
);
219 adapter_
->NotifyGattDescriptorValueChanged(descriptor
, value
);
222 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
223 const dbus::ObjectPath
& object_path
,
224 const std::string
& property_name
){
225 if (object_path
!= object_path_
)
228 VLOG(1) << "Service property changed: \"" << property_name
<< "\", "
229 << object_path
.value();
230 BluetoothGattServiceClient::Properties
* properties
=
231 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
235 if (property_name
!= properties
->characteristics
.name()) {
236 NotifyServiceChanged();
240 if (discovery_complete_
)
243 VLOG(1) << "All characteristics were discovered for service: "
244 << object_path
.value();
245 discovery_complete_
= true;
247 adapter_
->NotifyGattDiscoveryComplete(this);
250 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
251 const dbus::ObjectPath
& object_path
) {
252 if (characteristics_
.find(object_path
) != characteristics_
.end()) {
253 VLOG(1) << "Remote GATT characteristic already exists: "
254 << object_path
.value();
258 BluetoothGattCharacteristicClient::Properties
* properties
=
259 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
260 GetProperties(object_path
);
262 if (properties
->service
.value() != object_path_
) {
263 VLOG(2) << "Remote GATT characteristic does not belong to this service.";
267 VLOG(1) << "Adding new remote GATT characteristic for GATT service: "
268 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
270 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
=
271 new BluetoothRemoteGattCharacteristicChromeOS(this, object_path
);
272 characteristics_
[object_path
] = characteristic
;
273 DCHECK(characteristic
->GetIdentifier() == object_path
.value());
274 DCHECK(characteristic
->GetUUID().IsValid());
277 adapter_
->NotifyGattCharacteristicAdded(characteristic
);
280 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
281 const dbus::ObjectPath
& object_path
) {
282 CharacteristicMap::iterator iter
= characteristics_
.find(object_path
);
283 if (iter
== characteristics_
.end()) {
284 VLOG(2) << "Unknown GATT characteristic removed: " << object_path
.value();
288 VLOG(1) << "Removing remote GATT characteristic from service: "
289 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
291 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
= iter
->second
;
292 DCHECK(characteristic
->object_path() == object_path
);
293 characteristics_
.erase(iter
);
296 adapter_
->NotifyGattCharacteristicRemoved(characteristic
);
298 delete characteristic
;
301 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
302 const dbus::ObjectPath
& object_path
,
303 const std::string
& property_name
) {
304 CharacteristicMap::iterator iter
= characteristics_
.find(object_path
);
305 if (iter
== characteristics_
.end()) {
306 VLOG(3) << "Properties of unknown characteristic changed";
310 // We may receive a property changed event in certain cases, e.g. when the
311 // characteristic "Flags" property has been updated with values from the
312 // "Characteristic Extended Properties" descriptor. In this case, kick off
313 // a service changed observer event to let observers refresh the
315 BluetoothGattCharacteristicClient::Properties
* properties
=
316 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
317 GetProperties(object_path
);
322 if (property_name
== properties
->flags
.name())
323 NotifyServiceChanged();
324 else if (property_name
== properties
->value
.name())
325 adapter_
->NotifyGattCharacteristicValueChanged(iter
->second
,
326 properties
->value
.value());
329 } // namespace chromeos