OSDN Git Service

Serialize remote version query over LE am: 864e7734f2
[android-x86/system-bt.git] / service / gatt_server_old.cpp
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 <algorithm>
26 #include <array>
27 #include <condition_variable>
28 #include <map>
29 #include <memory>
30 #include <mutex>
31 #include <set>
32 #include <string>
33 #include <unordered_map>
34 #include <vector>
35
36 #include <hardware/bluetooth.h>
37 #include <hardware/bt_gatt.h>
38
39 #include "service/hal/bluetooth_interface.h"
40 #include "service/logging_helpers.h"
41
42 extern "C" {
43 #include "osi/include/log.h"
44 #include "osi/include/osi.h"
45 }  // extern "C"
46
47 namespace {
48
49 const size_t kMaxGattAttributeSize = 512;
50 // TODO(icoolidge): Difficult to generalize without knowing how many attributes.
51 const int kNumBlueDroidHandles = 60;
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
80 namespace bluetooth {
81 namespace gatt {
82
83 struct Characteristic {
84   UUID uuid;
85   int blob_section;
86   std::vector<uint8_t> blob;
87
88   // Support synchronized blob updates by latching under mutex.
89   std::vector<uint8_t> next_blob;
90   bool next_blob_pending;
91   bool notify;
92 };
93
94 struct ServerInternals {
95   ServerInternals();
96   ~ServerInternals();
97   int Initialize();
98   bt_status_t AddCharacteristic(
99       const UUID& uuid,
100       int properties,
101       int 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   btgatt_srvc_id_t service_id;
120   std::set<int> connections;
121
122   std::mutex lock;
123   std::condition_variable api_synchronize;
124   int pipefd[kPipeNumEnds];
125 };
126
127 }  // namespace gatt
128 }  // namespace bluetooth
129
130 namespace {
131
132 /** Callback invoked in response to register_server */
133 void RegisterServerCallback(int status, int server_if, bt_uuid_t *app_uuid) {
134   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d app_uuid:%p", __func__, status,
135            server_if, app_uuid);
136
137   g_internal->server_if = server_if;
138
139   btgatt_srvc_id_t service_id;
140   service_id.id.uuid = *app_uuid;
141   service_id.id.inst_id = 0;
142   service_id.is_primary = true;
143
144   g_internal->gatt->server->add_service(
145       server_if, &service_id, kNumBlueDroidHandles);
146 }
147
148 void ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
149                           int srvc_handle) {
150   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
151            __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
152
153   std::lock_guard<std::mutex> lock(g_internal->lock);
154   g_internal->server_if = server_if;
155   g_internal->service_handle = srvc_handle;
156   g_internal->service_id = *srvc_id;
157   // This finishes the Initialize call.
158   g_internal->api_synchronize.notify_one();
159 }
160
161 void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
162                          int attr_handle, int attribute_offset_octets,
163                          bool is_long) {
164   std::lock_guard<std::mutex> lock(g_internal->lock);
165
166   bluetooth::gatt::Characteristic &ch = g_internal->characteristics[attr_handle];
167
168   // Latch next_blob to blob on a 'fresh' read.
169   if (ch.next_blob_pending && attribute_offset_octets == 0 &&
170       ch.blob_section == 0) {
171     std::swap(ch.blob, ch.next_blob);
172     ch.next_blob_pending = false;
173   }
174
175   const size_t blob_offset_octets =
176       std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
177   const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
178   const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
179
180   std::string addr(BtAddrString(bda));
181   LOG_INFO(LOG_TAG,
182       "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
183       "blob_section:%u (is_long:%u)",
184       __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
185       ch.blob_section, is_long);
186
187   btgatt_response_t response;
188   response.attr_value.len = 0;
189
190   if (attribute_offset_octets < static_cast<int>(attribute_size)) {
191     std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
192               ch.blob.begin() + blob_offset_octets + attribute_size,
193               response.attr_value.value);
194     response.attr_value.len = attribute_size - attribute_offset_octets;
195   }
196
197   response.attr_value.handle = attr_handle;
198   response.attr_value.offset = attribute_offset_octets;
199   response.attr_value.auth_req = 0;
200   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
201 }
202
203 void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
204                           int attr_handle, int attribute_offset, int length,
205                           bool need_rsp, bool is_prep, uint8_t *value) {
206   std::string addr(BtAddrString(bda));
207   LOG_INFO(LOG_TAG,
208       "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
209       "length:%d "
210       "need_resp:%u is_prep:%u",
211       __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
212       length, need_rsp, is_prep);
213
214   std::lock_guard<std::mutex> lock(g_internal->lock);
215
216   bluetooth::gatt::Characteristic &ch =
217       g_internal->characteristics[attr_handle];
218
219   ch.blob.resize(attribute_offset + length);
220
221   std::copy(value, value + length, ch.blob.begin() + attribute_offset);
222
223   auto target_blob = g_internal->controlled_blobs.find(attr_handle);
224   // If this is a control attribute, adjust offset of the target blob.
225   if (target_blob != g_internal->controlled_blobs.end() &&
226       ch.blob.size() == 1u) {
227     g_internal->characteristics[target_blob->second].blob_section = ch.blob[0];
228     LOG_INFO(LOG_TAG, "%s: updating attribute %d blob_section to %u", __func__,
229         target_blob->second, ch.blob[0]);
230   } else if (!is_prep) {
231     // This is a single frame characteristic write.
232     // Notify upwards because we're done now.
233     const bluetooth::UUID::UUID128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
234     int status = write(g_internal->pipefd[kPipeWriteEnd], attr_uuid.data(),
235                        attr_uuid.size());
236     if (-1 == status)
237       LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
238   } else {
239     // This is a multi-frame characteristic write.
240     // Wait for an 'RequestExecWriteCallback' to notify completion.
241     g_internal->last_write = ch.uuid;
242   }
243
244   // Respond only if needed.
245   if (!need_rsp) return;
246
247   btgatt_response_t response;
248   response.attr_value.handle = attr_handle;
249   response.attr_value.offset = attribute_offset;
250   response.attr_value.len = length;
251   response.attr_value.auth_req = 0;
252   // Provide written data back to sender for the response.
253   // Remote stacks use this to validate the success of the write.
254   std::copy(value, value + length, response.attr_value.value);
255   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
256 }
257
258 void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
259                               int exec_write) {
260   std::string addr(BtAddrString(bda));
261   LOG_INFO(LOG_TAG, "%s: connection:%d (%s:trans:%d) exec_write:%d", __func__,
262       conn_id, addr.c_str(), trans_id, exec_write);
263
264   // This 'response' data is unused for ExecWriteResponses.
265   // It is only used to pass BlueDroid argument validation.
266   btgatt_response_t response = {};
267   g_internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
268
269   if (!exec_write)
270     return;
271
272   std::lock_guard<std::mutex> lock(g_internal->lock);
273   // Communicate the attribute UUID as notification of a write update.
274   const bluetooth::UUID::UUID128Bit uuid =
275       g_internal->last_write.GetFullBigEndian();
276   int status = write(g_internal->pipefd[kPipeWriteEnd],
277                      uuid.data(), uuid.size());
278   if (-1 == status)
279     LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
280 }
281
282 void ConnectionCallback(int conn_id, int server_if, int connected,
283                         bt_bdaddr_t *bda) {
284   std::string addr(BtAddrString(bda));
285   LOG_INFO(LOG_TAG, "%s: connection:%d server_if:%d connected:%d addr:%s",
286       __func__, conn_id, server_if, connected, addr.c_str());
287   if (connected == 1) {
288     g_internal->connections.insert(conn_id);
289   } else if (connected == 0) {
290     g_internal->connections.erase(conn_id);
291   }
292 }
293
294 void CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
295                                  int srvc_handle, int char_handle) {
296   LOG_INFO(LOG_TAG,
297       "%s: status:%d server_if:%d service_handle:%d char_handle:%d", __func__,
298       status, server_if, srvc_handle, char_handle);
299
300   bluetooth::UUID id(*uuid);
301
302   std::lock_guard<std::mutex> lock(g_internal->lock);
303
304   g_internal->uuid_to_attribute[id] = char_handle;
305   g_internal->characteristics[char_handle].uuid = id;
306   g_internal->characteristics[char_handle].blob_section = 0;
307
308   // This terminates an AddCharacteristic.
309   g_internal->api_synchronize.notify_one();
310 }
311
312 void DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
313                              int srvc_handle, int descr_handle) {
314   LOG_INFO(LOG_TAG,
315       "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
316       "descr_handle:%d",
317       __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
318 }
319
320 void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
321   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
322       status, server_if, srvc_handle);
323
324   // The UUID provided here is unimportant, and is only used to satisfy
325   // BlueDroid.
326   // It must be different than any other registered UUID.
327   bt_uuid_t client_id = g_internal->service_id.id.uuid;
328   ++client_id.uu[15];
329
330   bt_status_t btstat = g_internal->gatt->client->register_client(&client_id);
331   if (btstat != BT_STATUS_SUCCESS) {
332     LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
333   }
334 }
335
336 void RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
337   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
338       client_if, app_uuid->uu[0]);
339   g_internal->client_if = client_if;
340
341   // Setup our advertisement. This has no callback.
342   bt_status_t btstat = g_internal->gatt->client->set_adv_data(
343       client_if, false, /* beacon, not scan response */
344       false,            /* name */
345       false,            /* no txpower */
346       2, 2,             /* interval */
347       0,                /* appearance */
348       0, nullptr,       /* no mfg data */
349       0, nullptr,       /* no service data */
350       0, nullptr /* no service id yet */);
351   if (btstat != BT_STATUS_SUCCESS) {
352     LOG_ERROR(LOG_TAG, "Failed to set advertising data");
353     return;
354   }
355
356   // TODO(icoolidge): Deprecated, use multi-adv interface.
357   // This calls back to ListenCallback.
358   btstat = g_internal->gatt->client->listen(client_if, true);
359   if (btstat != BT_STATUS_SUCCESS) {
360     LOG_ERROR(LOG_TAG, "Failed to start listening");
361   }
362 }
363
364 void ListenCallback(int status, int client_if) {
365   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d", __func__, status, client_if);
366   // This terminates a Start call.
367   std::lock_guard<std::mutex> lock(g_internal->lock);
368   g_internal->api_synchronize.notify_one();
369 }
370
371 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
372   LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
373       status, server_if, srvc_handle);
374   // This terminates a Stop call.
375   // TODO(icoolidge): make this symmetric with start
376   std::lock_guard<std::mutex> lock(g_internal->lock);
377   g_internal->api_synchronize.notify_one();
378 }
379
380 void ScanResultCallback(bt_bdaddr_t *bda, int rssi, uint8_t *adv_data) {
381   std::string addr(BtAddrString(bda));
382   (void)adv_data;
383   std::lock_guard<std::mutex> lock(g_internal->lock);
384   g_internal->scan_results[addr] = rssi;
385 }
386
387 void ClientConnectCallback(int conn_id, int status, int client_if,
388                            bt_bdaddr_t *bda) {
389   std::string addr(BtAddrString(bda));
390   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
391       conn_id, status, client_if, addr.c_str());
392 }
393
394 void ClientDisconnectCallback(int conn_id, int status, int client_if,
395                               bt_bdaddr_t *bda) {
396   std::string addr(BtAddrString(bda));
397   LOG_INFO(LOG_TAG, "%s: conn_id:%d status:%d client_if:%d %s", __func__,
398       conn_id, status, client_if, addr.c_str());
399 }
400
401 void IndicationSentCallback(UNUSED_ATTR int conn_id,
402                             UNUSED_ATTR int status) {
403   // TODO(icoolidge): what to do
404 }
405
406 void ResponseConfirmationCallback(UNUSED_ATTR int status,
407                                   UNUSED_ATTR int handle) {
408   // TODO(icoolidge): what to do
409 }
410
411 const btgatt_server_callbacks_t gatt_server_callbacks = {
412     RegisterServerCallback,
413     ConnectionCallback,
414     ServiceAddedCallback,
415     nullptr, /* included_service_added_cb */
416     CharacteristicAddedCallback,
417     DescriptorAddedCallback,
418     ServiceStartedCallback,
419     ServiceStoppedCallback,
420     nullptr, /* service_deleted_cb */
421     RequestReadCallback,
422     RequestWriteCallback,
423     RequestExecWriteCallback,
424     ResponseConfirmationCallback,
425     IndicationSentCallback,
426     nullptr, /* congestion_cb*/
427     nullptr, /* mtu_changed_cb */
428 };
429
430 // TODO(eisenbach): Refactor GATT interface to not require servers
431 // to refer to the client interface.
432 const btgatt_client_callbacks_t gatt_client_callbacks = {
433     RegisterClientCallback,
434     ScanResultCallback,
435     ClientConnectCallback,
436     ClientDisconnectCallback,
437     nullptr, /* search_complete_cb; */
438     nullptr, /* search_result_cb; */
439     nullptr, /* get_characteristic_cb; */
440     nullptr, /* get_descriptor_cb; */
441     nullptr, /* get_included_service_cb; */
442     nullptr, /* register_for_notification_cb; */
443     nullptr, /* notify_cb; */
444     nullptr, /* read_characteristic_cb; */
445     nullptr, /* write_characteristic_cb; */
446     nullptr, /* read_descriptor_cb; */
447     nullptr, /* write_descriptor_cb; */
448     nullptr, /* execute_write_cb; */
449     nullptr, /* read_remote_rssi_cb; */
450     ListenCallback,
451     nullptr, /* configure_mtu_cb; */
452     nullptr, /* scan_filter_cfg_cb; */
453     nullptr, /* scan_filter_param_cb; */
454     nullptr, /* scan_filter_status_cb; */
455     nullptr, /* multi_adv_enable_cb */
456     nullptr, /* multi_adv_update_cb; */
457     nullptr, /* multi_adv_data_cb*/
458     nullptr, /* multi_adv_disable_cb; */
459     nullptr, /* congestion_cb; */
460     nullptr, /* batchscan_cfg_storage_cb; */
461     nullptr, /* batchscan_enb_disable_cb; */
462     nullptr, /* batchscan_reports_cb; */
463     nullptr, /* batchscan_threshold_cb; */
464     nullptr, /* track_adv_event_cb; */
465     nullptr, /* scan_parameter_setup_completed_cb; */
466 };
467
468 const btgatt_callbacks_t gatt_callbacks = {
469     /** Set to sizeof(btgatt_callbacks_t) */
470     sizeof(btgatt_callbacks_t),
471
472     /** GATT Client callbacks */
473     &gatt_client_callbacks,
474
475     /** GATT Server callbacks */
476     &gatt_server_callbacks};
477
478 }  // namespace
479
480 namespace bluetooth {
481 namespace gatt {
482
483 int ServerInternals::Initialize() {
484   // Get the interface to the GATT profile.
485   const bt_interface_t* bt_iface =
486       hal::BluetoothInterface::Get()->GetHALInterface();
487   gatt = reinterpret_cast<const btgatt_interface_t *>(
488       bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
489   if (!gatt) {
490     LOG_ERROR(LOG_TAG, "Error getting GATT interface");
491     return -1;
492   }
493
494   bt_status_t btstat = gatt->init(&gatt_callbacks);
495   if (btstat != BT_STATUS_SUCCESS) {
496     LOG_ERROR(LOG_TAG, "Failed to initialize gatt interface");
497     return -1;
498   }
499
500   int status = pipe(pipefd);
501   if (status == -1) {
502     LOG_ERROR(LOG_TAG, "pipe creation failed: %s", strerror(errno));
503     return -1;
504   }
505
506   return 0;
507 }
508
509 bt_status_t ServerInternals::AddCharacteristic(
510     const UUID& uuid,
511     int properties,
512     int permissions) {
513   bt_uuid_t c_uuid = uuid.GetBlueDroid();
514   return gatt->server->add_characteristic(
515       server_if, service_handle, &c_uuid, properties, permissions);
516 }
517
518 ServerInternals::ServerInternals()
519     : gatt(nullptr),
520       server_if(0),
521       client_if(0),
522       service_handle(0),
523       pipefd{INVALID_FD, INVALID_FD} {}
524
525 ServerInternals::~ServerInternals() {
526   if (pipefd[0] != INVALID_FD)
527     close(pipefd[0]);
528   if (pipefd[1] != INVALID_FD)
529     close(pipefd[1]);
530
531   gatt->server->delete_service(server_if, service_handle);
532   gatt->server->unregister_server(server_if);
533   gatt->client->unregister_client(client_if);
534 }
535
536 Server::Server() : internal_(nullptr) {}
537
538 Server::~Server() {}
539
540 bool Server::Initialize(const UUID& service_id, int* gatt_pipe) {
541   internal_.reset(new ServerInternals);
542   if (!internal_) {
543     LOG_ERROR(LOG_TAG, "Error creating internals");
544     return false;
545   }
546   g_internal = internal_.get();
547
548   std::unique_lock<std::mutex> lock(internal_->lock);
549   int status = internal_->Initialize();
550   if (status) {
551     LOG_ERROR(LOG_TAG, "Error initializing internals");
552     return false;
553   }
554
555   bt_uuid_t uuid = service_id.GetBlueDroid();
556
557   bt_status_t btstat = internal_->gatt->server->register_server(&uuid);
558   if (btstat != BT_STATUS_SUCCESS) {
559     LOG_ERROR(LOG_TAG, "Failed to register server");
560     return false;
561   }
562
563   internal_->api_synchronize.wait(lock);
564   // TODO(icoolidge): Better error handling.
565   if (internal_->server_if == 0) {
566     LOG_ERROR(LOG_TAG, "Initialization of server failed");
567     return false;
568   }
569
570   *gatt_pipe = internal_->pipefd[kPipeReadEnd];
571   LOG_INFO(LOG_TAG, "Server Initialize succeeded");
572   return true;
573 }
574
575 bool Server::SetAdvertisement(const std::vector<UUID>& ids,
576                               const std::vector<uint8_t>& service_data,
577                               const std::vector<uint8_t>& manufacturer_data,
578                               bool transmit_name) {
579   std::vector<uint8_t> id_data;
580   auto mutable_manufacturer_data = manufacturer_data;
581   auto mutable_service_data = service_data;
582
583   for (const UUID &id : ids) {
584     const auto le_id = id.GetFullLittleEndian();
585     id_data.insert(id_data.end(), le_id.begin(), le_id.end());
586   }
587
588   std::lock_guard<std::mutex> lock(internal_->lock);
589
590   // Setup our advertisement. This has no callback.
591   bt_status_t btstat = internal_->gatt->client->set_adv_data(
592       internal_->client_if, false, /* beacon, not scan response */
593       transmit_name,               /* name */
594       false,                       /* no txpower */
595       2, 2,                        /* interval */
596       0,                           /* appearance */
597       mutable_manufacturer_data.size(),
598       reinterpret_cast<char *>(mutable_manufacturer_data.data()),
599       mutable_service_data.size(),
600       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
601       reinterpret_cast<char *>(id_data.data()));
602   if (btstat != BT_STATUS_SUCCESS) {
603     LOG_ERROR(LOG_TAG, "Failed to set advertising data");
604     return false;
605   }
606   return true;
607 }
608
609 bool Server::SetScanResponse(const std::vector<UUID>& ids,
610                              const std::vector<uint8_t>& service_data,
611                              const std::vector<uint8_t>& manufacturer_data,
612                              bool transmit_name) {
613   std::vector<uint8_t> id_data;
614   auto mutable_manufacturer_data = manufacturer_data;
615   auto mutable_service_data = service_data;
616
617   for (const UUID &id : ids) {
618     const auto le_id = id.GetFullLittleEndian();
619     id_data.insert(id_data.end(), le_id.begin(), le_id.end());
620   }
621
622   std::lock_guard<std::mutex> lock(internal_->lock);
623
624   // Setup our advertisement. This has no callback.
625   bt_status_t btstat = internal_->gatt->client->set_adv_data(
626       internal_->client_if, true, /* scan response */
627       transmit_name,              /* name */
628       false,                      /* no txpower */
629       2, 2,                       /* interval */
630       0,                          /* appearance */
631       mutable_manufacturer_data.size(),
632       reinterpret_cast<char *>(mutable_manufacturer_data.data()),
633       mutable_service_data.size(),
634       reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
635       reinterpret_cast<char *>(id_data.data()));
636   if (btstat != BT_STATUS_SUCCESS) {
637     LOG_ERROR(LOG_TAG, "Failed to set scan response data");
638     return false;
639   }
640   return true;
641 }
642
643 bool Server::AddCharacteristic(
644     const UUID &id, int properties, int permissions) {
645   std::unique_lock<std::mutex> lock(internal_->lock);
646   bt_status_t btstat = internal_->AddCharacteristic(
647       id, properties, permissions);
648   if (btstat != BT_STATUS_SUCCESS) {
649     LOG_ERROR(LOG_TAG, "Failed to add characteristic to service: 0x%04x",
650               internal_->service_handle);
651     return false;
652   }
653   internal_->api_synchronize.wait(lock);
654   const int handle = internal_->uuid_to_attribute[id];
655   internal_->characteristics[handle].notify = properties & kPropertyNotify;
656   return true;
657 }
658
659 bool Server::AddBlob(const UUID &id, const UUID &control_id, int properties,
660                     int permissions) {
661   std::unique_lock<std::mutex> lock(internal_->lock);
662
663   // First, add the primary attribute (characteristic value)
664   bt_status_t btstat = internal_->AddCharacteristic(
665       id, properties, permissions);
666   if (btstat != BT_STATUS_SUCCESS) {
667     LOG_ERROR(LOG_TAG, "Failed to set scan response data");
668     return false;
669   }
670
671   internal_->api_synchronize.wait(lock);
672
673   // Next, add the secondary attribute (blob control).
674   // Control attributes have fixed permissions/properties.
675   btstat = internal_->AddCharacteristic(
676       control_id,
677       kPropertyRead | kPropertyWrite,
678       kPermissionRead | kPermissionWrite);
679   internal_->api_synchronize.wait(lock);
680
681   // Finally, associate the control attribute with the value attribute.
682   // Also, initialize the control attribute to a readable zero.
683   const int control_attribute = internal_->uuid_to_attribute[control_id];
684   const int blob_attribute = internal_->uuid_to_attribute[id];
685   internal_->controlled_blobs[control_attribute] = blob_attribute;
686   internal_->characteristics[blob_attribute].notify =
687       properties & kPropertyNotify;
688
689   Characteristic &ctrl = internal_->characteristics[control_attribute];
690   ctrl.next_blob.clear();
691   ctrl.next_blob.push_back(0);
692   ctrl.next_blob_pending = true;
693   ctrl.blob_section = 0;
694   ctrl.notify = false;
695   return true;
696 }
697
698 bool Server::Start() {
699   std::unique_lock<std::mutex> lock(internal_->lock);
700   bt_status_t btstat = internal_->gatt->server->start_service(
701       internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
702   if (btstat != BT_STATUS_SUCCESS) {
703     LOG_ERROR(LOG_TAG, "Failed to start service with handle: 0x%04x",
704               internal_->service_handle);
705     return false;
706   }
707   internal_->api_synchronize.wait(lock);
708   return true;
709 }
710
711 bool Server::Stop() {
712   std::unique_lock<std::mutex> lock(internal_->lock);
713   bt_status_t btstat = internal_->gatt->server->stop_service(
714       internal_->server_if, internal_->service_handle);
715   if (btstat != BT_STATUS_SUCCESS) {
716     LOG_ERROR(LOG_TAG, "Failed to stop service with handle: 0x%04x",
717               internal_->service_handle);
718     return false;
719   }
720   internal_->api_synchronize.wait(lock);
721   return true;
722 }
723
724 bool Server::ScanEnable() {
725   bt_status_t btstat = internal_->gatt->client->scan(true);
726   if (btstat) {
727     LOG_ERROR(LOG_TAG, "Enable scan failed: %d", btstat);
728     return false;
729   }
730   return true;
731 }
732
733 bool Server::ScanDisable() {
734   bt_status_t btstat = internal_->gatt->client->scan(false);
735   if (btstat) {
736     LOG_ERROR(LOG_TAG, "Disable scan failed: %d", btstat);
737     return false;
738   }
739   return true;
740 }
741
742 bool Server::GetScanResults(ScanResults *results) {
743   std::lock_guard<std::mutex> lock(internal_->lock);
744   *results = internal_->scan_results;
745   return true;
746 }
747
748 bool Server::SetCharacteristicValue(const UUID &id,
749                               const std::vector<uint8_t> &value) {
750   std::lock_guard<std::mutex> lock(internal_->lock);
751   const int attribute_id = internal_->uuid_to_attribute[id];
752   Characteristic &ch = internal_->characteristics[attribute_id];
753   ch.next_blob = value;
754   ch.next_blob_pending = true;
755
756   if (!ch.notify)
757     return true;
758
759   for (auto connection : internal_->connections) {
760     char dummy = 0;
761     internal_->gatt->server->send_indication(internal_->server_if,
762                                              attribute_id,
763                                              connection,
764                                              sizeof(dummy),
765                                              true,
766                                              &dummy);
767   }
768   return true;
769 }
770
771 bool Server::GetCharacteristicValue(const UUID &id, std::vector<uint8_t> *value) {
772   std::lock_guard<std::mutex> lock(internal_->lock);
773   const int attribute_id = internal_->uuid_to_attribute[id];
774   *value = internal_->characteristics[attribute_id].blob;
775   return true;
776 }
777
778 }  // namespace gatt
779 }  // namespace bluetooth