• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //  Copyright 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 //
16 
17 #define LOG_TAG "bt_gatts"
18 
19 #include "gatt_server_old.h"
20 
21 #include <base/bind.h>
22 #include <base/callback.h>
23 #include <hardware/bluetooth.h>
24 #include <hardware/bt_gatt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 
29 #include <algorithm>
30 #include <array>
31 #include <condition_variable>
32 #include <map>
33 #include <memory>
34 #include <mutex>
35 #include <set>
36 #include <string>
37 #include <unordered_map>
38 #include <unordered_set>
39 #include <vector>
40 
41 #include "bind_helpers.h"
42 #include "osi/include/log.h"
43 #include "osi/include/osi.h"
44 #include "service/hal/bluetooth_interface.h"
45 #include "service/logging_helpers.h"
46 #include "types/raw_address.h"
47 
48 namespace {
49 
50 const size_t kMaxGattAttributeSize = 512;
51 std::vector<btgatt_db_element_t> pending_svc_decl;
52 std::unordered_set<int> blob_index;
53 
54 // TODO(icoolidge): Support multiple instances
55 // TODO(armansito): Remove this variable. No point of having this if
56 // each bluetooth::gatt::Server instance already keeps a pointer to the
57 // ServerInternals that is associated with it (which is much cleaner). It looks
58 // like this variable exists because the btif callbacks don't allow the
59 // upper-layer to pass user data to them. We could:
60 //
61 //    1. Fix the btif callbacks so that some sort of continuation can be
62 //    attached to a callback. This might be a long shot since the callback
63 //    interface doesn't allow more than one caller to register its own callbacks
64 //    (which might be what we want though, since this would make the API more
65 //    flexible).
66 //
67 //    2. Allow creation of Server objects using a factory method that returns
68 //    the result asynchronously in a base::Callback. The RegisterServerCallback
69 //    provides an |app_uuid|, which can be used to store callback structures in
70 //    a map and lazily instantiate the Server and invoke the correct callback.
71 //    This is a general pattern that we should use throughout the daemon, since
72 //    all operations can timeout or fail and this is best reported in an
73 //    asynchronous base::Callback.
74 //
75 static bluetooth::gatt::ServerInternals* g_internal = nullptr;
76 
77 enum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
78 
79 }  // namespace
80 
81 namespace bluetooth {
82 namespace gatt {
83 
84 struct Characteristic {
85   Uuid uuid;
86   int blob_section;
87   std::vector<uint8_t> blob;
88 
89   // Support synchronized blob updates by latching under mutex.
90   std::vector<uint8_t> next_blob;
91   bool next_blob_pending;
92   bool notify;
93 };
94 
95 struct ServerInternals {
96   ServerInternals();
97   ~ServerInternals();
98   int Initialize();
99   bt_status_t AddCharacteristic(const Uuid& uuid, uint8_t properties,
100                                 uint16_t permissions);
101 
102   // This maps API attribute Uuids to BlueDroid handles.
103   std::map<Uuid, int> uuid_to_attribute;
104 
105   // The attribute cache, indexed by BlueDroid handles.
106   std::unordered_map<int, Characteristic> characteristics;
107 
108   // Associate a control attribute with its value attribute.
109   std::unordered_map<int, int> controlled_blobs;
110 
111   ScanResults scan_results;
112 
113   Uuid last_write;
114   const btgatt_interface_t* gatt;
115   int server_if;
116   int client_if;
117   int service_handle;
118   std::set<int> connections;
119 
120   std::mutex lock;
121   std::condition_variable api_synchronize;
122   int pipefd[kPipeNumEnds];
123 };
124 
125 }  // namespace gatt
126 }  // namespace bluetooth
127 
128 namespace {
129 
130 /** Callback invoked in response to register_server */
RegisterServerCallback(int status,int server_if,const bluetooth::Uuid & app_uuid)131 void RegisterServerCallback(int status, int server_if,
132                             const bluetooth::Uuid& app_uuid) {
133   LOG_INFO("%s: status:%d server_if:%d app_uuid:%p", __func__, status,
134            server_if, &app_uuid);
135 
136   g_internal->server_if = server_if;
137 
138   pending_svc_decl.push_back({
139       .uuid = app_uuid,
140       .type = BTGATT_DB_PRIMARY_SERVICE,
141   });
142 }
143 
ServiceAddedCallback(int status,int server_if,const btgatt_db_element_t * service,size_t service_count)144 void ServiceAddedCallback(int status, int server_if,
145                           const btgatt_db_element_t* service,
146                           size_t service_count) {
147   LOG_INFO("%s: status:%d server_if:%d count:%zu svc_handle:%d", __func__,
148            status, server_if, service_count, service[0].attribute_handle);
149 
150   std::lock_guard<std::mutex> lock(g_internal->lock);
151   g_internal->server_if = server_if;
152 
153   g_internal->service_handle = service[0].attribute_handle;
154 
155   uint16_t prev_char_handle = 0;
156   uint16_t prev_char_properties = 0;
157   for (size_t i = 1; i < service_count; i++) {
158     const btgatt_db_element_t& el = service[i];
159     if (el.type == BTGATT_DB_DESCRIPTOR) {
160       LOG_INFO("%s: descr_handle:%d", __func__, el.attribute_handle);
161     } else if (el.type == BTGATT_DB_CHARACTERISTIC) {
162       bluetooth::Uuid id(el.uuid);
163       uint16_t char_handle = el.attribute_handle;
164 
165       LOG_INFO("%s: char_handle:%d", __func__, char_handle);
166 
167       g_internal->uuid_to_attribute[id] = char_handle;
168       g_internal->characteristics[char_handle].uuid = id;
169       g_internal->characteristics[char_handle].blob_section = 0;
170 
171       // If the added characteristic is blob
172       if (blob_index.find(i) != blob_index.end()) {
173         // Finally, associate the control attribute with the value attribute.
174         // Also, initialize the control attribute to a readable zero.
175         const uint16_t control_attribute = char_handle;
176         const uint16_t blob_attribute = prev_char_handle;
177         g_internal->controlled_blobs[control_attribute] = blob_attribute;
178         g_internal->characteristics[blob_attribute].notify =
179             prev_char_properties & bluetooth::gatt::kPropertyNotify;
180 
181         bluetooth::gatt::Characteristic& ctrl =
182             g_internal->characteristics[control_attribute];
183         ctrl.next_blob.clear();
184         ctrl.next_blob.push_back(0);
185         ctrl.next_blob_pending = true;
186         ctrl.blob_section = 0;
187         ctrl.notify = false;
188       }
189       prev_char_handle = char_handle;
190       prev_char_properties = el.properties;
191     }
192   }
193 
194   pending_svc_decl.clear();
195   blob_index.clear();
196 
197   // The Uuid provided here is unimportant, and is only used to satisfy
198   // BlueDroid.
199   // It must be different than any other registered Uuid.
200   bluetooth::Uuid client_id = bluetooth::Uuid::GetRandom();
201 
202   bt_status_t btstat =
203       g_internal->gatt->client->register_client(client_id, false);
204   if (btstat != BT_STATUS_SUCCESS) {
205     LOG_ERROR("%s: Failed to register client", __func__);
206   }
207 }
208 
RequestReadCallback(int conn_id,int trans_id,const RawAddress & bda,int attr_handle,int attribute_offset_octets,bool is_long)209 void RequestReadCallback(int conn_id, int trans_id, const RawAddress& bda,
210                          int attr_handle, int attribute_offset_octets,
211                          bool is_long) {
212   std::lock_guard<std::mutex> lock(g_internal->lock);
213 
214   bluetooth::gatt::Characteristic& ch =
215       g_internal->characteristics[attr_handle];
216 
217   // Latch next_blob to blob on a 'fresh' read.
218   if (ch.next_blob_pending && attribute_offset_octets == 0 &&
219       ch.blob_section == 0) {
220     std::swap(ch.blob, ch.next_blob);
221     ch.next_blob_pending = false;
222   }
223 
224   const size_t blob_offset_octets =
225       std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
226   const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
227   const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
228 
229   std::string addr(BtAddrString(&bda));
230   LOG_INFO(
231       "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
232       "blob_section:%u (is_long:%u)",
233       __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
234       ch.blob_section, is_long);
235 
236   btgatt_response_t response;
237   response.attr_value.len = 0;
238 
239   if (attribute_offset_octets < static_cast<int>(attribute_size)) {
240     std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
241               ch.blob.begin() + blob_offset_octets + attribute_size,
242               response.attr_value.value);
243     response.attr_value.len = attribute_size - attribute_offset_octets;
244   }
245 
246   response.attr_value.handle = attr_handle;
247   response.attr_value.offset = attribute_offset_octets;
248   response.attr_value.auth_req = 0;
249   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
250 }
251 
RequestWriteCallback(int conn_id,int trans_id,const RawAddress & bda,int attr_handle,int attribute_offset,bool need_rsp,bool is_prep,const uint8_t * value,size_t length)252 void RequestWriteCallback(int conn_id, int trans_id, const RawAddress& bda,
253                           int attr_handle, int attribute_offset, bool need_rsp,
254                           bool is_prep, const uint8_t* value, size_t length) {
255   std::string addr(BtAddrString(&bda));
256   LOG_INFO(
257       "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
258       "length:%zu "
259       "need_resp:%u is_prep:%u",
260       __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
261       length, need_rsp, is_prep);
262 
263   std::lock_guard<std::mutex> lock(g_internal->lock);
264 
265   bluetooth::gatt::Characteristic& ch =
266       g_internal->characteristics[attr_handle];
267 
268   ch.blob.resize(attribute_offset + length);
269 
270   std::copy(value, value + length, ch.blob.begin() + attribute_offset);
271 
272   auto target_blob = g_internal->controlled_blobs.find(attr_handle);
273   // If this is a control attribute, adjust offset of the target blob.
274   if (target_blob != g_internal->controlled_blobs.end() &&
275       ch.blob.size() == 1u) {
276     g_internal->characteristics[target_blob->second].blob_section = ch.blob[0];
277     LOG_INFO("%s: updating attribute %d blob_section to %u", __func__,
278              target_blob->second, ch.blob[0]);
279   } else if (!is_prep) {
280     // This is a single frame characteristic write.
281     // Notify upwards because we're done now.
282     const bluetooth::Uuid::UUID128Bit& attr_uuid = ch.uuid.To128BitBE();
283     ssize_t status;
284     OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
285                                attr_uuid.data(), attr_uuid.size()));
286     if (-1 == status)
287       LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
288   } else {
289     // This is a multi-frame characteristic write.
290     // Wait for an 'RequestExecWriteCallback' to notify completion.
291     g_internal->last_write = ch.uuid;
292   }
293 
294   // Respond only if needed.
295   if (!need_rsp) return;
296 
297   btgatt_response_t response;
298   response.attr_value.handle = attr_handle;
299   response.attr_value.offset = attribute_offset;
300   response.attr_value.len = length;
301   response.attr_value.auth_req = 0;
302   // Provide written data back to sender for the response.
303   // Remote stacks use this to validate the success of the write.
304   std::copy(value, value + length, response.attr_value.value);
305   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
306 }
307 
RequestExecWriteCallback(int conn_id,int trans_id,const RawAddress & bda,int exec_write)308 void RequestExecWriteCallback(int conn_id, int trans_id, const RawAddress& bda,
309                               int exec_write) {
310   std::string addr(BtAddrString(&bda));
311   LOG_INFO("%s: connection:%d (%s:trans:%d) exec_write:%d", __func__, conn_id,
312            addr.c_str(), trans_id, exec_write);
313 
314   // This 'response' data is unused for ExecWriteResponses.
315   // It is only used to pass BlueDroid argument validation.
316   btgatt_response_t response = {};
317   g_internal->gatt->server->send_response(conn_id, trans_id, 0, response);
318 
319   if (!exec_write) return;
320 
321   std::lock_guard<std::mutex> lock(g_internal->lock);
322   // Communicate the attribute Uuid as notification of a write update.
323   const bluetooth::Uuid::UUID128Bit uuid = g_internal->last_write.To128BitBE();
324   ssize_t status;
325   OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
326                              uuid.size()));
327   if (-1 == status)
328     LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
329 }
330 
ConnectionCallback(int conn_id,int server_if,int connected,const RawAddress & bda)331 void ConnectionCallback(int conn_id, int server_if, int connected,
332                         const RawAddress& bda) {
333   std::string addr(BtAddrString(&bda));
334   LOG_INFO("%s: connection:%d server_if:%d connected:%d addr:%s", __func__,
335            conn_id, server_if, connected, addr.c_str());
336   if (connected == 1) {
337     g_internal->connections.insert(conn_id);
338   } else if (connected == 0) {
339     g_internal->connections.erase(conn_id);
340   }
341 }
342 
EnableAdvertisingCallback(uint8_t status)343 void EnableAdvertisingCallback(uint8_t status) {
344   LOG_INFO("%s: status:%d", __func__, status);
345   // This terminates a Start call.
346   std::lock_guard<std::mutex> lock(g_internal->lock);
347   g_internal->api_synchronize.notify_one();
348 }
349 
RegisterClientCallback(int status,int client_if,const bluetooth::Uuid & app_uuid)350 void RegisterClientCallback(int status, int client_if,
351                             const bluetooth::Uuid& app_uuid) {
352   LOG_INFO("%s: status:%d client_if:%d uuid[0]:%s", __func__, status, client_if,
353            app_uuid.ToString().c_str());
354   g_internal->client_if = client_if;
355 
356   // Setup our advertisement. This has no callback.
357   g_internal->gatt->advertiser->SetData(0 /* std_inst */, false,
358                                         {/*TODO: put inverval 2,2 here*/},
359                                         base::DoNothing());
360 
361   g_internal->gatt->advertiser->Enable(
362       0 /* std_inst */, true, base::Bind(&EnableAdvertisingCallback),
363       0 /* no duration */, 0 /* no maxExtAdvEvent*/, base::DoNothing());
364 }
365 
ServiceStoppedCallback(int status,int server_if,int srvc_handle)366 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
367   LOG_INFO("%s: status:%d server_if:%d srvc_handle:%d", __func__, status,
368            server_if, srvc_handle);
369   // This terminates a Stop call.
370   // TODO(icoolidge): make this symmetric with start
371   std::lock_guard<std::mutex> lock(g_internal->lock);
372   g_internal->api_synchronize.notify_one();
373 }
374 
ScanResultCallback(uint16_t ble_evt_type,uint8_t addr_type,RawAddress * bda,uint8_t ble_primary_phy,uint8_t ble_secondary_phy,uint8_t ble_advertising_sid,int8_t ble_tx_power,int8_t rssi,uint16_t ble_periodic_adv_int,std::vector<uint8_t> adv_data,RawAddress * original_bda)375 void ScanResultCallback(uint16_t ble_evt_type, uint8_t addr_type,
376                         RawAddress* bda, uint8_t ble_primary_phy,
377                         uint8_t ble_secondary_phy, uint8_t ble_advertising_sid,
378                         int8_t ble_tx_power, int8_t rssi,
379                         uint16_t ble_periodic_adv_int,
380                         std::vector<uint8_t> adv_data,
381                         RawAddress* original_bda) {
382   std::string addr(BtAddrString(bda));
383   std::lock_guard<std::mutex> lock(g_internal->lock);
384   g_internal->scan_results[addr] = rssi;
385 }
386 
ClientConnectCallback(int conn_id,int status,int client_if,const RawAddress & bda)387 void ClientConnectCallback(int conn_id, int status, int client_if,
388                            const RawAddress& bda) {
389   std::string addr(BtAddrString(&bda));
390   LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
391            status, client_if, addr.c_str());
392 }
393 
ClientDisconnectCallback(int conn_id,int status,int client_if,const RawAddress & bda)394 void ClientDisconnectCallback(int conn_id, int status, int client_if,
395                               const RawAddress& bda) {
396   std::string addr(BtAddrString(&bda));
397   LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
398            status, client_if, addr.c_str());
399 }
400 
IndicationSentCallback(UNUSED_ATTR int conn_id,UNUSED_ATTR int status)401 void IndicationSentCallback(UNUSED_ATTR int conn_id, UNUSED_ATTR int status) {
402   // TODO(icoolidge): what to do
403 }
404 
ResponseConfirmationCallback(UNUSED_ATTR int status,UNUSED_ATTR int handle)405 void ResponseConfirmationCallback(UNUSED_ATTR int status,
406                                   UNUSED_ATTR int handle) {
407   // TODO(icoolidge): what to do
408 }
409 
410 const btgatt_server_callbacks_t gatt_server_callbacks = {
411     RegisterServerCallback,
412     ConnectionCallback,
413     ServiceAddedCallback,
414     ServiceStoppedCallback,
415     nullptr, /* service_deleted_cb */
416     RequestReadCallback,
417     RequestReadCallback,
418     RequestWriteCallback,
419     RequestWriteCallback,
420     RequestExecWriteCallback,
421     ResponseConfirmationCallback,
422     IndicationSentCallback,
423     nullptr, /* congestion_cb*/
424     nullptr, /* mtu_changed_cb */
425     nullptr, /* phy_update_cb */
426     nullptr, /* conn_update_cb */
427 };
428 
429 // TODO(eisenbach): Refactor GATT interface to not require servers
430 // to refer to the client interface.
431 const btgatt_client_callbacks_t gatt_client_callbacks = {
432     RegisterClientCallback,
433     ClientConnectCallback,
434     ClientDisconnectCallback,
435     nullptr, /* search_complete_cb; */
436     nullptr, /* register_for_notification_cb; */
437     nullptr, /* notify_cb; */
438     nullptr, /* read_characteristic_cb; */
439     nullptr, /* write_characteristic_cb; */
440     nullptr, /* read_descriptor_cb; */
441     nullptr, /* write_descriptor_cb; */
442     nullptr, /* execute_write_cb; */
443     nullptr, /* read_remote_rssi_cb; */
444     nullptr, /* configure_mtu_cb; */
445     nullptr, /* congestion_cb; */
446     nullptr, /* get_gatt_db_cb; */
447     nullptr, /* services_removed_cb */
448     nullptr, /* services_added_cb */
449     nullptr, /* phy_update_cb */
450     nullptr, /* conn_update_cb */
451     nullptr, /* service_changed_cb*/
452 };
453 
454 const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
455     ScanResultCallback,
456     nullptr, /* batchscan_reports_cb; */
457     nullptr, /* batchscan_threshold_cb; */
458     nullptr, /* track_adv_event_cb; */
459 };
460 
461 const btgatt_callbacks_t gatt_callbacks = {
462     /** Set to sizeof(btgatt_callbacks_t) */
463     sizeof(btgatt_callbacks_t),
464 
465     /** GATT Client callbacks */
466     &gatt_client_callbacks,
467 
468     /** GATT Server callbacks */
469     &gatt_server_callbacks,
470 
471     /** GATT Server callbacks */
472     &gatt_scanner_callbacks,
473 };
474 
475 }  // namespace
476 
477 namespace bluetooth {
478 namespace gatt {
479 
Initialize()480 int ServerInternals::Initialize() {
481   // Get the interface to the GATT profile.
482   const bt_interface_t* bt_iface =
483       hal::BluetoothInterface::Get()->GetHALInterface();
484   gatt = reinterpret_cast<const btgatt_interface_t*>(
485       bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
486   if (!gatt) {
487     LOG_ERROR("Error getting GATT interface");
488     return -1;
489   }
490 
491   bt_status_t btstat = gatt->init(&gatt_callbacks);
492   if (btstat != BT_STATUS_SUCCESS) {
493     LOG_ERROR("Failed to initialize gatt interface");
494     return -1;
495   }
496 
497   int status = pipe(pipefd);
498   if (status == -1) {
499     LOG_ERROR("pipe creation failed: %s", strerror(errno));
500     return -1;
501   }
502 
503   return 0;
504 }
505 
AddCharacteristic(const Uuid & uuid,uint8_t properties,uint16_t permissions)506 bt_status_t ServerInternals::AddCharacteristic(const Uuid& uuid,
507                                                uint8_t properties,
508                                                uint16_t permissions) {
509   pending_svc_decl.push_back({.uuid = uuid,
510                               .type = BTGATT_DB_CHARACTERISTIC,
511                               .properties = properties,
512                               .permissions = permissions});
513   return BT_STATUS_SUCCESS;
514 }
515 
ServerInternals()516 ServerInternals::ServerInternals()
517     : gatt(nullptr),
518       server_if(0),
519       client_if(0),
520       service_handle(0),
521       pipefd{INVALID_FD, INVALID_FD} {}
522 
~ServerInternals()523 ServerInternals::~ServerInternals() {
524   if (pipefd[0] != INVALID_FD) close(pipefd[0]);
525   if (pipefd[1] != INVALID_FD) close(pipefd[1]);
526 
527   gatt->server->delete_service(server_if, service_handle);
528   gatt->server->unregister_server(server_if);
529   gatt->client->unregister_client(client_if);
530 }
531 
Server()532 Server::Server() : internal_(nullptr) {}
533 
~Server()534 Server::~Server() {}
535 
Initialize(const Uuid & service_id,int * gatt_pipe)536 bool Server::Initialize(const Uuid& service_id, int* gatt_pipe) {
537   internal_.reset(new ServerInternals);
538   if (!internal_) {
539     LOG_ERROR("Error creating internals");
540     return false;
541   }
542   g_internal = internal_.get();
543 
544   std::unique_lock<std::mutex> lock(internal_->lock);
545   int status = internal_->Initialize();
546   if (status) {
547     LOG_ERROR("Error initializing internals");
548     return false;
549   }
550 
551   bt_status_t btstat =
552       internal_->gatt->server->register_server(service_id, false);
553   if (btstat != BT_STATUS_SUCCESS) {
554     LOG_ERROR("Failed to register server");
555     return false;
556   }
557 
558   internal_->api_synchronize.wait(lock);
559   // TODO(icoolidge): Better error handling.
560   if (internal_->server_if == 0) {
561     LOG_ERROR("Initialization of server failed");
562     return false;
563   }
564 
565   *gatt_pipe = internal_->pipefd[kPipeReadEnd];
566   LOG_INFO("Server Initialize succeeded");
567   return true;
568 }
569 
SetAdvertisement(const std::vector<Uuid> & ids,const std::vector<uint8_t> & service_data,const std::vector<uint8_t> & manufacturer_data,bool transmit_name)570 bool Server::SetAdvertisement(const std::vector<Uuid>& ids,
571                               const std::vector<uint8_t>& service_data,
572                               const std::vector<uint8_t>& manufacturer_data,
573                               bool transmit_name) {
574   // std::vector<uint8_t> id_data;
575   // const auto& mutable_manufacturer_data = manufacturer_data;
576   // const auto& mutable_service_data = service_data;
577 
578   // for (const Uuid &id : ids) {
579   //   const auto le_id = id.To128BitLE();
580   //   id_data.insert(id_data.end(), le_id.begin(), le_id.end());
581   // }
582 
583   std::lock_guard<std::mutex> lock(internal_->lock);
584 
585   // Setup our advertisement. This has no callback.
586   internal_->gatt->advertiser->SetData(0, false, /* beacon, not scan response */
587                                        {}, base::DoNothing());
588   // transmit_name,               /* name */
589   // 2, 2,                         interval
590   // mutable_manufacturer_data,
591   // mutable_service_data,
592   // id_data);
593   return true;
594 }
595 
SetScanResponse(const std::vector<Uuid> & ids,const std::vector<uint8_t> & service_data,const std::vector<uint8_t> & manufacturer_data,bool transmit_name)596 bool Server::SetScanResponse(const std::vector<Uuid>& ids,
597                              const std::vector<uint8_t>& service_data,
598                              const std::vector<uint8_t>& manufacturer_data,
599                              bool transmit_name) {
600   // std::vector<uint8_t> id_data;
601   // const auto& mutable_manufacturer_data = manufacturer_data;
602   // const auto& mutable_service_data = service_data;
603 
604   // for (const Uuid &id : ids) {
605   //   const auto le_id = id.To128BitLE();
606   //   id_data.insert(id_data.end(), le_id.begin(), le_id.end());
607   // }
608 
609   std::lock_guard<std::mutex> lock(internal_->lock);
610 
611   // Setup our advertisement. This has no callback.
612   internal_->gatt->advertiser->SetData(0, true, /* scan response */
613                                        {}, base::DoNothing());
614   // transmit_name,              /* name */
615   // false,                      /* no txpower */
616   // 2, 2,                        interval
617   // 0,                          /* appearance */
618   // mutable_manufacturer_data,
619   // mutable_service_data,
620   // id_data);
621   return true;
622 }
623 
AddCharacteristic(const Uuid & id,int properties,int permissions)624 bool Server::AddCharacteristic(const Uuid& id, int properties,
625                                int permissions) {
626   std::unique_lock<std::mutex> lock(internal_->lock);
627   bt_status_t btstat =
628       internal_->AddCharacteristic(id, properties, permissions);
629   if (btstat != BT_STATUS_SUCCESS) {
630     LOG_ERROR("Failed to add characteristic to service: 0x%04x",
631               internal_->service_handle);
632     return false;
633   }
634   internal_->api_synchronize.wait(lock);
635   const int handle = internal_->uuid_to_attribute[id];
636   internal_->characteristics[handle].notify = properties & kPropertyNotify;
637   return true;
638 }
639 
AddBlob(const Uuid & id,const Uuid & control_id,int properties,int permissions)640 bool Server::AddBlob(const Uuid& id, const Uuid& control_id, int properties,
641                      int permissions) {
642   std::unique_lock<std::mutex> lock(internal_->lock);
643 
644   // First, add the primary attribute (characteristic value)
645   bt_status_t btstat =
646       internal_->AddCharacteristic(id, properties, permissions);
647   if (btstat != BT_STATUS_SUCCESS) {
648     LOG_ERROR("Failed to set scan response data");
649     return false;
650   }
651 
652   // Next, add the secondary attribute (blob control).
653   // Control attributes have fixed permissions/properties.
654   // Remember position at which blob was added.
655   blob_index.insert(pending_svc_decl.size());
656   btstat =
657       internal_->AddCharacteristic(control_id, kPropertyRead | kPropertyWrite,
658                                    kPermissionRead | kPermissionWrite);
659 
660   return true;
661 }
662 
Start()663 bool Server::Start() {
664   std::unique_lock<std::mutex> lock(internal_->lock);
665   bt_status_t btstat = internal_->gatt->server->add_service(
666       internal_->server_if, pending_svc_decl.data(), pending_svc_decl.size());
667   if (btstat != BT_STATUS_SUCCESS) {
668     LOG_ERROR("Failed to start service with handle: 0x%04x",
669               internal_->service_handle);
670     return false;
671   }
672   internal_->api_synchronize.wait(lock);
673   return true;
674 }
675 
Stop()676 bool Server::Stop() {
677   std::unique_lock<std::mutex> lock(internal_->lock);
678   bt_status_t btstat = internal_->gatt->server->stop_service(
679       internal_->server_if, internal_->service_handle);
680   if (btstat != BT_STATUS_SUCCESS) {
681     LOG_ERROR("Failed to stop service with handle: 0x%04x",
682               internal_->service_handle);
683     return false;
684   }
685   internal_->api_synchronize.wait(lock);
686   return true;
687 }
688 
ScanEnable()689 bool Server::ScanEnable() {
690   internal_->gatt->scanner->Scan(true);
691   return true;
692 }
693 
ScanDisable()694 bool Server::ScanDisable() {
695   internal_->gatt->scanner->Scan(false);
696   return true;
697 }
698 
GetScanResults(ScanResults * results)699 bool Server::GetScanResults(ScanResults* results) {
700   std::lock_guard<std::mutex> lock(internal_->lock);
701   *results = internal_->scan_results;
702   return true;
703 }
704 
SetCharacteristicValue(const Uuid & id,const std::vector<uint8_t> & value)705 bool Server::SetCharacteristicValue(const Uuid& id,
706                                     const std::vector<uint8_t>& value) {
707   std::lock_guard<std::mutex> lock(internal_->lock);
708   const int attribute_id = internal_->uuid_to_attribute[id];
709   Characteristic& ch = internal_->characteristics[attribute_id];
710   ch.next_blob = value;
711   ch.next_blob_pending = true;
712 
713   if (!ch.notify) return true;
714 
715   std::vector<uint8_t> ind_value = {0};
716   for (auto connection : internal_->connections) {
717     internal_->gatt->server->send_indication(internal_->server_if, attribute_id,
718                                              connection, true, ind_value.data(),
719                                              ind_value.size());
720   }
721   return true;
722 }
723 
GetCharacteristicValue(const Uuid & id,std::vector<uint8_t> * value)724 bool Server::GetCharacteristicValue(const Uuid& id,
725                                     std::vector<uint8_t>* value) {
726   std::lock_guard<std::mutex> lock(internal_->lock);
727   const int attribute_id = internal_->uuid_to_attribute[id];
728   *value = internal_->characteristics[attribute_id].blob;
729   return true;
730 }
731 
732 }  // namespace gatt
733 }  // namespace bluetooth
734