Implement TDS functionalities 87/246487/2
authorWootak Jung <wootak.jung@samsung.com>
Fri, 30 Oct 2020 03:14:22 +0000 (12:14 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Wed, 11 Nov 2020 02:28:09 +0000 (11:28 +0900)
Change-Id: I5cb28e6ac1f43ae94a17c8fc0faf266c97b27b55
Signed-off-by: Wootak Jung <wootak.jung@samsung.com>
27 files changed:
bt-oal/CMakeLists.txt
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/src/bt-hal-adapter-le.c
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-dbus-common-utils.h
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-tds.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-tds.h [new file with mode: 0644]
bt-oal/hardware/bluetooth.h
bt-oal/hardware/bt_gatt_server.h
bt-oal/hardware/bt_tds.h [new file with mode: 0644]
bt-oal/include/oal-event.h
bt-oal/include/oal-gatt.h
bt-oal/include/oal-tds.h [new file with mode: 0644]
bt-oal/oal-gatt.c
bt-oal/oal-tds.c [new file with mode: 0644]
bt-service/CMakeLists.txt
bt-service/services/adapter/bt-service-core-adapter-le.c
bt-service/services/adapter/bt-service-core-adapter.c
bt-service/services/bt-request-handler.c
bt-service/services/bt-service-event-receiver.c
bt-service/services/include/bt-service-core-adapter-le.h
bt-service/services/include/bt-service-event-receiver.h
bt-service/services/include/bt-service-tds.h [new file with mode: 0644]
bt-service/services/tds/bt-service-tds.c [new file with mode: 0644]

index e183c0a..c77b19a 100755 (executable)
@@ -29,6 +29,7 @@ oal-hdp.c
 oal-gatt.c
 oal-hf-client.c
 oal-mesh.c
+oal-tds.c
 common/oal-utils.c
 common/oal-common.c
 common/oal-event-dispatcher.c
index 2ac18ae..e388be9 100644 (file)
@@ -37,6 +37,8 @@ SET(SRCS
 ./src/bt-hal-hf-client-dbus-handler.c
 ./src/bt-hal-mesh.c
 ./src/bt-hal-mesh-dbus-handler.c
+./src/bt-hal-tds.c
+./src/bt-hal-tds-dbus-handler.c
 )
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
index b1b4b1a..2a9642f 100644 (file)
@@ -855,6 +855,16 @@ int _bt_hal_set_advertising_data(btgatt_adv_param_setup_t adv_param_setup)
                DBG("After Manuf Data: Index [%d]", index);
        }
 
+       /* Transport Discovery Data */
+       if (adv_param_setup.tds_data_len > 0) {
+               adv_data[index] = 1 + adv_param_setup.tds_data_len;
+               adv_data[index+1] = 0x26;
+               memcpy(&adv_data[index+2], adv_param_setup.tds_data, adv_param_setup.tds_data_len);
+               index += (2 + adv_param_setup.tds_data_len);
+               length += (2 + adv_param_setup.tds_data_len);
+               DBG("After Transport Discovery Data: Index [%d]", index);
+       }
+
        for (i = 0; i < length; i++)
                snprintf(&adv_data_str[i * 2], 3, "%02X", adv_data[i]);
        INFO("Set adv data. Index [%d] length [%d] Data[%s]", index, length, adv_data_str);
index cf409a0..72bb4fb 100644 (file)
@@ -48,6 +48,7 @@
 #endif
 #include <bt-hal-hf-client.h>
 #include <bt-hal-mesh.h>
+#include <bt-hal-tds.h>
 
 #define enum_prop_to_hal(prop, hal_prop, type) do { \
        static type e; \
@@ -315,6 +316,9 @@ static const void *get_profile_interface(const char *profile_id)
                return bt_get_mesh_interface();
        }
 
+       if (!strcmp(profile_id, BT_PROFILE_TDS_ID))
+               return bt_get_tds_interface();
+
        return NULL;
 }
 
index e0716da..283d317 100644 (file)
@@ -109,7 +109,7 @@ extern "C" {
 #define BT_HAL_MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
 #define BT_HAL_OBEX_TRANSFER_INTERFACE "org.bluez.obex.Transfer1"
 #define BT_HAL_HEADSET_INTERFACE "org.bluez.Headset"
-
+#define BT_HAL_TDS_PROVIDER_INTERFACE "org.bluez.TdsServiceProvider1"
 
 #define BT_HAL_INTERFACES_ADDED "InterfacesAdded"
 #define BT_HAL_INTERFACES_REMOVED "InterfacesRemoved"
index e88a1f6..885fb08 100644 (file)
@@ -40,6 +40,7 @@
 #include "bt-hal-gatt-server.h"
 #include "bt-hal-gatt-client.h"
 #include "bt-hal-adapter-dbus-handler.h"
+#include "bt-hal-tds.h"
 
 #include "bt-internal-types.h"
 
@@ -1004,6 +1005,33 @@ static void __bt_hal_handle_gatt_service_event(GVariant *parameters, const char
        }
 }
 
+static void __bt_hal_handle_tds_provider_event(GVariant *parameters, const char *signal_name, const char *path)
+{
+       if (signal_name == NULL)
+               return;
+
+       if (strcasecmp(signal_name, "TdsActivationRequested") == 0) {
+               GVariant *value = NULL;
+               int len = 0;
+               unsigned char *buffer = NULL;
+               unsigned char org_id;
+
+               g_variant_get(parameters, "(y@ay)", &org_id, &value);
+               DBG("org_id: 0x%.2x", org_id);
+               len = g_variant_get_size(value);
+               if (len > 0) {
+                       int i;
+                       buffer = (unsigned char *)g_variant_get_data(value);
+                       for (i = 0; i < len; i++)
+                               DBG("0x%.2x", buffer[i]);
+               }
+
+               /* Send event only registered client */
+               _bt_tds_handle_activation_request(path, org_id, buffer, len);
+               g_variant_unref(value);
+       }
+}
+
 static gboolean __bt_hal_event_manager(gpointer data)
 {
        bt_hal_event_type_t bt_event = 0x00;
@@ -1124,6 +1152,9 @@ static gboolean __bt_hal_event_manager(gpointer data)
        } else if (g_strcmp0(param->interface_name, BT_HAL_GATT_SERVICE_INTERFACE) == 0) {
                DBG("Manager Event: Interface Name: BT_HAL_GATT_SERVICE_INTERFACE");
                __bt_hal_handle_gatt_service_event(param->parameters, param->signal_name);
+       } else if (g_strcmp0(param->interface_name, BT_HAL_TDS_PROVIDER_INTERFACE) == 0) {
+               DBG("Manager Event: Interface Name: BT_HAL_TDS_PROVIDER_INTERFACE");
+               __bt_hal_handle_tds_provider_event(param->parameters, param->signal_name, param->object_path);
        }
 
 done:
