blob: bb92b5095d65d5690bee7bf7c9efa45355756d60 [file] [log] [blame]
Ian Coolidge611fcf92015-06-03 17:20:30 -07001//
2// Copyright (C) 2015 Google, Inc.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Marie Janssen49a86702015-07-08 11:48:57 -070016
Arman Uguray0f2d4892015-09-22 14:20:42 -070017#include "service/gatt_server.h"
Marie Janssen49a86702015-07-08 11:48:57 -070018
Arman Uguraydf0b2712015-09-23 17:25:54 -070019#include "service/hal/gatt_helpers.h"
20
Arman Uguray0f2d4892015-09-22 14:20:42 -070021using std::lock_guard;
22using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070023
24namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070025
Arman Uguray0f2d4892015-09-22 14:20:42 -070026// GattServer implementation
27// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070028
Arman Uguray0f2d4892015-09-22 14:20:42 -070029GattServer::GattServer(const UUID& uuid, int server_if)
30 : app_identifier_(uuid),
31 server_if_(server_if) {
Ian Coolidge611fcf92015-06-03 17:20:30 -070032}
33
Arman Uguray0f2d4892015-09-22 14:20:42 -070034GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070035 // Automatically unregister the server.
36 VLOG(1) << "GattServer unregistering: " << server_if_;
37
38 // Unregister as observer so we no longer receive any callbacks.
39 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
40
41 // Unregister this server, stop all services, and ignore the result.
42 // TODO(armansito): stop and remove all services here? unregister_server
43 // should really take care of that.
Arman Uguray0f2d4892015-09-22 14:20:42 -070044 hal::BluetoothGattInterface::Get()->
45 GetServerHALInterface()->unregister_server(server_if_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070046}
47
Arman Uguray0f2d4892015-09-22 14:20:42 -070048const UUID& GattServer::GetAppIdentifier() const {
49 return app_identifier_;
50}
Ian Coolidge611fcf92015-06-03 17:20:30 -070051
Arman Uguray0f2d4892015-09-22 14:20:42 -070052int GattServer::GetClientId() const {
53 return server_if_;
54}
Ian Coolidge611fcf92015-06-03 17:20:30 -070055
Arman Uguraydf0b2712015-09-23 17:25:54 -070056std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration(
57 const UUID& uuid, bool is_primary) {
Arman Uguray91613742015-09-24 22:45:16 -070058 VLOG(1) << __func__ << " server_if: " << server_if_
Arman Uguraydf0b2712015-09-23 17:25:54 -070059 << " - UUID: " << uuid.ToString()
60 << ", is_primary: " << is_primary;
61 lock_guard<mutex> lock(mutex_);
62
63 if (pending_decl_) {
64 LOG(ERROR) << "Already began service declaration";
65 return nullptr;
66 }
67
68 CHECK(!pending_id_);
69 CHECK(!pending_decl_);
70 CHECK(!pending_end_decl_cb_);
71
72 // Calculate the instance ID for this service by searching through the handle
73 // map to see how many occurrences of the same service UUID we find.
74 int inst_id = 0;
75 for (const auto& iter : handle_map_) {
76 const GattIdentifier* gatt_id = &iter.first;
77
78 if (!gatt_id->IsService())
79 continue;
80
81 if (gatt_id->service_uuid() == uuid)
82 ++inst_id;
83 }
84
85 // Pass empty string for the address as this is a local service.
86 auto service_id = GattIdentifier::CreateServiceId(
87 "", inst_id, uuid, is_primary);
88
Arman Uguray91613742015-09-24 22:45:16 -070089 // Pass 0 for permissions and properties as this is a service decl.
90 AttributeEntry entry(
91 *service_id, kCharacteristicPropertyNone, kAttributePermissionNone);
92
Arman Uguraydf0b2712015-09-23 17:25:54 -070093 pending_decl_.reset(new ServiceDeclaration());
94 pending_decl_->num_handles++; // 1 handle for the service decl. attribute
95 pending_decl_->service_id = *service_id;
Arman Uguray91613742015-09-24 22:45:16 -070096 pending_decl_->attributes.push_back(entry);
Arman Uguraydf0b2712015-09-23 17:25:54 -070097
98 return service_id;
99}
100
Arman Uguray91613742015-09-24 22:45:16 -0700101std::unique_ptr<GattIdentifier> GattServer::AddCharacteristic(
102 const UUID& uuid, int properties, int permissions) {
103 VLOG(1) << __func__ << " server_if: " << server_if_
104 << " - UUID: " << uuid.ToString()
105 << ", properties: " << properties
106 << ", permissions: " << permissions;
107 lock_guard<mutex> lock(mutex_);
108
109 if (!pending_decl_) {
110 LOG(ERROR) << "Service declaration not begun";
111 return nullptr;
112 }
113
114 // Calculate the instance ID for this characteristic by searching through the
115 // pending entries.
116 int inst_id = 0;
117 for (const auto& entry : pending_decl_->attributes) {
118 const GattIdentifier* gatt_id = &entry.id;
119
120 if (!gatt_id->IsCharacteristic())
121 continue;
122
123 if (gatt_id->characteristic_uuid() == uuid)
124 ++inst_id;
125 }
126
127 CHECK(pending_decl_->service_id.IsService());
128
129 auto char_id = GattIdentifier::CreateCharacteristicId(
130 inst_id, uuid, pending_decl_->service_id);
131
132 AttributeEntry entry(*char_id, properties, permissions);
133
134 // 2 handles for the characteristic declaration and the value attributes.
135 pending_decl_->num_handles += 2;
136 pending_decl_->attributes.push_back(entry);
137
138 return char_id;
139}
140
Arman Uguraydf0b2712015-09-23 17:25:54 -0700141bool GattServer::EndServiceDeclaration(const ResultCallback& callback) {
Arman Uguray91613742015-09-24 22:45:16 -0700142 VLOG(1) << __func__ << " server_if: " << server_if_;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700143 lock_guard<mutex> lock(mutex_);
144
145 if (!callback) {
146 LOG(ERROR) << "|callback| cannot be NULL";
147 return false;
148 }
149
150 if (!pending_decl_) {
151 LOG(ERROR) << "Service declaration not begun";
152 return false;
153 }
154
155 if (pending_end_decl_cb_) {
156 LOG(ERROR) << "EndServiceDeclaration already in progress";
157 return false;
158 }
159
160 CHECK(!pending_id_);
161
162 // There has to be at least one entry here for the service declaration
163 // attribute.
164 CHECK(pending_decl_->num_handles > 0);
165 CHECK(!pending_decl_->attributes.empty());
166
167 std::unique_ptr<GattIdentifier> service_id = PopNextId();
168 CHECK(service_id->IsService());
169 CHECK(*service_id == pending_decl_->service_id);
170
171 btgatt_srvc_id_t hal_id;
172 hal::GetHALServiceId(*service_id, &hal_id);
173
174 bt_status_t status = hal::BluetoothGattInterface::Get()->
175 GetServerHALInterface()->add_service(
176 server_if_, &hal_id, pending_decl_->num_handles);
177 if (status != BT_STATUS_SUCCESS) {
178 LOG(ERROR) << "Failed to initiate call to populate GATT service";
179 CleanUpPendingData();
180 return false;
181 }
182
183 pending_id_ = std::move(service_id);
184 pending_end_decl_cb_ = callback;
185
186 return true;
187}
188
189void GattServer::ServiceAddedCallback(
190 hal::BluetoothGattInterface* gatt_iface,
191 int status, int server_if,
192 const btgatt_srvc_id_t& srvc_id,
Arman Uguray91613742015-09-24 22:45:16 -0700193 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700194 lock_guard<mutex> lock(mutex_);
195
196 if (server_if != server_if_)
197 return;
198
199 // Construct a GATT identifier.
200 auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
201 CHECK(pending_id_);
202 CHECK(*gatt_id == *pending_id_);
203 CHECK(*gatt_id == pending_decl_->service_id);
204 CHECK(pending_id_->IsService());
205
Arman Uguray91613742015-09-24 22:45:16 -0700206 VLOG(1) << __func__ << " - status: " << status
207 << " server_if: " << server_if
208 << " handle: " << service_handle
Arman Uguraydf0b2712015-09-23 17:25:54 -0700209 << " UUID: " << gatt_id->service_uuid().ToString();
210
211 if (status != BT_STATUS_SUCCESS) {
212 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
213 return;
214 }
215
216 // Add this to the handle map.
Arman Uguray91613742015-09-24 22:45:16 -0700217 pending_handle_map_[*gatt_id] = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700218 CHECK(-1 == pending_decl_->service_handle);
Arman Uguray91613742015-09-24 22:45:16 -0700219 pending_decl_->service_handle = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700220
Arman Uguray91613742015-09-24 22:45:16 -0700221 HandleNextEntry(gatt_iface);
222}
Arman Uguraydf0b2712015-09-23 17:25:54 -0700223
Arman Uguray91613742015-09-24 22:45:16 -0700224void GattServer::CharacteristicAddedCallback(
225 hal::BluetoothGattInterface* gatt_iface,
226 int status, int server_if,
227 const bt_uuid_t& uuid,
228 int service_handle,
229 int char_handle) {
230 lock_guard<mutex> lock(mutex_);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700231
Arman Uguray91613742015-09-24 22:45:16 -0700232 if (server_if != server_if_)
233 return;
234
235 CHECK(pending_decl_);
236 CHECK(pending_decl_->service_handle == service_handle);
237 CHECK(pending_id_);
238 CHECK(pending_id_->IsCharacteristic());
239 CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
240
241 VLOG(1) << __func__ << " - status: " << status
242 << " server_if: " << server_if
243 << " service_handle: " << service_handle
244 << " char_handle: " << char_handle;
245
246 if (status != BT_STATUS_SUCCESS) {
247 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
248 pending_decl_->service_id);
249 return;
250 }
251
252 // Add this to the handle map and continue.
253 pending_handle_map_[*pending_id_] = char_handle;
254 HandleNextEntry(gatt_iface);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700255}
256
257void GattServer::ServiceStartedCallback(
258 hal::BluetoothGattInterface* gatt_iface,
259 int status, int server_if,
Arman Uguray91613742015-09-24 22:45:16 -0700260 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700261 lock_guard<mutex> lock(mutex_);
262
263 if (server_if != server_if_)
264 return;
265
266 CHECK(pending_id_);
267 CHECK(pending_decl_);
Arman Uguray91613742015-09-24 22:45:16 -0700268 CHECK(pending_decl_->service_handle == service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700269
270 VLOG(1) << __func__ << " - server_if: " << server_if
Arman Uguray91613742015-09-24 22:45:16 -0700271 << " handle: " << service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700272
273 // If we failed to start the service, remove it from the database and ignore
274 // the result.
275 if (status != BT_STATUS_SUCCESS) {
276 gatt_iface->GetServerHALInterface()->delete_service(
Arman Uguray91613742015-09-24 22:45:16 -0700277 server_if_, service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700278 }
279
280 // Complete the operation.
281 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
282 pending_decl_->service_id);
283}
284
285void GattServer::ServiceStoppedCallback(
286 hal::BluetoothGattInterface* /* gatt_iface */,
287 int /* status */,
288 int /* server_if */,
Arman Uguray91613742015-09-24 22:45:16 -0700289 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700290 // TODO(armansito): Support stopping a service.
291}
292
293void GattServer::NotifyEndCallbackAndClearData(
294 BLEStatus status, const GattIdentifier& id) {
295 VLOG(1) << __func__ << " status: " << status;
296 CHECK(pending_end_decl_cb_);
297
298 if (status == BLE_STATUS_SUCCESS)
299 handle_map_.insert(pending_handle_map_.begin(), pending_handle_map_.end());
300
301 pending_end_decl_cb_(status, id);
302
303 CleanUpPendingData();
304}
305
306void GattServer::CleanUpPendingData() {
307 pending_id_ = nullptr;
308 pending_decl_ = nullptr;
309 pending_end_decl_cb_ = ResultCallback();
310 pending_handle_map_.clear();
311}
312
Arman Uguray91613742015-09-24 22:45:16 -0700313void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
314 CHECK(pending_decl_);
315 CHECK(gatt_iface);
316
317 auto next_entry = PopNextEntry();
318 if (!next_entry) {
319 // No more entries. Call start_service to finish up.
320 bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
321 server_if_,
322 pending_decl_->service_handle,
323 TRANSPORT_BREDR | TRANSPORT_LE);
324
325 // Terminate the procedure in the case of an error.
326 if (status != BT_STATUS_SUCCESS) {
327 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
328 pending_decl_->service_id);
329 }
330
331 return;
332 }
333
334 if (next_entry->id.IsCharacteristic()) {
335 bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
336 bt_status_t status = gatt_iface->GetServerHALInterface()->
337 add_characteristic(
338 server_if_,
339 pending_decl_->service_handle,
340 &char_uuid,
341 next_entry->char_properties,
342 next_entry->permissions);
343
344 // Terminate the procedure in the case of an error.
345 if (status != BT_STATUS_SUCCESS) {
346 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
347 pending_decl_->service_id);
348 return;
349 }
350
351 pending_id_.reset(new GattIdentifier(next_entry->id));
352
353 return;
354 }
355
356 NOTREACHED() << "Unexpected entry type";
357}
358
359std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700360 CHECK(pending_decl_);
361
362 if (pending_decl_->attributes.empty())
363 return nullptr;
364
Arman Uguray91613742015-09-24 22:45:16 -0700365 const auto& next = pending_decl_->attributes.front();
366 std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700367
Arman Uguray91613742015-09-24 22:45:16 -0700368 pending_decl_->attributes.pop_front();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700369
Arman Uguray91613742015-09-24 22:45:16 -0700370 return entry;
371}
372
373std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
374 auto entry = PopNextEntry();
375 if (!entry)
376 return nullptr;
377
378 return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700379}
380
Arman Uguray0f2d4892015-09-22 14:20:42 -0700381// GattServerFactory implementation
382// ========================================================
383
384GattServerFactory::GattServerFactory() {
385 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
386}
387
388GattServerFactory::~GattServerFactory() {
389 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
390}
391
392bool GattServerFactory::RegisterClient(const UUID& uuid,
393 const RegisterCallback& callback) {
394 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
395 lock_guard<mutex> lock(pending_calls_lock_);
396
397 if (pending_calls_.find(uuid) != pending_calls_.end()) {
398 LOG(ERROR) << "GATT-server client with given UUID already being registered "
399 << " - UUID: " << uuid.ToString();
400 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700401 }
402
Arman Uguray0f2d4892015-09-22 14:20:42 -0700403 const btgatt_server_interface_t* hal_iface =
404 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
405 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700406
Arman Uguray0f2d4892015-09-22 14:20:42 -0700407 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
408 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700409
Arman Uguray0f2d4892015-09-22 14:20:42 -0700410 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700411
Arman Uguray0f2d4892015-09-22 14:20:42 -0700412 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700413}
414
Arman Uguray0f2d4892015-09-22 14:20:42 -0700415void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700416 hal::BluetoothGattInterface* gatt_iface,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700417 int status, int server_if,
418 const bt_uuid_t& app_uuid) {
419 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700420
Arman Uguray0f2d4892015-09-22 14:20:42 -0700421 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
422 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700423
Arman Uguray0f2d4892015-09-22 14:20:42 -0700424 auto iter = pending_calls_.find(uuid);
425 if (iter == pending_calls_.end()) {
426 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700427 return;
428 }
429
Arman Uguray0f2d4892015-09-22 14:20:42 -0700430 // No need to construct a server if the call wasn't successful.
431 std::unique_ptr<GattServer> server;
432 BLEStatus result = BLE_STATUS_FAILURE;
433 if (status == BT_STATUS_SUCCESS) {
434 server.reset(new GattServer(uuid, server_if));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700435
436 // Use the unsafe variant to register this as an observer to prevent a
437 // deadlock since this callback is currently holding the lock.
438 gatt_iface->AddServerObserverUnsafe(server.get());
439
Arman Uguray0f2d4892015-09-22 14:20:42 -0700440 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700441 }
442
Arman Uguray0f2d4892015-09-22 14:20:42 -0700443 // Notify the result via the result callback.
444 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700445
Arman Uguray0f2d4892015-09-22 14:20:42 -0700446 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700447}
448
Ian Coolidge611fcf92015-06-03 17:20:30 -0700449} // namespace bluetooth