OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/strings/stringprintf.h" | |
9 #include "device/bluetooth/bluetooth_adapter_chromeos.h" | |
10 #include "device/bluetooth/bluetooth_device_chromeos.h" | |
11 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h" | |
12 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h" | |
13 #include "device/bluetooth/dbus/bluetooth_gatt_service_client.h" | |
14 #include "device/bluetooth/dbus/bluez_dbus_manager.h" | |
15 | |
16 namespace chromeos { | |
17 | |
18 namespace { | |
19 | |
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"; | |
28 | |
29 } // namespace | |
30 | |
31 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS( | |
32 BluetoothAdapterChromeOS* adapter, | |
33 BluetoothDeviceChromeOS* device, | |
34 const dbus::ObjectPath& object_path) | |
35 : object_path_(object_path), | |
36 adapter_(adapter), | |
37 device_(device), | |
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(); | |
42 DCHECK(adapter_); | |
43 | |
44 bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver( | |
45 this); | |
46 bluez::BluezDBusManager::Get() | |
47 ->GetBluetoothGattCharacteristicClient() | |
48 ->AddObserver(this); | |
49 | |
50 // Add all known GATT characteristics. | |
51 const std::vector<dbus::ObjectPath>& gatt_chars = | |
52 bluez::BluezDBusManager::Get() | |
53 ->GetBluetoothGattCharacteristicClient() | |
54 ->GetCharacteristics(); | |
55 for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin(); | |
56 iter != gatt_chars.end(); ++iter) | |
57 GattCharacteristicAdded(*iter); | |
58 } | |
59 | |
60 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() { | |
61 bluez::BluezDBusManager::Get() | |
62 ->GetBluetoothGattServiceClient() | |
63 ->RemoveObserver(this); | |
64 bluez::BluezDBusManager::Get() | |
65 ->GetBluetoothGattCharacteristicClient() | |
66 ->RemoveObserver(this); | |
67 | |
68 // Clean up all the characteristics. Copy the characteristics list here and | |
69 // clear the original so that when we send GattCharacteristicRemoved(), | |
70 // GetCharacteristics() returns no characteristics. | |
71 CharacteristicMap characteristics = characteristics_; | |
72 characteristics_.clear(); | |
73 for (CharacteristicMap::iterator iter = characteristics.begin(); | |
74 iter != characteristics.end(); ++iter) { | |
75 DCHECK(adapter_); | |
76 adapter_->NotifyGattCharacteristicRemoved(iter->second); | |
77 | |
78 delete iter->second; | |
79 } | |
80 } | |
81 | |
82 std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const { | |
83 return object_path_.value(); | |
84 } | |
85 | |
86 device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const { | |
87 bluez::BluetoothGattServiceClient::Properties* properties = | |
88 bluez::BluezDBusManager::Get() | |
89 ->GetBluetoothGattServiceClient() | |
90 ->GetProperties(object_path_); | |
91 DCHECK(properties); | |
92 return device::BluetoothUUID(properties->uuid.value()); | |
93 } | |
94 | |
95 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const { | |
96 return false; | |
97 } | |
98 | |
99 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const { | |
100 bluez::BluetoothGattServiceClient::Properties* properties = | |
101 bluez::BluezDBusManager::Get() | |
102 ->GetBluetoothGattServiceClient() | |
103 ->GetProperties(object_path_); | |
104 DCHECK(properties); | |
105 return properties->primary.value(); | |
106 } | |
107 | |
108 device::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const { | |
109 return device_; | |
110 } | |
111 | |
112 std::vector<device::BluetoothGattCharacteristic*> | |
113 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const { | |
114 std::vector<device::BluetoothGattCharacteristic*> characteristics; | |
115 for (CharacteristicMap::const_iterator iter = characteristics_.begin(); | |
116 iter != characteristics_.end(); ++iter) { | |
117 characteristics.push_back(iter->second); | |
118 } | |
119 return characteristics; | |
120 } | |
121 | |
122 std::vector<device::BluetoothGattService*> | |
123 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const { | |
124 // TODO(armansito): Return the actual included services here. | |
125 return std::vector<device::BluetoothGattService*>(); | |
126 } | |
127 | |
128 device::BluetoothGattCharacteristic* | |
129 BluetoothRemoteGattServiceChromeOS::GetCharacteristic( | |
130 const std::string& identifier) const { | |
131 CharacteristicMap::const_iterator iter = | |
132 characteristics_.find(dbus::ObjectPath(identifier)); | |
133 if (iter == characteristics_.end()) | |
134 return NULL; | |
135 return iter->second; | |
136 } | |
137 | |
138 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic( | |
139 device::BluetoothGattCharacteristic* characteristic) { | |
140 VLOG(1) << "Characteristics cannot be added to a remote GATT service."; | |
141 return false; | |
142 } | |
143 | |
144 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService( | |
145 device::BluetoothGattService* service) { | |
146 VLOG(1) << "Included services cannot be added to a remote GATT service."; | |
147 return false; | |
148 } | |
149 | |
150 void BluetoothRemoteGattServiceChromeOS::Register( | |
151 const base::Closure& callback, | |
152 const ErrorCallback& error_callback) { | |
153 VLOG(1) << "A remote GATT service cannot be registered."; | |
154 error_callback.Run(); | |
155 } | |
156 | |
157 void BluetoothRemoteGattServiceChromeOS::Unregister( | |
158 const base::Closure& callback, | |
159 const ErrorCallback& error_callback) { | |
160 VLOG(1) << "A remote GATT service cannot be unregistered."; | |
161 error_callback.Run(); | |
162 } | |
163 | |
164 // static | |
165 device::BluetoothGattService::GattErrorCode | |
166 BluetoothRemoteGattServiceChromeOS::DBusErrorToServiceError( | |
167 std::string error_name) { | |
168 device::BluetoothGattService::GattErrorCode code = GATT_ERROR_UNKNOWN; | |
169 if (error_name == kErrorFailed) { | |
170 code = GATT_ERROR_FAILED; | |
171 } else if (error_name == kErrorInProgress) { | |
172 code = GATT_ERROR_IN_PROGRESS; | |
173 } else if (error_name == kErrorInvalidValueLength) { | |
174 code = GATT_ERROR_INVALID_LENGTH; | |
175 } else if (error_name == kErrorNotPermitted) { | |
176 code = GATT_ERROR_NOT_PERMITTED; | |
177 } else if (error_name == kErrorNotAuthorized) { | |
178 code = GATT_ERROR_NOT_AUTHORIZED; | |
179 } else if (error_name == kErrorNotPaired) { | |
180 code = GATT_ERROR_NOT_PAIRED; | |
181 } else if (error_name == kErrorNotSupported) { | |
182 code = GATT_ERROR_NOT_SUPPORTED; | |
183 } | |
184 return code; | |
185 } | |
186 | |
187 BluetoothAdapterChromeOS* | |
188 BluetoothRemoteGattServiceChromeOS::GetAdapter() const { | |
189 return adapter_; | |
190 } | |
191 | |
192 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() { | |
193 // Don't send service changed unless we know that all characteristics have | |
194 // already been discovered. This is to prevent spammy events before sending | |
195 // out the first Gatt | |
196 if (!discovery_complete_) | |
197 return; | |
198 | |
199 DCHECK(adapter_); | |
200 adapter_->NotifyGattServiceChanged(this); | |
201 } | |
202 | |
203 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved( | |
204 BluetoothRemoteGattCharacteristicChromeOS* characteristic, | |
205 BluetoothRemoteGattDescriptorChromeOS* descriptor, | |
206 bool added) { | |
207 DCHECK(characteristic->GetService() == this); | |
208 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
209 DCHECK(adapter_); | |
210 | |
211 if (added) { | |
212 adapter_->NotifyGattDescriptorAdded(descriptor); | |
213 return; | |
214 } | |
215 | |
216 adapter_->NotifyGattDescriptorRemoved(descriptor); | |
217 } | |
218 | |
219 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged( | |
220 BluetoothRemoteGattCharacteristicChromeOS* characteristic, | |
221 BluetoothRemoteGattDescriptorChromeOS* descriptor, | |
222 const std::vector<uint8>& value) { | |
223 DCHECK(characteristic->GetService() == this); | |
224 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
225 DCHECK(adapter_); | |
226 adapter_->NotifyGattDescriptorValueChanged(descriptor, value); | |
227 } | |
228 | |
229 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged( | |
230 const dbus::ObjectPath& object_path, | |
231 const std::string& property_name){ | |
232 if (object_path != object_path_) | |
233 return; | |
234 | |
235 VLOG(1) << "Service property changed: \"" << property_name << "\", " | |
236 << object_path.value(); | |
237 bluez::BluetoothGattServiceClient::Properties* properties = | |
238 bluez::BluezDBusManager::Get() | |
239 ->GetBluetoothGattServiceClient() | |
240 ->GetProperties(object_path); | |
241 DCHECK(properties); | |
242 | |
243 if (property_name != properties->characteristics.name()) { | |
244 NotifyServiceChanged(); | |
245 return; | |
246 } | |
247 | |
248 if (discovery_complete_) | |
249 return; | |
250 | |
251 VLOG(1) << "All characteristics were discovered for service: " | |
252 << object_path.value(); | |
253 discovery_complete_ = true; | |
254 DCHECK(adapter_); | |
255 adapter_->NotifyGattDiscoveryComplete(this); | |
256 } | |
257 | |
258 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded( | |
259 const dbus::ObjectPath& object_path) { | |
260 if (characteristics_.find(object_path) != characteristics_.end()) { | |
261 VLOG(1) << "Remote GATT characteristic already exists: " | |
262 << object_path.value(); | |
263 return; | |
264 } | |
265 | |
266 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
267 bluez::BluezDBusManager::Get() | |
268 ->GetBluetoothGattCharacteristicClient() | |
269 ->GetProperties(object_path); | |
270 DCHECK(properties); | |
271 if (properties->service.value() != object_path_) { | |
272 VLOG(2) << "Remote GATT characteristic does not belong to this service."; | |
273 return; | |
274 } | |
275 | |
276 VLOG(1) << "Adding new remote GATT characteristic for GATT service: " | |
277 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
278 | |
279 BluetoothRemoteGattCharacteristicChromeOS* characteristic = | |
280 new BluetoothRemoteGattCharacteristicChromeOS(this, object_path); | |
281 characteristics_[object_path] = characteristic; | |
282 DCHECK(characteristic->GetIdentifier() == object_path.value()); | |
283 DCHECK(characteristic->GetUUID().IsValid()); | |
284 | |
285 DCHECK(adapter_); | |
286 adapter_->NotifyGattCharacteristicAdded(characteristic); | |
287 } | |
288 | |
289 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved( | |
290 const dbus::ObjectPath& object_path) { | |
291 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
292 if (iter == characteristics_.end()) { | |
293 VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value(); | |
294 return; | |
295 } | |
296 | |
297 VLOG(1) << "Removing remote GATT characteristic from service: " | |
298 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
299 | |
300 BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second; | |
301 DCHECK(characteristic->object_path() == object_path); | |
302 characteristics_.erase(iter); | |
303 | |
304 DCHECK(adapter_); | |
305 adapter_->NotifyGattCharacteristicRemoved(characteristic); | |
306 | |
307 delete characteristic; | |
308 } | |
309 | |
310 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged( | |
311 const dbus::ObjectPath& object_path, | |
312 const std::string& property_name) { | |
313 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
314 if (iter == characteristics_.end()) { | |
315 VLOG(3) << "Properties of unknown characteristic changed"; | |
316 return; | |
317 } | |
318 | |
319 // We may receive a property changed event in certain cases, e.g. when the | |
320 // characteristic "Flags" property has been updated with values from the | |
321 // "Characteristic Extended Properties" descriptor. In this case, kick off | |
322 // a service changed observer event to let observers refresh the | |
323 // characteristics. | |
324 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
325 bluez::BluezDBusManager::Get() | |
326 ->GetBluetoothGattCharacteristicClient() | |
327 ->GetProperties(object_path); | |
328 | |
329 DCHECK(properties); | |
330 DCHECK(adapter_); | |
331 | |
332 if (property_name == properties->flags.name()) | |
333 NotifyServiceChanged(); | |
334 else if (property_name == properties->value.name()) | |
335 adapter_->NotifyGattCharacteristicValueChanged(iter->second, | |
336 properties->value.value()); | |
337 } | |
338 | |
339 } // namespace chromeos | |
OLD | NEW |