Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 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 | // |
Marie Janssen | 49a8670 | 2015-07-08 11:48:57 -0700 | [diff] [blame] | 16 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 17 | #include "service/gatt_server.h" |
Marie Janssen | 49a8670 | 2015-07-08 11:48:57 -0700 | [diff] [blame] | 18 | |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 19 | #include "service/hal/gatt_helpers.h" |
| 20 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 21 | using std::lock_guard; |
| 22 | using std::mutex; |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 23 | |
| 24 | namespace bluetooth { |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 25 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 26 | // GattServer implementation |
| 27 | // ======================================================== |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 28 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 29 | GattServer::GattServer(const UUID& uuid, int server_if) |
| 30 | : app_identifier_(uuid), |
| 31 | server_if_(server_if) { |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 32 | } |
| 33 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 34 | GattServer::~GattServer() { |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 35 | // 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 Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 44 | hal::BluetoothGattInterface::Get()-> |
| 45 | GetServerHALInterface()->unregister_server(server_if_); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 46 | } |
| 47 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 48 | const UUID& GattServer::GetAppIdentifier() const { |
| 49 | return app_identifier_; |
| 50 | } |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 51 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 52 | int GattServer::GetClientId() const { |
| 53 | return server_if_; |
| 54 | } |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 55 | |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 56 | std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration( |
| 57 | const UUID& uuid, bool is_primary) { |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 58 | VLOG(1) << __func__ << " server_if: " << server_if_ |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 59 | << " - 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 Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 89 | // Pass 0 for permissions and properties as this is a service decl. |
| 90 | AttributeEntry entry( |
| 91 | *service_id, kCharacteristicPropertyNone, kAttributePermissionNone); |
| 92 | |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 93 | 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 Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 96 | pending_decl_->attributes.push_back(entry); |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 97 | |
| 98 | return service_id; |
| 99 | } |
| 100 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 101 | std::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 Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 141 | bool GattServer::EndServiceDeclaration(const ResultCallback& callback) { |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 142 | VLOG(1) << __func__ << " server_if: " << server_if_; |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 143 | 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 | |
| 189 | void GattServer::ServiceAddedCallback( |
| 190 | hal::BluetoothGattInterface* gatt_iface, |
| 191 | int status, int server_if, |
| 192 | const btgatt_srvc_id_t& srvc_id, |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 193 | int service_handle) { |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 194 | 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 Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 206 | VLOG(1) << __func__ << " - status: " << status |
| 207 | << " server_if: " << server_if |
| 208 | << " handle: " << service_handle |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 209 | << " 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 Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 217 | pending_handle_map_[*gatt_id] = service_handle; |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 218 | CHECK(-1 == pending_decl_->service_handle); |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 219 | pending_decl_->service_handle = service_handle; |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 220 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 221 | HandleNextEntry(gatt_iface); |
| 222 | } |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 223 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 224 | void 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 Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 231 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 232 | 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 Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 255 | } |
| 256 | |
| 257 | void GattServer::ServiceStartedCallback( |
| 258 | hal::BluetoothGattInterface* gatt_iface, |
| 259 | int status, int server_if, |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 260 | int service_handle) { |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 261 | lock_guard<mutex> lock(mutex_); |
| 262 | |
| 263 | if (server_if != server_if_) |
| 264 | return; |
| 265 | |
| 266 | CHECK(pending_id_); |
| 267 | CHECK(pending_decl_); |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 268 | CHECK(pending_decl_->service_handle == service_handle); |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 269 | |
| 270 | VLOG(1) << __func__ << " - server_if: " << server_if |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 271 | << " handle: " << service_handle; |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 272 | |
| 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 Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 277 | server_if_, service_handle); |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | // Complete the operation. |
| 281 | NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), |
| 282 | pending_decl_->service_id); |
| 283 | } |
| 284 | |
| 285 | void GattServer::ServiceStoppedCallback( |
| 286 | hal::BluetoothGattInterface* /* gatt_iface */, |
| 287 | int /* status */, |
| 288 | int /* server_if */, |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 289 | int /* service_handle */) { |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 290 | // TODO(armansito): Support stopping a service. |
| 291 | } |
| 292 | |
| 293 | void 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 | |
| 306 | void GattServer::CleanUpPendingData() { |
| 307 | pending_id_ = nullptr; |
| 308 | pending_decl_ = nullptr; |
| 309 | pending_end_decl_cb_ = ResultCallback(); |
| 310 | pending_handle_map_.clear(); |
| 311 | } |
| 312 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 313 | void 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 | |
| 359 | std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() { |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 360 | CHECK(pending_decl_); |
| 361 | |
| 362 | if (pending_decl_->attributes.empty()) |
| 363 | return nullptr; |
| 364 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 365 | const auto& next = pending_decl_->attributes.front(); |
| 366 | std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next)); |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 367 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 368 | pending_decl_->attributes.pop_front(); |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 369 | |
Arman Uguray | 9161374 | 2015-09-24 22:45:16 -0700 | [diff] [blame^] | 370 | return entry; |
| 371 | } |
| 372 | |
| 373 | std::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 Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 379 | } |
| 380 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 381 | // GattServerFactory implementation |
| 382 | // ======================================================== |
| 383 | |
| 384 | GattServerFactory::GattServerFactory() { |
| 385 | hal::BluetoothGattInterface::Get()->AddServerObserver(this); |
| 386 | } |
| 387 | |
| 388 | GattServerFactory::~GattServerFactory() { |
| 389 | hal::BluetoothGattInterface::Get()->RemoveServerObserver(this); |
| 390 | } |
| 391 | |
| 392 | bool 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 Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 401 | } |
| 402 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 403 | const btgatt_server_interface_t* hal_iface = |
| 404 | hal::BluetoothGattInterface::Get()->GetServerHALInterface(); |
| 405 | bt_uuid_t app_uuid = uuid.GetBlueDroid(); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 406 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 407 | if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS) |
| 408 | return false; |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 409 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 410 | pending_calls_[uuid] = callback; |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 411 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 412 | return true; |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 413 | } |
| 414 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 415 | void GattServerFactory::RegisterServerCallback( |
Arman Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 416 | hal::BluetoothGattInterface* gatt_iface, |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 417 | int status, int server_if, |
| 418 | const bt_uuid_t& app_uuid) { |
| 419 | UUID uuid(app_uuid); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 420 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 421 | VLOG(1) << __func__ << " - UUID: " << uuid.ToString(); |
| 422 | lock_guard<mutex> lock(pending_calls_lock_); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 423 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 424 | auto iter = pending_calls_.find(uuid); |
| 425 | if (iter == pending_calls_.end()) { |
| 426 | VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString(); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 427 | return; |
| 428 | } |
| 429 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 430 | // 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 Uguray | df0b271 | 2015-09-23 17:25:54 -0700 | [diff] [blame] | 435 | |
| 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 Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 440 | result = BLE_STATUS_SUCCESS; |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 441 | } |
| 442 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 443 | // Notify the result via the result callback. |
| 444 | iter->second(result, uuid, std::move(server)); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 445 | |
Arman Uguray | 0f2d489 | 2015-09-22 14:20:42 -0700 | [diff] [blame] | 446 | pending_calls_.erase(iter); |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 447 | } |
| 448 | |
Ian Coolidge | 611fcf9 | 2015-06-03 17:20:30 -0700 | [diff] [blame] | 449 | } // namespace bluetooth |