From aeac9973ff098d3fafa07e8ca8e884bcc5194a7f Mon Sep 17 00:00:00 2001
From: Pawel Wasowski
Date: Wed, 12 Aug 2020 13:25:10 +0200
Subject: [PATCH] [Bluetooth][gatt] Add registerService method
https://code.sec.samsung.net/jira/browse/TWDAPI-263
[Description]
Added:
+ BluetoothGATTServer::RegisterService()
+ BluetoothGATTServer::services getter
[Verification]
tested on chrome console
Change-Id: I9588d6c613293d3c5f139263c0e8703de8ab02c3
Signed-off-by: Dawid Juszczak
Signed-off-by: Pawel Wasowski
---
src/bluetooth/bluetooth.gyp | 4 +-
src/bluetooth/bluetooth_api.js | 83 +++-
src/bluetooth/bluetooth_gatt_server.cc | 59 ++-
src/bluetooth/bluetooth_gatt_server.h | 6 +-
.../bluetooth_gatt_server_service.cc | 406 ++++++++++++++++++
src/bluetooth/bluetooth_gatt_server_service.h | 66 +++
src/bluetooth/bluetooth_instance.cc | 22 +-
src/bluetooth/bluetooth_instance.h | 3 +
8 files changed, 633 insertions(+), 16 deletions(-)
create mode 100644 src/bluetooth/bluetooth_gatt_server_service.cc
create mode 100644 src/bluetooth/bluetooth_gatt_server_service.h
diff --git a/src/bluetooth/bluetooth.gyp b/src/bluetooth/bluetooth.gyp
index f99eb6b7..560710d8 100644
--- a/src/bluetooth/bluetooth.gyp
+++ b/src/bluetooth/bluetooth.gyp
@@ -44,7 +44,9 @@
'uuid.cc',
'uuid.h',
'bluetooth_gatt_server.cc',
- 'bluetooth_gatt_server.h'
+ 'bluetooth_gatt_server.h',
+ 'bluetooth_gatt_server_service.cc',
+ 'bluetooth_gatt_server_service.h'
],
'includes': [
'../common/pkg-config.gypi',
diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js
index 09677975..5cd60055 100755
--- a/src/bluetooth/bluetooth_api.js
+++ b/src/bluetooth/bluetooth_api.js
@@ -3219,20 +3219,83 @@ BluetoothAdapter.prototype.getBluetoothProfileHandler = function() {
};
// class BluetoothGATTServer ////////////////////////
+var _BluetoothGATTServerServices = [];
+
var BluetoothGATTServer = function() {
- var services_ = [];
- Object.defineProperties(this, {
- services: {
- get: function() {
- return services_;
- },
- set: function() {}
- }
- });
-}
+ Object.defineProperties(this, {
+ services: {
+ enumerable: true,
+ get: function() {
+ return _BluetoothGATTServerServices;
+ },
+ set: function() {}
+ }
+ });
+};
var AbortError = new WebAPIException('AbortError', 'An unknown error occurred');
+var BluetoothGATTServer_valid_registerService_errors = [
+ 'InvalidStateError',
+ 'NotSupportedError',
+ 'InvalidValuesError',
+ 'AbortError'
+];
+var BluetoothGATTServer_valid_registerService_exceptions = [
+ 'InvalidStateError',
+ 'TypeMismatchError',
+ 'SecurityError'
+];
+
+BluetoothGATTServer.prototype.registerService = function() {
+ var args = AV.validateArgs(arguments, [
+ {
+ name: 'service',
+ type: AV.Types.DICTIONARY
+ },
+ {
+ name: 'successCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ var service = new BluetoothGATTServerService(args.service);
+
+ var callback = function(result) {
+ if (native.isFailure(result)) {
+ native.callIfPossible(
+ args.errorCallback,
+ native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_registerService_errors,
+ AbortError
+ )
+ );
+ } else {
+ _BluetoothGATTServerServicesRegisteredInNativeLayer[service._id] = true;
+ _BluetoothGATTServerServices.push(service);
+ native.callIfPossible(args.successCallback);
+ }
+ };
+
+ var result = native.call('BluetoothGATTServerRegisterService', service, callback);
+ if (native.isFailure(result)) {
+ throw native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_registerService_exceptions,
+ AbortError
+ );
+ }
+};
+
var BluetoothGATTServer_valid_start_errors = ['InvalidStateError', 'NotSupportedError', 'AbortError'];
var BluetoothGATTServer_valid_start_exceptions = ['InvalidStateError', 'TypeMismatchError', 'SecurityError'];
diff --git a/src/bluetooth/bluetooth_gatt_server.cc b/src/bluetooth/bluetooth_gatt_server.cc
index b2273112..0d131a08 100644
--- a/src/bluetooth/bluetooth_gatt_server.cc
+++ b/src/bluetooth/bluetooth_gatt_server.cc
@@ -27,10 +27,14 @@ using namespace common::tools;
namespace extension {
namespace bluetooth {
-BluetoothGATTServer::BluetoothGATTServer(const BluetoothInstance& instance)
- : instance_{instance}, initialized_{false}, running_{false}, handle_{nullptr} {
+BluetoothGATTServer::BluetoothGATTServer(const BluetoothInstance& instance,
+ BluetoothGATTServerService& service)
+ : instance_{instance},
+ service_{service},
+ initialized_{false},
+ running_{false},
+ handle_{nullptr} {
ScopeLogger();
-
/*
* TODO: register a callback, that deinitializes a server, unregisters its
* services, destroys handle_ and sets running_ to false
@@ -129,6 +133,55 @@ void BluetoothGATTServer::GetConnectionMtu(const picojson::value& args,
ReportSuccess(picojson::value{static_cast(mtu)}, out);
}
+void BluetoothGATTServer::RegisterService(const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ bt_gatt_h service_handle = nullptr;
+
+ /*
+ * Each successfully created GATT{Service, Characteristic, Descriptor} has a
+ * corresponding entry in service_.gatt_objects, mapping its _id field of its JS
+ * object to its bt_gatt_h handle.
+ * new_gatt_objects is a container for the entries, that are added to
+ * service_.gatt_objects if both CreateService() and RegisterService()
+ * succeed.
+ * Otherwise, the service is not registered and the map is not updated.
+ */
+ std::vector> new_gatt_objects;
+ auto result = service_.CreateService(args, &service_handle, new_gatt_objects);
+ if (result.IsError()) {
+ ReportError(result, &out);
+ return;
+ }
+
+ if (!initialized_) {
+ /*
+ * Server is initialized when its services are registered.
+ * However, the case when server is uninitialized until start is
+ * also valid. It happens, when user doesn't register any services
+ * and starts the server with the default ones.
+ */
+ auto result = InitializeAndCreateHandle();
+ if (!result) {
+ result.SetMessage("Couldn't register the service");
+ ReportError(result, &out);
+ return;
+ }
+ }
+
+ result = service_.RegisterService(service_handle, this->handle_, new_gatt_objects);
+ if (result.IsError()) {
+ ReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+bool BluetoothGATTServer::IsRunning() {
+ return running_;
+}
+
PlatformResult BluetoothGATTServer::Initialize() {
ScopeLogger();
diff --git a/src/bluetooth/bluetooth_gatt_server.h b/src/bluetooth/bluetooth_gatt_server.h
index e28789c8..82185f4f 100644
--- a/src/bluetooth/bluetooth_gatt_server.h
+++ b/src/bluetooth/bluetooth_gatt_server.h
@@ -19,6 +19,7 @@
#include
+#include "bluetooth/bluetooth_gatt_server_service.h"
#include "common/picojson.h"
#include "common/platform_result.h"
@@ -31,12 +32,14 @@ class BluetoothInstance;
class BluetoothGATTServer {
public:
- BluetoothGATTServer(const BluetoothInstance&);
+ BluetoothGATTServer(const BluetoothInstance& instance, BluetoothGATTServerService& service);
~BluetoothGATTServer();
void Start(picojson::object& out);
void Stop(picojson::object& out);
void GetConnectionMtu(const picojson::value& args, picojson::object& out);
+ void RegisterService(const picojson::value& args, picojson::object& out);
+ bool IsRunning();
static bool DestroyService(int total, int index, bt_gatt_h handle, void* user_data);
static bool DestroyCharacteristic(int total, int index, bt_gatt_h handle, void* user_data);
@@ -44,6 +47,7 @@ class BluetoothGATTServer {
private:
const BluetoothInstance& instance_;
+ BluetoothGATTServerService& service_;
bool initialized_;
bool running_;
bt_gatt_server_h handle_;
diff --git a/src/bluetooth/bluetooth_gatt_server_service.cc b/src/bluetooth/bluetooth_gatt_server_service.cc
new file mode 100644
index 00000000..dcf0e6d4
--- /dev/null
+++ b/src/bluetooth/bluetooth_gatt_server_service.cc
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "bluetooth/bluetooth_gatt_server.h"
+#include "bluetooth/bluetooth_gatt_server_service.h"
+#include "bluetooth/bluetooth_util.h"
+#include "bluetooth/uuid.h"
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/tools.h"
+
+using namespace extension::bluetooth::util;
+using common::PlatformResult;
+using common::ErrorCode;
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+const std::string kUuid = "uuid";
+const std::string kServiceUuid = "serviceUuid";
+const std::string kIsPrimary = "isPrimary";
+const std::string kCharacteristics = "characteristics";
+
+const std::string kServices = "services";
+const std::string kDescriptors = "descriptors";
+const std::string kIsBroadcast = "isBroadcast";
+const std::string kHasExtendedProperties = "hasExtendedProperties";
+const std::string kIsNotify = "isNotify";
+const std::string kIsIndication = "isIndication";
+const std::string kIsReadable = "isReadable";
+const std::string kIsSignedWrite = "isSignedWrite";
+const std::string kIsWritable = "isWritable";
+const std::string kIsWriteNoResponse = "isWriteNoResponse";
+const std::string kReadPermission = "readPermission";
+const std::string kWritePermission = "writePermission";
+const std::string kEncryptedReadPermission = "encryptedReadPermission";
+const std::string kEncryptedWritePermission = "encryptedWritePermission";
+const std::string kEncryptedSignedReadPermission = "encryptedSignedReadPermission";
+const std::string kEncryptedSignedWritePermission = "encryptedSignedWritePermission";
+
+const std::string kId = "_id";
+
+int GetPermissionsInt(const picojson::value& permissions) {
+ ScopeLogger("permissions: %s", permissions.serialize().c_str());
+
+ int ret = 0;
+ if (permissions.get(kReadPermission).get()) {
+ ret |= BT_GATT_PERMISSION_READ;
+ }
+ if (permissions.get(kWritePermission).get()) {
+ ret |= BT_GATT_PERMISSION_WRITE;
+ }
+ if (permissions.get(kEncryptedReadPermission).get()) {
+ ret |= BT_GATT_PERMISSION_ENCRYPT_READ;
+ }
+ if (permissions.get(kEncryptedWritePermission).get()) {
+ ret |= BT_GATT_PERMISSION_ENCRYPT_WRITE;
+ }
+ if (permissions.get(kEncryptedSignedReadPermission).get()) {
+ ret |= BT_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ;
+ }
+ if (permissions.get(kEncryptedSignedWritePermission).get()) {
+ ret |= BT_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE;
+ }
+
+ LoggerD("Permissions: %x", static_cast(ret));
+ return ret;
+}
+
+int GetPropertiesInt(const picojson::value& properties) {
+ ScopeLogger("properties: %s", properties.serialize().c_str());
+
+ int ret = 0;
+ if (properties.get(kIsBroadcast).get()) {
+ ret |= BT_GATT_PROPERTY_BROADCAST;
+ }
+ if (properties.get(kIsReadable).get()) {
+ ret |= BT_GATT_PROPERTY_READ;
+ }
+ if (properties.get(kIsWriteNoResponse).get()) {
+ ret |= BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE;
+ }
+ if (properties.get(kIsWritable).get()) {
+ ret |= BT_GATT_PROPERTY_WRITE;
+ }
+ if (properties.get(kIsNotify).get()) {
+ ret |= BT_GATT_PROPERTY_NOTIFY;
+ }
+ if (properties.get(kIsIndication).get()) {
+ ret |= BT_GATT_PROPERTY_INDICATE;
+ }
+ if (properties.get(kIsSignedWrite).get()) {
+ ret |= BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES;
+ }
+ if (properties.get(kHasExtendedProperties).get()) {
+ ret |= BT_GATT_PROPERTY_EXTENDED_PROPERTIES;
+ }
+
+ LoggerD("Properties: %x", static_cast(ret));
+ return ret;
+}
+
+} // namespace
+
+bool BluetoothGATTServerService::DestroyService(int total, int index, bt_gatt_h handle, void* user_data) {
+ ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
+
+ /*
+ * Undocumented behavior of native Bluetooth API:
+ * bt_gatt_service_destroy() destroys not only the service, but also all
+ * its components (included services, characteristics, descriptors)
+ * recursively.
+ */
+ auto ret = bt_gatt_service_destroy(handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_service_destroy(): %d (%s)", ret, get_error_message(ret));
+ }
+ LoggerD("bt_gatt_service_destroy(): success");
+
+ return true;
+}
+
+bool BluetoothGATTServerService::DestroyCharacteristic(int total, int index, bt_gatt_h handle,
+ void* user_data) {
+ ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
+
+ auto ret = bt_gatt_characteristic_destroy(handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_characteristic_destroy(): %d (%s)", ret, get_error_message(ret));
+ }
+ LoggerD("bt_gatt_characteristic_destroy(): success");
+
+ return true;
+}
+
+bool BluetoothGATTServerService::DestroyDescriptor(int total, int index, bt_gatt_h handle,
+ void* user_data) {
+ ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
+
+ auto ret = bt_gatt_descriptor_destroy(handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_descriptor_destroy(): %d (%s)", ret, get_error_message(ret));
+ }
+ LoggerD("bt_gatt_descriptor_destroy(): success");
+
+ return true;
+}
+BluetoothGATTServerService::BluetoothGATTServerService() {
+ ScopeLogger();
+}
+
+BluetoothGATTServerService::~BluetoothGATTServerService() {
+ ScopeLogger();
+}
+
+common::PlatformResult BluetoothGATTServerService::AddDescriptors(
+ const picojson::array& descriptors_init, bt_gatt_h characteristic_handle,
+ std::vector>& new_gatt_objects) {
+ ScopeLogger("descriptors_init length: %zu", descriptors_init.size());
+
+ /*
+ * This function expects valid input.
+ * If it gets descriptors missing any: uuid, permission,
+ * or with one of these with a wrong type, the application will crash.
+ */
+
+ for (const auto& descriptor_init_data : descriptors_init) {
+ const auto& uuid_str = descriptor_init_data.get(kUuid).get();
+ /*
+ * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
+ * form to assure, it will be accepted by the native API.
+ *
+ * We assume, UUID::create() returns a valid object, because the input is valid.
+ */
+ auto uuid = UUID::create(uuid_str);
+ int permissions = GetPermissionsInt(descriptor_init_data);
+ bt_gatt_h descriptor_handle = nullptr;
+
+ int ret = bt_gatt_descriptor_create(uuid->uuid_128_bit.c_str(), permissions, nullptr, 0,
+ &descriptor_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_descriptor_create() failed: %d (%s)", ret, get_error_message(ret));
+ return BluetoothErrorToPlatformResult(ret, "Failed to create a descriptor");
+ }
+ LoggerD("bt_gatt_descriptor_create(): success");
+
+ ret = bt_gatt_characteristic_add_descriptor(characteristic_handle, descriptor_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_characteristic_add_descriptor() failed: %d (%s)", ret,
+ get_error_message(ret));
+ DestroyDescriptor(0, 0, descriptor_handle, nullptr);
+ return BluetoothErrorToPlatformResult(ret, "Failed to add descriptor to characteristic");
+ }
+ LoggerD("bt_gatt_characteristic_add_descriptor(): success");
+
+ const auto _id = static_cast(descriptor_init_data.get(kId).get());
+ new_gatt_objects.push_back({_id, descriptor_handle});
+ }
+
+ return common::PlatformResult();
+}
+
+common::PlatformResult BluetoothGATTServerService::AddCharacteristics(
+ const picojson::array& characteristics_init, bt_gatt_h service_handle,
+ std::vector>& new_gatt_objects) {
+ ScopeLogger("characteristics_init length: %zu", characteristics_init.size());
+
+ /*
+ * This function expects valid input.
+ * If it gets characteristics missing any: uuid, permission, property,
+ * or with any of these with a wrong type, the application will crash.
+ */
+
+ for (const auto& characteristic_init_data : characteristics_init) {
+ const auto& uuid_str = characteristic_init_data.get(kUuid).get();
+ /*
+ * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
+ * form to assure, it will be accepted by the native API.
+ *
+ * We assume, UUID::create() returns a valid object, because the input is valid.
+ */
+ auto uuid = UUID::create(uuid_str);
+
+ int permissions = GetPermissionsInt(characteristic_init_data);
+ int properties = GetPropertiesInt(characteristic_init_data);
+ bt_gatt_h characteristic_handle = nullptr;
+
+ int ret = bt_gatt_characteristic_create(uuid->uuid_128_bit.c_str(), permissions, properties,
+ nullptr, 0, &characteristic_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_characteristic_create() failed: %d (%s)", ret, get_error_message(ret));
+ return BluetoothErrorToPlatformResult(ret, "Failed to create a characteristic");
+ }
+ LoggerD("bt_gatt_characteristic_create(): success");
+
+ if (characteristic_init_data.get(kDescriptors).is()) {
+ const auto& descriptors = characteristic_init_data.get(kDescriptors).get();
+ auto result = AddDescriptors(descriptors, characteristic_handle, new_gatt_objects);
+ if (!result) {
+ DestroyCharacteristic(0, 0, characteristic_handle, nullptr);
+ return result;
+ }
+ }
+
+ ret = bt_gatt_service_add_characteristic(service_handle, characteristic_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_service_add_characteristic() failed: %d (%s)", ret, get_error_message(ret));
+ DestroyCharacteristic(0, 0, characteristic_handle, nullptr);
+ return BluetoothErrorToPlatformResult(ret, "Failed to add a characteristic to a service");
+ }
+ LoggerD("bt_gatt_service_add_characteristic(): success");
+
+ const auto _id = static_cast(characteristic_init_data.get(kId).get());
+ new_gatt_objects.push_back({_id, characteristic_handle});
+ }
+
+ return common::PlatformResult();
+}
+
+common::PlatformResult BluetoothGATTServerService::AddIncludedServices(
+ const picojson::array& included_services_init, bt_gatt_h parent_service_handle,
+ std::vector>& new_gatt_objects) {
+ ScopeLogger("included_services_init length: %zu", included_services_init.size());
+
+ /*
+ * This function expects valid input.
+ * If it gets included_services missing a uuid
+ * or with any of these with a wrong type, the application will crash.
+ */
+
+ for (const auto& service_init_data : included_services_init) {
+ bt_gatt_h included_service_handle = nullptr;
+ auto result = CreateService(service_init_data, &included_service_handle, new_gatt_objects);
+ if (!result) {
+ LoggerE("Failed to create included service");
+ return result;
+ }
+
+ int ret = bt_gatt_service_add_included_service(parent_service_handle, included_service_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_service_add_included_service() failed: %d (%s)", ret,
+ get_error_message(ret));
+ DestroyService(0, 0, included_service_handle, nullptr);
+ return BluetoothErrorToPlatformResult(ret, "Failed to add included service");
+ }
+ LoggerD("bt_gatt_service_add_included_service(): success");
+
+ const auto _id = static_cast(service_init_data.get(kId).get());
+ new_gatt_objects.push_back({_id, parent_service_handle});
+ }
+
+ return common::PlatformResult();
+}
+
+common::PlatformResult BluetoothGATTServerService::CreateService(
+ const picojson::value& service_init, bt_gatt_h* new_service_handle,
+ std::vector>& new_gatt_objects) {
+ ScopeLogger("service_init: %s", service_init.serialize().c_str());
+ /*
+ * This function expects valid input.
+ * If it gets service_init without any of the expected members or with a member of
+ * a wrong type, the application will crash.
+ */
+
+ const auto& uuid_str = service_init.get(kServiceUuid).get();
+ /*
+ * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
+ * form to assure, it will be accepted by the native API.
+ *
+ * We assume, UUID::create() returns a valid object, because the input is valid.
+ */
+ auto uuid = UUID::create(uuid_str);
+ bool primary = service_init.get(kIsPrimary).get();
+ bt_gatt_service_type_e type =
+ primary ? BT_GATT_SERVICE_TYPE_PRIMARY : BT_GATT_SERVICE_TYPE_SECONDARY;
+ bt_gatt_h service_handle = nullptr;
+
+ int err = bt_gatt_service_create(uuid->uuid_128_bit.c_str(), type, &service_handle);
+ if (BT_ERROR_NONE != err) {
+ LoggerE("bt_gatt_service_create error: %d (%s)", err, get_error_message(err));
+ return BluetoothErrorToPlatformResult(err, "Failed to create GATT service");
+ }
+ LoggerD("bt_gatt_service_create(): success");
+
+ if (service_init.get(kServices).is()) {
+ const auto& services = service_init.get(kServices).get();
+ auto result = AddIncludedServices(services, service_handle, new_gatt_objects);
+ if (!result) {
+ DestroyService(0, 0, service_handle, nullptr);
+ return result;
+ }
+ }
+
+ if (service_init.get(kCharacteristics).is()) {
+ const auto& characteristics = service_init.get(kCharacteristics).get();
+ auto result = AddCharacteristics(characteristics, service_handle, new_gatt_objects);
+ if (!result) {
+ DestroyService(0, 0, service_handle, nullptr);
+ return result;
+ }
+ }
+
+ const auto _id = static_cast(service_init.get(kId).get());
+ new_gatt_objects.push_back({_id, service_handle});
+
+ *new_service_handle = service_handle;
+
+ return common::PlatformResult();
+}
+
+common::PlatformResult BluetoothGATTServerService::RegisterService(
+ bt_gatt_h service_handle, bt_gatt_server_h server,
+ const std::vector>& new_gatt_objects) {
+ ScopeLogger();
+
+ int ret = bt_gatt_server_register_service(server, service_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_server_register_service() failed: %d (%s)", ret, get_error_message(ret));
+ return BluetoothErrorToPlatformResult(ret, "Failed to register GATT service");
+ }
+
+ gatt_objects_.insert(new_gatt_objects.begin(), new_gatt_objects.end());
+
+ return common::PlatformResult();
+}
+
+
+common::PlatformResult BluetoothGATTServerService::UnregisterService(const picojson::value& args, bt_gatt_server_h server) {
+ ScopeLogger();
+
+ auto _id = static_cast(args.get(kId).get());
+ LoggerD("Unregistering service with _id: %d", _id);
+
+ auto service_handle = gatt_objects_[_id];
+
+ auto ret = bt_gatt_server_unregister_service(server, service_handle);
+ if (BT_ERROR_NONE != ret) {
+ LoggerE("bt_gatt_server_unregister_service() failed: %d (%s)", ret, get_error_message(ret));
+ return BluetoothErrorToPlatformResult(ret, "Failed to unregister GATT service");
+ }
+ LoggerD("bt_gatt_server_unregister_service(): SUCCESS");
+
+ gatt_objects_.erase(_id);
+ return common::PlatformResult{};
+
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/src/bluetooth/bluetooth_gatt_server_service.h b/src/bluetooth/bluetooth_gatt_server_service.h
new file mode 100644
index 00000000..cecd9d2b
--- /dev/null
+++ b/src/bluetooth/bluetooth_gatt_server_service.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BLUETOOTH_BLUETOOTH_GATT_SERVER_SERVICE_H_
+#define BLUETOOTH_BLUETOOTH_GATT_SERVER_SERVICE_H_
+
+#include