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