2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "bluetooth/bluetooth_gatt_server.h"
18 #include "bluetooth/bluetooth_instance.h"
19 #include "bluetooth/bluetooth_util.h"
21 #include "common/logger.h"
22 #include "common/tools.h"
24 using namespace extension::bluetooth::util;
25 using namespace common;
26 using namespace common::tools;
31 BluetoothGATTServer::BluetoothGATTServer(BluetoothInstance& instance,
32 BluetoothGATTServerService& service)
33 : instance_{instance},
38 power_state_change_callback_id_{-1} {
41 power_state_change_callback_id_ =
42 instance_.GetBluetoothAdapter().AddPowerStateListener([this](const int state) {
43 ScopeLogger("BluetoothGATTServer PowerStateListenerCallback: %d", state);
44 if ((false == state) && (true == running_)) {
45 UnregisterAllServicesImpl();
46 DestroyAllGATTObjects();
48 PowerStateChangeCb(false);
49 SetRunningState(false);
54 BluetoothGATTServer::~BluetoothGATTServer() {
57 instance_.GetBluetoothAdapter().RemovePowerStateListener(power_state_change_callback_id_);
58 UnregisterAllServicesImpl();
59 DestroyAllGATTObjects();
63 void BluetoothGATTServer::Start(picojson::object& out) {
67 LoggerD("Server is running");
74 * Server is initialized when its services are registered.
75 * However, the case when server is uninitialized until start is
76 * also valid. It happens, when user doesn't register any services
77 * and starts the server with the default ones.
79 auto result = InitializeAndCreateHandle();
81 result.SetMessage("Couldn't start GATT server");
82 ReportError(result, &out);
87 auto ret = bt_gatt_server_start();
88 if (BT_ERROR_NONE != ret) {
89 LoggerE("bt_gatt_server_start(): %d (%s)", ret, get_error_message(ret));
90 ReportError(BluetoothErrorToPlatformResult(ret, "Couldn't start GATT server"), &out);
93 LoggerD("bt_gatt_server_start(): success");
95 SetRunningState(true);
99 void BluetoothGATTServer::Stop(picojson::object& out) {
103 LoggerD("Server is not running");
108 // Unregistering all services should not fail.
109 // Even if it does we just let UnregisterAllSerivcesImpl() log the error
110 // and proceed with server destruction.
111 UnregisterAllServicesImpl();
113 // DestroyAllGATTObjects() should not fail
114 // If it does, it logs the error message.
115 DestroyAllGATTObjects();
117 // Deinitialize() is the function that actually stops the server,
118 // thus we return the result, it returns.
119 auto result = Deinitialize();
121 result.SetMessage("Couldn't stop GATT server");
122 ReportError(result, &out);
125 SetRunningState(false);
129 void BluetoothGATTServer::GetConnectionMtu(const picojson::value& args, picojson::object& out) {
132 const auto client_address = args.get("clientAddress").get<std::string>();
134 unsigned int mtu = 0;
135 auto ret = bt_gatt_server_get_device_mtu(client_address.c_str(), &mtu);
136 if (BT_ERROR_NONE != ret) {
137 LoggerE("bt_gatt_server_get_device_mtu(): %d (%s)", ret, get_error_message(ret));
138 ReportError(BluetoothErrorToPlatformResult(ret), &out);
140 LoggerD("bt_gatt_server_get_device_mtu(): success, MTU: %u", mtu);
142 ReportSuccess(picojson::value{static_cast<double>(mtu)}, out);
145 void BluetoothGATTServer::RegisterService(const picojson::value& args, picojson::object& out) {
148 bt_gatt_h service_handle = nullptr;
151 * Each successfully created GATT{Service, Characteristic, Descriptor} has a
152 * corresponding entry in service_.gatt_objects, mapping its _id field of its JS
153 * object to its bt_gatt_h handle.
154 * new_gatt_objects is a container for the entries, that are added to
155 * service_.gatt_objects if both CreateService() and RegisterService()
157 * Otherwise, the service is not registered and the map is not updated.
159 std::vector<std::pair<int, bt_gatt_h>> new_gatt_objects;
160 auto result = service_.CreateService(args, &service_handle, new_gatt_objects);
161 if (result.IsError()) {
162 ReportError(result, &out);
168 * Server is initialized when its services are registered.
169 * However, the case when server is uninitialized until start is
170 * also valid. It happens, when user doesn't register any services
171 * and starts the server with the default ones.
173 auto result = InitializeAndCreateHandle();
175 result.SetMessage("Couldn't register the service");
176 ReportError(result, &out);
181 result = service_.RegisterService(service_handle, this->handle_, new_gatt_objects);
182 if (result.IsError()) {
183 ReportError(result, &out);
190 void BluetoothGATTServer::UnregisterService(const picojson::value& args, picojson::object& out) {
193 auto result = service_.UnregisterService(args, handle_);
195 if (result.IsError()) {
196 ReportError(result, &out);
203 void BluetoothGATTServer::SetReadValueRequestCallback(const picojson::value& args,
204 picojson::object& out) {
207 auto result = service_.SetReadValueRequestCallback(args);
209 if (result.IsError()) {
210 ReportError(result, &out);
217 void BluetoothGATTServer::SetWriteValueRequestCallback(const picojson::value& args,
218 picojson::object& out) {
221 auto result = service_.SetWriteValueRequestCallback(args);
223 if (result.IsError()) {
224 ReportError(result, &out);
231 void BluetoothGATTServer::SendResponse(const picojson::value& args, picojson::object& out) {
234 auto result = service_.SendResponse(args);
236 if (result.IsError()) {
237 ReportError(result, &out);
244 bool BluetoothGATTServer::IsRunning() {
248 void BluetoothGATTServer::NotifyAboutValueChange(const picojson::value& args,
249 picojson::object& out) {
253 LoggerE("Server not started");
254 ReportError(common::PlatformResult{common::ErrorCode::ABORT_ERR, "Server not started"}, &out);
258 auto result = service_.NotifyAboutValueChange(args);
259 if (result.IsError()) {
260 ReportError(result, &out);
267 PlatformResult BluetoothGATTServer::Initialize() {
270 auto ret = bt_gatt_server_initialize();
271 if (BT_ERROR_NONE != ret) {
272 LoggerE("bt_gatt_server_initialize(): %d (%s)", ret, get_error_message(ret));
273 return BluetoothErrorToPlatformResult(ret);
275 LoggerD("bt_gatt_server_initialize(): success");
278 return PlatformResult{};
281 PlatformResult BluetoothGATTServer::CreateHandle() {
285 LoggerE("Server handle is already created");
286 return PlatformResult{ErrorCode::INVALID_STATE_ERR};
289 auto ret = bt_gatt_server_create(&handle_);
290 if (BT_ERROR_NONE != ret) {
291 LoggerE("bt_gatt_server_create(): %d (%s)", ret, get_error_message(ret));
293 LoggerD("bt_gatt_server_create(): success");
296 return BluetoothErrorToPlatformResult(ret);
299 PlatformResult BluetoothGATTServer::Deinitialize() {
303 LoggerE("Server is not initialized");
304 return PlatformResult{ErrorCode::INVALID_STATE_ERR};
307 auto ret = bt_gatt_server_deinitialize();
308 if (BT_ERROR_NONE != ret) {
309 LoggerE("bt_gatt_server_deinitialize(): %d (%s)", ret, get_error_message(ret));
310 return BluetoothErrorToPlatformResult(ret);
313 LoggerD("bt_gatt_server_deinitialize(): success");
314 initialized_ = false;
317 * Undocumented behavior of native API: bt_gatt_server_deinitialize() calls
318 * bt_gatt_server_destroy() - after Deinitialize() bt_gatt_server_destroy()
319 * should not be called (a call results in a BT_INVALID_STATE_ERROR).
320 * handle_ is to be nullified, as it is no longer valid.
324 return PlatformResult{};
327 PlatformResult BluetoothGATTServer::InitializeAndCreateHandle() {
330 auto result = Initialize();
335 result = CreateHandle();
342 PlatformResult BluetoothGATTServer::UnregisterAllServicesImpl() {
346 LoggerE("Server handle is a nullptr");
347 return PlatformResult{ErrorCode::INVALID_STATE_ERR};
350 service_.ClearGATTData();
352 auto ret = bt_gatt_server_unregister_all_services(handle_);
353 if (BT_ERROR_NONE != ret) {
354 LoggerE("bt_gatt_server_unregister_all_services(): %d (%s)", ret, get_error_message(ret));
355 return BluetoothErrorToPlatformResult(ret);
357 LoggerD("bt_gatt_server_unregister_all_services(): success");
358 return PlatformResult{};
362 PlatformResult BluetoothGATTServer::DestroyAllGATTObjects() {
366 LoggerE("Server handle is a nullptr");
367 return PlatformResult{ErrorCode::INVALID_STATE_ERR};
370 auto ret = bt_gatt_server_foreach_services(handle_, DestroyService, nullptr);
371 if (BT_ERROR_NONE != ret) {
372 LoggerE("bt_gatt_server_unregister_all_services(): %d (%s)", ret, get_error_message(ret));
373 return BluetoothErrorToPlatformResult(ret);
375 LoggerD("bt_gatt_server_unregister_all_services(): success");
376 return PlatformResult{};
380 * TODO: remove handles from service id -> service handle map
384 bool BluetoothGATTServer::DestroyService(int total, int index, bt_gatt_h handle, void* user_data) {
385 ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
387 auto ret = bt_gatt_service_foreach_included_services(handle, DestroyService, nullptr);
388 if (BT_ERROR_NONE != ret) {
389 LoggerE("bt_gatt_service_foreach_included_servics(): %d (%s)", ret, get_error_message(ret));
391 LoggerD("bt_gatt_service_foreach_included_servics(): success");
393 ret = bt_gatt_service_foreach_characteristics(handle, DestroyCharacteristic, nullptr);
394 if (BT_ERROR_NONE != ret) {
395 LoggerE("bt_gatt_service_foreach_characteristics(): %d (%s)", ret, get_error_message(ret));
397 LoggerD("bt_gatt_service_foreach_characteristics(): success");
399 ret = bt_gatt_service_destroy(handle);
400 if (BT_ERROR_NONE != ret) {
401 LoggerE("bt_gatt_service_destroy(): %d (%s)", ret, get_error_message(ret));
407 bool BluetoothGATTServer::DestroyCharacteristic(int total, int index, bt_gatt_h handle,
409 ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
411 auto ret = bt_gatt_characteristic_foreach_descriptors(handle, DestroyDescriptor, nullptr);
412 if (BT_ERROR_NONE != ret) {
413 LoggerE("bt_gatt_characteristic_foreach_descriptors(): %d (%s)", ret, get_error_message(ret));
415 LoggerD("bt_gatt_characteristic_foreach_descriptors(): success");
417 ret = bt_gatt_characteristic_destroy(handle);
418 if (BT_ERROR_NONE != ret) {
419 LoggerE("bt_gatt_characteristic_destroy(): %d (%s)", ret, get_error_message(ret));
425 bool BluetoothGATTServer::DestroyDescriptor(int total, int index, bt_gatt_h handle,
427 ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
429 auto ret = bt_gatt_descriptor_destroy(handle);
430 if (BT_ERROR_NONE != ret) {
431 LoggerE("bt_gatt_descriptor_destroy(): %d (%s)", ret, get_error_message(ret));
436 void BluetoothGATTServer::PowerStateChangeCb(bool state) {
438 picojson::value result{picojson::object{}};
439 auto& obj = result.get<picojson::object>();
442 std::make_pair("listenerId", "BluetoothGattServerBluetoothAdapterStateChangeListener"));
443 obj.insert(std::make_pair("state", picojson::value(state)));
445 Instance::PostMessage(&instance_, result.serialize().c_str());
448 void BluetoothGATTServer::SetRunningState(bool state) {
450 if (state != running_) {
451 LoggerD("Changing GATTServer running state to: %s", state ? "start" : "stop");
453 picojson::value result{picojson::object{}};
454 auto& obj = result.get<picojson::object>();
456 obj.insert(std::make_pair("listenerId", "BluetoothGattServerIsRunningChangeListener"));
457 obj.insert(std::make_pair("state", picojson::value(running_)));
459 Instance::PostMessage(&instance_, result.serialize().c_str());
463 } // namespace bluetooth
464 } // namespace extension