blob: b0441a64362321d8e314015f01980619b025ac50 [file] [log] [blame]
Ian Coolidge611fcf92015-06-03 17:20:30 -07001//
2// Copyright (C) 2015 Google, Inc.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Marie Janssen49a86702015-07-08 11:48:57 -070016
Arman Uguray0f2d4892015-09-22 14:20:42 -070017#include "service/gatt_server.h"
Marie Janssen49a86702015-07-08 11:48:57 -070018
Arman Uguray234138e2015-10-06 15:56:36 -070019#include "service/common/bluetooth/util/address_helper.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070020#include "service/hal/gatt_helpers.h"
Arman Uguray514bf602015-09-29 19:38:03 -070021#include "service/logging_helpers.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070022
Arman Uguray0f2d4892015-09-22 14:20:42 -070023using std::lock_guard;
24using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070025
26namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070027
Arman Uguray514bf602015-09-29 19:38:03 -070028namespace {
29
30bool operator==(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
31 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
32}
33
34bool operator!=(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
35 return !(lhs == rhs);
36}
37
38} // namespace
39
Arman Uguray0f2d4892015-09-22 14:20:42 -070040// GattServer implementation
41// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070042
Arman Uguraybb18c412015-11-12 13:44:31 -080043GattServer::GattServer(const UUID& uuid, int server_id)
Arman Uguray0f2d4892015-09-22 14:20:42 -070044 : app_identifier_(uuid),
Arman Uguraybb18c412015-11-12 13:44:31 -080045 server_id_(server_id),
Arman Uguray514bf602015-09-29 19:38:03 -070046 delegate_(nullptr) {
Ian Coolidge611fcf92015-06-03 17:20:30 -070047}
48
Arman Uguray0f2d4892015-09-22 14:20:42 -070049GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070050 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080051 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070052
53 // Unregister as observer so we no longer receive any callbacks.
54 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
55
56 // Unregister this server, stop all services, and ignore the result.
57 // TODO(armansito): stop and remove all services here? unregister_server
58 // should really take care of that.
Arman Uguray0f2d4892015-09-22 14:20:42 -070059 hal::BluetoothGattInterface::Get()->
Arman Uguraybb18c412015-11-12 13:44:31 -080060 GetServerHALInterface()->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070061}
62
Arman Uguray514bf602015-09-29 19:38:03 -070063void GattServer::SetDelegate(Delegate* delegate) {
64 lock_guard<mutex> lock(mutex_);
65 delegate_ = delegate;
66}
67
Arman Uguray0f2d4892015-09-22 14:20:42 -070068const UUID& GattServer::GetAppIdentifier() const {
69 return app_identifier_;
70}
Ian Coolidge611fcf92015-06-03 17:20:30 -070071
Arman Uguraybb18c412015-11-12 13:44:31 -080072int GattServer::GetInstanceId() const {
73 return server_id_;
Arman Uguray0f2d4892015-09-22 14:20:42 -070074}
Ian Coolidge611fcf92015-06-03 17:20:30 -070075
Arman Uguraydf0b2712015-09-23 17:25:54 -070076std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration(
77 const UUID& uuid, bool is_primary) {
Arman Uguraybb18c412015-11-12 13:44:31 -080078 VLOG(1) << __func__ << " server_id: " << server_id_
Arman Uguraydf0b2712015-09-23 17:25:54 -070079 << " - UUID: " << uuid.ToString()
80 << ", is_primary: " << is_primary;
81 lock_guard<mutex> lock(mutex_);
82
83 if (pending_decl_) {
84 LOG(ERROR) << "Already began service declaration";
85 return nullptr;
86 }
87
88 CHECK(!pending_id_);
89 CHECK(!pending_decl_);
90 CHECK(!pending_end_decl_cb_);
91
Arman Ugurayd9b05522015-09-25 19:31:24 -070092 auto service_id = GetIdForService(uuid, is_primary);
93 CHECK(service_id);
Arman Uguraydf0b2712015-09-23 17:25:54 -070094
Arman Uguray91613742015-09-24 22:45:16 -070095 // Pass 0 for permissions and properties as this is a service decl.
96 AttributeEntry entry(
97 *service_id, kCharacteristicPropertyNone, kAttributePermissionNone);
98
Arman Uguraydf0b2712015-09-23 17:25:54 -070099 pending_decl_.reset(new ServiceDeclaration());
100 pending_decl_->num_handles++; // 1 handle for the service decl. attribute
101 pending_decl_->service_id = *service_id;
Arman Uguray91613742015-09-24 22:45:16 -0700102 pending_decl_->attributes.push_back(entry);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700103
104 return service_id;
105}
106
Arman Uguray91613742015-09-24 22:45:16 -0700107std::unique_ptr<GattIdentifier> GattServer::AddCharacteristic(
108 const UUID& uuid, int properties, int permissions) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800109 VLOG(1) << __func__ << " server_id: " << server_id_
Arman Uguray91613742015-09-24 22:45:16 -0700110 << " - UUID: " << uuid.ToString()
111 << ", properties: " << properties
112 << ", permissions: " << permissions;
113 lock_guard<mutex> lock(mutex_);
114
115 if (!pending_decl_) {
116 LOG(ERROR) << "Service declaration not begun";
117 return nullptr;
118 }
119
Arman Ugurayd9b05522015-09-25 19:31:24 -0700120 if (pending_end_decl_cb_) {
121 LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
122 return nullptr;
Arman Uguray91613742015-09-24 22:45:16 -0700123 }
124
Arman Ugurayd9b05522015-09-25 19:31:24 -0700125 auto char_id = GetIdForCharacteristic(uuid);
126 CHECK(char_id);
Arman Uguray91613742015-09-24 22:45:16 -0700127 AttributeEntry entry(*char_id, properties, permissions);
128
129 // 2 handles for the characteristic declaration and the value attributes.
130 pending_decl_->num_handles += 2;
131 pending_decl_->attributes.push_back(entry);
132
133 return char_id;
134}
135
Arman Ugurayd9b05522015-09-25 19:31:24 -0700136std::unique_ptr<GattIdentifier> GattServer::AddDescriptor(
137 const UUID& uuid, int permissions) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800138 VLOG(1) << __func__ << " server_id: " << server_id_
Arman Ugurayd9b05522015-09-25 19:31:24 -0700139 << " - UUID: " << uuid.ToString()
140 << ", permissions: " << permissions;
141 lock_guard<mutex> lock(mutex_);
142
143 if (!pending_decl_) {
144 LOG(ERROR) << "Service declaration not begun";
145 return nullptr;
146 }
147
148 if (pending_end_decl_cb_) {
149 LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
150 return nullptr;
151 }
152
153 auto desc_id = GetIdForDescriptor(uuid);
154 if (!desc_id)
155 return nullptr;
156
157 AttributeEntry entry(*desc_id, kCharacteristicPropertyNone, permissions);
158
159 // 1 handle for the descriptor attribute.
160 pending_decl_->num_handles += 1;
161 pending_decl_->attributes.push_back(entry);
162
163 return desc_id;
164}
165
Arman Uguraydf0b2712015-09-23 17:25:54 -0700166bool GattServer::EndServiceDeclaration(const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800167 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700168 lock_guard<mutex> lock(mutex_);
169
170 if (!callback) {
171 LOG(ERROR) << "|callback| cannot be NULL";
172 return false;
173 }
174
175 if (!pending_decl_) {
176 LOG(ERROR) << "Service declaration not begun";
177 return false;
178 }
179
180 if (pending_end_decl_cb_) {
181 LOG(ERROR) << "EndServiceDeclaration already in progress";
182 return false;
183 }
184
185 CHECK(!pending_id_);
186
187 // There has to be at least one entry here for the service declaration
188 // attribute.
189 CHECK(pending_decl_->num_handles > 0);
190 CHECK(!pending_decl_->attributes.empty());
191
192 std::unique_ptr<GattIdentifier> service_id = PopNextId();
193 CHECK(service_id->IsService());
194 CHECK(*service_id == pending_decl_->service_id);
195
196 btgatt_srvc_id_t hal_id;
197 hal::GetHALServiceId(*service_id, &hal_id);
198
199 bt_status_t status = hal::BluetoothGattInterface::Get()->
200 GetServerHALInterface()->add_service(
Arman Uguraybb18c412015-11-12 13:44:31 -0800201 server_id_, &hal_id, pending_decl_->num_handles);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700202 if (status != BT_STATUS_SUCCESS) {
203 LOG(ERROR) << "Failed to initiate call to populate GATT service";
204 CleanUpPendingData();
205 return false;
206 }
207
208 pending_id_ = std::move(service_id);
209 pending_end_decl_cb_ = callback;
210
211 return true;
212}
213
Arman Ugurayd9b05522015-09-25 19:31:24 -0700214std::unique_ptr<GattIdentifier> GattServer::GetIdForService(
215 const UUID& uuid, bool is_primary) {
216 // Calculate the instance ID for this service by searching through the handle
217 // map to see how many occurrences of the same service UUID we find.
218 int inst_id = 0;
Arman Uguray514bf602015-09-29 19:38:03 -0700219 for (const auto& iter : id_to_handle_map_) {
Arman Ugurayd9b05522015-09-25 19:31:24 -0700220 const GattIdentifier* gatt_id = &iter.first;
221
222 if (!gatt_id->IsService())
223 continue;
224
225 if (gatt_id->service_uuid() == uuid)
226 ++inst_id;
227 }
228
229 // Pass empty string for the address as this is a local service.
230 return GattIdentifier::CreateServiceId("", inst_id, uuid, is_primary);
231}
232
233std::unique_ptr<GattIdentifier> GattServer::GetIdForCharacteristic(
234 const UUID& uuid) {
235 CHECK(pending_decl_);
236
237 // Calculate the instance ID for this characteristic by searching through the
238 // pending entries.
239 int inst_id = 0;
240 for (const auto& entry : pending_decl_->attributes) {
241 const GattIdentifier& gatt_id = entry.id;
242
243 if (!gatt_id.IsCharacteristic())
244 continue;
245
246 if (gatt_id.characteristic_uuid() == uuid)
247 ++inst_id;
248 }
249
250 CHECK(pending_decl_->service_id.IsService());
251
252 return GattIdentifier::CreateCharacteristicId(
253 inst_id, uuid, pending_decl_->service_id);
254}
255
256std::unique_ptr<GattIdentifier> GattServer::GetIdForDescriptor(
257 const UUID& uuid) {
258 CHECK(pending_decl_);
259
260 // Calculate the instance ID for this descriptor by searching through the
261 // pending entries. We iterate in reverse until we find a characteristic
262 // entry.
263 CHECK(!pending_decl_->attributes.empty());
264 int inst_id = 0;
265 bool char_found = false;
266 GattIdentifier char_id;
267 for (auto iter = pending_decl_->attributes.end() - 1;
268 iter != pending_decl_->attributes.begin(); // Begin is always a service
269 --iter) {
270 const GattIdentifier& gatt_id = iter->id;
271
272 if (gatt_id.IsCharacteristic()) {
273 // Found the owning characteristic.
274 char_found = true;
275 char_id = gatt_id;
276 break;
277 }
278
279 if (!gatt_id.IsDescriptor()) {
280 // A descriptor must be preceded by a descriptor or a characteristic.
281 LOG(ERROR) << "Descriptors must come directly after a characteristic or "
282 << "another descriptor.";
283 return nullptr;
284 }
285
286 if (gatt_id.descriptor_uuid() == uuid)
287 ++inst_id;
288 }
289
290 if (!char_found) {
291 LOG(ERROR) << "No characteristic found to add the descriptor to.";
292 return nullptr;
293 }
294
295 return GattIdentifier::CreateDescriptorId(inst_id, uuid, char_id);
296}
297
Arman Uguray514bf602015-09-29 19:38:03 -0700298bool GattServer::SendResponse(
299 const std::string& device_address, int request_id,
300 GATTError error, int offset,
301 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800302 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700303 << " device_address: " << device_address
304 << " request_id: " << request_id
305 << " error: " << error
306 << " offset: " << offset;
307 lock_guard<mutex> lock(mutex_);
308
309 bt_bdaddr_t addr;
310 if (!util::BdAddrFromString(device_address, &addr)) {
311 LOG(ERROR) << "Invalid device address given: " << device_address;
312 return false;
313 }
314
315 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
316 LOG(ERROR) << "Value is too large";
317 return false;
318 }
319
320 // Find the correct connection ID for |device_address| and |request_id|.
321 auto iter = conn_addr_map_.find(device_address);
322 if (iter == conn_addr_map_.end()) {
323 LOG(ERROR) << "No known connections for device address: " << device_address;
324 return false;
325 }
326
327 std::shared_ptr<Connection> connection;
328 for (auto tmp : iter->second) {
329 if (tmp->request_id_to_handle.find(request_id) ==
330 tmp->request_id_to_handle.end())
331 continue;
332
333 connection = tmp;
334 }
335
336 if (!connection) {
337 LOG(ERROR) << "Pending request with ID " << request_id
338 << " not found for device with BD_ADDR: " << device_address;
339 return false;
340 }
341
342 btgatt_response_t response;
343 memset(&response, 0, sizeof(response));
344
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700345 // We keep -1 as the handle for "Execute Write Request". In that case,
346 // there is no need to populate the response data. Just send zeros back.
347 int handle = connection->request_id_to_handle[request_id];
348 response.handle = handle;
349 response.attr_value.handle = handle;
350 if (handle != -1) {
351 memcpy(response.attr_value.value, value.data(), value.size());
352 response.attr_value.offset = offset;
353 response.attr_value.len = value.size();
354 }
Arman Uguray514bf602015-09-29 19:38:03 -0700355
356 bt_status_t result = hal::BluetoothGattInterface::Get()->
357 GetServerHALInterface()->send_response(
358 connection->conn_id, request_id, error, &response);
359 if (result != BT_STATUS_SUCCESS) {
360 LOG(ERROR) << "Failed to initiate call to send GATT response";
361 return false;
362 }
363
364 connection->request_id_to_handle.erase(request_id);
365
366 return true;
367}
368
Arman Uguraycd644e32015-10-01 16:36:38 -0700369bool GattServer::SendNotification(
370 const std::string& device_address,
371 const GattIdentifier& characteristic_id,
372 bool confirm,
373 const std::vector<uint8_t>& value,
374 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800375 VLOG(1) << " - server_id: " << server_id_
Arman Uguraycd644e32015-10-01 16:36:38 -0700376 << " device_address: " << device_address
377 << " confirm: " << confirm;
378 lock_guard<mutex> lock(mutex_);
379
380 bt_bdaddr_t addr;
381 if (!util::BdAddrFromString(device_address, &addr)) {
382 LOG(ERROR) << "Invalid device address given: " << device_address;
383 return false;
384 }
385
386 // Get the connection IDs for which we will send this notification.
387 auto conn_iter = conn_addr_map_.find(device_address);
388 if (conn_iter == conn_addr_map_.end()) {
389 LOG(ERROR) << "No known connections for device with address: "
390 << device_address;
391 return false;
392 }
393
394 // Make sure that |characteristic_id| matches a valid attribute handle.
395 auto handle_iter = id_to_handle_map_.find(characteristic_id);
396 if (handle_iter == id_to_handle_map_.end()) {
397 LOG(ERROR) << "Unknown characteristic";
398 return false;
399 }
400
401 std::shared_ptr<PendingIndication> pending_ind(
402 new PendingIndication(callback));
403
404 // Send the notification/indication on all matching connections.
405 int send_count = 0;
406 for (auto conn : conn_iter->second) {
407 // Make sure that one isn't already pending for this connection.
408 if (pending_indications_.find(conn->conn_id) !=
409 pending_indications_.end()) {
410 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
411 << " is already pending for connection: " << conn->conn_id;
412 continue;
413 }
414
415 // The HAL API takes char* rather const char* for |value|, so we have to
416 // cast away the const.
417 // TODO(armansito): Make HAL accept const char*.
418 bt_status_t status = hal::BluetoothGattInterface::Get()->
419 GetServerHALInterface()->send_indication(
Arman Uguraybb18c412015-11-12 13:44:31 -0800420 server_id_,
Arman Uguraycd644e32015-10-01 16:36:38 -0700421 handle_iter->second,
422 conn->conn_id,
Arman Uguraycd644e32015-10-01 16:36:38 -0700423 confirm,
Jakub Pawlowskiec79baa2016-05-27 15:48:03 -0700424 value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700425
426 // Increment the send count if this was successful. We don't immediately
427 // fail if the HAL returned an error. It's better to report success as long
428 // as we sent out at least one notification to this device as
429 // multi-transport GATT connections from the same BD_ADDR will be rare
430 // enough already.
431 if (status != BT_STATUS_SUCCESS)
432 continue;
433
434 send_count++;
435 pending_indications_[conn->conn_id] = pending_ind;
436 }
437
438 if (send_count == 0) {
439 LOG(ERROR) << "Failed to send notifications/indications to device: "
440 << device_address;
441 return false;
442 }
443
444 return true;
445}
446
Arman Uguray514bf602015-09-29 19:38:03 -0700447void GattServer::ConnectionCallback(
448 hal::BluetoothGattInterface* /* gatt_iface */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800449 int conn_id, int server_id,
Arman Uguray514bf602015-09-29 19:38:03 -0700450 int connected,
451 const bt_bdaddr_t& bda) {
452 lock_guard<mutex> lock(mutex_);
453
Arman Uguraybb18c412015-11-12 13:44:31 -0800454 if (server_id != server_id_)
Arman Uguray514bf602015-09-29 19:38:03 -0700455 return;
456
457 std::string device_address = BtAddrString(&bda);
458
459 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
460 << " BD_ADDR: " << device_address;
461
462 if (!connected) {
463 // Erase the entry if we were connected to it.
464 VLOG(1) << "No longer connected: " << device_address;
465 conn_id_map_.erase(conn_id);
466 auto iter = conn_addr_map_.find(device_address);
467 if (iter == conn_addr_map_.end())
468 return;
469
470 // Remove the appropriate connection objects in the address.
471 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
472 ++conn_iter) {
473 if ((*conn_iter)->conn_id != conn_id)
474 continue;
475
476 iter->second.erase(conn_iter);
477 break;
478 }
479
Jakub Pawlowski79327272016-07-07 16:40:11 -0700480 if (delegate_)
481 delegate_->OnConnectionStateChanged(this, device_address, false);
482
Arman Uguray514bf602015-09-29 19:38:03 -0700483 return;
484 }
485
486 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
487 LOG(WARNING) << "Connection entry already exists; "
488 << "ignoring ConnectionCallback";
489 return;
490 }
491
492 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
493 << " device address: " << device_address;
494 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
495 conn_id_map_[conn_id] = connection;
496 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700497
498 if (delegate_)
499 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700500}
501
Arman Uguraydf0b2712015-09-23 17:25:54 -0700502void GattServer::ServiceAddedCallback(
503 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800504 int status, int server_id,
Arman Uguraydf0b2712015-09-23 17:25:54 -0700505 const btgatt_srvc_id_t& srvc_id,
Arman Uguray91613742015-09-24 22:45:16 -0700506 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700507 lock_guard<mutex> lock(mutex_);
508
Arman Uguraybb18c412015-11-12 13:44:31 -0800509 if (server_id != server_id_)
Arman Uguraydf0b2712015-09-23 17:25:54 -0700510 return;
511
512 // Construct a GATT identifier.
513 auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
514 CHECK(pending_id_);
515 CHECK(*gatt_id == *pending_id_);
516 CHECK(*gatt_id == pending_decl_->service_id);
517 CHECK(pending_id_->IsService());
518
Arman Uguray91613742015-09-24 22:45:16 -0700519 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800520 << " server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700521 << " handle: " << service_handle
Arman Uguraydf0b2712015-09-23 17:25:54 -0700522 << " UUID: " << gatt_id->service_uuid().ToString();
523
524 if (status != BT_STATUS_SUCCESS) {
525 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
526 return;
527 }
528
529 // Add this to the handle map.
Arman Uguray91613742015-09-24 22:45:16 -0700530 pending_handle_map_[*gatt_id] = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700531 CHECK(-1 == pending_decl_->service_handle);
Arman Uguray91613742015-09-24 22:45:16 -0700532 pending_decl_->service_handle = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700533
Arman Uguray91613742015-09-24 22:45:16 -0700534 HandleNextEntry(gatt_iface);
535}
Arman Uguraydf0b2712015-09-23 17:25:54 -0700536
Arman Uguray91613742015-09-24 22:45:16 -0700537void GattServer::CharacteristicAddedCallback(
538 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800539 int status, int server_id,
Arman Uguray91613742015-09-24 22:45:16 -0700540 const bt_uuid_t& uuid,
541 int service_handle,
542 int char_handle) {
543 lock_guard<mutex> lock(mutex_);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700544
Arman Uguraybb18c412015-11-12 13:44:31 -0800545 if (server_id != server_id_)
Arman Uguray91613742015-09-24 22:45:16 -0700546 return;
547
548 CHECK(pending_decl_);
549 CHECK(pending_decl_->service_handle == service_handle);
550 CHECK(pending_id_);
551 CHECK(pending_id_->IsCharacteristic());
552 CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
553
554 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800555 << " server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700556 << " service_handle: " << service_handle
557 << " char_handle: " << char_handle;
558
559 if (status != BT_STATUS_SUCCESS) {
560 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
561 pending_decl_->service_id);
562 return;
563 }
564
565 // Add this to the handle map and continue.
566 pending_handle_map_[*pending_id_] = char_handle;
567 HandleNextEntry(gatt_iface);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700568}
569
Arman Ugurayd9b05522015-09-25 19:31:24 -0700570void GattServer::DescriptorAddedCallback(
571 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800572 int status, int server_id,
Arman Ugurayd9b05522015-09-25 19:31:24 -0700573 const bt_uuid_t& uuid,
574 int service_handle,
575 int desc_handle) {
576 lock_guard<mutex> lock(mutex_);
577
Arman Uguraybb18c412015-11-12 13:44:31 -0800578 if (server_id != server_id_)
Arman Ugurayd9b05522015-09-25 19:31:24 -0700579 return;
580
581 CHECK(pending_decl_);
582 CHECK(pending_decl_->service_handle == service_handle);
583 CHECK(pending_id_);
584 CHECK(pending_id_->IsDescriptor());
585 CHECK(pending_id_->descriptor_uuid() == UUID(uuid));
586
587 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800588 << " server_id: " << server_id
Arman Ugurayd9b05522015-09-25 19:31:24 -0700589 << " service_handle: " << service_handle
590 << " desc_handle: " << desc_handle;
591
592 if (status != BT_STATUS_SUCCESS) {
593 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
594 pending_decl_->service_id);
595 return;
596 }
597
598 // Add this to the handle map and contiue.
599 pending_handle_map_[*pending_id_] = desc_handle;
600 HandleNextEntry(gatt_iface);
601}
602
Arman Uguraydf0b2712015-09-23 17:25:54 -0700603void GattServer::ServiceStartedCallback(
604 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800605 int status, int server_id,
Arman Uguray91613742015-09-24 22:45:16 -0700606 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700607 lock_guard<mutex> lock(mutex_);
608
Arman Uguraybb18c412015-11-12 13:44:31 -0800609 if (server_id != server_id_)
Arman Uguraydf0b2712015-09-23 17:25:54 -0700610 return;
611
612 CHECK(pending_id_);
613 CHECK(pending_decl_);
Arman Uguray91613742015-09-24 22:45:16 -0700614 CHECK(pending_decl_->service_handle == service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700615
Arman Uguraybb18c412015-11-12 13:44:31 -0800616 VLOG(1) << __func__ << " - server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700617 << " handle: " << service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700618
619 // If we failed to start the service, remove it from the database and ignore
620 // the result.
621 if (status != BT_STATUS_SUCCESS) {
622 gatt_iface->GetServerHALInterface()->delete_service(
Arman Uguraybb18c412015-11-12 13:44:31 -0800623 server_id_, service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700624 }
625
626 // Complete the operation.
627 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
628 pending_decl_->service_id);
629}
630
631void GattServer::ServiceStoppedCallback(
632 hal::BluetoothGattInterface* /* gatt_iface */,
633 int /* status */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800634 int /* server_id */,
Arman Uguray91613742015-09-24 22:45:16 -0700635 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700636 // TODO(armansito): Support stopping a service.
637}
638
Arman Uguray514bf602015-09-29 19:38:03 -0700639void GattServer::RequestReadCallback(
640 hal::BluetoothGattInterface* /* gatt_iface */,
641 int conn_id, int trans_id,
642 const bt_bdaddr_t& bda,
643 int attribute_handle, int offset,
644 bool is_long) {
645 lock_guard<mutex> lock(mutex_);
646
647 // Check to see if we know about this connection. Otherwise ignore the
648 // request.
649 auto conn = GetConnection(conn_id, bda, trans_id);
650 if (!conn)
651 return;
652
653 std::string device_address = BtAddrString(&bda);
654
655 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
656 << " BD_ADDR: " << device_address
657 << " attribute_handle: " << attribute_handle << " offset: " << offset
658 << " is_long: " << is_long;
659
660 // Make sure that the handle is valid.
661 auto iter = handle_to_id_map_.find(attribute_handle);
662 if (iter == handle_to_id_map_.end()) {
663 LOG(ERROR) << "Request received for unknown handle: " << attribute_handle;
664 return;
665 }
666
667 conn->request_id_to_handle[trans_id] = attribute_handle;
668
669 // If there is no delegate then there is nobody to handle request. The request
670 // will eventually timeout and we should get a connection update that
671 // terminates the connection.
672 if (!delegate_) {
673 // TODO(armansito): Require a delegate at server registration so that this
674 // is never possible.
675 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
676 << "will time out.";
677 return;
678 }
679
680 if (iter->second.IsCharacteristic()) {
681 delegate_->OnCharacteristicReadRequest(
682 this, device_address, trans_id, offset, is_long, iter->second);
683 } else if (iter->second.IsDescriptor()) {
684 delegate_->OnDescriptorReadRequest(
685 this, device_address, trans_id, offset, is_long, iter->second);
686 } else {
687 // Our API only delegates to applications those read requests for
688 // characteristic value and descriptor attributes. Everything else should be
689 // handled by the stack.
690 LOG(WARNING) << "Read request received for unsupported attribute";
691 }
692}
693
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700694void GattServer::RequestWriteCallback(
695 hal::BluetoothGattInterface* /* gatt_iface */,
696 int conn_id, int trans_id,
697 const bt_bdaddr_t& bda,
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700698 int attr_handle, int offset,
699 bool need_rsp, bool is_prep,
700 vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700701 lock_guard<mutex> lock(mutex_);
702
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700703 // Check to see if we know about this connection. Otherwise ignore the
704 // request.
705 auto conn = GetConnection(conn_id, bda, trans_id);
706 if (!conn)
707 return;
708
709 std::string device_address = BtAddrString(&bda);
710
711 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
712 << " BD_ADDR: " << device_address
713 << " attr_handle: " << attr_handle << " offset: " << offset
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700714 << " length: " << value.size() << " need_rsp: " << need_rsp
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700715 << " is_prep: " << is_prep;
716
717 // Make sure that the handle is valid.
718 auto iter = handle_to_id_map_.find(attr_handle);
719 if (iter == handle_to_id_map_.end()) {
720 LOG(ERROR) << "Request received for unknown handle: " << attr_handle;
721 return;
722 }
723
724 // Store the request ID only if this is not a write-without-response. If
725 // another request occurs after this with the same request ID, then we'll
726 // simply process it normally, though that shouldn't ever happen.
727 if (need_rsp)
728 conn->request_id_to_handle[trans_id] = attr_handle;
729
730 // If there is no delegate then there is nobody to handle request. The request
731 // will eventually timeout and we should get a connection update that
732 // terminates the connection.
733 if (!delegate_) {
734 // TODO(armansito): Require a delegate at server registration so that this
735 // is never possible.
736 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
737 << "will time out.";
738 return;
739 }
740
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700741 if (iter->second.IsCharacteristic()) {
742 delegate_->OnCharacteristicWriteRequest(
743 this, device_address, trans_id, offset, is_prep, need_rsp,
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700744 std::move(value), iter->second);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700745 } else if (iter->second.IsDescriptor()) {
746 delegate_->OnDescriptorWriteRequest(
747 this, device_address, trans_id, offset, is_prep, need_rsp,
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700748 std::move(value), iter->second);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700749 } else {
750 // Our API only delegates to applications those read requests for
751 // characteristic value and descriptor attributes. Everything else should be
752 // handled by the stack.
753 LOG(WARNING) << "Write request received for unsupported attribute";
754 }
755}
756
757void GattServer::RequestExecWriteCallback(
758 hal::BluetoothGattInterface* /* gatt_iface */,
759 int conn_id, int trans_id,
760 const bt_bdaddr_t& bda, int exec_write) {
761 lock_guard<mutex> lock(mutex_);
762
763 // Check to see if we know about this connection. Otherwise ignore the
764 // request.
765 auto conn = GetConnection(conn_id, bda, trans_id);
766 if (!conn)
767 return;
768
769 std::string device_address = BtAddrString(&bda);
770
771 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
772 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
773
774 // Just store a dummy invalid handle as this request doesn't apply to a
775 // specific handle.
776 conn->request_id_to_handle[trans_id] = -1;
777
778 // If there is no delegate then there is nobody to handle request. The request
779 // will eventually timeout and we should get a connection update that
780 // terminates the connection.
781 if (!delegate_) {
782 // TODO(armansito): Require a delegate at server registration so that this
783 // is never possible.
784 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
785 << "will time out.";
786 return;
787 }
788
789 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
790}
791
Arman Uguraycd644e32015-10-01 16:36:38 -0700792void GattServer::IndicationSentCallback(
793 hal::BluetoothGattInterface* /* gatt_iface */,
794 int conn_id, int status) {
795 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
796 lock_guard<mutex> lock(mutex_);
797
798 const auto& pending_ind_iter = pending_indications_.find(conn_id);
799 if (pending_ind_iter == pending_indications_.end()) {
800 VLOG(1) << "Unknown connection: " << conn_id;
801 return;
802 }
803
804 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
805 pending_indications_.erase(pending_ind_iter);
806
807 if (status == BT_STATUS_SUCCESS)
808 pending_ind->has_success = true;
809
810 // Invoke it if this was the last reference to the confirmation callback.
811 if (pending_ind.unique() && pending_ind->callback) {
812 pending_ind->callback(
813 pending_ind->has_success ?
814 GATT_ERROR_NONE : static_cast<GATTError>(status));
815 }
816}
817
Arman Uguraydf0b2712015-09-23 17:25:54 -0700818void GattServer::NotifyEndCallbackAndClearData(
819 BLEStatus status, const GattIdentifier& id) {
820 VLOG(1) << __func__ << " status: " << status;
821 CHECK(pending_end_decl_cb_);
822
Arman Uguray514bf602015-09-29 19:38:03 -0700823 if (status == BLE_STATUS_SUCCESS) {
824 id_to_handle_map_.insert(pending_handle_map_.begin(),
825 pending_handle_map_.end());
826 for (auto& iter : pending_handle_map_)
827 handle_to_id_map_[iter.second] = iter.first;
828 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700829
830 pending_end_decl_cb_(status, id);
831
832 CleanUpPendingData();
833}
834
835void GattServer::CleanUpPendingData() {
836 pending_id_ = nullptr;
837 pending_decl_ = nullptr;
838 pending_end_decl_cb_ = ResultCallback();
839 pending_handle_map_.clear();
840}
841
Arman Uguray91613742015-09-24 22:45:16 -0700842void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
843 CHECK(pending_decl_);
844 CHECK(gatt_iface);
845
846 auto next_entry = PopNextEntry();
847 if (!next_entry) {
848 // No more entries. Call start_service to finish up.
849 bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
Arman Uguraybb18c412015-11-12 13:44:31 -0800850 server_id_,
Arman Uguray91613742015-09-24 22:45:16 -0700851 pending_decl_->service_handle,
852 TRANSPORT_BREDR | TRANSPORT_LE);
853
854 // Terminate the procedure in the case of an error.
855 if (status != BT_STATUS_SUCCESS) {
856 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
857 pending_decl_->service_id);
858 }
859
860 return;
861 }
862
863 if (next_entry->id.IsCharacteristic()) {
864 bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
865 bt_status_t status = gatt_iface->GetServerHALInterface()->
866 add_characteristic(
Arman Uguraybb18c412015-11-12 13:44:31 -0800867 server_id_,
Arman Uguray91613742015-09-24 22:45:16 -0700868 pending_decl_->service_handle,
869 &char_uuid,
870 next_entry->char_properties,
871 next_entry->permissions);
872
873 // Terminate the procedure in the case of an error.
874 if (status != BT_STATUS_SUCCESS) {
875 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
876 pending_decl_->service_id);
877 return;
878 }
879
880 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Ugurayd9b05522015-09-25 19:31:24 -0700881 return;
882 }
Arman Uguray91613742015-09-24 22:45:16 -0700883
Arman Ugurayd9b05522015-09-25 19:31:24 -0700884 if (next_entry->id.IsDescriptor()) {
885 bt_uuid_t desc_uuid = next_entry->id.descriptor_uuid().GetBlueDroid();
886 bt_status_t status = gatt_iface->GetServerHALInterface()->
887 add_descriptor(
Arman Uguraybb18c412015-11-12 13:44:31 -0800888 server_id_,
Arman Ugurayd9b05522015-09-25 19:31:24 -0700889 pending_decl_->service_handle,
890 &desc_uuid,
891 next_entry->permissions);
892
893 // Terminate the procedure in the case of an error.
894 if (status != BT_STATUS_SUCCESS) {
895 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
896 pending_decl_->service_id);
897 return;
898 }
899
900 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Uguray91613742015-09-24 22:45:16 -0700901 return;
902 }
903
904 NOTREACHED() << "Unexpected entry type";
905}
906
Arman Uguray514bf602015-09-29 19:38:03 -0700907std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
908 int conn_id, const bt_bdaddr_t& bda, int request_id) {
909 auto iter = conn_id_map_.find(conn_id);
910 if (iter == conn_id_map_.end()) {
911 VLOG(1) << "Connection doesn't belong to this server";
912 return nullptr;
913 }
914
915 auto conn = iter->second;
916 if (conn->bdaddr != bda) {
917 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
918 << "connection ID: " << conn_id;
919 return nullptr;
920 }
921
922 if (conn->request_id_to_handle.find(request_id) !=
923 conn->request_id_to_handle.end()) {
924 VLOG(1) << "Request with ID: " << request_id << " already exists for "
925 << " connection: " << conn_id;
926 return nullptr;
927 }
928
929 return conn;
930}
931
Arman Uguray91613742015-09-24 22:45:16 -0700932std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700933 CHECK(pending_decl_);
934
935 if (pending_decl_->attributes.empty())
936 return nullptr;
937
Arman Uguray91613742015-09-24 22:45:16 -0700938 const auto& next = pending_decl_->attributes.front();
939 std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700940
Arman Uguray91613742015-09-24 22:45:16 -0700941 pending_decl_->attributes.pop_front();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700942
Arman Uguray91613742015-09-24 22:45:16 -0700943 return entry;
944}
945
946std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
947 auto entry = PopNextEntry();
948 if (!entry)
949 return nullptr;
950
951 return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700952}
953
Arman Uguray0f2d4892015-09-22 14:20:42 -0700954// GattServerFactory implementation
955// ========================================================
956
957GattServerFactory::GattServerFactory() {
958 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
959}
960
961GattServerFactory::~GattServerFactory() {
962 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
963}
964
Arman Uguraybb18c412015-11-12 13:44:31 -0800965bool GattServerFactory::RegisterInstance(
966 const UUID& uuid,
967 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700968 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
969 lock_guard<mutex> lock(pending_calls_lock_);
970
971 if (pending_calls_.find(uuid) != pending_calls_.end()) {
972 LOG(ERROR) << "GATT-server client with given UUID already being registered "
973 << " - UUID: " << uuid.ToString();
974 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700975 }
976
Arman Uguray0f2d4892015-09-22 14:20:42 -0700977 const btgatt_server_interface_t* hal_iface =
978 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
979 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700980
Arman Uguray0f2d4892015-09-22 14:20:42 -0700981 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
982 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700983
Arman Uguray0f2d4892015-09-22 14:20:42 -0700984 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700985
Arman Uguray0f2d4892015-09-22 14:20:42 -0700986 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700987}
988
Arman Uguray0f2d4892015-09-22 14:20:42 -0700989void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700990 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800991 int status, int server_id,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700992 const bt_uuid_t& app_uuid) {
993 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700994
Arman Uguray0f2d4892015-09-22 14:20:42 -0700995 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
996 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700997
Arman Uguray0f2d4892015-09-22 14:20:42 -0700998 auto iter = pending_calls_.find(uuid);
999 if (iter == pending_calls_.end()) {
1000 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -07001001 return;
1002 }
1003
Arman Uguray0f2d4892015-09-22 14:20:42 -07001004 // No need to construct a server if the call wasn't successful.
1005 std::unique_ptr<GattServer> server;
1006 BLEStatus result = BLE_STATUS_FAILURE;
1007 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -08001008 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -07001009
Jakub Pawlowski25689c12016-01-20 16:24:03 -08001010 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -07001011
Arman Uguray0f2d4892015-09-22 14:20:42 -07001012 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -07001013 }
1014
Arman Uguray0f2d4892015-09-22 14:20:42 -07001015 // Notify the result via the result callback.
1016 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -07001017
Arman Uguray0f2d4892015-09-22 14:20:42 -07001018 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -07001019}
1020
Ian Coolidge611fcf92015-06-03 17:20:30 -07001021} // namespace bluetooth