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 kErrorReadNotPermitted
[] = "org.bluez.Error.ReadNotPermitted";
28 const char kErrorWriteNotPermitted
[] = "org.bluez.Error.WriteNotPermitted";
32 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
33 BluetoothAdapterChromeOS
* adapter
,
34 BluetoothDeviceChromeOS
* device
,
35 const dbus::ObjectPath
& object_path
)
36 : object_path_(object_path
),
39 discovery_complete_(false),
40 weak_ptr_factory_(this) {
41 VLOG(1) << "Creating remote GATT service with identifier: "
42 << object_path
.value() << ", UUID: " << GetUUID().canonical_value();
45 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
46 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
49 // Add all known GATT characteristics.
50 const std::vector
<dbus::ObjectPath
>& gatt_chars
=
51 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
53 for (std::vector
<dbus::ObjectPath
>::const_iterator iter
= gatt_chars
.begin();
54 iter
!= gatt_chars
.end(); ++iter
)
55 GattCharacteristicAdded(*iter
);
58 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
59 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
61 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
64 // Clean up all the characteristics. Copy the characteristics list here and
65 // clear the original so that when we send GattCharacteristicRemoved(),
66 // GetCharacteristics() returns no characteristics.
67 CharacteristicMap characteristics
= characteristics_
;
68 characteristics_
.clear();
69 for (CharacteristicMap::iterator iter
= characteristics
.begin();
70 iter
!= characteristics
.end(); ++iter
) {
72 adapter_
->NotifyGattCharacteristicRemoved(iter
->second
);
78 std::string
BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
79 return object_path_
.value();
82 device::BluetoothUUID
BluetoothRemoteGattServiceChromeOS::GetUUID() const {
83 BluetoothGattServiceClient::Properties
* properties
=
84 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
85 GetProperties(object_path_
);
87 return device::BluetoothUUID(properties
->uuid
.value());
90 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const {
94 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
95 BluetoothGattServiceClient::Properties
* properties
=
96 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
97 GetProperties(object_path_
);
99 return properties
->primary
.value();
102 device::BluetoothDevice
* BluetoothRemoteGattServiceChromeOS::GetDevice() const {
106 std::vector
<device::BluetoothGattCharacteristic
*>
107 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const {
108 std::vector
<device::BluetoothGattCharacteristic
*> characteristics
;
109 for (CharacteristicMap::const_iterator iter
= characteristics_
.begin();
110 iter
!= characteristics_
.end(); ++iter
) {
111 characteristics
.push_back(iter
->second
);
113 return characteristics
;
116 std::vector
<device::BluetoothGattService
*>
117 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const {
118 // TODO(armansito): Return the actual included services here.
119 return std::vector
<device::BluetoothGattService
*>();
122 device::BluetoothGattCharacteristic
*
123 BluetoothRemoteGattServiceChromeOS::GetCharacteristic(
124 const std::string
& identifier
) const {
125 CharacteristicMap::const_iterator iter
=
126 characteristics_
.find(dbus::ObjectPath(identifier
));
127 if (iter
== characteristics_
.end())
132 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic(
133 device::BluetoothGattCharacteristic
* characteristic
) {
134 VLOG(1) << "Characteristics cannot be added to a remote GATT service.";
138 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService(
139 device::BluetoothGattService
* service
) {
140 VLOG(1) << "Included services cannot be added to a remote GATT service.";
144 void BluetoothRemoteGattServiceChromeOS::Register(
145 const base::Closure
& callback
,
146 const ErrorCallback
& error_callback
) {
147 VLOG(1) << "A remote GATT service cannot be registered.";
148 error_callback
.Run();
151 void BluetoothRemoteGattServiceChromeOS::Unregister(
152 const base::Closure
& callback
,
153 const ErrorCallback
& error_callback
) {
154 VLOG(1) << "A remote GATT service cannot be unregistered.";
155 error_callback
.Run();
159 device::BluetoothGattService::GattErrorCode
160 BluetoothRemoteGattServiceChromeOS::DBusErrorToServiceError(
161 std::string error_name
) {
162 device::BluetoothGattService::GattErrorCode code
= GATT_ERROR_UNKNOWN
;
163 if (error_name
== kErrorFailed
) {
164 code
= GATT_ERROR_FAILED
;
165 } else if (error_name
== kErrorInProgress
) {
166 code
= GATT_ERROR_IN_PROGRESS
;
167 } else if (error_name
== kErrorInvalidValueLength
) {
168 code
= GATT_ERROR_INVALID_LENGTH
;
169 } else if (error_name
== kErrorReadNotPermitted
||
170 error_name
== kErrorWriteNotPermitted
) {
171 code
= GATT_ERROR_NOT_PERMITTED
;
172 } else if (error_name
== kErrorNotAuthorized
) {
173 code
= GATT_ERROR_NOT_AUTHORIZED
;
174 } else if (error_name
== kErrorNotPaired
) {
175 code
= GATT_ERROR_NOT_PAIRED
;
176 } else if (error_name
== kErrorNotSupported
) {
177 code
= GATT_ERROR_NOT_SUPPORTED
;
182 BluetoothAdapterChromeOS
*
183 BluetoothRemoteGattServiceChromeOS::GetAdapter() const {
187 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
188 // Don't send service changed unless we know that all characteristics have
189 // already been discovered. This is to prevent spammy events before sending
190 // out the first Gatt
191 if (!discovery_complete_
)
195 adapter_
->NotifyGattServiceChanged(this);
198 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
199 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
200 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
202 DCHECK(characteristic
->GetService() == this);
203 DCHECK(descriptor
->GetCharacteristic() == characteristic
);
207 adapter_
->NotifyGattDescriptorAdded(descriptor
);
211 adapter_
->NotifyGattDescriptorRemoved(descriptor
);
214 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
215 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
216 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
217 const std::vector
<uint8
>& value
) {
218 DCHECK(characteristic
->GetService() == this);
219 DCHECK(descriptor
->GetCharacteristic() == characteristic
);
221 adapter_
->NotifyGattDescriptorValueChanged(descriptor
, value
);
224 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
225 const dbus::ObjectPath
& object_path
,
226 const std::string
& property_name
){
227 if (object_path
!= object_path_
)
230 VLOG(1) << "Service property changed: \"" << property_name
<< "\", "
231 << object_path
.value();
232 BluetoothGattServiceClient::Properties
* properties
=
233 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
237 if (property_name
!= properties
->characteristics
.name()) {
238 NotifyServiceChanged();
242 if (discovery_complete_
)
245 VLOG(1) << "All characteristics were discovered for service: "
246 << object_path
.value();
247 discovery_complete_
= true;
249 adapter_
->NotifyGattDiscoveryComplete(this);
252 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
253 const dbus::ObjectPath
& object_path
) {
254 if (characteristics_
.find(object_path
) != characteristics_
.end()) {
255 VLOG(1) << "Remote GATT characteristic already exists: "
256 << object_path
.value();
260 BluetoothGattCharacteristicClient::Properties
* properties
=
261 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
262 GetProperties(object_path
);
264 if (properties
->service
.value() != object_path_
) {
265 VLOG(2) << "Remote GATT characteristic does not belong to this service.";
269 VLOG(1) << "Adding new remote GATT characteristic for GATT service: "
270 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
272 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
=
273 new BluetoothRemoteGattCharacteristicChromeOS(this, object_path
);
274 characteristics_
[object_path
] = characteristic
;
275 DCHECK(characteristic
->GetIdentifier() == object_path
.value());
276 DCHECK(characteristic
->GetUUID().IsValid());
279 adapter_
->NotifyGattCharacteristicAdded(characteristic
);
282 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
283 const dbus::ObjectPath
& object_path
) {
284 CharacteristicMap::iterator iter
= characteristics_
.find(object_path
);
285 if (iter
== characteristics_
.end()) {
286 VLOG(2) << "Unknown GATT characteristic removed: " << object_path
.value();
290 VLOG(1) << "Removing remote GATT characteristic from service: "
291 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
293 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
= iter
->second
;
294 DCHECK(characteristic
->object_path() == object_path
);
295 characteristics_
.erase(iter
);
298 adapter_
->NotifyGattCharacteristicRemoved(characteristic
);
300 delete characteristic
;
303 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
304 const dbus::ObjectPath
& object_path
,
305 const std::string
& property_name
) {
306 CharacteristicMap::iterator iter
= characteristics_
.find(object_path
);
307 if (iter
== characteristics_
.end()) {
308 VLOG(3) << "Properties of unknown characteristic changed";
312 // We may receive a property changed event in certain cases, e.g. when the
313 // characteristic "Flags" property has been updated with values from the
314 // "Characteristic Extended Properties" descriptor. In this case, kick off
315 // a service changed observer event to let observers refresh the
317 BluetoothGattCharacteristicClient::Properties
* properties
=
318 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
319 GetProperties(object_path
);
324 if (property_name
== properties
->flags
.name())
325 NotifyServiceChanged();
326 else if (property_name
== properties
->value
.name())
327 adapter_
->NotifyGattCharacteristicValueChanged(iter
->second
,
328 properties
->value
.value());
331 } // namespace chromeos