10f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
20f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Copyright (C) 2015 Google, Inc.
30f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
40f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Licensed under the Apache License, Version 2.0 (the "License");
50f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  you may not use this file except in compliance with the License.
60f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  You may obtain a copy of the License at:
70f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
80f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  http://www.apache.org/licenses/LICENSE-2.0
90f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  Unless required by applicable law or agreed to in writing, software
110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  distributed under the License is distributed on an "AS IS" BASIS,
120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  See the License for the specific language governing permissions and
140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//  limitations under the License.
150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#define LOG_TAG "bt_gatts"
180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "gatt_server_old.h"
200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <stdio.h>
220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <stdlib.h>
230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <unistd.h>
240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <algorithm>
260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <array>
270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <condition_variable>
280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <map>
290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <memory>
300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <mutex>
310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <set>
320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <string>
330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <unordered_map>
340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <vector>
350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <hardware/bluetooth.h>
370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include <hardware/bt_gatt.h>
380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "service/hal/bluetooth_interface.h"
400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "service/logging_helpers.h"
410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
420f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayextern "C" {
430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "osi/include/log.h"
440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray#include "osi/include/osi.h"
450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // extern "C"
460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace {
480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
490f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayconst size_t kMaxGattAttributeSize = 512;
500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// TODO(icoolidge): Difficult to generalize without knowing how many attributes.
510f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayconst int kNumBlueDroidHandles = 60;
520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// TODO(icoolidge): Support multiple instances
540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// TODO(armansito): Remove this variable. No point of having this if
550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// each bluetooth::gatt::Server instance already keeps a pointer to the
560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// ServerInternals that is associated with it (which is much cleaner). It looks
570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// like this variable exists because the btif callbacks don't allow the
580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// upper-layer to pass user data to them. We could:
590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    1. Fix the btif callbacks so that some sort of continuation can be
610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    attached to a callback. This might be a long shot since the callback
620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    interface doesn't allow more than one caller to register its own callbacks
630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    (which might be what we want though, since this would make the API more
640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    flexible).
650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    2. Allow creation of Server objects using a factory method that returns
670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    the result asynchronously in a base::Callback. The RegisterServerCallback
680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    provides an |app_uuid|, which can be used to store callback structures in
690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    a map and lazily instantiate the Server and invoke the correct callback.
700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    This is a general pattern that we should use throughout the daemon, since
710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    all operations can timeout or fail and this is best reported in an
720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//    asynchronous base::Callback.
730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray//
740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraystatic bluetooth::gatt::ServerInternals *g_internal = nullptr;
750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
760f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayenum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace
790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace bluetooth {
810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace gatt {
820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraystruct Characteristic {
840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID uuid;
850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int blob_section;
860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::vector<uint8_t> blob;
870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Support synchronized blob updates by latching under mutex.
890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::vector<uint8_t> next_blob;
900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bool next_blob_pending;
910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bool notify;
920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraystruct ServerInternals {
950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ServerInternals();
960f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ~ServerInternals();
970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int Initialize();
980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t AddCharacteristic(
990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      const UUID& uuid,
1000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      int properties,
1010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      int permissions);
1020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This maps API attribute UUIDs to BlueDroid handles.
1040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::map<UUID, int> uuid_to_attribute;
1050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // The attribute cache, indexed by BlueDroid handles.
1070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unordered_map<int, Characteristic> characteristics;
1080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Associate a control attribute with its value attribute.
1100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unordered_map<int, int> controlled_blobs;
1110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ScanResults scan_results;
1130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  UUID last_write;
1150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const btgatt_interface_t *gatt;
1160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int server_if;
1170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int client_if;
1180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int service_handle;
1190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btgatt_srvc_id_t service_id;
1200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::set<int> connections;
1210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::mutex lock;
1230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::condition_variable api_synchronize;
1240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int pipefd[kPipeNumEnds];
1250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
1260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace gatt
1280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace bluetooth
1290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace {
1310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray/** Callback invoked in response to register_server */
1330f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid RegisterServerCallback(int status, int server_if, bt_uuid_t *app_uuid) {
1340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d app_uuid:%p", __func__, status,
1350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray           server_if, app_uuid);
1360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->server_if = server_if;
1380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btgatt_srvc_id_t service_id;
1400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  service_id.id.uuid = *app_uuid;
1410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  service_id.id.inst_id = 0;
1420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  service_id.is_primary = true;
1430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->gatt->server->add_service(
1450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      server_if, &service_id, kNumBlueDroidHandles);
1460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
1470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1480f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
1490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                          int srvc_handle) {
1500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
1510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray           __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
1520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
1540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->server_if = server_if;
1550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->service_handle = srvc_handle;
1560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->service_id = *srvc_id;
1570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This finishes the Initialize call.
1580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->api_synchronize.notify_one();
1590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
1600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1610f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
1620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                         int attr_handle, int attribute_offset_octets,
1630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                         bool is_long) {
1640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
1650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bluetooth::gatt::Characteristic &ch = g_internal->characteristics[attr_handle];
1670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Latch next_blob to blob on a 'fresh' read.
1690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (ch.next_blob_pending && attribute_offset_octets == 0 &&
1700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      ch.blob_section == 0) {
1710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    std::swap(ch.blob, ch.next_blob);
1720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ch.next_blob_pending = false;
1730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
1740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const size_t blob_offset_octets =
1760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
1770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
1780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
1790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
1810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG,
1820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
1830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "blob_section:%u (is_long:%u)",
1840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
1850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      ch.blob_section, is_long);
1860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btgatt_response_t response;
1880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.len = 0;
1890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (attribute_offset_octets < static_cast<int>(attribute_size)) {
1910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
1920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray              ch.blob.begin() + blob_offset_octets + attribute_size,
1930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray              response.attr_value.value);
1940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    response.attr_value.len = attribute_size - attribute_offset_octets;
1950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
1960f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
1970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.handle = attr_handle;
1980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.offset = attribute_offset_octets;
1990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.auth_req = 0;
2000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
2010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
2020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2030f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
2040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                          int attr_handle, int attribute_offset, int length,
2050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                          bool need_rsp, bool is_prep, uint8_t *value) {
2060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
2070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG,
2080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
2090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "length:%d "
2100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "need_resp:%u is_prep:%u",
2110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
2120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      length, need_rsp, is_prep);
2130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
2150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bluetooth::gatt::Characteristic &ch =
2170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      g_internal->characteristics[attr_handle];
2180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ch.blob.resize(attribute_offset + length);
2200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::copy(value, value + length, ch.blob.begin() + attribute_offset);
2220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto target_blob = g_internal->controlled_blobs.find(attr_handle);
2240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // If this is a control attribute, adjust offset of the target blob.
2250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (target_blob != g_internal->controlled_blobs.end() &&
2260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      ch.blob.size() == 1u) {
2270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    g_internal->characteristics[target_blob->second].blob_section = ch.blob[0];
2280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_INFO(LOG_TAG, "%s: updating attribute %d blob_section to %u", __func__,
2290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray        target_blob->second, ch.blob[0]);
2300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  } else if (!is_prep) {
2310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    // This is a single frame characteristic write.
2320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    // Notify upwards because we're done now.
2330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    const bluetooth::UUID::UUID128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
234574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    ssize_t status;
235574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov    OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
236574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov                               attr_uuid.data(), attr_uuid.size()));
2370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    if (-1 == status)
2380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
2390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  } else {
2400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    // This is a multi-frame characteristic write.
2410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    // Wait for an 'RequestExecWriteCallback' to notify completion.
2420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    g_internal->last_write = ch.uuid;
2430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
2440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Respond only if needed.
2460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (!need_rsp) return;
2470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btgatt_response_t response;
2490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.handle = attr_handle;
2500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.offset = attribute_offset;
2510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.len = length;
2520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  response.attr_value.auth_req = 0;
2530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Provide written data back to sender for the response.
2540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Remote stacks use this to validate the success of the write.
2550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::copy(value, value + length, response.attr_value.value);
2560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
2570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
2580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2590f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
2600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              int exec_write) {
2610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
2620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: connection:%d (%s:trans:%d) exec_write:%d", __func__,
2630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      conn_id, addr.c_str(), trans_id, exec_write);
2640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This 'response' data is unused for ExecWriteResponses.
2660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // It is only used to pass BlueDroid argument validation.
2670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btgatt_response_t response = {};
2680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
2690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (!exec_write)
2710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return;
2720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
2740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Communicate the attribute UUID as notification of a write update.
2750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const bluetooth::UUID::UUID128Bit uuid =
2760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      g_internal->last_write.GetFullBigEndian();
277574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov  ssize_t status;
278574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov  OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
279574dcfb73e3741d715f7d4394fe5d3bd587cb0d2Pavlin Radoslavov                             uuid.size()));
2800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (-1 == status)
2810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
2820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
2830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2840f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ConnectionCallback(int conn_id, int server_if, int connected,
2850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                        bt_bdaddr_t *bda) {
2860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
2870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: connection:%d server_if:%d connected:%d addr:%s",
2880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      __func__, conn_id, server_if, connected, addr.c_str());
2890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (connected == 1) {
2900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    g_internal->connections.insert(conn_id);
2910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  } else if (connected == 0) {
2920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    g_internal->connections.erase(conn_id);
2930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
2940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
2950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
2960f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
2970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                 int srvc_handle, int char_handle) {
2980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG,
2990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "%s: status:%d server_if:%d service_handle:%d char_handle:%d", __func__,
3000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      status, server_if, srvc_handle, char_handle);
3010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bluetooth::UUID id(*uuid);
3030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
3050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->uuid_to_attribute[id] = char_handle;
3070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->characteristics[char_handle].uuid = id;
3080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->characteristics[char_handle].blob_section = 0;
3090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This terminates an AddCharacteristic.
3110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->api_synchronize.notify_one();
3120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3140f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
3150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                             int srvc_handle, int descr_handle) {
3160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG,
3170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
3180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      "descr_handle:%d",
3190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
3200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3220f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ServiceStartedCallback(int status, int server_if, int srvc_handle) {
3230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
3240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      status, server_if, srvc_handle);
3250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // The UUID provided here is unimportant, and is only used to satisfy
3270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // BlueDroid.
3280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // It must be different than any other registered UUID.
3290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_uuid_t client_id = g_internal->service_id.id.uuid;
3300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ++client_id.uu[15];
3310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = g_internal->gatt->client->register_client(&client_id);
3330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
3340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
3350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
3360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3380f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
3390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
3400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      client_if, app_uuid->uu[0]);
3410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->client_if = client_if;
3420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Setup our advertisement. This has no callback.
3440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = g_internal->gatt->client->set_adv_data(
3450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      client_if, false, /* beacon, not scan response */
3460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      false,            /* name */
3470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      false,            /* no txpower */
3480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      2, 2,             /* interval */
3490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0,                /* appearance */
3500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0, nullptr,       /* no mfg data */
3510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0, nullptr,       /* no service data */
3520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0, nullptr /* no service id yet */);
3530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
3540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to set advertising data");
3550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return;
3560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
3570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // TODO(icoolidge): Deprecated, use multi-adv interface.
3590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This calls back to ListenCallback.
3600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btstat = g_internal->gatt->client->listen(client_if, true);
3610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
3620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to start listening");
3630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
3640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3660f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ListenCallback(int status, int client_if) {
3670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d", __func__, status, client_if);
3680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This terminates a Start call.
3690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
3700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->api_synchronize.notify_one();
3710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3730f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
3740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
3750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      status, server_if, srvc_handle);
3760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // This terminates a Stop call.
3770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // TODO(icoolidge): make this symmetric with start
3780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
3790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->api_synchronize.notify_one();
3800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3820f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ScanResultCallback(bt_bdaddr_t *bda, int rssi, uint8_t *adv_data) {
3830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
3840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  (void)adv_data;
3850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(g_internal->lock);
3860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal->scan_results[addr] = rssi;
3870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3890f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ClientConnectCallback(int conn_id, int status, int client_if,
3900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                           bt_bdaddr_t *bda) {
3910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
3920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
3930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      conn_id, status, client_if, addr.c_str());
3940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
3950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
3960f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ClientDisconnectCallback(int conn_id, int status, int client_if,
3970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              bt_bdaddr_t *bda) {
3980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::string addr(BtAddrString(bda));
3990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
4000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      conn_id, status, client_if, addr.c_str());
4010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
4020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4030f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid IndicationSentCallback(UNUSED_ATTR int conn_id,
4040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                            UNUSED_ATTR int status) {
4050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // TODO(icoolidge): what to do
4060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
4070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4080f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayvoid ResponseConfirmationCallback(UNUSED_ATTR int status,
4090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                  UNUSED_ATTR int handle) {
4100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // TODO(icoolidge): what to do
4110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
4120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4130f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayconst btgatt_server_callbacks_t gatt_server_callbacks = {
4140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    RegisterServerCallback,
4150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ConnectionCallback,
4160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ServiceAddedCallback,
4170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* included_service_added_cb */
4180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    CharacteristicAddedCallback,
4190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    DescriptorAddedCallback,
4200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ServiceStartedCallback,
4210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ServiceStoppedCallback,
4220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* service_deleted_cb */
4230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    RequestReadCallback,
4240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    RequestWriteCallback,
4250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    RequestExecWriteCallback,
4260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ResponseConfirmationCallback,
4270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    IndicationSentCallback,
4280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* congestion_cb*/
4290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* mtu_changed_cb */
4300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
4310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// TODO(eisenbach): Refactor GATT interface to not require servers
4330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray// to refer to the client interface.
4340f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayconst btgatt_client_callbacks_t gatt_client_callbacks = {
4350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    RegisterClientCallback,
4360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ScanResultCallback,
4370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ClientConnectCallback,
4380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ClientDisconnectCallback,
4390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* search_complete_cb; */
4400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* register_for_notification_cb; */
4410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* notify_cb; */
4420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* read_characteristic_cb; */
4430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* write_characteristic_cb; */
4440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* read_descriptor_cb; */
4450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* write_descriptor_cb; */
4460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* execute_write_cb; */
4470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* read_remote_rssi_cb; */
4480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    ListenCallback,
4490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* configure_mtu_cb; */
4500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* scan_filter_cfg_cb; */
4510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* scan_filter_param_cb; */
4520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* scan_filter_status_cb; */
4530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* multi_adv_enable_cb */
4540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* multi_adv_update_cb; */
4550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* multi_adv_data_cb*/
4560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* multi_adv_disable_cb; */
4570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* congestion_cb; */
4580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* batchscan_cfg_storage_cb; */
4590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* batchscan_enb_disable_cb; */
4600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* batchscan_reports_cb; */
4610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* batchscan_threshold_cb; */
4620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* track_adv_event_cb; */
4630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    nullptr, /* scan_parameter_setup_completed_cb; */
4646859e0c7e3e20b1d1725b360378b546dd73dcb90Jakub Pawlowski    nullptr, /* get_gatt_db_cb; */
4650bd8fa5b24103f5376afb4ddd593ecb1a6a2588cJakub Pawlowski    nullptr, /* services_removed_cb */
4660bd8fa5b24103f5376afb4ddd593ecb1a6a2588cJakub Pawlowski    nullptr, /* services_added_cb */
4670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray};
4680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4690f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayconst btgatt_callbacks_t gatt_callbacks = {
4700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    /** Set to sizeof(btgatt_callbacks_t) */
4710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    sizeof(btgatt_callbacks_t),
4720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    /** GATT Client callbacks */
4740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    &gatt_client_callbacks,
4750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    /** GATT Server callbacks */
4770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    &gatt_server_callbacks};
4780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace
4800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace bluetooth {
4820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraynamespace gatt {
4830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4840f2d4897046f037a9f181f47f3d349a9dd646478Arman Ugurayint ServerInternals::Initialize() {
4850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Get the interface to the GATT profile.
4860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const bt_interface_t* bt_iface =
4870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      hal::BluetoothInterface::Get()->GetHALInterface();
4880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  gatt = reinterpret_cast<const btgatt_interface_t *>(
4890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
4900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (!gatt) {
4910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Error getting GATT interface");
4920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return -1;
4930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
4940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
4950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = gatt->init(&gatt_callbacks);
4960f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
4970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to initialize gatt interface");
4980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return -1;
4990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int status = pipe(pipefd);
5020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (status == -1) {
5030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "pipe creation failed: %s", strerror(errno));
5040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return -1;
5050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return 0;
5080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
5090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybt_status_t ServerInternals::AddCharacteristic(
5110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    const UUID& uuid,
5120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    int properties,
5130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    int permissions) {
5140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_uuid_t c_uuid = uuid.GetBlueDroid();
5150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return gatt->server->add_characteristic(
5160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      server_if, service_handle, &c_uuid, properties, permissions);
5170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
5180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5190f2d4897046f037a9f181f47f3d349a9dd646478Arman UgurayServerInternals::ServerInternals()
5200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    : gatt(nullptr),
5210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      server_if(0),
5220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      client_if(0),
5230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      service_handle(0),
5240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      pipefd{INVALID_FD, INVALID_FD} {}
5250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5260f2d4897046f037a9f181f47f3d349a9dd646478Arman UgurayServerInternals::~ServerInternals() {
5270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (pipefd[0] != INVALID_FD)
5280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    close(pipefd[0]);
5290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (pipefd[1] != INVALID_FD)
5300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    close(pipefd[1]);
5310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  gatt->server->delete_service(server_if, service_handle);
5330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  gatt->server->unregister_server(server_if);
5340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  gatt->client->unregister_client(client_if);
5350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
5360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5370f2d4897046f037a9f181f47f3d349a9dd646478Arman UgurayServer::Server() : internal_(nullptr) {}
5380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5390f2d4897046f037a9f181f47f3d349a9dd646478Arman UgurayServer::~Server() {}
5400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::Initialize(const UUID& service_id, int* gatt_pipe) {
5420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_.reset(new ServerInternals);
5430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (!internal_) {
5440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Error creating internals");
5450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
5460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  g_internal = internal_.get();
5480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_lock<std::mutex> lock(internal_->lock);
5500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  int status = internal_->Initialize();
5510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (status) {
5520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Error initializing internals");
5530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
5540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_uuid_t uuid = service_id.GetBlueDroid();
5570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->server->register_server(&uuid);
5590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
5600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to register server");
5610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
5620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
5650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // TODO(icoolidge): Better error handling.
5660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (internal_->server_if == 0) {
5670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Initialization of server failed");
5680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
5690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  *gatt_pipe = internal_->pipefd[kPipeReadEnd];
5720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  LOG_INFO(LOG_TAG, "Server Initialize succeeded");
5730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
5740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
5750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::SetAdvertisement(const std::vector<UUID>& ids,
5770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              const std::vector<uint8_t>& service_data,
5780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              const std::vector<uint8_t>& manufacturer_data,
5790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              bool transmit_name) {
5800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::vector<uint8_t> id_data;
5810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto mutable_manufacturer_data = manufacturer_data;
5820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto mutable_service_data = service_data;
5830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  for (const UUID &id : ids) {
5850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    const auto le_id = id.GetFullLittleEndian();
5860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    id_data.insert(id_data.end(), le_id.begin(), le_id.end());
5870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
5880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(internal_->lock);
5900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
5910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Setup our advertisement. This has no callback.
5920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->client->set_adv_data(
5930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      internal_->client_if, false, /* beacon, not scan response */
5940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      transmit_name,               /* name */
5950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      false,                       /* no txpower */
5960f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      2, 2,                        /* interval */
5970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0,                           /* appearance */
5980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      mutable_manufacturer_data.size(),
5990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(mutable_manufacturer_data.data()),
6000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      mutable_service_data.size(),
6010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
6020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(id_data.data()));
6030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
6040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to set advertising data");
6050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
6060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
6070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
6080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
6090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::SetScanResponse(const std::vector<UUID>& ids,
6110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                             const std::vector<uint8_t>& service_data,
6120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                             const std::vector<uint8_t>& manufacturer_data,
6130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                             bool transmit_name) {
6140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::vector<uint8_t> id_data;
6150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto mutable_manufacturer_data = manufacturer_data;
6160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  auto mutable_service_data = service_data;
6170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  for (const UUID &id : ids) {
6190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    const auto le_id = id.GetFullLittleEndian();
6200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    id_data.insert(id_data.end(), le_id.begin(), le_id.end());
6210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
6220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(internal_->lock);
6240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Setup our advertisement. This has no callback.
6260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->client->set_adv_data(
6270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      internal_->client_if, true, /* scan response */
6280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      transmit_name,              /* name */
6290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      false,                      /* no txpower */
6300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      2, 2,                       /* interval */
6310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      0,                          /* appearance */
6320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      mutable_manufacturer_data.size(),
6330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(mutable_manufacturer_data.data()),
6340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      mutable_service_data.size(),
6350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
6360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      reinterpret_cast<char *>(id_data.data()));
6370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
6380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to set scan response data");
6390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
6400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
6410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
6420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
6430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::AddCharacteristic(
6450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    const UUID &id, int properties, int permissions) {
6460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_lock<std::mutex> lock(internal_->lock);
6470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->AddCharacteristic(
6480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      id, properties, permissions);
6490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
6500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to add characteristic to service: 0x%04x",
6510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray              internal_->service_handle);
6520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
6530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
6540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
6550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const int handle = internal_->uuid_to_attribute[id];
6560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->characteristics[handle].notify = properties & kPropertyNotify;
6570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
6580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
6590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::AddBlob(const UUID &id, const UUID &control_id, int properties,
6610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                    int permissions) {
6620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_lock<std::mutex> lock(internal_->lock);
6630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // First, add the primary attribute (characteristic value)
6650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->AddCharacteristic(
6660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      id, properties, permissions);
6670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
6680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to set scan response data");
6690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
6700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
6710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
6730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Next, add the secondary attribute (blob control).
6750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Control attributes have fixed permissions/properties.
6760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  btstat = internal_->AddCharacteristic(
6770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      control_id,
6780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      kPropertyRead | kPropertyWrite,
6790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      kPermissionRead | kPermissionWrite);
6800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
6810f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6820f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Finally, associate the control attribute with the value attribute.
6830f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  // Also, initialize the control attribute to a readable zero.
6840f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const int control_attribute = internal_->uuid_to_attribute[control_id];
6850f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const int blob_attribute = internal_->uuid_to_attribute[id];
6860f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->controlled_blobs[control_attribute] = blob_attribute;
6870f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->characteristics[blob_attribute].notify =
6880f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      properties & kPropertyNotify;
6890f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6900f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  Characteristic &ctrl = internal_->characteristics[control_attribute];
6910f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ctrl.next_blob.clear();
6920f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ctrl.next_blob.push_back(0);
6930f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ctrl.next_blob_pending = true;
6940f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ctrl.blob_section = 0;
6950f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ctrl.notify = false;
6960f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
6970f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
6980f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
6990f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::Start() {
7000f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_lock<std::mutex> lock(internal_->lock);
7010f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->server->start_service(
7020f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
7030f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
7040f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to start service with handle: 0x%04x",
7050f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray              internal_->service_handle);
7060f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
7070f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
7080f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
7090f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7100f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7110f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7120f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::Stop() {
7130f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::unique_lock<std::mutex> lock(internal_->lock);
7140f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->server->stop_service(
7150f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray      internal_->server_if, internal_->service_handle);
7160f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat != BT_STATUS_SUCCESS) {
7170f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Failed to stop service with handle: 0x%04x",
7180f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray              internal_->service_handle);
7190f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
7200f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
7210f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  internal_->api_synchronize.wait(lock);
7220f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7230f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7240f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7250f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::ScanEnable() {
7260f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->client->scan(true);
7270f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat) {
7280f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Enable scan failed: %d", btstat);
7290f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
7300f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
7310f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7320f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7330f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7340f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::ScanDisable() {
7350f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  bt_status_t btstat = internal_->gatt->client->scan(false);
7360f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (btstat) {
7370f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    LOG_ERROR(LOG_TAG, "Disable scan failed: %d", btstat);
7380f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return false;
7390f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
7400f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7410f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7420f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7430f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::GetScanResults(ScanResults *results) {
7440f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(internal_->lock);
7450f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  *results = internal_->scan_results;
7460f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7470f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7480f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7490f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::SetCharacteristicValue(const UUID &id,
7500f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                              const std::vector<uint8_t> &value) {
7510f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(internal_->lock);
7520f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const int attribute_id = internal_->uuid_to_attribute[id];
7530f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  Characteristic &ch = internal_->characteristics[attribute_id];
7540f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ch.next_blob = value;
7550f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  ch.next_blob_pending = true;
7560f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7570f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  if (!ch.notify)
7580f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    return true;
7590f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7600f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  for (auto connection : internal_->connections) {
7610f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    char dummy = 0;
7620f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray    internal_->gatt->server->send_indication(internal_->server_if,
7630f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                             attribute_id,
7640f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                             connection,
7650f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                             sizeof(dummy),
7660f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                             true,
7670f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray                                             &dummy);
7680f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  }
7690f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7700f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7710f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7720f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguraybool Server::GetCharacteristicValue(const UUID &id, std::vector<uint8_t> *value) {
7730f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  std::lock_guard<std::mutex> lock(internal_->lock);
7740f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  const int attribute_id = internal_->uuid_to_attribute[id];
7750f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  *value = internal_->characteristics[attribute_id].blob;
7760f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray  return true;
7770f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}
7780f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray
7790f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace gatt
7800f2d4897046f037a9f181f47f3d349a9dd646478Arman Uguray}  // namespace bluetooth
781