diff --git a/bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.c
new file mode 100644 (file)
index 0000000..f98732b
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <dlog.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-tds-dbus-handler.h"
+
+bt_status_t _bt_hal_tds_register_provider()
+{
+       GDBusConnection *gconn;
+       char *adapter_path;
+       GDBusProxy *provider_proxy;
+       GVariant *result;
+       GError *error = NULL;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return  BT_STATUS_FAIL;
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (adapter_path == NULL)
+               return BT_STATUS_FAIL;
+
+       provider_proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_TDS_PROVIDER_INTERFACE,  NULL, NULL);
+       g_free(adapter_path);
+       if (provider_proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       result = g_dbus_proxy_call_sync(provider_proxy, "RegisterTdsProvider",
+                       NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       if (result == NULL) {
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call [%s]\n", error->message);
+                       g_error_free(error);
+               }
+               g_object_unref(provider_proxy);
+               return BT_STATUS_FAIL;
+       }
+       g_variant_unref(result);
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_tds_unregister_provider()
+{
+       GDBusConnection *gconn;
+       char *adapter_path;
+       GDBusProxy *provider_proxy;
+       GVariant *result;
+       GError *error = NULL;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return  BT_STATUS_FAIL;
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (adapter_path == NULL)
+               return BT_STATUS_FAIL;
+
+       provider_proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_TDS_PROVIDER_INTERFACE,  NULL, NULL);
+       g_free(adapter_path);
+       if (provider_proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       result = g_dbus_proxy_call_sync(provider_proxy, "UnregisterTdsProvider",
+                       NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       if (result == NULL) {
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call [%s]\n", error->message);
+                       g_error_free(error);
+               }
+               g_object_unref(provider_proxy);
+               return BT_STATUS_FAIL;
+       }
+       g_variant_unref(result);
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_tds_set_block_data(unsigned char *data, unsigned int data_len)
+{
+       GDBusConnection *gconn;
+       char *adapter_path;
+       GDBusProxy *provider_proxy;
+       GVariant *result;
+       GError *error = NULL;
+       GVariantBuilder *builder;
+       GVariant *temp;
+       int i;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return  BT_STATUS_FAIL;
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (adapter_path == NULL)
+               return BT_STATUS_FAIL;
+
+       /* Create block data */
+       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       for (i = 0; i < data_len; i++)
+               g_variant_builder_add(builder, "y", data[i]);
+       temp = g_variant_new("ay", builder);
+       g_variant_builder_unref(builder);
+
+       provider_proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_TDS_PROVIDER_INTERFACE,  NULL, NULL);
+       g_free(adapter_path);
+       if (provider_proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       result = g_dbus_proxy_call_sync(provider_proxy, "SetTdsBlockData",
+                       g_variant_new("(@ay)", temp),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       if (result == NULL) {
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call [%s]\n", error->message);
+                       g_error_free(error);
+               }
+               g_object_unref(provider_proxy);
+               return BT_STATUS_FAIL;
+       }
+       g_variant_unref(result);
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_tds_send_activation_response(unsigned char response,
+               unsigned char *data, unsigned int data_len)
+{
+       GDBusConnection *gconn;
+       char *adapter_path;
+       GDBusProxy *provider_proxy;
+       GVariant *result;
+       GError *error = NULL;
+       GVariantBuilder *builder;
+       GVariant *temp;
+       int i;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return  BT_STATUS_FAIL;
+
+       adapter_path = _bt_hal_get_adapter_path();
+       if (adapter_path == NULL)
+               return BT_STATUS_FAIL;
+
+       /* Create response data */
+       builder = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+       for (i = 0; i < data_len; i++)
+               g_variant_builder_add(builder, "y", data[i]);
+       temp = g_variant_new("ay", builder);
+       g_variant_builder_unref(builder);
+
+       provider_proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME, adapter_path,
+                       BT_HAL_TDS_PROVIDER_INTERFACE,  NULL, NULL);
+       g_free(adapter_path);
+       if (provider_proxy == NULL)
+               return BT_STATUS_FAIL;
+
+       result = g_dbus_proxy_call_sync(provider_proxy, "TdsActivationResponse",
+                       g_variant_new("(y@ay)", response, temp),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       if (result == NULL) {
+               if (error != NULL) {
+                       ERR("Error occured in Proxy call [%s]\n", error->message);
+                       g_error_free(error);
+               }
+               g_object_unref(provider_proxy);
+               return BT_STATUS_FAIL;
+       }
+       g_variant_unref(result);
+
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-tds-dbus-handler.h
new file mode 100644 (file)
index 0000000..9dbb3f8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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 _BT_HAL_TDS_DBUS_HANDLER_H_
+#define _BT_HAL_TDS_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <hardware/bt_tds.h>
+
+#include "bt_tds.h"
+
+bt_status_t _bt_hal_tds_register_provider();
+bt_status_t _bt_hal_tds_unregister_provider();
+bt_status_t _bt_hal_tds_set_block_data(unsigned char *data, unsigned int data_len);
+bt_status_t _bt_hal_tds_send_activation_response(unsigned char response,
+               unsigned char *data, unsigned int data_len);
+
+#endif /* _BT_HAL_TDS_DBUS_HANDLER_H_ */
diff --git a/bt-oal/bluez_hal/src/bt-hal-tds.c b/bt-oal/bluez_hal/src/bt-hal-tds.c
new file mode 100644 (file)
index 0000000..3764826
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlog.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <hardware/bluetooth.h>
+#include <hardware/bt_tds.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+#include "bt-hal-tds-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+
+static const bttds_callbacks_t *bt_hal_tds_callbacks = NULL;
+
+static bool interface_ready(void)
+{
+       return bt_hal_tds_callbacks != NULL;
+}
+
+void _bt_tds_handle_activation_request(const char *path,
+               unsigned char org_id, unsigned char *buf, int len)
+{
+       char address[BT_HAL_ADDRESS_STRING_SIZE];
+       _bt_hal_convert_device_path_to_address(path, address);
+
+       if (bt_hal_tds_callbacks->activation_requested_cb)
+               bt_hal_tds_callbacks->activation_requested_cb(address, org_id, buf, len);
+}
+
+static bt_status_t init(bttds_callbacks_t *callbacks)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_SUCCESS;
+
+       bt_hal_tds_callbacks = callbacks;
+       INFO("Register TDS events callback function");
+
+       return BT_STATUS_SUCCESS;
+}
+
+static bt_status_t tds_register_provider()
+{
+       DBG("");
+       return _bt_hal_tds_register_provider();
+}
+
+static bt_status_t tds_unregister_provider()
+{
+       DBG("");
+       return _bt_hal_tds_unregister_provider();
+}
+
+static bt_status_t tds_set_block_data(unsigned char *data, unsigned int data_len)
+{
+       DBG("");
+       return _bt_hal_tds_set_block_data(data, data_len);
+}
+
+static bt_status_t tds_send_activation_response(unsigned char response,
+               unsigned char *data, unsigned int data_len)
+{
+       DBG("");
+       return _bt_hal_tds_send_activation_response(response, data, data_len);
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       bt_hal_tds_callbacks = NULL;
+}
+
+static const bttds_interface_t tds_if = {
+       .size = sizeof(tds_if),
+       .init = init,
+       .register_provider = tds_register_provider,
+       .unregister_provider = tds_unregister_provider,
+       .set_block_data = tds_set_block_data,
+       .send_activation_response = tds_send_activation_response,
+       .cleanup = cleanup
+};
+
+const bttds_interface_t *bt_get_tds_interface()
+{
+       return &tds_if;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-tds.h b/bt-oal/bluez_hal/src/bt-hal-tds.h
new file mode 100644 (file)
index 0000000..332042e
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 __BT_HAL_TDS_H__
+#define __BT_HAL_TDS_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+#include <hardware/bt_tds.h>
+
+bool _bt_hal_tds_interface_ready(void);
+void _bt_tds_handle_activation_request(const char *path,
+               unsigned char org_id, unsigned char *buf, int len);
+bttds_interface_t *bt_get_tds_interface(void);
+
+#endif /* __BT_HAL_TDS_H__ */
index 67185b8..f0a3aa1 100644 (file)
@@ -52,6 +52,7 @@ __BEGIN_DECLS
 #define BT_PROFILE_MESH_ID "mesh"
 #define BT_PROFILE_AV_RC_ID "avrcp"
 #define BT_PROFILE_AV_RC_CTRL_ID "avrcp_ctrl"
+#define BT_PROFILE_TDS_ID "tds"
 #define BT_MANUFACTURER_DATA_LENGTH_MAX 31 /**< This specifies the Maximum manufacturer data Length>*/
 
 /** Bluetooth Address */
index ef7a190..f683506 100644 (file)
@@ -62,6 +62,8 @@ typedef struct {
        uint8_t  chnl_map;
        uint8_t  tx_power;
        uint8_t  timeout_s;
+       char*    tds_data;
+       uint16_t tds_data_len;
 } btgatt_adv_param_setup_t;
 
 
diff --git a/bt-oal/hardware/bt_tds.h b/bt-oal/hardware/bt_tds.h
new file mode 100644 (file)
index 0000000..6e0c716
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 TIZEN_INCLUDE_BT_TDS_H
+#define TIZEN_INCLUDE_BT_TDS_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/** Callback Signatures */
+typedef void (*activation_requested_callback)(char *address, unsigned char org_id, unsigned char *data, unsigned int data_len);
+
+/** BT-TDS callback structure. */
+typedef struct {
+       activation_requested_callback activation_requested_cb;
+} bttds_callbacks_t;
+
+/** Represents the standard BT-TDS interface. */
+typedef struct {
+       size_t size;
+       bt_status_t (*init)(bttds_callbacks_t *callbacks);
+       bt_status_t (*register_provider)(void);
+       bt_status_t (*unregister_provider)(void);
+       bt_status_t (*set_block_data)(unsigned char *data, unsigned int data_len);
+       bt_status_t (*send_activation_response)(unsigned char response, unsigned char *data, unsigned int data_len);
+       void (*cleanup)(void);
+} bttds_interface_t;
+
+__END_DECLS
+
+#endif /* TIZEN_INCLUDE_BT_TDS_H */
index 320efc8..87ca441 100644 (file)
@@ -201,6 +201,7 @@ extern "C" {
        EVENT(OAL_EVENT_MESH_APPKEY_EXECUTE_EVENT)  /* AppKey Operations (Add/Update/Delete) Event */\
        EVENT(OAL_EVENT_MESH_DEVKEY_MESSAGE_RECEIVED)  /* DevKey message received Event */\
        EVENT(OAL_EVENT_MESH_MODEL_MESSAGE_RECEIVED)  /* Message received Event */\
+       EVENT(OAL_EVENT_TDS_ACTIVATION_REQUESTED)  /* Message received Event */\
        EVENT(OAL_EVENT_END)                                /* End of event*/\
 
 
@@ -579,6 +580,14 @@ typedef struct {
        notif_event_avrcp_ct_play_status_t play_status;
 } event_avrcp_ct_play_status_t;
 
+#define TDS_ACTIVATION_DATA_LENGTH 100
+typedef struct {
+       char address[BT_ADDRESS_STR_LEN];
+       unsigned char org_id;
+       unsigned char tds_data[TDS_ACTIVATION_DATA_LENGTH];
+       unsigned int data_len;
+} event_tds_activation_requested_t;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 22cc4ce..787f320 100644 (file)
@@ -91,6 +91,8 @@ typedef struct {
        uint8_t  chnl_map;
        uint16_t  tx_power;
        uint8_t  timeout_s;
+       char*    tds_data;
+       uint16_t tds_data_len;
 } oal_ble_multi_adv_param_setup_t;
 
 typedef struct {
diff --git a/bt-oal/include/oal-tds.h b/bt-oal/include/oal-tds.h
new file mode 100644 (file)
index 0000000..1e5a654
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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 _OAL_TDS_H_
+#define _OAL_TDS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+oal_status_t tds_enable(void);
+oal_status_t tds_disable(void);
+oal_status_t tds_provider_register();
+oal_status_t tds_provider_unregister();
+oal_status_t tds_provider_set_block_data(unsigned char *data, unsigned int data_len);
+oal_status_t tds_provider_send_activation_response(unsigned char response, unsigned char *data, unsigned int data_len);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OAL_TDS_H_ */
index 9445cf2..190efe9 100644 (file)
@@ -583,6 +583,8 @@ oal_status_t gatts_multi_adv_set_inst_data(int instance_id,
        adv_setup.chnl_map = adv_param_setup->chnl_map;
        adv_setup.tx_power = adv_param_setup->tx_power;
        adv_setup.timeout_s = adv_param_setup->timeout_s;
+       adv_setup.tds_data = adv_param_setup->tds_data;
+       adv_setup.tds_data_len = adv_param_setup->tds_data_len;
 
        adv_setup.server_if = instance_id;
 
diff --git a/bt-oal/oal-tds.c b/bt-oal/oal-tds.c
new file mode 100644 (file)
index 0000000..ece914e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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 <dlog.h>
+#include <bluetooth.h>
+#include "bt_tds.h"
+#include "oal-event.h"
+#include "oal-internal.h"
+#include "oal-manager.h"
+#include "oal-utils.h"
+#include "oal-common.h"
+#include "oal-tds.h"
+
+#define CHECK_OAL_TDS_ENABLED() \
+       do { \
+               if (tds_api == NULL) { \
+                       BT_ERR("TDS Not Enabled"); \
+                       return OAL_STATUS_NOT_READY; \
+               } \
+       } while (0)
+
+static const bttds_interface_t *tds_api;
+
+static void tds_activation_requested_cb(char *address, unsigned char org_id, unsigned char *data, unsigned int data_len)
+{
+       event_tds_activation_requested_t *event = g_malloc0(sizeof(event_tds_activation_requested_t));
+       g_strlcpy(event->address, address, BT_ADDRESS_STR_LEN);
+       event->org_id = org_id;
+       memcpy(event->tds_data, data, sizeof(event->tds_data));
+       event->data_len = data_len;
+
+       send_event(OAL_EVENT_TDS_ACTIVATION_REQUESTED, event, sizeof(event_tds_activation_requested_t));
+}
+
+static bttds_callbacks_t tds_callbacks = {
+       .activation_requested_cb = tds_activation_requested_cb,
+};
+
+oal_status_t tds_enable(void)
+{
+       const bt_interface_t * blued_api;
+       int ret;
+
+       /* Get stack interface */
+       blued_api = (const bt_interface_t *)adapter_get_stack_interface();
+
+       if (blued_api == NULL) {
+               BT_ERR("Stack is not initialized");
+               return OAL_STATUS_NOT_READY;
+       }
+
+       if (tds_api) {
+               BT_WARN("TDS Interface is already initialized...");
+               return OAL_STATUS_ALREADY_DONE;
+       }
+
+       tds_api = (const bttds_interface_t *)blued_api->get_profile_interface(BT_PROFILE_TDS_ID);
+       if (tds_api == NULL) {
+               BT_ERR("TDS interface failed");
+               return OAL_STATUS_INTERNAL_ERROR;
+       }
+
+       if ((ret = tds_api->init(&tds_callbacks)) != BT_STATUS_SUCCESS) {
+               BT_ERR("Error: Unable to initialise TDS :%s", status2string(ret));
+               tds_api->cleanup();
+               tds_api = NULL;
+               return convert_to_oal_status(ret);
+       }
+
+       BT_INFO("TDS successfully initialized");
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t tds_disable(void)
+{
+       if (tds_api) {
+               tds_api->cleanup();
+               tds_api = NULL;
+       }
+
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t tds_provider_send_activation_response(unsigned char response,
+               unsigned char *data, unsigned int data_len)
+{
+       int ret;
+       API_TRACE();
+       CHECK_OAL_TDS_ENABLED();
+
+       ret = tds_api->send_activation_response(response, data, data_len);
+       if (ret != BT_STATUS_SUCCESS) {
+               BT_ERR("send_activation_response() failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t tds_provider_set_block_data(unsigned char *data, unsigned int data_len)
+{
+       int ret;
+       API_TRACE();
+       CHECK_OAL_TDS_ENABLED();
+
+       ret = tds_api->set_block_data(data, data_len);
+       if (ret != BT_STATUS_SUCCESS) {
+               BT_ERR("set_block_data() failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t tds_provider_unregister()
+{
+       int ret;
+       API_TRACE();
+       CHECK_OAL_TDS_ENABLED();
+
+       ret = tds_api->unregister_provider();
+       if (ret != BT_STATUS_SUCCESS) {
+               BT_ERR("unregister_provider() failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t tds_provider_register()
+{
+       int ret;
+       API_TRACE();
+       CHECK_OAL_TDS_ENABLED();
+
+       ret = tds_api->register_provider();
+       if (ret != BT_STATUS_SUCCESS) {
+               BT_ERR("register_provider() failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+       return OAL_STATUS_SUCCESS;
+}
index 8a8e64f..b330b6e 100644 (file)
@@ -40,6 +40,7 @@ SET(SRCS
 ./services/mesh/bt-service-mesh-main.c
 ./services/mesh/bt-service-mesh-config-client.c
 ./services/mesh/bt-service-mesh-model.c
+./services/tds/bt-service-tds.c
 )
 
 IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_OBEX")
index d16e6ae..642fde8 100644 (file)
@@ -36,6 +36,7 @@
 #include "bt-service-oob.h"
 #include "bt-service-battery-monitor.h"
 #include "bt-service-mesh-common.h"
+#include "bt-service-tds.h"
 
 #include <oal-hardware.h>
 #include <oal-manager.h>
@@ -503,6 +504,9 @@ static void __bt_le_multi_advertising_disabled(event_ble_multiadv_status *event)
                /* Free allocated slot or server instance from stack to be used for other advertisng */
                result = _bt_unregister_server_instance(sender, adv_handle);
 
+               /* Advertising disabled, notify TDS */
+               _bt_tds_handle_adv_disabled(sender);
+
                /* Free data */
                g_free(info->sender);
                g_free(info);
@@ -526,6 +530,9 @@ static void __bt_le_multi_advertising_set_data(event_ble_multiadv_status *event)
                if (event->status != OAL_STATUS_SUCCESS)
                        result = BLUETOOTH_ERROR_INTERNAL;
 
+               /* Check whether this request is from TDS or not */
+               _bt_tds_set_advertising_data_completed_cb(sender, adv_handle);
+
                info = g_malloc0(sizeof(bt_pending_adv_data_set_t));
                info->sender = sender;
                info->adv_handle = adv_handle;
@@ -1568,6 +1575,12 @@ static int __bt_set_multi_adv_param(oal_ble_multi_adv_param_setup_t *adv_setup,
                        memcpy(&adv_setup->appearance, (ptr + 2), (len - 1));
                        break;
                }
+               case 0x26: { /* Transport Discovery Data */
+                       adv_setup->tds_data = g_malloc0(sizeof(char) * len - 1);
+                       memcpy(adv_setup->tds_data, ptr + 2, len - 1);
+                       adv_setup->tds_data_len = len - 1;
+                       break;
+               }
                default:
                        BT_ERR("Unknown type: %x", type);
                        break;
index 65613f7..4b47b83 100644 (file)
@@ -49,6 +49,7 @@
 #include "bt-service-hiddevice.h"
 #include "bt-service-socket.h"
 #include "bt-service-hdp.h"
+#include "bt-service-tds.h"
 
 /* OAL headers */
 #include <oal-event.h>
@@ -1290,6 +1291,10 @@ int _bt_init_profiles()
        if (ret != BLUETOOTH_ERROR_NONE)
                BT_ERR("_bt_gatt_init Failed");
 
+       ret = _bt_tds_init();
+       if (ret != BLUETOOTH_ERROR_NONE)
+               BT_ERR("_bt_tds_init Failed");
+
        /* Initialize HF Client */
        ret = _bt_audio_initialize(BT_HFP_MODULE);
        if (ret != BLUETOOTH_ERROR_NONE)
index ae7dee0..b95b11c 100644 (file)
@@ -51,6 +51,7 @@
 #include "bt-service-hidhost.h"
 #include "bt-service-rfcomm.h"
 #include "bt-service-hdp.h"
+#include "bt-service-tds.h"
 
 /*Obex*/
 #include "bt-service-obex-server.h"
@@ -3355,6 +3356,107 @@ normal:
                break;
        }
 
+       case BT_TDS_PROVIDER_REGISTER: {
+               char *sender = NULL;
+
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+               result = _bt_tds_provider_register(sender);
+
+               break;
+       }
+
+       case BT_TDS_PROVIDER_UNREGISTER: {
+               char *sender = NULL;
+
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+               result = _bt_tds_provider_unregister(sender);
+
+               break;
+       }
+
+       case BT_TDS_PROVIDER_SET_MANUF_DATA: {
+               char *sender = NULL;
+               unsigned int length = 0;
+               bluetooth_advertising_data_t manuf_data;
+
+               __bt_service_get_parameters(in_param1,
+                               &length, sizeof(unsigned int));
+               __bt_service_get_parameters(in_param2,
+                               &manuf_data, sizeof(bluetooth_advertising_data_t));
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+
+               result = _bt_tds_provider_set_manuf_data(sender, manuf_data.data, length);
+               break;
+       }
+
+       case BT_TDS_PROVIDER_CREATE: {
+               char *sender = NULL;
+               unsigned int tds_handle = 0;
+               int transport;
+
+               __bt_service_get_parameters(in_param1,
+                               &tds_handle, sizeof(unsigned int));
+               __bt_service_get_parameters(in_param2,
+                               &transport, sizeof(int));
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+               result = _bt_tds_provider_transport_create(sender, transport, tds_handle);
+
+               break;
+       }
+
+       case BT_TDS_PROVIDER_DESTROY: {
+               char *sender = NULL;
+               unsigned int tds_handle = 0;
+
+               __bt_service_get_parameters(in_param1,
+                               &tds_handle, sizeof(unsigned int));
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+               result = _bt_tds_provider_transport_remove(sender, tds_handle);
+
+               break;
+       }
+
+       case BT_TDS_PROVIDER_SET_TRANSPORT_DATA: {
+               char *sender = NULL;
+               unsigned int tds_handle = 0;
+               int transport_state = 0;
+               bluetooth_tds_data_t tds_data;
+
+               __bt_service_get_parameters(in_param1,
+                               &tds_handle, sizeof(unsigned int));
+               __bt_service_get_parameters(in_param2,
+                               &transport_state, sizeof(int));
+               __bt_service_get_parameters(in_param3,
+                               &tds_data, sizeof(bluetooth_tds_data_t));
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+
+               result = _bt_tds_provider_set_transport_data(sender, tds_handle,
+                               transport_state, tds_data.data, tds_data.length);
+               break;
+       }
+
+       case BT_TDS_SEND_ACTIVATION_RESPONSE: {
+               bluetooth_device_address_t address = { {0} };
+               bluetooth_tds_data_t tds_data;
+               char *sender = NULL;
+               unsigned int tds_handle = 0;
+               int response;
+
+               __bt_service_get_parameters(in_param1,
+                               &tds_handle, sizeof(unsigned int));
+               __bt_service_get_parameters(in_param2,
+                               &response, sizeof(int));
+               __bt_service_get_parameters(in_param3, &address,
+                       sizeof(bluetooth_device_address_t));
+               __bt_service_get_parameters(in_param4,
+                               &tds_data, sizeof(bluetooth_tds_data_t));
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+
+               result = _bt_tds_provider_send_activation_response(sender, tds_handle,
+                               &address, response, tds_data.data, tds_data.length);
+               break;
+       }
+
        case BT_MESH_INIT:
                sender = (char*)g_dbus_method_invocation_get_sender(context);
                BT_INFO("Mesh: Init by [%s]", sender);
@@ -5345,6 +5447,9 @@ static void __name_owner_changed(GDBusConnection *connection,
 
        /* Mesh App Termination */
        _bt_check_mesh_app_termination(name);
+
+       /* Stop the Transport Discovery service */
+       _bt_tds_stop_by_terminated_process(name);
 }
 
 static void __bt_service_bus_acquired_handler(GDBusConnection *connection,
index 867e661..78334d7 100644 (file)
@@ -52,6 +52,7 @@ static _bt_service_event_handler_callback adapter_le_cb;
 static _bt_service_event_handler_callback adapter_gatt_cb;
 static _bt_service_event_handler_callback hf_client_cb;
 static _bt_service_event_handler_callback mesh_cb;
+static _bt_service_event_handler_callback tds_cb;
 
 void _bt_service_register_event_handler_callback(
                bt_service_module_t module, _bt_service_event_handler_callback cb)
@@ -121,6 +122,10 @@ void _bt_service_register_event_handler_callback(
                BT_INFO("Register BT_MESH_MODULE callback");
                mesh_cb = cb;
                break;
+       case BT_TDS_MODULE:
+               BT_INFO("Register BT_TDS_MODULE callback");
+               tds_cb = cb;
+               break;
        default:
                BT_INFO("Unknown module");
        }
@@ -177,6 +182,10 @@ void _bt_service_unregister_event_handler_callback(bt_service_module_t module)
                BT_INFO("Un-Register BT_MESH_MODULE callback");
                mesh_cb = NULL;
                break;
+       case BT_TDS_MODULE:
+               BT_INFO("Un-Register BT_TDS_MODULE callback");
+               tds_cb = NULL;
+               break;
        default:
                BT_INFO("Unknown module");
        }
@@ -421,6 +430,11 @@ static gboolean __bt_handle_oal_events(gpointer data)
                if (mesh_cb)
                        mesh_cb(event_type, event_data);
                break;
+       case OAL_EVENT_TDS_ACTIVATION_REQUESTED:
+               BT_INFO("TDS: Event");
+               if (tds_cb)
+                       tds_cb(event_type, event_data);
+               break;
        default:
                BT_ERR("Unhandled Event: %d", event_type);
                break;
index 5d345c5..a4a4954 100644 (file)
@@ -53,6 +53,7 @@ typedef enum {
        BT_LE_AD_TYPE_LIST_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14,
        BT_LE_AD_TYPE_LIST_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15,
        BT_LE_AD_TYPE_SERVICE_DATA = 0x16,
+       BT_LE_AD_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26,
        BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF,
 } bt_le_ad_type_t;
 
index 17c8ce8..88b04a0 100644 (file)
@@ -47,6 +47,7 @@ typedef enum {
        BT_ADAPTER_LE_MODULE,
        BT_GATT_MODULE,
        BT_MESH_MODULE,
+       BT_TDS_MODULE,
 } bt_service_module_t;
 
 void _bt_service_oal_event_receiver(int event_type, gpointer event_data, gsize len);
diff --git a/bt-service/services/include/bt-service-tds.h b/bt-service/services/include/bt-service-tds.h
new file mode 100644 (file)
index 0000000..49b42a7
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 _BT_SERVICE_TDS_H_
+#define _BT_SERVICE_TDS_H_
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+#include "oal-tds.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _bt_tds_init(void);
+int _bt_tds_provider_register(const char *sender);
+int _bt_tds_provider_unregister(const char *sender);
+int _bt_tds_provider_transport_create(const char *sender,
+               int transport, unsigned int tds_handle);
+int _bt_tds_provider_transport_remove(const char *sender,
+               unsigned int tds_handle);
+int _bt_tds_provider_set_manuf_data(char *sender,
+               unsigned char *data, unsigned int len);
+int _bt_tds_provider_set_transport_data(char *sender,
+               int tds_handle, int transport_state,
+               unsigned char *data, unsigned int len);
+int _bt_tds_provider_send_activation_response(char *sender,
+               unsigned int tds_handle, bluetooth_device_address_t *address,
+               int response, unsigned char *data, unsigned int len);
+
+void _bt_tds_set_advertising_data_completed_cb(char *sender, int adv_handle);
+void _bt_tds_handle_activation_request(const char *path,
+               unsigned char org_id, unsigned char *buf, int len);
+void _bt_tds_stop_by_terminated_process(const char *name);
+void _bt_tds_handle_adv_disabled(const char *sender);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_SERVICE_TDS_H_*/
diff --git a/bt-service/services/tds/bt-service-tds.c b/bt-service/services/tds/bt-service-tds.c
new file mode 100644 (file)
index 0000000..6b9bb7c
--- /dev/null
@@ -0,0 +1,959 @@
+/*
+ * 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 <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <string.h>
+
+#include "bluetooth-api.h"
+#include "bt-internal-types.h"
+
+#include "bt-service-common.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-core-adapter-le.h"
+#include "bt-service-event.h"
+#include "bt-service-event-receiver.h"
+#include "bt-service-core-adapter.h"
+#include "bt-service-util.h"
+#include "bt-service-tds.h"
+
+#include <oal-hardware.h>
+#include <oal-event.h>
+#include <oal-tds.h>
+
+#define TDS_CONTROL_POINT_RESPONSE_SUCCESS               0x00
+#define TDS_CONTROL_POINT_RESPONSE_OP_CODE_NOT_SUPPORTED 0x01
+#define TDS_CONTROL_POINT_RESPONSE_INVALID_PARAMETER     0x02
+#define TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID    0x03
+#define TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED      0x04
+
+#define BT_ADV_FLAG_LEN        3
+#define TDS_DATA_LEN_MAX       1024
+#define NUM_TDS_PROVIDER_MAX   10
+#define TDS_MANUF_DATA_LEN_MAX 29
+
+typedef enum {
+       TDS_ROLE_UNSPECIFIED = 0,
+       TDS_ROLE_SEEKER,
+       TDS_ROLE_PROVIDER,
+       TDS_ROLE_SEEKER_PROVIDER
+} bt_tds_role_t;
+
+typedef struct {
+       unsigned int tds_handle;
+       bt_tds_role_t role;
+       bluetooth_tds_transport_t transport;
+       bluetooth_tds_transport_state_t state;
+       unsigned int data_len;
+       unsigned char *data;
+} bt_tds_transport_info_t;
+
+typedef struct {
+       char *sender;
+       int adv_handle;
+       unsigned int manuf_data_len;
+       unsigned char *manuf_data;
+       GSList *transports;
+       int set_adv_data_requested;
+       int set_scan_resp_data_requested;
+} bt_tds_provider_t;
+
+GSList *provider_list = NULL;
+static int assigned_adv_handle;
+static gboolean adv_handle_used[NUM_TDS_PROVIDER_MAX];
+static gboolean tds_enabled;
+
+static void __bt_init_adv_handle(void)
+{
+       assigned_adv_handle = 0;
+       memset(adv_handle_used, 0x00, sizeof(adv_handle_used));
+}
+
+static int __bt_provider_get_adv_handle(void)
+{
+       int index;
+
+       index = assigned_adv_handle + 1;
+
+       if (index >= NUM_TDS_PROVIDER_MAX)
+               index = 0;
+
+       while (adv_handle_used[index] == TRUE) {
+               if (index == assigned_adv_handle) {
+                       /* No available ID */
+                       BT_ERR("All adv_handles are used");
+                       return -1;
+               }
+
+               index++;
+
+               if (index >= NUM_TDS_PROVIDER_MAX)
+                       index = 0;
+       }
+
+       assigned_adv_handle = index;
+       adv_handle_used[index] = TRUE;
+
+       return assigned_adv_handle;
+}
+
+static void __bt_provider_delete_adv_handle(int handle)
+{
+       ret_if(handle >= NUM_TDS_PROVIDER_MAX);
+       ret_if(handle < 0);
+
+       adv_handle_used[handle] = FALSE;
+}
+
+static unsigned char __bt_tds_get_organization_id(int transport)
+{
+       BT_INFO("transport: %d", transport);
+
+       switch (transport) {
+       case BLUETOOTH_TDS_TRANSPORT_BT:
+               return 0x01;
+       case BLUETOOTH_TDS_TRANSPORT_CUSTOM:
+               return 0x02;
+       default:
+               BT_ERR("Invaid transport");
+               return 0x00;
+       }
+}
+
+static int __bt_tds_get_transport(unsigned char org_id)
+{
+       BT_INFO("org_id: %d", org_id);
+
+       switch (org_id) {
+       case 0x01:
+               return BLUETOOTH_TDS_TRANSPORT_BT;
+       case 0x02:
+               return BLUETOOTH_TDS_TRANSPORT_CUSTOM;
+       default:
+               BT_ERR("Invaid org_id");
+               return BLUETOOTH_TDS_TRANSPORT_INVALID;
+       }
+}
+
+static unsigned char __bt_tds_set_role(unsigned char flag, bt_tds_role_t role)
+{
+
+       BT_INFO("Flag: 0x%x, Role: %d", flag, role);
+
+       switch (role) {
+       case TDS_ROLE_UNSPECIFIED:
+               flag = flag & 0xFC;
+               break;
+       case TDS_ROLE_SEEKER:
+               flag = flag & 0xFC;
+               flag = flag | 0x01;
+               break;
+       case TDS_ROLE_PROVIDER:
+               flag = flag & 0xFC;
+               flag = flag | 0x02;
+               break;
+       case TDS_ROLE_SEEKER_PROVIDER:
+               flag = flag & 0xFC;
+               flag = flag | 0x03;
+               break;
+       default:
+               BT_ERR("Invalid role received");
+       }
+
+       return flag;
+}
+
+static int __bt_tds_get_role(unsigned char flag)
+{
+
+       BT_INFO("Flag: 0x%x", flag);
+
+       if (0x03 == (flag & 0x03))
+               return TDS_ROLE_SEEKER_PROVIDER;
+       else if (0x02 == (flag & 0x02))
+               return TDS_ROLE_PROVIDER;
+       else if (0x01 == (flag & 0x01))
+               return TDS_ROLE_SEEKER;
+       else
+               return TDS_ROLE_UNSPECIFIED;
+}
+
+static unsigned char __bt_tds_set_transport_data_incomplete(
+               unsigned char flag, gboolean state)
+{
+       BT_INFO("Flag: 0x%x, Data state: %d", flag, state);
+
+       if (state)
+               flag = flag | 0x04; /* Set incomplete bit to 1 */
+       else
+               flag = flag & 0xFB; /* Set incomplete bit to 0 */
+
+       return flag;
+}
+
+static unsigned char __bt_tds_set_transport_state(
+               unsigned char flag, bluetooth_tds_transport_state_t state)
+{
+       BT_INFO("Flag: 0x%x, Transport state: %d", flag, state);
+
+       switch (state) {
+       case BLUETOOTH_TDS_TRANSPORT_STATE_OFF:
+               flag = flag & 0xE7;
+               break;
+       case BLUETOOTH_TDS_TRANSPORT_STATE_ON:
+               flag = flag & 0xE7;
+               flag = flag | 0x08;
+               break;
+       case BLUETOOTH_TDS_TRANSPORT_STATE_UNAVAILABLE:
+               flag = flag & 0xE7;
+               flag = flag | 0x10;
+               break;
+       case BLUETOOTH_TDS_TRANSPORT_STATE_RESERVED:
+               flag = flag & 0xE7;
+               flag = flag | 0x18;
+               break;
+       default:
+               BT_ERR("Invalid transport state received");
+       }
+
+       return flag;
+}
+
+static unsigned char __bt_tds_get_activation_response_code(int result)
+{
+       unsigned char resp;
+
+       switch (result) {
+       case BLUETOOTH_ERROR_NONE:
+               resp = TDS_CONTROL_POINT_RESPONSE_SUCCESS; /* Success */
+               break;
+       case BLUETOOTH_ERROR_INVALID_PARAM:
+               resp = TDS_CONTROL_POINT_RESPONSE_INVALID_PARAMETER; /*Invalid Parameter */
+               break;
+       case BLUETOOTH_ERROR_NOT_SUPPORT:
+               resp = TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID; /* Unsupported Organization ID*/
+               break;
+       case BLUETOOTH_ERROR_INTERNAL:
+               resp = TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED; /* */
+               break;
+       default:
+               BT_INFO("Unknown response code: %d received", result);
+               resp = TDS_CONTROL_POINT_RESPONSE_OPERATION_FAILED;
+       }
+
+       return resp;
+}
+
+static bt_tds_provider_t* __bt_tds_provider_find_from_list(const char *sender)
+{
+       GSList *l;
+
+       retv_if(sender == NULL, NULL);
+
+       for (l = provider_list; l != NULL; l = g_slist_next(l)) {
+               bt_tds_provider_t *provider = l->data;
+               if (provider && (g_strcmp0(provider->sender, sender) == 0))
+                       return provider;
+       }
+
+       return NULL;
+}
+
+static unsigned char* __bt_tds_provider_get_tds_blocks(unsigned int *length)
+{
+       GSList *l;
+       GSList *l1;
+       unsigned int len = 0;
+       unsigned char data[TDS_DATA_LEN_MAX] = { 0, };
+
+       retv_if(length == NULL, NULL);
+
+       for (l = provider_list; NULL != l; l = g_slist_next(l)) {
+               bt_tds_provider_t *provider = l->data;
+
+               if (!provider)
+                       continue;
+
+               for (l1 = provider->transports; l1 != NULL; l1 = g_slist_next(l1)) {
+                       bt_tds_transport_info_t *transport_info = l1->data;
+
+                       if (!transport_info || !transport_info->data)
+                               continue;
+
+                       if (len + transport_info->data_len > sizeof(data)) {
+                               BT_ERR("Could not set complete the tds data, size exceeded");
+                               break;
+                       }
+
+                       memcpy(&(data[len]), transport_info->data, transport_info->data_len);
+                       len += transport_info->data_len;
+               }
+       }
+
+       *length = len;
+       BT_INFO("length = %d", *length);
+       return g_memdup(data, *length);
+}
+
+static void __bt_tds_set_scan_resp_data(bt_tds_provider_t *provider)
+{
+       bluetooth_scan_resp_data_t scan_resp;
+       char *name;
+       int adv_handle = 0;
+       int len = 0;
+       int ret;
+
+       BT_DBG("+");
+
+       name = provider->sender;
+       adv_handle = provider->adv_handle;
+
+       if (provider->manuf_data_len > 0) {
+               scan_resp.data[len++] = provider->manuf_data_len + 1;
+               scan_resp.data[len++] = BT_LE_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
+               memcpy(&(scan_resp.data[len]), provider->manuf_data, provider->manuf_data_len);
+               len += provider->manuf_data_len;
+       }
+
+       if (len <= (BLUETOOTH_SCAN_RESP_DATA_LENGTH_MAX - 2)) {
+               /* Include name */
+               scan_resp.data[len++] = 1;
+               scan_resp.data[len++] = BT_LE_AD_TYPE_COMPLETE_LOCAL_NAME;
+       }
+
+       ret = _bt_set_scan_response_data(name, adv_handle, &scan_resp, len, FALSE);
+       if (ret != BLUETOOTH_ERROR_NONE)
+               BT_ERR("Failed to set scan response data. ret: %d", ret);
+
+       BT_DBG("-");
+}
+
+/* If multi adv supported set each provider's data in seperate adv slot */
+static int __bt_tds_provider_get_tds_multi_adv_data(bt_tds_provider_t *provider, guint8 *adv_data)
+{
+       GSList *l;
+       unsigned int len = 0;
+       unsigned int max_adv_len = BLUETOOTH_ADVERTISING_DATA_LENGTH_MAX - BT_ADV_FLAG_LEN;
+       int count;
+
+       retv_if(provider == NULL, -1);
+       retv_if(adv_data == NULL, -1);
+
+       count = g_slist_length(provider->transports);
+       adv_data[1] = BT_LE_AD_TYPE_TRANSPORT_DISCOVERY_DATA;
+       len = 2;
+
+       for (l = provider->transports; l != NULL; l = g_slist_next(l)) {
+               bt_tds_transport_info_t *transport_info = l->data;
+
+               if (!transport_info || !transport_info->data)
+                       continue;
+
+               if ((len + transport_info->data_len < max_adv_len - 3) ||
+                               (count <= 1 && (len + transport_info->data_len < max_adv_len))) {
+                       memcpy(&(adv_data[len]), transport_info->data, transport_info->data_len);
+                       len += transport_info->data_len;
+               } else {
+                       /* Not able to accomodated complete data in adv pkt */
+                       adv_data[len++] = transport_info->data[0];      /* Organization Id */
+                       adv_data[len++] = __bt_tds_set_transport_data_incomplete(
+                                       transport_info->data[1], TRUE);
+                       adv_data[len++] = 0;    /* Set Transport data len = 0 */
+                       break;
+               }
+
+               count--;
+       }
+
+       BT_INFO("len = %d", len);
+       if (len <= 2)
+               return -1; /* No data */
+
+       adv_data[0] = len - 1;
+       return len;
+}
+
+void _bt_tds_set_advertising_data_completed_cb(char *sender, int adv_handle)
+{
+       bt_tds_provider_t *provider;
+
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return;
+
+       if (provider->set_adv_data_requested) {
+               provider->set_adv_data_requested = FALSE;
+               BT_DBG("Setting adv data completed. Set response data");
+               __bt_tds_set_scan_resp_data(provider);
+               provider->set_scan_resp_data_requested = TRUE;
+               /* _bt_tds_set_advertising_data_completed_cb() will be called */
+               return;
+       }
+
+       if (provider->set_scan_resp_data_requested) {
+               bluetooth_advertising_params_t param = {0, };
+               int ret;
+
+               provider->set_scan_resp_data_requested = FALSE;
+               BT_DBG("Setting response data completed. Start advertising");
+
+               param.interval_min = 500;
+               param.interval_max = 500;
+               param.filter_policy = BLUETOOTH_ALLOW_SCAN_CONN_ALL;
+               param.type = BLUETOOTH_ADV_CONNECTABLE;
+
+               ret = _bt_set_custom_advertising(sender, adv_handle, TRUE, &param, FALSE);
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("Failed to enable advertising. ret: %d", ret);
+                       return;
+               }
+       }
+}
+
+static int __bt_tds_set_advertising(bt_tds_provider_t *provider)
+{
+       bluetooth_advertising_data_t adv;
+       char *name;
+       int adv_handle;
+       int length;
+       int ret;
+       int i;
+
+       BT_DBG("+");
+
+       name = provider->sender;
+       adv_handle = provider->adv_handle;
+
+       /* Get updated TDS advertising data */
+       length = __bt_tds_provider_get_tds_multi_adv_data(provider, adv.data);
+       if (length == 0)
+               return BLUETOOTH_ERROR_NONE;
+
+       for (i = 0; i < length; i++)
+               BT_DBG("adv_data: 0x%x", adv.data[i]);
+
+       ret = _bt_set_advertising_data(name, adv_handle, &adv, length, FALSE);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to set advertising data. ret: %d", ret);
+               return ret;
+       }
+       provider->set_adv_data_requested = TRUE;
+       /* _bt_tds_set_advertising_data_completed_cb() will be called */
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+static int __bt_tds_disable_advertising(bt_tds_provider_t *provider)
+{
+       char *name;
+       int adv_handle;
+       int ret;
+
+       BT_DBG("+");
+
+       name = provider->sender;
+       adv_handle = provider->adv_handle;
+
+       /* First try to disable adv in case already advertising */
+       ret = _bt_set_advertising(name, adv_handle, FALSE, FALSE);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_DBG("Failed to disable advertising. ret: %d", ret);
+               ret = __bt_tds_set_advertising(provider);
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("Failed to enable advertising. ret: %d", ret);
+                       return ret;
+               }
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+static int __bt_tds_provider_update_transport_data(bt_tds_provider_t *provider)
+{
+       unsigned char *buf = NULL;
+       unsigned int length = 0;
+       int ret;
+
+       BT_DBG("+");
+
+       buf = __bt_tds_provider_get_tds_blocks(&length);
+       retv_if(length == 0, BLUETOOTH_ERROR_NONE);
+       retv_if(buf == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       ret = tds_provider_set_block_data(buf, length);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("tds_provider_register() failed. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+static void __bt_free_tds_transport_info(gpointer data, gpointer user_data)
+{
+       bt_tds_transport_info_t *transport_info = data;
+
+       ret_if(transport_info == NULL);
+
+       BT_DBG("+");
+
+       g_free(transport_info->data);
+       g_free(transport_info);
+
+       BT_DBG("-");
+}
+
+static bt_tds_transport_info_t * __bt_tds_find_transport_info(
+               bt_tds_provider_t *provider, unsigned int handle)
+{
+       GSList *l;
+
+       retv_if(provider == NULL, NULL);
+
+       for (l = provider->transports; l != NULL; l = g_slist_next(l)) {
+               bt_tds_transport_info_t *transport_info = l->data;
+
+               if (!transport_info)
+                       continue;
+
+               if (transport_info->tds_handle == handle)
+                       return transport_info;
+       }
+
+       return NULL;
+}
+
+int _bt_tds_provider_register(const char *sender)
+{
+       bt_tds_provider_t *provider;
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       if (__bt_tds_provider_find_from_list(sender))
+               return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
+
+       if (0 == g_slist_length(provider_list)) {
+               if (tds_enabled == FALSE) {
+                       ret = tds_enable();
+                       if (ret != BLUETOOTH_ERROR_NONE) {
+                               BT_ERR("tds_enable() failed. ret: %d", ret);
+                               return ret;
+                       }
+                       tds_enabled = TRUE;
+               }
+
+               ret = tds_provider_register();
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("tds_provider_register() failed. ret: %d", ret);
+                       return ret;
+               }
+               /* Init adv_handle list */
+               __bt_init_adv_handle();
+       }
+
+       provider = g_malloc0(sizeof(bt_tds_provider_t));
+       provider->sender = g_strdup(sender);
+       provider->adv_handle = __bt_provider_get_adv_handle();
+       if (0 > provider->adv_handle) {
+               g_free(provider->sender);
+               g_free(provider);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       provider_list = g_slist_append(provider_list, provider);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_unregister(const char *sender)
+{
+       bt_tds_provider_t *provider = NULL;
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       if (1 == g_slist_length(provider_list)) {
+               ret = tds_provider_unregister();
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("tds_provider_register() failed. ret: %d", ret);
+                       return ret;
+               }
+       }
+
+       /* Disable advertisement for sender */
+       ret = _bt_set_advertising(provider->sender, provider->adv_handle, FALSE, FALSE);
+       if (ret != BLUETOOTH_ERROR_NONE)
+               BT_ERR("Failed to disable advertising. ret: %d", ret);
+
+       provider_list = g_slist_remove(provider_list, provider);
+       g_slist_foreach(provider->transports, __bt_free_tds_transport_info, NULL);
+       g_slist_free(provider->transports);
+       __bt_provider_delete_adv_handle(provider->adv_handle);
+       g_free(provider->sender);
+       g_free(provider);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_transport_create(const char *sender, int transport, unsigned int tds_handle)
+{
+       bt_tds_transport_info_t *transport_info;
+       bt_tds_provider_t *provider = NULL;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       if (BLUETOOTH_TDS_TRANSPORT_BT > transport ||
+                       BLUETOOTH_TDS_TRANSPORT_INVALID <= transport) {
+               BT_ERR("transport value: %d not in range", transport);
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+       }
+
+       BT_DBG("+");
+
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       transport_info = g_malloc0(sizeof(bt_tds_transport_info_t));
+       transport_info->transport = transport;
+       transport_info->tds_handle = tds_handle;
+       transport_info->role = TDS_ROLE_PROVIDER;
+       transport_info->state = BLUETOOTH_TDS_TRANSPORT_STATE_OFF;
+       provider->transports = g_slist_append(provider->transports, transport_info);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_transport_remove(const char *sender, unsigned int tds_handle)
+{
+       bt_tds_provider_t *provider = NULL;
+       bt_tds_transport_info_t *transport_info;
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       transport_info = __bt_tds_find_transport_info(provider, tds_handle);
+       if (!transport_info)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       provider->transports = g_slist_remove(provider->transports, transport_info);
+       __bt_free_tds_transport_info(transport_info, NULL);
+
+       /* Set/update transport data in gatt db */
+       ret = __bt_tds_provider_update_transport_data(provider);
+       if (BLUETOOTH_ERROR_NONE != ret) {
+               BT_ERR("Failed to update transport data. ret: %d", ret);
+               return ret;
+       }
+
+       /*
+        * Disable advertising here. Later on receiving advertising disabled event,
+        * advertising will be enabled again with updated advertising data.
+        */
+       ret = __bt_tds_disable_advertising(provider);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to enable advertising. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_set_manuf_data(char *sender, unsigned char *data, unsigned int len)
+{
+       bt_tds_provider_t *provider;
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(len == 0 || len > TDS_MANUF_DATA_LEN_MAX, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(data == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       BT_INFO("sender: %s", sender);
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       /*
+        * Set manufacturer data and disable advertising here. Later on receiving advertising
+        * disabled event, advertising will be enabled again with updated advertising data.
+        */
+       g_free(provider->manuf_data);
+       provider->manuf_data_len = len;
+       provider->manuf_data = g_malloc0(provider->manuf_data_len);
+       memcpy(provider->manuf_data, data, len);
+
+       ret = __bt_tds_disable_advertising(provider);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to enable advertising. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_set_transport_data(char *sender, int tds_handle,
+               int transport_state, unsigned char *data, unsigned int len)
+{
+       bt_tds_provider_t *provider;
+       bt_tds_transport_info_t *transport_info;
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(len > 0 && data == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       if (BLUETOOTH_TDS_TRANSPORT_STATE_OFF > transport_state ||
+                       BLUETOOTH_TDS_TRANSPORT_STATE_RESERVED <= transport_state) {
+               BT_ERR("transport_state value: %d not in range", transport_state);
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+       }
+
+       BT_INFO("sender: %s, tds_handle: 0x%x", sender, tds_handle);
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       transport_info = __bt_tds_find_transport_info(provider, tds_handle);
+       if (!transport_info)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       transport_info->state = transport_state;
+       g_free(transport_info->data);
+       transport_info->data_len = len + 3;
+       transport_info->data = g_malloc0(transport_info->data_len);
+       /* TDS Orgnazition Id */
+       transport_info->data[0] = __bt_tds_get_organization_id(transport_info->transport);
+       /* TDS block flag */
+       if (TDS_ROLE_SEEKER_PROVIDER != __bt_tds_get_role(transport_info->data[1]))
+               transport_info->data[1] = __bt_tds_set_role(transport_info->data[1], transport_info->role);
+       transport_info->data[1] = __bt_tds_set_transport_data_incomplete(transport_info->data[1], FALSE);
+       transport_info->data[1] = __bt_tds_set_transport_state(transport_info->data[1], transport_state);
+       /* TDS block data length */
+       transport_info->data[2] = len;
+       memcpy(&(transport_info->data[3]), data, len);
+
+       /* Set/update transport data in gatt db */
+       ret = __bt_tds_provider_update_transport_data(provider);
+       if (BLUETOOTH_ERROR_NONE != ret) {
+               BT_ERR("Failed to update transport data. ret: %d", ret);
+               return ret;
+       }
+
+       /*
+        * Disable advertising here. Later on receiving advertising disabled event,
+        * advertising will be enabled again with updated advertising data.
+        */
+       ret = __bt_tds_disable_advertising(provider);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to enable advertising. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+static int __bt_tds_send_activation_response(char *address,
+               unsigned char response, unsigned char *data, unsigned int len)
+{
+       int ret;
+
+       retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(data == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       ret = tds_provider_send_activation_response(response, data, len);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("tds_provider_register() failed. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int _bt_tds_provider_send_activation_response(char *sender, unsigned int tds_handle,
+       bluetooth_device_address_t *address, int response, unsigned char *data, unsigned int len)
+{
+       bt_tds_provider_t *provider;
+       bt_tds_transport_info_t *transport_info;
+       unsigned char resp;
+       char addr[BT_ADDRESS_STRING_SIZE];
+       int ret;
+
+       retv_if(sender == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(address == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+       retv_if(data == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       BT_DBG("+");
+
+       BT_INFO("sender: %s, tds_handle: 0x%x", sender, tds_handle);
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider)
+               return BLUETOOTH_ERROR_NOT_INITIALIZED;
+
+       transport_info = __bt_tds_find_transport_info(provider, tds_handle);
+       if (!transport_info)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       if (BLUETOOTH_ERROR_NONE == response) {
+               /* Activation success, set transport state enabled */
+               _bt_tds_provider_set_transport_data(provider->sender,
+                       transport_info->transport, BLUETOOTH_TDS_TRANSPORT_STATE_ON,
+                       transport_info->data, transport_info->data_len);
+       }
+
+       _bt_convert_addr_type_to_string(addr, address->addr);
+       resp = __bt_tds_get_activation_response_code(response);
+
+       ret = __bt_tds_send_activation_response(addr, resp, data, len);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to send activation response. ret: %d", ret);
+               return ret;
+       }
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+static void __bt_tds_handle_activation_request(char *address,
+               unsigned char org_id, unsigned char *data, int data_len)
+{
+       int transport;
+       GVariant *tds_data;
+       GVariant *param;
+       int count = 0;
+       GSList *l;
+       GSList *l1;
+
+       ret_if(address == NULL);
+       ret_if(data_len > 0 && data == NULL);
+
+       transport = __bt_tds_get_transport(org_id);
+       if (BLUETOOTH_TDS_TRANSPORT_INVALID == transport)
+               goto err;
+
+       BT_DBG("Address: %s, transport: 0x%x", address, transport);
+       tds_data = g_variant_new_from_data((const GVariantType *)"ay",
+                       data, data_len, TRUE, NULL, NULL);
+       param = g_variant_new("(si@ay)", address, transport, tds_data);
+
+       /* Find provider with transport type in list and send event to them */
+       for (l = provider_list; l != NULL; l = g_slist_next(l)) {
+               bt_tds_provider_t *provider = l->data;
+               if (!provider)
+                       continue;
+
+               for (l1 = provider->transports; l1 != NULL; l1 = g_slist_next(l1)) {
+                       bt_tds_transport_info_t *transport_info = l1->data;
+
+                       if (transport_info && transport_info->transport == transport) {
+                               _bt_send_event_to_dest(provider->sender, BT_TDS_EVENT,
+                                               BLUETOOTH_EVENT_TDS_ACTIVATION_REQUESTED, param);
+                               count++;
+                       }
+               }
+       }
+       g_variant_unref(tds_data);
+
+       /* If no provider found for transport type, send error */
+       if (0 == count)
+               goto err;
+
+       BT_DBG("-");
+       return;
+err:
+       /* send activation response as error to bluez */
+       __bt_tds_send_activation_response(address,
+               TDS_CONTROL_POINT_RESPONSE_UNSUPPORTED_ORG_ID, NULL, 0);
+}
+
+void _bt_tds_stop_by_terminated_process(const char *name)
+{
+       bt_tds_provider_t *provider = NULL;
+
+       provider = __bt_tds_provider_find_from_list(name);
+       if (!provider)
+               return;
+
+       _bt_tds_provider_unregister(provider->sender);
+}
+
+void _bt_tds_handle_adv_disabled(const char *sender)
+{
+       bt_tds_provider_t *provider = NULL;
+
+       ret_if(sender == NULL);
+       BT_INFO("sender: %s", sender);
+
+       provider = __bt_tds_provider_find_from_list(sender);
+       if (!provider) {
+               BT_ERR("Provider not found");
+               return;
+       }
+
+       __bt_tds_set_advertising(provider);
+}
+
+static void __bt_tds_event_handler(int event_type, gpointer event_data)
+{
+       BT_INFO("OAL event = %d", event_type);
+
+       switch (event_type) {
+       case OAL_EVENT_TDS_ACTIVATION_REQUESTED: {
+               event_tds_activation_requested_t *data = event_data;
+               __bt_tds_handle_activation_request(data->address, data->org_id,
+                               data->tds_data, data->data_len);
+               }
+               break;
+       }
+}
+
+int _bt_tds_init(void)
+{
+       /* Register TDS event handler */
+       _bt_service_register_event_handler_callback(BT_TDS_MODULE, __bt_tds_event_handler);
+       return BLUETOOTH_ERROR_NONE;
+}