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_bluez.h" | |
6 | |
7 #include <iterator> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/callback_forward.h" | |
11 #include "base/logging.h" | |
12 #include "dbus/property.h" | |
13 #include "device/bluetooth/bluetooth_adapter_bluez.h" | |
14 #include "device/bluetooth/bluetooth_device_bluez.h" | |
15 #include "device/bluetooth/bluetooth_gatt_characteristic_bluez.h" | |
16 #include "device/bluetooth/bluetooth_gatt_descriptor_bluez.h" | |
17 #include "device/bluetooth/bluetooth_gatt_service.h" | |
18 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_bluez.h" | |
19 #include "device/bluetooth/dbus/bluez_dbus_manager.h" | |
20 | |
21 namespace bluez { | |
22 | |
23 BluetoothRemoteGattServiceBlueZ::BluetoothRemoteGattServiceBlueZ( | |
24 BluetoothAdapterBlueZ* adapter, | |
25 BluetoothDeviceBlueZ* device, | |
26 const dbus::ObjectPath& object_path) | |
27 : BluetoothGattServiceBlueZ(adapter, object_path), | |
28 device_(device), | |
29 discovery_complete_(false), | |
30 weak_ptr_factory_(this) { | |
31 VLOG(1) << "Creating remote GATT service with identifier: " | |
32 << object_path.value(); | |
33 DCHECK(GetAdapter()); | |
34 | |
35 bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver( | |
36 this); | |
37 bluez::BluezDBusManager::Get() | |
38 ->GetBluetoothGattCharacteristicClient() | |
39 ->AddObserver(this); | |
40 | |
41 // Add all known GATT characteristics. | |
42 const std::vector<dbus::ObjectPath>& gatt_chars = | |
43 bluez::BluezDBusManager::Get() | |
44 ->GetBluetoothGattCharacteristicClient() | |
45 ->GetCharacteristics(); | |
46 for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin(); | |
47 iter != gatt_chars.end(); ++iter) | |
48 GattCharacteristicAdded(*iter); | |
49 } | |
50 | |
51 BluetoothRemoteGattServiceBlueZ::~BluetoothRemoteGattServiceBlueZ() { | |
52 bluez::BluezDBusManager::Get() | |
53 ->GetBluetoothGattServiceClient() | |
54 ->RemoveObserver(this); | |
55 bluez::BluezDBusManager::Get() | |
56 ->GetBluetoothGattCharacteristicClient() | |
57 ->RemoveObserver(this); | |
58 | |
59 // Clean up all the characteristics. Copy the characteristics list here and | |
60 // clear the original so that when we send GattCharacteristicRemoved(), | |
61 // GetCharacteristics() returns no characteristics. | |
62 CharacteristicMap characteristics = characteristics_; | |
63 characteristics_.clear(); | |
64 for (CharacteristicMap::iterator iter = characteristics.begin(); | |
65 iter != characteristics.end(); ++iter) { | |
66 DCHECK(GetAdapter()); | |
67 GetAdapter()->NotifyGattCharacteristicRemoved(iter->second); | |
68 | |
69 delete iter->second; | |
70 } | |
71 } | |
72 | |
73 device::BluetoothUUID BluetoothRemoteGattServiceBlueZ::GetUUID() const { | |
74 bluez::BluetoothGattServiceClient::Properties* properties = | |
75 bluez::BluezDBusManager::Get() | |
76 ->GetBluetoothGattServiceClient() | |
77 ->GetProperties(object_path()); | |
78 DCHECK(properties); | |
79 return device::BluetoothUUID(properties->uuid.value()); | |
80 } | |
81 | |
82 bool BluetoothRemoteGattServiceBlueZ::IsLocal() const { | |
83 return false; | |
84 } | |
85 | |
86 bool BluetoothRemoteGattServiceBlueZ::IsPrimary() const { | |
87 bluez::BluetoothGattServiceClient::Properties* properties = | |
88 bluez::BluezDBusManager::Get() | |
89 ->GetBluetoothGattServiceClient() | |
90 ->GetProperties(object_path()); | |
91 DCHECK(properties); | |
92 return properties->primary.value(); | |
93 } | |
94 | |
95 device::BluetoothDevice* BluetoothRemoteGattServiceBlueZ::GetDevice() const { | |
96 return device_; | |
97 } | |
98 | |
99 bool BluetoothRemoteGattServiceBlueZ::AddCharacteristic( | |
100 device::BluetoothGattCharacteristic* characteristic) { | |
101 VLOG(1) << "Characteristics cannot be added to a remote GATT service."; | |
102 return false; | |
103 } | |
104 | |
105 bool BluetoothRemoteGattServiceBlueZ::AddIncludedService( | |
106 device::BluetoothGattService* service) { | |
107 VLOG(1) << "Included services cannot be added to a remote GATT service."; | |
108 return false; | |
109 } | |
110 | |
111 void BluetoothRemoteGattServiceBlueZ::Register( | |
112 const base::Closure& callback, | |
113 const ErrorCallback& error_callback) { | |
114 VLOG(1) << "A remote GATT service cannot be registered."; | |
115 error_callback.Run(GATT_ERROR_NOT_SUPPORTED); | |
116 } | |
117 | |
118 void BluetoothRemoteGattServiceBlueZ::Unregister( | |
119 const base::Closure& callback, | |
120 const ErrorCallback& error_callback) { | |
121 VLOG(1) << "A remote GATT service cannot be unregistered."; | |
122 error_callback.Run(GATT_ERROR_NOT_SUPPORTED); | |
123 } | |
124 | |
125 void BluetoothRemoteGattServiceBlueZ::NotifyServiceChanged() { | |
126 // Don't send service changed unless we know that all characteristics have | |
127 // already been discovered. This is to prevent spammy events before sending | |
128 // out the first Gatt | |
129 if (!discovery_complete_) | |
130 return; | |
131 | |
132 DCHECK(GetAdapter()); | |
133 GetAdapter()->NotifyGattServiceChanged(this); | |
134 } | |
135 | |
136 void BluetoothRemoteGattServiceBlueZ::NotifyDescriptorAddedOrRemoved( | |
137 BluetoothRemoteGattCharacteristicBlueZ* characteristic, | |
138 BluetoothGattDescriptorBlueZ* descriptor, | |
139 bool added) { | |
140 DCHECK(characteristic->GetService() == this); | |
141 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
142 DCHECK(GetAdapter()); | |
143 | |
144 if (added) { | |
145 GetAdapter()->NotifyGattDescriptorAdded(descriptor); | |
146 return; | |
147 } | |
148 | |
149 GetAdapter()->NotifyGattDescriptorRemoved(descriptor); | |
150 } | |
151 | |
152 void BluetoothRemoteGattServiceBlueZ::NotifyDescriptorValueChanged( | |
153 BluetoothRemoteGattCharacteristicBlueZ* characteristic, | |
154 BluetoothGattDescriptorBlueZ* descriptor, | |
155 const std::vector<uint8_t>& value) { | |
156 DCHECK(characteristic->GetService() == this); | |
157 DCHECK(descriptor->GetCharacteristic() == characteristic); | |
158 DCHECK(GetAdapter()); | |
159 GetAdapter()->NotifyGattDescriptorValueChanged(descriptor, value); | |
160 } | |
161 | |
162 void BluetoothRemoteGattServiceBlueZ::GattServicePropertyChanged( | |
163 const dbus::ObjectPath& object_path, | |
164 const std::string& property_name) { | |
165 if (object_path != this->object_path()) | |
166 return; | |
167 | |
168 VLOG(1) << "Service property changed: \"" << property_name << "\", " | |
169 << object_path.value(); | |
170 bluez::BluetoothGattServiceClient::Properties* properties = | |
171 bluez::BluezDBusManager::Get() | |
172 ->GetBluetoothGattServiceClient() | |
173 ->GetProperties(object_path); | |
174 DCHECK(properties); | |
175 | |
176 if (property_name != properties->characteristics.name()) { | |
177 NotifyServiceChanged(); | |
178 return; | |
179 } | |
180 | |
181 if (discovery_complete_) | |
182 return; | |
183 | |
184 VLOG(1) << "All characteristics were discovered for service: " | |
185 << object_path.value(); | |
186 discovery_complete_ = true; | |
187 DCHECK(GetAdapter()); | |
188 GetAdapter()->NotifyGattDiscoveryComplete(this); | |
189 } | |
190 | |
191 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicAdded( | |
192 const dbus::ObjectPath& object_path) { | |
193 if (characteristics_.find(object_path) != characteristics_.end()) { | |
194 VLOG(1) << "Remote GATT characteristic already exists: " | |
195 << object_path.value(); | |
196 return; | |
197 } | |
198 | |
199 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
200 bluez::BluezDBusManager::Get() | |
201 ->GetBluetoothGattCharacteristicClient() | |
202 ->GetProperties(object_path); | |
203 DCHECK(properties); | |
204 if (properties->service.value() != this->object_path()) { | |
205 VLOG(2) << "Remote GATT characteristic does not belong to this service."; | |
206 return; | |
207 } | |
208 | |
209 VLOG(1) << "Adding new remote GATT characteristic for GATT service: " | |
210 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
211 | |
212 BluetoothRemoteGattCharacteristicBlueZ* characteristic = | |
213 new BluetoothRemoteGattCharacteristicBlueZ(this, object_path); | |
214 characteristics_[object_path] = characteristic; | |
215 DCHECK(characteristic->GetIdentifier() == object_path.value()); | |
216 DCHECK(characteristic->GetUUID().IsValid()); | |
217 | |
218 DCHECK(GetAdapter()); | |
219 GetAdapter()->NotifyGattCharacteristicAdded(characteristic); | |
220 } | |
221 | |
222 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicRemoved( | |
223 const dbus::ObjectPath& object_path) { | |
224 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
225 if (iter == characteristics_.end()) { | |
226 VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value(); | |
227 return; | |
228 } | |
229 | |
230 VLOG(1) << "Removing remote GATT characteristic from service: " | |
231 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value(); | |
232 | |
233 BluetoothGattCharacteristicBlueZ* characteristic = iter->second; | |
234 DCHECK(characteristic->object_path() == object_path); | |
235 characteristics_.erase(iter); | |
236 | |
237 DCHECK(GetAdapter()); | |
238 GetAdapter()->NotifyGattCharacteristicRemoved(characteristic); | |
239 | |
240 delete characteristic; | |
241 } | |
242 | |
243 void BluetoothRemoteGattServiceBlueZ::GattCharacteristicPropertyChanged( | |
244 const dbus::ObjectPath& object_path, | |
245 const std::string& property_name) { | |
246 CharacteristicMap::iterator iter = characteristics_.find(object_path); | |
247 if (iter == characteristics_.end()) { | |
248 VLOG(3) << "Properties of unknown characteristic changed"; | |
249 return; | |
250 } | |
251 | |
252 // We may receive a property changed event in certain cases, e.g. when the | |
253 // characteristic "Flags" property has been updated with values from the | |
254 // "Characteristic Extended Properties" descriptor. In this case, kick off | |
255 // a service changed observer event to let observers refresh the | |
256 // characteristics. | |
257 bluez::BluetoothGattCharacteristicClient::Properties* properties = | |
258 bluez::BluezDBusManager::Get() | |
259 ->GetBluetoothGattCharacteristicClient() | |
260 ->GetProperties(object_path); | |
261 | |
262 DCHECK(properties); | |
263 DCHECK(GetAdapter()); | |
264 | |
265 if (property_name == properties->flags.name()) | |
266 NotifyServiceChanged(); | |
267 else if (property_name == properties->value.name()) | |
268 GetAdapter()->NotifyGattCharacteristicValueChanged( | |
269 iter->second, properties->value.value()); | |
270 } | |
271 | |
272 } // namespace bluez | |
OLD | NEW |