OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "components/proximity_auth/ble/bluetooth_low_energy_connection.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/memory/ref_counted.h" | |
9 #include "base/memory/weak_ptr.h" | |
10 #include "components/proximity_auth/connection_finder.h" | |
11 #include "components/proximity_auth/ble/fake_wire_message.h" | |
12 #include "components/proximity_auth/wire_message.h" | |
13 #include "device/bluetooth/bluetooth_adapter.h" | |
14 #include "device/bluetooth/bluetooth_device.h" | |
15 #include "device/bluetooth/bluetooth_gatt_characteristic.h" | |
16 #include "device/bluetooth/bluetooth_gatt_connection.h" | |
17 #include "device/bluetooth/bluetooth_gatt_notify_session.h" | |
18 #include "device/bluetooth/bluetooth_uuid.h" | |
19 | |
20 using device::BluetoothAdapter; | |
21 using device::BluetoothDevice; | |
22 using device::BluetoothGattConnection; | |
23 using device::BluetoothGattService; | |
24 using device::BluetoothGattCharacteristic; | |
25 using device::BluetoothGattNotifySession; | |
26 using device::BluetoothUUID; | |
27 | |
28 namespace proximity_auth { | |
29 | |
30 BluetoothLowEnergyConnection::BluetoothLowEnergyConnection( | |
31 const RemoteDevice& device, | |
32 scoped_refptr<device::BluetoothAdapter> adapter, | |
33 BluetoothUUID remote_service_uuid, | |
34 scoped_ptr<BluetoothGattConnection> gatt_connection) | |
35 : Connection(device), | |
36 adapter_(adapter), | |
37 remote_service_uuid_(remote_service_uuid), | |
38 connection_(gatt_connection.Pass()), | |
39 notify_session_pending_(false), | |
40 weak_ptr_factory_(this) { | |
41 if (connection_) { | |
msarda
2015/05/05 11:56:13
Can |connection_| be null? If not, then it is bett
sacomoto
2015/05/06 13:47:58
Done.
| |
42 SetStatus(IN_PROGRESS); | |
43 } | |
44 | |
45 if (adapter_) { | |
msarda
2015/05/05 11:56:14
DCHECK(adapter_)?
sacomoto
2015/05/06 13:47:58
Done.
| |
46 adapter_->AddObserver(this); | |
47 } | |
48 } | |
49 | |
50 BluetoothLowEnergyConnection::~BluetoothLowEnergyConnection() { | |
51 Disconnect(); | |
52 if (adapter_) { | |
53 adapter_->RemoveObserver(this); | |
54 adapter_ = NULL; | |
55 } | |
56 } | |
57 | |
58 void BluetoothLowEnergyConnection::Connect() { | |
59 NOTREACHED(); | |
60 } | |
61 | |
62 void BluetoothLowEnergyConnection::Disconnect() { | |
63 StopNotifySession(); | |
64 if (connection_) { | |
65 connection_.reset(); | |
66 BluetoothDevice* device = GetRemoteDevice(); | |
67 if (device) { | |
68 VLOG(1) << "Forget device " << device->GetAddress(); | |
69 device->Forget(base::Bind(&base::DoNothing)); | |
msarda
2015/05/05 11:56:14
Please add a comment that disconnect actually forg
sacomoto
2015/05/06 13:47:58
Done.
| |
70 } | |
71 } | |
72 } | |
73 | |
74 // TODO(sacomoto): Send a Socketeer incoming signal. Implement a sender with | |
msarda
2015/05/05 11:56:13
Remove all reference to Socketeer.
sacomoto
2015/05/06 13:47:58
Done.
| |
75 // full support for messages larger than a single characteristic value. | |
76 void BluetoothLowEnergyConnection::SendMessageImpl( | |
77 scoped_ptr<WireMessage> message) { | |
78 DCHECK(!GetGattCharacteristic(to_peripheral_char_id_)); | |
79 VLOG(1) << "Sending message " << message->Serialize(); | |
80 | |
81 std::string serialized_message = message->Serialize(); | |
82 std::vector<uint8> bytes(serialized_message.begin(), | |
83 serialized_message.end()); | |
84 | |
85 GetGattCharacteristic(to_peripheral_char_id_) | |
86 ->WriteRemoteCharacteristic( | |
87 bytes, base::Bind(&base::DoNothing), | |
88 base::Bind( | |
89 &BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError, | |
90 weak_ptr_factory_.GetWeakPtr())); | |
91 } | |
92 | |
93 void BluetoothLowEnergyConnection::DeviceRemoved(BluetoothAdapter* adapter, | |
94 BluetoothDevice* device) { | |
95 if (device && device->GetAddress() == remote_device_address()) { | |
96 VLOG(1) << "device removed " << remote_device_address(); | |
msarda
2015/05/05 11:56:13
Log should state with CAPS:
s/device/Device
sacomoto
2015/05/06 13:47:57
Done.
| |
97 Disconnect(); | |
98 } | |
99 } | |
100 | |
101 void BluetoothLowEnergyConnection::GattDiscoveryCompleteForService( | |
102 BluetoothAdapter* adapter, | |
103 BluetoothGattService* service) { | |
104 if (service && service->GetUUID() == remote_service_uuid_) { | |
105 VLOG(1) << "All characteristics discovered for " | |
106 << remote_service_uuid_.canonical_value(); | |
107 | |
108 std::vector<device::BluetoothGattCharacteristic*> characteristics = | |
109 service->GetCharacteristics(); | |
110 for (auto iter = characteristics.begin(); iter != characteristics.end(); | |
111 iter++) { | |
112 HandleCharacteristicUpdate(*iter); | |
113 } | |
114 | |
115 if (to_peripheral_char_id_.empty() || from_peripheral_char_id_.empty()) { | |
116 VLOG(1) << "Connection error, missing characteristics for service."; | |
msarda
2015/05/05 11:56:13
s/service/Smart Lock service
msarda
2015/05/05 11:56:13
Please also log which one of |to_peripheral_char_i
sacomoto
2015/05/06 13:47:58
Done.
sacomoto
2015/05/06 13:47:58
Done.
| |
117 Disconnect(); | |
118 } | |
119 } | |
120 } | |
121 | |
122 void BluetoothLowEnergyConnection::GattCharacteristicAdded( | |
123 BluetoothAdapter* adapter, | |
124 BluetoothGattCharacteristic* characteristic) { | |
125 VLOG(1) << "new char found: " << characteristic->GetUUID().canonical_value(); | |
126 HandleCharacteristicUpdate(characteristic); | |
127 } | |
128 | |
129 // TODO(sacomoto): Parse the Sockeeter incoming signal. Implement a receiver | |
msarda
2015/05/05 11:56:13
Remove Socketeer.
sacomoto
2015/05/06 13:47:58
Done.
| |
130 // with full suport for messages larger than a single characteristic value. | |
131 void BluetoothLowEnergyConnection::GattCharacteristicValueChanged( | |
132 BluetoothAdapter* adapter, | |
133 BluetoothGattCharacteristic* characteristic, | |
134 const std::vector<uint8>& value) { | |
135 VLOG(1) << "Characteristic value changed: " | |
136 << characteristic->GetUUID().canonical_value(); | |
137 if (characteristic->GetIdentifier() == from_peripheral_char_id_) { | |
138 std::string message(value.begin(), value.end()); | |
139 VLOG(1) << "value: " << message; | |
140 // TODO(sacomoto): Actually handle the message and call OnBytesReceived when | |
141 // complete. | |
142 } | |
143 } | |
144 | |
145 scoped_ptr<WireMessage> BluetoothLowEnergyConnection::DeserializeWireMessage( | |
146 bool* is_incomplete_message) { | |
147 return FakeWireMessage::Deserialize(received_bytes(), is_incomplete_message); | |
148 } | |
149 | |
150 void BluetoothLowEnergyConnection::HandleCharacteristicUpdate( | |
151 BluetoothGattCharacteristic* characteristic) { | |
152 // Checks if |characteristic| is equal to |from_peripheral_char_| or | |
153 // |to_peripheral_char_| are present. | |
154 UpdateCharacteristicsStatus(characteristic); | |
155 | |
156 // Starts a notify session for |from_peripheral_char_|. | |
157 if (characteristic->GetIdentifier() == from_peripheral_char_id_) | |
158 StartNotifySession(); | |
159 | |
160 // Checks if the connection is complete. | |
161 CompleteConnection(); | |
162 } | |
163 | |
164 void BluetoothLowEnergyConnection::CompleteConnection() { | |
165 if (status() == IN_PROGRESS && !to_peripheral_char_id_.empty() && | |
166 !from_peripheral_char_id_.empty() && notify_session_) { | |
167 VLOG(1) << "Connection completed"; | |
168 SetStatus(CONNECTED); | |
169 SendInviteToConnectSignal(); | |
msarda
2015/05/05 11:56:13
Should we wait for a reply to invite signal before
sacomoto
2015/05/06 13:47:58
Done.
| |
170 } | |
171 } | |
172 | |
173 void BluetoothLowEnergyConnection::StartNotifySession() { | |
174 BluetoothGattCharacteristic* characteristic = | |
175 GetGattCharacteristic(from_peripheral_char_id_); | |
176 if (!characteristic) { | |
177 VLOG(1) << "Characteristic " << from_peripheral_char_ << " not found."; | |
178 return; | |
179 } | |
180 | |
181 if (notify_session_ || notify_session_pending_) { | |
182 VLOG(1) << "Notify session already started."; | |
183 return; | |
184 } | |
185 | |
186 notify_session_pending_ = true; | |
187 characteristic->StartNotifySession( | |
188 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionStarted, | |
189 weak_ptr_factory_.GetWeakPtr()), | |
190 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionError, | |
191 weak_ptr_factory_.GetWeakPtr())); | |
192 } | |
193 | |
194 void BluetoothLowEnergyConnection::OnNotifySessionError( | |
195 BluetoothGattService::GattErrorCode error) { | |
196 VLOG(1) << "Error starting notification session: " << error; | |
197 notify_session_pending_ = false; | |
198 } | |
199 | |
200 void BluetoothLowEnergyConnection::OnNotifySessionStarted( | |
201 scoped_ptr<BluetoothGattNotifySession> notify_session) { | |
202 VLOG(1) << "Notification session started " | |
203 << notify_session->GetCharacteristicIdentifier(); | |
204 notify_session_ = notify_session.Pass(); | |
205 notify_session_pending_ = false; | |
206 | |
207 // Checks if the connection is complete. | |
208 CompleteConnection(); | |
209 } | |
210 | |
211 void BluetoothLowEnergyConnection::StopNotifySession() { | |
212 if (notify_session_) { | |
213 notify_session_->Stop(base::Bind(&base::DoNothing)); | |
214 notify_session_.reset(); | |
215 } | |
216 } | |
217 | |
218 void BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError( | |
219 BluetoothGattService::GattErrorCode error) { | |
220 VLOG(1) << "Error writing characteristic" << to_peripheral_char_; | |
221 } | |
222 | |
223 void BluetoothLowEnergyConnection::SendInviteToConnectSignal() { | |
224 // From Socketeer library: connect signal is 0 (32-bit int). | |
225 const char connect_signal[4] = {}; | |
226 SendMessage(scoped_ptr<FakeWireMessage>(new FakeWireMessage(connect_signal))); | |
227 } | |
228 | |
229 void BluetoothLowEnergyConnection::UpdateCharacteristicsStatus( | |
230 BluetoothGattCharacteristic* characteristic) { | |
231 if (characteristic) { | |
232 std::string canonical_value = characteristic->GetUUID().canonical_value(); | |
233 VLOG(1) << canonical_value; | |
234 if (to_peripheral_char_ == canonical_value) { | |
235 to_peripheral_char_id_ = characteristic->GetIdentifier(); | |
236 } | |
237 if (from_peripheral_char_ == canonical_value) { | |
238 from_peripheral_char_id_ = characteristic->GetIdentifier(); | |
239 } | |
240 BluetoothGattService* service = characteristic->GetService(); | |
241 if (service && service->GetUUID() == remote_service_uuid_) | |
242 remote_service_id_ = service->GetIdentifier(); | |
243 } | |
244 } | |
245 | |
246 BluetoothDevice* BluetoothLowEnergyConnection::GetRemoteDevice() { | |
247 if (!adapter_ || !adapter_->IsInitialized()) { | |
248 VLOG(1) << "adapter not ready"; | |
249 return NULL; | |
250 } | |
251 return adapter_->GetDevice(remote_device_address()); | |
252 } | |
253 | |
254 BluetoothGattService* BluetoothLowEnergyConnection::GetRemoteService() { | |
255 BluetoothDevice* remote_device = GetRemoteDevice(); | |
256 if (!remote_device) { | |
257 VLOG(1) << "device not found"; | |
258 return NULL; | |
259 } | |
260 return remote_device->GetGattService(remote_service_id_); | |
261 } | |
262 | |
263 BluetoothGattCharacteristic* | |
264 BluetoothLowEnergyConnection::GetGattCharacteristic( | |
265 const std::string& gatt_characteristic) { | |
266 BluetoothGattService* remote_service = GetRemoteService(); | |
267 if (!remote_service) { | |
268 VLOG(1) << "service not found"; | |
269 return NULL; | |
270 } | |
271 return remote_service->GetCharacteristic(gatt_characteristic); | |
272 } | |
273 | |
274 } // namespace proximity_auth | |
OLD | NEW |