blob: e70f093bc991a2e6f3c6ec9388550f5655a3a1fb [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,
423 value.size(),
424 confirm,
425 reinterpret_cast<char*>(const_cast<uint8_t*>(value.data())));
426
427 // Increment the send count if this was successful. We don't immediately
428 // fail if the HAL returned an error. It's better to report success as long
429 // as we sent out at least one notification to this device as
430 // multi-transport GATT connections from the same BD_ADDR will be rare
431 // enough already.
432 if (status != BT_STATUS_SUCCESS)
433 continue;
434
435 send_count++;
436 pending_indications_[conn->conn_id] = pending_ind;
437 }
438
439 if (send_count == 0) {
440 LOG(ERROR) << "Failed to send notifications/indications to device: "
441 << device_address;
442 return false;
443 }
444
445 return true;
446}
447
Arman Uguray514bf602015-09-29 19:38:03 -0700448void GattServer::ConnectionCallback(
449 hal::BluetoothGattInterface* /* gatt_iface */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800450 int conn_id, int server_id,
Arman Uguray514bf602015-09-29 19:38:03 -0700451 int connected,
452 const bt_bdaddr_t& bda) {
453 lock_guard<mutex> lock(mutex_);
454
Arman Uguraybb18c412015-11-12 13:44:31 -0800455 if (server_id != server_id_)
Arman Uguray514bf602015-09-29 19:38:03 -0700456 return;
457
458 std::string device_address = BtAddrString(&bda);
459
460 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
461 << " BD_ADDR: " << device_address;
462
463 if (!connected) {
464 // Erase the entry if we were connected to it.
465 VLOG(1) << "No longer connected: " << device_address;
466 conn_id_map_.erase(conn_id);
467 auto iter = conn_addr_map_.find(device_address);
468 if (iter == conn_addr_map_.end())
469 return;
470
471 // Remove the appropriate connection objects in the address.
472 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
473 ++conn_iter) {
474 if ((*conn_iter)->conn_id != conn_id)
475 continue;
476
477 iter->second.erase(conn_iter);
478 break;
479 }
480
481 return;
482 }
483
484 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
485 LOG(WARNING) << "Connection entry already exists; "
486 << "ignoring ConnectionCallback";
487 return;
488 }
489
490 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
491 << " device address: " << device_address;
492 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
493 conn_id_map_[conn_id] = connection;
494 conn_addr_map_[device_address].push_back(connection);
495}
496
Arman Uguraydf0b2712015-09-23 17:25:54 -0700497void GattServer::ServiceAddedCallback(
498 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800499 int status, int server_id,
Arman Uguraydf0b2712015-09-23 17:25:54 -0700500 const btgatt_srvc_id_t& srvc_id,
Arman Uguray91613742015-09-24 22:45:16 -0700501 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700502 lock_guard<mutex> lock(mutex_);
503
Arman Uguraybb18c412015-11-12 13:44:31 -0800504 if (server_id != server_id_)
Arman Uguraydf0b2712015-09-23 17:25:54 -0700505 return;
506
507 // Construct a GATT identifier.
508 auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
509 CHECK(pending_id_);
510 CHECK(*gatt_id == *pending_id_);
511 CHECK(*gatt_id == pending_decl_->service_id);
512 CHECK(pending_id_->IsService());
513
Arman Uguray91613742015-09-24 22:45:16 -0700514 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800515 << " server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700516 << " handle: " << service_handle
Arman Uguraydf0b2712015-09-23 17:25:54 -0700517 << " UUID: " << gatt_id->service_uuid().ToString();
518
519 if (status != BT_STATUS_SUCCESS) {
520 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
521 return;
522 }
523
524 // Add this to the handle map.
Arman Uguray91613742015-09-24 22:45:16 -0700525 pending_handle_map_[*gatt_id] = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700526 CHECK(-1 == pending_decl_->service_handle);
Arman Uguray91613742015-09-24 22:45:16 -0700527 pending_decl_->service_handle = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700528
Arman Uguray91613742015-09-24 22:45:16 -0700529 HandleNextEntry(gatt_iface);
530}
Arman Uguraydf0b2712015-09-23 17:25:54 -0700531
Arman Uguray91613742015-09-24 22:45:16 -0700532void GattServer::CharacteristicAddedCallback(
533 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800534 int status, int server_id,
Arman Uguray91613742015-09-24 22:45:16 -0700535 const bt_uuid_t& uuid,
536 int service_handle,
537 int char_handle) {
538 lock_guard<mutex> lock(mutex_);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700539
Arman Uguraybb18c412015-11-12 13:44:31 -0800540 if (server_id != server_id_)
Arman Uguray91613742015-09-24 22:45:16 -0700541 return;
542
543 CHECK(pending_decl_);
544 CHECK(pending_decl_->service_handle == service_handle);
545 CHECK(pending_id_);
546 CHECK(pending_id_->IsCharacteristic());
547 CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
548
549 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800550 << " server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700551 << " service_handle: " << service_handle
552 << " char_handle: " << char_handle;
553
554 if (status != BT_STATUS_SUCCESS) {
555 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
556 pending_decl_->service_id);
557 return;
558 }
559
560 // Add this to the handle map and continue.
561 pending_handle_map_[*pending_id_] = char_handle;
562 HandleNextEntry(gatt_iface);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700563}
564
Arman Ugurayd9b05522015-09-25 19:31:24 -0700565void GattServer::DescriptorAddedCallback(
566 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800567 int status, int server_id,
Arman Ugurayd9b05522015-09-25 19:31:24 -0700568 const bt_uuid_t& uuid,
569 int service_handle,
570 int desc_handle) {
571 lock_guard<mutex> lock(mutex_);
572
Arman Uguraybb18c412015-11-12 13:44:31 -0800573 if (server_id != server_id_)
Arman Ugurayd9b05522015-09-25 19:31:24 -0700574 return;
575
576 CHECK(pending_decl_);
577 CHECK(pending_decl_->service_handle == service_handle);
578 CHECK(pending_id_);
579 CHECK(pending_id_->IsDescriptor());
580 CHECK(pending_id_->descriptor_uuid() == UUID(uuid));
581
582 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800583 << " server_id: " << server_id
Arman Ugurayd9b05522015-09-25 19:31:24 -0700584 << " service_handle: " << service_handle
585 << " desc_handle: " << desc_handle;
586
587 if (status != BT_STATUS_SUCCESS) {
588 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
589 pending_decl_->service_id);
590 return;
591 }
592
593 // Add this to the handle map and contiue.
594 pending_handle_map_[*pending_id_] = desc_handle;
595 HandleNextEntry(gatt_iface);
596}
597
Arman Uguraydf0b2712015-09-23 17:25:54 -0700598void GattServer::ServiceStartedCallback(
599 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800600 int status, int server_id,
Arman Uguray91613742015-09-24 22:45:16 -0700601 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700602 lock_guard<mutex> lock(mutex_);
603
Arman Uguraybb18c412015-11-12 13:44:31 -0800604 if (server_id != server_id_)
Arman Uguraydf0b2712015-09-23 17:25:54 -0700605 return;
606
607 CHECK(pending_id_);
608 CHECK(pending_decl_);
Arman Uguray91613742015-09-24 22:45:16 -0700609 CHECK(pending_decl_->service_handle == service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700610
Arman Uguraybb18c412015-11-12 13:44:31 -0800611 VLOG(1) << __func__ << " - server_id: " << server_id
Arman Uguray91613742015-09-24 22:45:16 -0700612 << " handle: " << service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700613
614 // If we failed to start the service, remove it from the database and ignore
615 // the result.
616 if (status != BT_STATUS_SUCCESS) {
617 gatt_iface->GetServerHALInterface()->delete_service(
Arman Uguraybb18c412015-11-12 13:44:31 -0800618 server_id_, service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700619 }
620
621 // Complete the operation.
622 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
623 pending_decl_->service_id);
624}
625
626void GattServer::ServiceStoppedCallback(
627 hal::BluetoothGattInterface* /* gatt_iface */,
628 int /* status */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800629 int /* server_id */,
Arman Uguray91613742015-09-24 22:45:16 -0700630 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700631 // TODO(armansito): Support stopping a service.
632}
633
Arman Uguray514bf602015-09-29 19:38:03 -0700634void GattServer::RequestReadCallback(
635 hal::BluetoothGattInterface* /* gatt_iface */,
636 int conn_id, int trans_id,
637 const bt_bdaddr_t& bda,
638 int attribute_handle, int offset,
639 bool is_long) {
640 lock_guard<mutex> lock(mutex_);
641
642 // Check to see if we know about this connection. Otherwise ignore the
643 // request.
644 auto conn = GetConnection(conn_id, bda, trans_id);
645 if (!conn)
646 return;
647
648 std::string device_address = BtAddrString(&bda);
649
650 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
651 << " BD_ADDR: " << device_address
652 << " attribute_handle: " << attribute_handle << " offset: " << offset
653 << " is_long: " << is_long;
654
655 // Make sure that the handle is valid.
656 auto iter = handle_to_id_map_.find(attribute_handle);
657 if (iter == handle_to_id_map_.end()) {
658 LOG(ERROR) << "Request received for unknown handle: " << attribute_handle;
659 return;
660 }
661
662 conn->request_id_to_handle[trans_id] = attribute_handle;
663
664 // If there is no delegate then there is nobody to handle request. The request
665 // will eventually timeout and we should get a connection update that
666 // terminates the connection.
667 if (!delegate_) {
668 // TODO(armansito): Require a delegate at server registration so that this
669 // is never possible.
670 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
671 << "will time out.";
672 return;
673 }
674
675 if (iter->second.IsCharacteristic()) {
676 delegate_->OnCharacteristicReadRequest(
677 this, device_address, trans_id, offset, is_long, iter->second);
678 } else if (iter->second.IsDescriptor()) {
679 delegate_->OnDescriptorReadRequest(
680 this, device_address, trans_id, offset, is_long, iter->second);
681 } else {
682 // Our API only delegates to applications those read requests for
683 // characteristic value and descriptor attributes. Everything else should be
684 // handled by the stack.
685 LOG(WARNING) << "Read request received for unsupported attribute";
686 }
687}
688
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700689void GattServer::RequestWriteCallback(
690 hal::BluetoothGattInterface* /* gatt_iface */,
691 int conn_id, int trans_id,
692 const bt_bdaddr_t& bda,
693 int attr_handle, int offset, int length,
694 bool need_rsp, bool is_prep, uint8_t* value) {
695 lock_guard<mutex> lock(mutex_);
696
697 if (length < 0) {
698 LOG(WARNING) << "Negative length value received";
699 return;
700 }
701
702 // Check to see if we know about this connection. Otherwise ignore the
703 // request.
704 auto conn = GetConnection(conn_id, bda, trans_id);
705 if (!conn)
706 return;
707
708 std::string device_address = BtAddrString(&bda);
709
710 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
711 << " BD_ADDR: " << device_address
712 << " attr_handle: " << attr_handle << " offset: " << offset
713 << " length: " << length << " need_rsp: " << need_rsp
714 << " is_prep: " << is_prep;
715
716 // Make sure that the handle is valid.
717 auto iter = handle_to_id_map_.find(attr_handle);
718 if (iter == handle_to_id_map_.end()) {
719 LOG(ERROR) << "Request received for unknown handle: " << attr_handle;
720 return;
721 }
722
723 // Store the request ID only if this is not a write-without-response. If
724 // another request occurs after this with the same request ID, then we'll
725 // simply process it normally, though that shouldn't ever happen.
726 if (need_rsp)
727 conn->request_id_to_handle[trans_id] = attr_handle;
728
729 // If there is no delegate then there is nobody to handle request. The request
730 // will eventually timeout and we should get a connection update that
731 // terminates the connection.
732 if (!delegate_) {
733 // TODO(armansito): Require a delegate at server registration so that this
734 // is never possible.
735 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
736 << "will time out.";
737 return;
738 }
739
740 std::vector<uint8_t> value_vec(value, value + length);
741
742 if (iter->second.IsCharacteristic()) {
743 delegate_->OnCharacteristicWriteRequest(
744 this, device_address, trans_id, offset, is_prep, need_rsp,
745 value_vec, iter->second);
746 } else if (iter->second.IsDescriptor()) {
747 delegate_->OnDescriptorWriteRequest(
748 this, device_address, trans_id, offset, is_prep, need_rsp,
749 value_vec, iter->second);
750 } else {
751 // Our API only delegates to applications those read requests for
752 // characteristic value and descriptor attributes. Everything else should be
753 // handled by the stack.
754 LOG(WARNING) << "Write request received for unsupported attribute";
755 }
756}
757
758void GattServer::RequestExecWriteCallback(
759 hal::BluetoothGattInterface* /* gatt_iface */,
760 int conn_id, int trans_id,
761 const bt_bdaddr_t& bda, int exec_write) {
762 lock_guard<mutex> lock(mutex_);
763
764 // Check to see if we know about this connection. Otherwise ignore the
765 // request.
766 auto conn = GetConnection(conn_id, bda, trans_id);
767 if (!conn)
768 return;
769
770 std::string device_address = BtAddrString(&bda);
771
772 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
773 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
774
775 // Just store a dummy invalid handle as this request doesn't apply to a
776 // specific handle.
777 conn->request_id_to_handle[trans_id] = -1;
778
779 // If there is no delegate then there is nobody to handle request. The request
780 // will eventually timeout and we should get a connection update that
781 // terminates the connection.
782 if (!delegate_) {
783 // TODO(armansito): Require a delegate at server registration so that this
784 // is never possible.
785 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
786 << "will time out.";
787 return;
788 }
789
790 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
791}
792
Arman Uguraycd644e32015-10-01 16:36:38 -0700793void GattServer::IndicationSentCallback(
794 hal::BluetoothGattInterface* /* gatt_iface */,
795 int conn_id, int status) {
796 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
797 lock_guard<mutex> lock(mutex_);
798
799 const auto& pending_ind_iter = pending_indications_.find(conn_id);
800 if (pending_ind_iter == pending_indications_.end()) {
801 VLOG(1) << "Unknown connection: " << conn_id;
802 return;
803 }
804
805 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
806 pending_indications_.erase(pending_ind_iter);
807
808 if (status == BT_STATUS_SUCCESS)
809 pending_ind->has_success = true;
810
811 // Invoke it if this was the last reference to the confirmation callback.
812 if (pending_ind.unique() && pending_ind->callback) {
813 pending_ind->callback(
814 pending_ind->has_success ?
815 GATT_ERROR_NONE : static_cast<GATTError>(status));
816 }
817}
818
Arman Uguraydf0b2712015-09-23 17:25:54 -0700819void GattServer::NotifyEndCallbackAndClearData(
820 BLEStatus status, const GattIdentifier& id) {
821 VLOG(1) << __func__ << " status: " << status;
822 CHECK(pending_end_decl_cb_);
823
Arman Uguray514bf602015-09-29 19:38:03 -0700824 if (status == BLE_STATUS_SUCCESS) {
825 id_to_handle_map_.insert(pending_handle_map_.begin(),
826 pending_handle_map_.end());
827 for (auto& iter : pending_handle_map_)
828 handle_to_id_map_[iter.second] = iter.first;
829 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700830
831 pending_end_decl_cb_(status, id);
832
833 CleanUpPendingData();
834}
835
836void GattServer::CleanUpPendingData() {
837 pending_id_ = nullptr;
838 pending_decl_ = nullptr;
839 pending_end_decl_cb_ = ResultCallback();
840 pending_handle_map_.clear();
841}
842
Arman Uguray91613742015-09-24 22:45:16 -0700843void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
844 CHECK(pending_decl_);
845 CHECK(gatt_iface);
846
847 auto next_entry = PopNextEntry();
848 if (!next_entry) {
849 // No more entries. Call start_service to finish up.
850 bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
Arman Uguraybb18c412015-11-12 13:44:31 -0800851 server_id_,
Arman Uguray91613742015-09-24 22:45:16 -0700852 pending_decl_->service_handle,
853 TRANSPORT_BREDR | TRANSPORT_LE);
854
855 // Terminate the procedure in the case of an error.
856 if (status != BT_STATUS_SUCCESS) {
857 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
858 pending_decl_->service_id);
859 }
860
861 return;
862 }
863
864 if (next_entry->id.IsCharacteristic()) {
865 bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
866 bt_status_t status = gatt_iface->GetServerHALInterface()->
867 add_characteristic(
Arman Uguraybb18c412015-11-12 13:44:31 -0800868 server_id_,
Arman Uguray91613742015-09-24 22:45:16 -0700869 pending_decl_->service_handle,
870 &char_uuid,
871 next_entry->char_properties,
872 next_entry->permissions);
873
874 // Terminate the procedure in the case of an error.
875 if (status != BT_STATUS_SUCCESS) {
876 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
877 pending_decl_->service_id);
878 return;
879 }
880
881 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Ugurayd9b05522015-09-25 19:31:24 -0700882 return;
883 }
Arman Uguray91613742015-09-24 22:45:16 -0700884
Arman Ugurayd9b05522015-09-25 19:31:24 -0700885 if (next_entry->id.IsDescriptor()) {
886 bt_uuid_t desc_uuid = next_entry->id.descriptor_uuid().GetBlueDroid();
887 bt_status_t status = gatt_iface->GetServerHALInterface()->
888 add_descriptor(
Arman Uguraybb18c412015-11-12 13:44:31 -0800889 server_id_,
Arman Ugurayd9b05522015-09-25 19:31:24 -0700890 pending_decl_->service_handle,
891 &desc_uuid,
892 next_entry->permissions);
893
894 // Terminate the procedure in the case of an error.
895 if (status != BT_STATUS_SUCCESS) {
896 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
897 pending_decl_->service_id);
898 return;
899 }
900
901 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Uguray91613742015-09-24 22:45:16 -0700902 return;
903 }
904
905 NOTREACHED() << "Unexpected entry type";
906}
907
Arman Uguray514bf602015-09-29 19:38:03 -0700908std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
909 int conn_id, const bt_bdaddr_t& bda, int request_id) {
910 auto iter = conn_id_map_.find(conn_id);
911 if (iter == conn_id_map_.end()) {
912 VLOG(1) << "Connection doesn't belong to this server";
913 return nullptr;
914 }
915
916 auto conn = iter->second;
917 if (conn->bdaddr != bda) {
918 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
919 << "connection ID: " << conn_id;
920 return nullptr;
921 }
922
923 if (conn->request_id_to_handle.find(request_id) !=
924 conn->request_id_to_handle.end()) {
925 VLOG(1) << "Request with ID: " << request_id << " already exists for "
926 << " connection: " << conn_id;
927 return nullptr;
928 }
929
930 return conn;
931}
932
Arman Uguray91613742015-09-24 22:45:16 -0700933std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700934 CHECK(pending_decl_);
935
936 if (pending_decl_->attributes.empty())
937 return nullptr;
938
Arman Uguray91613742015-09-24 22:45:16 -0700939 const auto& next = pending_decl_->attributes.front();
940 std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700941
Arman Uguray91613742015-09-24 22:45:16 -0700942 pending_decl_->attributes.pop_front();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700943
Arman Uguray91613742015-09-24 22:45:16 -0700944 return entry;
945}
946
947std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
948 auto entry = PopNextEntry();
949 if (!entry)
950 return nullptr;
951
952 return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700953}
954
Arman Uguray0f2d4892015-09-22 14:20:42 -0700955// GattServerFactory implementation
956// ========================================================
957
958GattServerFactory::GattServerFactory() {
959 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
960}
961
962GattServerFactory::~GattServerFactory() {
963 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
964}
965
Arman Uguraybb18c412015-11-12 13:44:31 -0800966bool GattServerFactory::RegisterInstance(
967 const UUID& uuid,
968 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700969 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
970 lock_guard<mutex> lock(pending_calls_lock_);
971
972 if (pending_calls_.find(uuid) != pending_calls_.end()) {
973 LOG(ERROR) << "GATT-server client with given UUID already being registered "
974 << " - UUID: " << uuid.ToString();
975 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700976 }
977
Arman Uguray0f2d4892015-09-22 14:20:42 -0700978 const btgatt_server_interface_t* hal_iface =
979 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
980 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700981
Arman Uguray0f2d4892015-09-22 14:20:42 -0700982 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
983 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700984
Arman Uguray0f2d4892015-09-22 14:20:42 -0700985 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700986
Arman Uguray0f2d4892015-09-22 14:20:42 -0700987 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700988}
989
Arman Uguray0f2d4892015-09-22 14:20:42 -0700990void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700991 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800992 int status, int server_id,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700993 const bt_uuid_t& app_uuid) {
994 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700995
Arman Uguray0f2d4892015-09-22 14:20:42 -0700996 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
997 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700998
Arman Uguray0f2d4892015-09-22 14:20:42 -0700999 auto iter = pending_calls_.find(uuid);
1000 if (iter == pending_calls_.end()) {
1001 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -07001002 return;
1003 }
1004
Arman Uguray0f2d4892015-09-22 14:20:42 -07001005 // No need to construct a server if the call wasn't successful.
1006 std::unique_ptr<GattServer> server;
1007 BLEStatus result = BLE_STATUS_FAILURE;
1008 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -08001009 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -07001010
Jakub Pawlowski25689c12016-01-20 16:24:03 -08001011 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -07001012
Arman Uguray0f2d4892015-09-22 14:20:42 -07001013 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -07001014 }
1015
Arman Uguray0f2d4892015-09-22 14:20:42 -07001016 // Notify the result via the result callback.
1017 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -07001018
Arman Uguray0f2d4892015-09-22 14:20:42 -07001019 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -07001020}
1021
Ian Coolidge611fcf92015-06-03 17:20:30 -07001022} // namespace bluetooth