[TDS] Implement TDS Seeker role CAPI's 72/110472/1 accepted/tizen/3.0/common/20170120.102141 accepted/tizen/3.0/ivi/20170120.072803 accepted/tizen/3.0/mobile/20170120.072707 accepted/tizen/3.0/tv/20170120.072742 accepted/tizen/3.0/wearable/20170120.072752 submit/tizen_3.0/20170118.073413 submit/tizen_3.0/20170202.043546
authorAnupam Roy <anupam.r@samsung.com>
Mon, 16 Jan 2017 11:00:16 +0000 (16:30 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Mon, 16 Jan 2017 15:05:41 +0000 (20:35 +0530)
This patch implements the Seeker role of
TDS Connection handover profile. Following
CAPI's AND callbacks are handled in this patch

1/ Find Remote TDS providers- BLE Scan to find
   all devices which support TDS Service
2/ TDS Seeker Create/Destroy
3/ TDS Connect/Disconnect
4/ TDS Read Transport specific complete data
5/ Activate TDS Control point- This will attempt
   to activate Alternate transport in TDS Provider
   from GATT database of remote TDS provider

Change-Id: Iaf4f79d23093da3e4e597c4c3974a06764206493
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
include/bluetooth_private.h
include/mobile/bluetooth_internal.h
include/mobile/bluetooth_type_internal.h
include/tv/bluetooth_internal.h
include/tv/bluetooth_type_internal.h
include/wearable/bluetooth_internal.h
include/wearable/bluetooth_type_internal.h
src/bluetooth-common.c
src/bluetooth-tds.c
test/bt_unit_test.c
test/bt_unit_test.h

index 63b0b0683f524066f2cbca4f20ca94ce303e6a51..c7781c79461aa8e30da1a5a9900a5576a71f094b 100644 (file)
@@ -161,6 +161,7 @@ typedef enum {
        BT_EVENT_MAP_CLIENT_GET_MESSAGE, /**< MAP - getMessage event*/
        BT_EVENT_MAP_CLIENT_PUSH_MESSAGE, /**< MAP - pushMessage event*/
        BT_EVENT_TDS_ACTIVATION_REQUESTED, /**< TDS - transport activation requested event */
+       BT_EVENT_TDS_PROVIDER_FOUND_RESULT, /**< TDS - CUSTOM Provider */
        BT_EVENT_MAX
 } bt_event_e;
 
@@ -214,6 +215,7 @@ typedef enum {
        BT_ADAPTER_LE_ADVERTISING_DATA_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15, /**< List of 128-bit Service Solicitation UUIDs*/
        BT_ADAPTER_LE_ADVERTISING_DATA_SERVICE_DATA = 0x16, /**< Service data */
        BT_ADAPTER_LE_ADVERTISING_DATA_APPEARANCE = 0x19, /**< Appearance*/
+       BT_ADAPTER_LE_ADVERTISING_DATA_TRANSPORT_DISCOVERY = 0x26, /**< Transport Discovery*/
        BT_ADAPTER_LE_ADVERTISING_DATA_MANUFACTURER_SPECIFIC_DATA = 0xff, /**< Manufacturer data */
 } bt_adapter_le_advertising_data_type_e;
 
@@ -637,6 +639,13 @@ int _bt_get_error_code(int origin_error);
 int _bt_get_bt_device_info_s(bt_device_info_s **dest_dev, bluetooth_device_info_t *source_dev);
 
 
+/**
+ * @internal
+ * @brief Filter Advertising data based on AD type.
+ */
+int _bt_get_ad_data_by_type(char *in_data, int in_len,
+               char in_type, char **data, int *data_len);
+
 /**
  * @internal
  * @brief Free bt_device_info_s.
@@ -847,6 +856,48 @@ int _bt_check_proximity_is_initialized(bool *is_initialized);
  */
 int _bt_proximity_connection_set_state_changed(int result, const char *remote_address, bool connected);
 
+/**
+ * @internal
+ * @brief Send GATT connection state changed status with remote TDS provider.
+ */
+void _bt_tds_update_seeker_connection_state_changed(int result, const char *remote_address, bool connected);
+
+/**
+ * @internal
+ * @brief  Parses TDS AD Type data recived in scan, to extract meaningful transport specific data.
+ */
+int _bt_tds_parse_transport_blocks(bt_tds_transport_block_list_s **info, char *data, int data_len);
+
+/**
+ * @internal
+ * @brief  Handles complete TDS specific data to be sent to application.
+ */
+void _bt_tds_send_complete_transport_data(int result, const char *address, char *data, int data_len);
+
+/**
+ * @internal
+ * @brief Send Result of TDS specific CCCD enabled event of Remote TDS provider.
+ */
+void _bt_tds_control_point_enabled_update(int result, const char *remote_address);
+
+/**
+ * @internal
+ * @brief Send Result of TDS control point activate ACK event.
+ */
+void _bt_tds_control_point_activation_result_update(int result, const char *remote_address);
+
+/**
+ * @internal
+ * @brief Send TDS Indication response from remote TDS provider.
+ */
+void _bt_tds_control_point_indication_response_update(const char *address, bluetooth_tds_indication_res_t *info);
+
+/**
+ * @internal
+ * @brief Sends GATT primary service status changed of Remote Provider.
+ */
+void _bt_tds_check_service_changed(char *address, bt_gatt_service_change_t *service_change);
+
 #ifdef __cplusplus
 }
 #endif
index a2e6c878897270bb9c00c481e8958af13b2de39e..aeed803e951e0f8ae29c549cb0cbb8e43a3f0527 100644 (file)
@@ -3889,6 +3889,69 @@ int bt_tds_set_transport_activation_requested_cb(
  */
 int bt_tds_unset_transport_activation_requested_cb(void);
 
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to start seeking Remote TDS providers only
+ */
+int bt_tds_start_seeking_providers(bt_tds_provider_scan_result_cb cb, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to stop seeking Remote TDS providers
+ */
+int bt_tds_stop_seeking_providers(void);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to create Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_create(const char *remote_address, bt_tds_seeker_h *seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to destroy Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_destroy(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to set connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_set_connection_state_changed_cb(bt_tds_seeker_h seeker,
+               bt_tds_seeker_connection_state_changed_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to unset connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_unset_connection_state_changed_cb(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to connect to Remote TDS provider
+ */
+int bt_tds_seeker_connect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to disconnect to Remote TDS provider
+ */
+int bt_tds_seeker_disconnect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to read complete TDS block data which is stored in Remote TDS provider's GATT database
+ */
+int bt_tds_seeker_get_complete_transport_blocks(bt_tds_seeker_h seeker,
+               bt_tds_seeker_complete_transport_data_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to Activate ALternate transport supported by Remote TDS provider
+ */
+int bt_tds_seeker_activate_control_point(bt_tds_seeker_h seeker,
+               bt_tds_transport_e transport, unsigned char *buffer, int len,
+               bt_tds_control_point_activation_indication_cb callback, void *user_data);
 /**
  * @}
  */
index 50b2426786e28d5cb41e9b9d6dc6d508e025fd52..96dd8d23c9212375a75d709e7f1cdd8429dd9047 100644 (file)
@@ -710,9 +710,9 @@ typedef void (*bt_proximity_reporter_connection_state_changed_cb)
  * @since_tizen 3.0
  */
 typedef enum {
-       BT_TDS_TRANSPORT_STATE_OFF,
-       BT_TDS_TRANSPORT_STATE_ON,
-       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,
+       BT_TDS_TRANSPORT_STATE_OFF,     /**< Transport is currently in OFF state */
+       BT_TDS_TRANSPORT_STATE_ON,      /**< Transport is currently in ON state */
+       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,     /**< Transport is temporarily unavailable */
 } bt_tds_transport_state_e;
 
 /**
@@ -727,6 +727,29 @@ typedef enum {
        BT_TDS_TRANSPORT_INVALID
 } bt_tds_transport_e;
 
+/**
+ * @internal
+ * @brief The structure type of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       bt_tds_transport_e transport;
+       bt_tds_transport_state_e state;
+       bool is_data_complete;
+       char *data;
+       int length;
+} tds_transport_data_s;
+
+/**
+ * @internal
+ * @brief The structure type of list of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       int num_transport_block;            /**< Number of Transport Data Blocks */
+       tds_transport_data_s **data;        /**< Array of Transport Data Block */
+} bt_tds_transport_block_list_s;
+
 /**
  * @internal
  * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE
@@ -801,6 +824,47 @@ typedef void *bt_tds_provider_h;
  */
 typedef void (*bt_tds_activation_requested_cb)(char *remote_bd_addr,
        bt_tds_transport_e transport, unsigned char *buf, int len, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE
+ * @brief The handle of a TDS Seeker client which is associated with a remote TDS provider
+ * @since_tizen 3.0
+ */
+typedef void *bt_tds_seeker_h;
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Scan result callback containing filtered TDS service information and
+ * complete LE discovery informations
+ */
+typedef void (*bt_tds_provider_scan_result_cb)(int result, const char *remote_address,
+               bt_tds_transport_block_list_s *info, bt_adapter_le_device_scan_result_info_s *scan_info,
+               void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Connection State changed callback which is associated with a remote TDS provider
+ */
+typedef void (*bt_tds_seeker_connection_state_changed_cb)
+               (int result, const char *remote_address, bt_tds_seeker_h seeker, bool connected, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile complete TDS data block read callback from remote TDS provider
+ */
+typedef void (*bt_tds_seeker_complete_transport_data_cb)
+               (int result, const char *remote_address, bt_tds_transport_block_list_s *info, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile TDS Control Point Activation request callback which is associated with remote TDS provider
+ */
+typedef void (*bt_tds_control_point_activation_indication_cb)
+               (int result, const char *remote_address, unsigned char *data, int data_length, void *user_data);
 /**
  * @}
  */
index a2e6c878897270bb9c00c481e8958af13b2de39e..aeed803e951e0f8ae29c549cb0cbb8e43a3f0527 100644 (file)
@@ -3889,6 +3889,69 @@ int bt_tds_set_transport_activation_requested_cb(
  */
 int bt_tds_unset_transport_activation_requested_cb(void);
 
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to start seeking Remote TDS providers only
+ */
+int bt_tds_start_seeking_providers(bt_tds_provider_scan_result_cb cb, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to stop seeking Remote TDS providers
+ */
+int bt_tds_stop_seeking_providers(void);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to create Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_create(const char *remote_address, bt_tds_seeker_h *seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to destroy Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_destroy(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to set connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_set_connection_state_changed_cb(bt_tds_seeker_h seeker,
+               bt_tds_seeker_connection_state_changed_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to unset connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_unset_connection_state_changed_cb(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to connect to Remote TDS provider
+ */
+int bt_tds_seeker_connect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to disconnect to Remote TDS provider
+ */
+int bt_tds_seeker_disconnect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to read complete TDS block data which is stored in Remote TDS provider's GATT database
+ */
+int bt_tds_seeker_get_complete_transport_blocks(bt_tds_seeker_h seeker,
+               bt_tds_seeker_complete_transport_data_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to Activate ALternate transport supported by Remote TDS provider
+ */
+int bt_tds_seeker_activate_control_point(bt_tds_seeker_h seeker,
+               bt_tds_transport_e transport, unsigned char *buffer, int len,
+               bt_tds_control_point_activation_indication_cb callback, void *user_data);
 /**
  * @}
  */
index b9d8af8914ed87718e0d45606c9f1692e11086d4..8b2404c742851c6876c677d4480a418b8fd5cf36 100644 (file)
@@ -710,9 +710,9 @@ typedef void (*bt_proximity_reporter_connection_state_changed_cb)
  * @since_tizen 3.0
  */
 typedef enum {
-       BT_TDS_TRANSPORT_STATE_OFF,
-       BT_TDS_TRANSPORT_STATE_ON,
-       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,
+       BT_TDS_TRANSPORT_STATE_OFF,     /**< Transport is currently in OFF state */
+       BT_TDS_TRANSPORT_STATE_ON,      /**< Transport is currently in ON state */
+       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,     /**< Transport is temporarily unavailable */
 } bt_tds_transport_state_e;
 
 /**
@@ -727,6 +727,29 @@ typedef enum {
        BT_TDS_TRANSPORT_INVALID
 } bt_tds_transport_e;
 
+/**
+ * @internal
+ * @brief The structure type of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       bt_tds_transport_e transport;
+       bt_tds_transport_state_e state;
+       bool is_data_complete;
+       char *data;
+       int length;
+} tds_transport_data_s;
+
+/**
+ * @internal
+ * @brief The structure type of list of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       int num_transport_block;            /**< Number of Transport Data Blocks */
+       tds_transport_data_s **data;        /**< Array of Transport Data Block */
+} bt_tds_transport_block_list_s;
+
 /**
  * @internal
  * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE
@@ -801,6 +824,50 @@ typedef void *bt_tds_provider_h;
  */
 typedef void (*bt_tds_activation_requested_cb)(char *remote_bd_addr,
        bt_tds_transport_e transport, unsigned char *buf, int len, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE
+ * @brief The handle of a TDS Seeker client which is associated with a remote TDS provider
+ * @since_tizen 3.0
+ */
+typedef void *bt_tds_seeker_h;
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Scan result callback containing filtered TDS service information and
+ * complete LE discovery informations
+ */
+typedef void (*bt_tds_provider_scan_result_cb)(int result, const char *remote_address,
+               bt_tds_transport_block_list_s *info, bt_adapter_le_device_scan_result_info_s *scan_info,
+               void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Connection State changed callback which is associated with a remote TDS provider
+ */
+typedef void (*bt_tds_seeker_connection_state_changed_cb)
+               (int result, const char *remote_address,
+               bt_tds_seeker_h seeker, bool connected, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile complete TDS data block read callback from remote TDS provider
+ */
+typedef void (*bt_tds_seeker_complete_transport_data_cb)
+               (int result, const char *remote_address,
+               bt_tds_transport_block_list_s *info, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile TDS Control Point Activation request callback which is associated with remote TDS provider
+ */
+typedef void (*bt_tds_control_point_activation_indication_cb)
+               (int result, const char *remote_address,
+               unsigned char *data, int data_length, void *user_data);
 /**
  * @}
  */
index 776bff6c0b2491aa28fb5be6681c29d0c594b9bd..af664b3a6e9d20b32ded0c37fb0e0402f632cdae 100644 (file)
@@ -4070,6 +4070,69 @@ int bt_tds_set_transport_activation_requested_cb(
  */
 int bt_tds_unset_transport_activation_requested_cb(void);
 
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to start seeking Remote TDS providers only
+ */
+int bt_tds_start_seeking_providers(bt_tds_provider_scan_result_cb cb, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to stop seeking Remote TDS providers
+ */
+int bt_tds_stop_seeking_providers(void);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to create Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_create(const char *remote_address, bt_tds_seeker_h *seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to destroy Seeker Role associated with Remote TDS provider
+ */
+int bt_tds_seeker_destroy(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to set connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_set_connection_state_changed_cb(bt_tds_seeker_h seeker,
+               bt_tds_seeker_connection_state_changed_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to unset connection state changed event associated with Remote TDS provider
+ */
+int bt_tds_seeker_unset_connection_state_changed_cb(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to connect to Remote TDS provider
+ */
+int bt_tds_seeker_connect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to disconnect to Remote TDS provider
+ */
+int bt_tds_seeker_disconnect(bt_tds_seeker_h seeker);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to read complete TDS block data which is stored in Remote TDS provider's GATT database
+ */
+int bt_tds_seeker_get_complete_transport_blocks(bt_tds_seeker_h seeker,
+               bt_tds_seeker_complete_transport_data_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief TDS Seeker Profile API to Activate ALternate transport supported by Remote TDS provider
+ */
+int bt_tds_seeker_activate_control_point(bt_tds_seeker_h seeker,
+                               bt_tds_transport_e transport, unsigned char *buffer, int len,
+                               bt_tds_control_point_activation_indication_cb callback, void *user_data);
 /**
  * @}
  */
index 814c6cb2669e8f2fd3b60659abfe6fac2e80d332..f7a3851d46b80acf792ae90284481ec8e518e348 100644 (file)
@@ -743,9 +743,9 @@ typedef void (*bt_proximity_reporter_connection_state_changed_cb)
  * @since_tizen 3.0
  */
 typedef enum {
-       BT_TDS_TRANSPORT_STATE_OFF,
-       BT_TDS_TRANSPORT_STATE_ON,
-       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,
+       BT_TDS_TRANSPORT_STATE_OFF,     /**< Transport is currently in OFF state */
+       BT_TDS_TRANSPORT_STATE_ON,      /**< Transport is currently in ON state */
+       BT_TDS_TRANSPORT_STATE_UNAVAILABLE,     /**< Transport is temporarily unavailable */
 } bt_tds_transport_state_e;
 
 /**
@@ -760,6 +760,29 @@ typedef enum {
        BT_TDS_TRANSPORT_INVALID
 } bt_tds_transport_e;
 
+/**
+ * @internal
+ * @brief The structure type of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       bt_tds_transport_e transport;
+       bt_tds_transport_state_e state;
+       bool is_data_complete;
+       char *data;
+       int length;
+} tds_transport_data_s;
+
+/**
+ * @internal
+ * @brief The structure type of list of TDS transport data block
+ * @since_tizen 3.0
+ */
+typedef struct {
+       int num_transport_block;            /**< Number of Transport Data Blocks */
+       tds_transport_data_s **data;        /**< Array of Transport Data Block */
+} bt_tds_transport_block_list_s;
+
 /**
  * @internal
  * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_MODULE
@@ -847,6 +870,50 @@ typedef void *bt_tds_provider_h;
  */
 typedef void (*bt_tds_activation_requested_cb)(char *remote_bd_addr,
        bt_tds_transport_e transport, unsigned char *buf, int len, void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE
+ * @brief The handle of a TDS Seeker client which is associated with a remote TDS provider
+ * @since_tizen 3.0
+ */
+typedef void *bt_tds_seeker_h;
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Scan result callback containing filtered TDS service information and
+ * complete LE discovery informations
+ */
+typedef void (*bt_tds_provider_scan_result_cb)(int result, const char *remote_address,
+               bt_tds_transport_block_list_s *info, bt_adapter_le_device_scan_result_info_s *scan_info,
+               void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile Connection State changed callback which is associated with a remote TDS provider
+ */
+typedef void (*bt_tds_seeker_connection_state_changed_cb)
+               (int result, const char *remote_address,
+               bt_tds_seeker_h seeker, bool connected, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile complete TDS data block read callback from remote TDS provider
+ */
+typedef void (*bt_tds_seeker_complete_transport_data_cb)
+               (int result, const char *remote_address,
+               bt_tds_transport_block_list_s *info, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief TDS Seeker profile TDS Control Point Activation request callback which is associated with remote TDS provider
+ */
+typedef void (*bt_tds_control_point_activation_indication_cb)
+               (int result, const char *remote_address,
+               unsigned char *data, int data_length, void *user_data);
 /**
  * @}
  */
index 023dab39737c00a0084c2b68316d5b924b918986..f17bb6a28008e067840082bddf3c95f54acc9541 100644 (file)
@@ -51,6 +51,9 @@ static void __bt_free_bt_adapter_device_discovery_info_s(bt_adapter_device_disco
 static int __bt_get_bt_adapter_le_device_scan_info_s(bt_adapter_le_device_scan_result_info_s **scan_info, bluetooth_le_device_info_t *source_info);
 static void __bt_free_bt_adapter_le_device_scan_info_s(bt_adapter_le_device_scan_result_info_s *scan_info);
 
+/* TDS Forward declarations */
+static void __bt_free_tds_scan_result_info_s(bt_tds_transport_block_list_s *discovery_info);
+
 #if !defined(TIZEN_PROFILE_WEARABLE) && !defined(TIZEN_PROFILE_IVI)
 static int __bt_get_bt_adapter_le_device_discovery_info_s(bt_adapter_le_device_discovery_info_s **le_discovery_info, bluetooth_le_device_info_t *source_info);
 static void __bt_free_bt_adapter_le_device_discovery_info_s(bt_adapter_le_device_discovery_info_s *discovery_info);
@@ -487,6 +490,55 @@ void _bt_free_bt_device_info_s(bt_device_info_s *device_info)
 }
 /* LCOV_EXCL_STOP */
 
+int _bt_get_ad_data_by_type(char *in_data, int in_len,
+               char in_type, char **data, int *data_len)
+{
+       if (in_data == NULL || data == NULL || data_len == NULL)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       if (in_len < 0)
+               return BLUETOOTH_ERROR_INTERNAL;
+
+       int i;
+       int len = 0;
+       int type = 0;
+
+       for (i = 0; i < in_len; i++) {
+               len = in_data[i];
+               if (len <= 0 || i + 1 >= in_len) {
+                       BT_ERR("Invalid advertising data");
+                       return BLUETOOTH_ERROR_INTERNAL;
+               }
+
+               type = in_data[i + 1];
+               if (type == in_type) {
+                       i = i + 2;
+                       len--;
+                       break;
+               }
+
+               i += len;
+               len = 0;
+       }
+
+       if (i + len > in_len) {
+               BT_ERR("Invalid advertising data");
+               return BLUETOOTH_ERROR_INTERNAL;
+       } else if (len == 0) {
+               BT_DBG("AD Type 0x%02x data is not set", in_type);
+               *data = NULL;
+               *data_len = 0;
+               return BLUETOOTH_ERROR_NONE;
+       }
+
+       *data = g_memdup(&in_data[i], len);
+       if (*data == NULL)
+               return BLUETOOTH_ERROR_OUT_OF_MEMORY;
+       *data_len = len;
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
 int _bt_convert_address_to_string(char **addr_str, bluetooth_device_address_t *addr_hex)
 {
        char address[18] = { 0, };
@@ -999,6 +1051,10 @@ static bool __bt_need_to_handle(int event)
        case BLUETOOTH_EVENT_GATT_SERVER_READ_REQUESTED:
        case BLUETOOTH_EVENT_GATT_SERVER_NOTIFICATION_COMPLETED:
        case BLUETOOTH_EVENT_GATT_CLIENT_SERVICE_CHANGED:
+       case BLUETOOTH_EVENT_TDS_TRANSPORT_DATA_RECEIVED:
+       case BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT:
+       case BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED:
+       case BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION:
                return true;
        default:
                break;
@@ -1937,6 +1993,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                if (is_pxp_initialized)
                        _bt_proximity_connection_set_state_changed(param->result, device_addr, TRUE);
 
+               /* TDS Seeker */
+               _bt_tds_update_seeker_connection_state_changed(param->result, device_addr, TRUE);
+
                g_free(device_addr);
                device_addr = NULL;
                break;
@@ -1961,6 +2020,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                if (is_pxp_initialized)
                        _bt_proximity_connection_set_state_changed(param->result, device_addr, FALSE);
 
+               /* TDS Seeker */
+               _bt_tds_update_seeker_connection_state_changed(param->result, device_addr, FALSE);
+
                g_free(device_addr);
                device_addr = NULL;
                break;
@@ -2255,6 +2317,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                _bt_convert_address_to_string(&device_addr,
                                &service_change->device_addr);
 
+               /* Check if TDS Service removed */
+               _bt_tds_check_service_changed(device_addr, service_change);
+
                client = _bt_gatt_get_client(device_addr);
                g_free(device_addr);
                device_addr = NULL;
@@ -2746,6 +2811,63 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                        free(device_addr); /* LCOV_EXCL_STOP */
                break;
        }
+       case BLUETOOTH_EVENT_TDS_TRANSPORT_DATA_RECEIVED: {
+               BT_DBG("BLUETOOTH_EVENT_TDS_TRANSPORT_DATA_RECEIVED"); /* LCOV_EXCL_LINE */
+               bluetooth_tds_transport_data_info_t *info = NULL;
+               bluetooth_device_address_t *addr = NULL;
+
+               if (_bt_get_error_code(param->result) == BT_ERROR_NONE) {
+                       info = (bluetooth_tds_transport_data_info_t *)(param->param_data);
+                       _bt_convert_address_to_string(&device_addr, &info->device_address);
+                       _bt_tds_send_complete_transport_data(_bt_get_error_code(param->result), device_addr,
+                                       info->data, info->data_length);
+               } else {
+                       BT_ERR("TDS Complete data Read request failed!!!");
+                       addr = (bluetooth_device_address_t *)(param->param_data);
+                       _bt_convert_address_to_string(&device_addr, addr);
+                       _bt_tds_send_complete_transport_data(_bt_get_error_code(param->result), device_addr,
+                                       NULL, 0);
+               }
+               BT_DBG("TDS Complete data blocks received: Remote provider address [%s]", device_addr);
+               if (device_addr != NULL)
+                       free(device_addr); /* LCOV_EXCL_STOP */
+               break;
+       }
+       case BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT: {
+               BT_DBG("BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT"); /* LCOV_EXCL_LINE */
+               _bt_convert_address_to_string(&device_addr,
+                       (bluetooth_device_address_t *)(param->param_data));
+
+               _bt_tds_control_point_activation_result_update(_bt_get_error_code(param->result), device_addr);
+
+               if (device_addr != NULL)
+                       free(device_addr); /* LCOV_EXCL_STOP */
+               break;
+       }
+       case BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED: {
+               BT_DBG("BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED"); /* LCOV_EXCL_LINE */
+               _bt_convert_address_to_string(&device_addr,
+                       (bluetooth_device_address_t *)(param->param_data));
+
+               _bt_tds_control_point_enabled_update(_bt_get_error_code(param->result), device_addr);
+
+               if (device_addr != NULL)
+                       free(device_addr); /* LCOV_EXCL_STOP */
+               break;
+       } case BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION: {
+               BT_DBG("BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION"); /* LCOV_EXCL_LINE */
+               bluetooth_tds_indication_res_t *tds_act_ind_res = NULL;
+               tds_act_ind_res = (bluetooth_tds_indication_res_t *)(param->param_data);
+
+               _bt_convert_address_to_string(&device_addr, &tds_act_ind_res->rem_addr);
+
+               BT_ERR("Address [%s]", device_addr);
+               _bt_tds_control_point_indication_response_update(device_addr, tds_act_ind_res);
+
+               if (device_addr != NULL)
+                       free(device_addr); /* LCOV_EXCL_STOP */
+               break;
+       }
        default:
                BT_INFO("Unknown function");
                break;
@@ -2798,7 +2920,6 @@ static void __bt_le_event_proxy(int event, bluetooth_event_param_t *param, void
                        if (__bt_get_bt_adapter_le_device_scan_info_s(&scan_info, (bluetooth_le_device_info_t *)(param->param_data)) == BT_ERROR_NONE) {
                                ((bt_adapter_le_scan_result_cb)bt_event_slot_container[event_index].callback)
                                        (_bt_get_error_code(param->result), scan_info, bt_event_slot_container[event_index].user_data);
-                               __bt_free_bt_adapter_le_device_scan_info_s(scan_info);
                        } else {
                                ((bt_adapter_le_scan_result_cb)bt_event_slot_container[event_index].callback)
                                        (_bt_get_error_code(param->result), NULL, bt_event_slot_container[event_index].user_data);
@@ -2817,8 +2938,43 @@ static void __bt_le_event_proxy(int event, bluetooth_event_param_t *param, void
                        }
                }
 #endif
-               break;
+               /* TDS Provider Search: Uses Scan Info */
+               if (bt_event_slot_container[BT_EVENT_TDS_PROVIDER_FOUND_RESULT].callback != NULL) {
+                       char *data = NULL;
+                       int data_len = 0;
+                       if (!scan_info) {
+                               /* Get Scan Info */
+                               if (__bt_get_bt_adapter_le_device_scan_info_s(&scan_info,
+                                                       (bluetooth_le_device_info_t *)(param->param_data)) != BT_ERROR_NONE) { /* LCOV_EXCL_LINE */
+                                       break;
+                               }
+                       }
+                       _bt_get_ad_data_by_type((char*)scan_info->adv_data, scan_info->adv_data_len,
+                                       BT_ADAPTER_LE_ADVERTISING_DATA_TRANSPORT_DISCOVERY,
+                                       &data, &data_len);
+                       if (data != NULL) {
+                               BT_DBG("TDS Service available Data length[%d]", data_len);
+                               bt_tds_transport_block_list_s *info = g_malloc0(sizeof(bt_tds_transport_block_list_s));
+
+                               if (_bt_tds_parse_transport_blocks(&info, data, data_len) == BT_ERROR_NONE) {
+                                       ((bt_tds_provider_scan_result_cb)bt_event_slot_container[BT_EVENT_TDS_PROVIDER_FOUND_RESULT].callback) /* LCOV_EXCL_LINE */
+                                               (_bt_get_error_code(param->result),
+                                                scan_info->remote_address, info,
+                                                scan_info,
+                                                bt_event_slot_container[BT_EVENT_TDS_PROVIDER_FOUND_RESULT].user_data);
+                               }
+                               __bt_free_tds_scan_result_info_s(info);
+
+                               if (data) {
+                                       g_free(data);
+                                       data = NULL;
+                               }
+                       }
+               }
 
+               if (scan_info)
+                       __bt_free_bt_adapter_le_device_scan_info_s(scan_info);
+               break;
        default:
                break;
        }
@@ -2960,6 +3116,23 @@ static void __bt_free_bt_adapter_le_device_scan_info_s(bt_adapter_le_device_scan
        scan_info = NULL;
 } /* LCOV_EXCL_STOP */
 
+static void __bt_free_tds_scan_result_info_s(bt_tds_transport_block_list_s *discovery_info)
+{
+       int k;
+
+       if (discovery_info == NULL)
+               return;
+
+       for (k = 0; k < discovery_info->num_transport_block; k++) {
+               g_free(discovery_info->data[k]->data);
+               g_free(discovery_info->data[k]);
+       }
+
+       g_free(discovery_info);
+       discovery_info = NULL;
+
+}
+
 /* LCOV_EXCL_START */
 #if !defined(TIZEN_PROFILE_WEARABLE) && !defined(TIZEN_PROFILE_IVI)
 static int __bt_get_bt_adapter_le_device_discovery_info_s(
index 16aa5c6b78e35cffb4ec71c278fde8f106bba8b3..5445053a0bef66cf3c3a33f88cf146a30d5f45ce 100644 (file)
        BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE); \
 }
 
+#define BT_TDS_SERVICE_UUID "00001824-0000-1000-8000-00805f9b34fb"
+#define BT_TDS_CONTROL_POINT_UUID "00002abc-0000-1000-8000-00805f9b34fb"
+#define BT_TDS_USER_DATA_DESCRIPTOR "00002a56-0000-1000-8000-00805f9b34fb"
+
 typedef struct {
        unsigned int tds_handle;
        bluetooth_tds_transport_t transport;
        bluetooth_tds_transport_state_t state;
 } bt_tds_provider_s;
 
+typedef struct bt_tds_transport_slot_s {
+       bool is_seek_ongoing;
+} bt_tds_transport_slot_s;
+
+typedef struct {
+       char *remote_address;
+       bool connected;
+
+       const void *connection_callback;
+       void *conn_cb_user_data;
+
+       const void *complete_data_callback;  /* Callback for receiving complete TDS data block */
+       void *complete_data_cb_user_data;    /* User data for complete TDS data block callback */
+
+       char *tds_service_handle;            /* TDS Primary Service Handle */
+       char *tds_control_point;             /* TDS Control Point characteristic handle */
+       char *tds_control_point_cccd;        /* TDS Control Point CCCD handle */
+       char *tds_user_data_desciptor;       /* TDS User descriptor handle: This will store the Entire TDS block data in GATT Server */
+
+       bool cccd_enabled;                   /* TDS Control Point CCCD is enabled or not */
+
+       bool tds_activation_ongoing;         /* TDS Actvation is ongoing or not */
+       void *control_point_act_cb;          /* TDS Control Point Activation Response callback */
+       void *control_point_act_user_data;   /* User data for TDS Control Point Activation Response callback*/
+
+       unsigned char *activation_data;      /* TDS Activation data */
+       int data_len;
+} bt_tds_seeker_s;
+
 gboolean tds_provider_registered = FALSE;
 GSList *providers_list;
+GSList *tds_seeker_list;
+
+static int __bt_update_tds_transport_data(bluetooth_device_address_t *address, bt_tds_seeker_s *seeker_s);
+static void __bt_tds_reset_seeker_data(bt_tds_seeker_s *seeker);
 
 int bt_tds_set_transport_activation_requested_cb(
                bt_tds_activation_requested_cb callback, void *user_data)
@@ -303,3 +340,840 @@ int bt_tds_provider_set_manufacturer_data(unsigned char *buf, int length)
 
        return error_code;
 }
+
+static bt_tds_seeker_s *_bt_tds_seeker_find(const char *remote_address)
+{
+       GSList *l;
+
+       for (l = tds_seeker_list; l; l = g_slist_next(l)) {
+
+               if (!g_ascii_strcasecmp(((bt_tds_seeker_s *)l->data)->remote_address, remote_address))
+                       return ((bt_tds_seeker_s *)l->data);
+       }
+       return NULL;
+}
+
+static void __bt_tds_free_transport_data(bt_tds_transport_block_list_s *info)
+{
+       int k;
+
+       if (info == NULL)
+               return;
+
+       for (k = 0; k < info->num_transport_block; k++) {
+               g_free(info->data[k]->data);
+               g_free(info->data[k]);
+       }
+
+       g_free(info);
+}
+
+void _bt_tds_check_service_changed(char *address, bt_gatt_service_change_t *service_change)
+{
+       bt_tds_seeker_s *seeker_s = NULL;
+       int error_code = BLUETOOTH_ERROR_NONE;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       if (!address) {
+               BT_ERR("Abnormal Result!!");
+               return;
+       }
+       seeker_s = _bt_tds_seeker_find(address);
+       BT_DBG("GATT Service state changed [%d]", service_change->change_type);
+       BT_DBG("GATT Service [%s]", service_change->svc_path);
+       if (seeker_s) {
+               if (service_change->change_type ==  BLUETOOTH_GATT_SERVICE_CHANGE_TYPE_REMOVE) {
+                       if (seeker_s->tds_service_handle &&
+                                       g_strcmp0(seeker_s->tds_service_handle, service_change->svc_path) == 0) {
+                               BT_ERR("TDS Primary Service removed abnormally from Remote Provider [%s]", address);
+                               __bt_tds_reset_seeker_data(seeker_s);
+                       }
+               } else {
+                       _bt_convert_address_to_hex(&addr_hex, address);
+
+                       /* Attempt to update TDS Service data if service added is TDS service */
+                       if (__bt_update_tds_transport_data(&addr_hex, seeker_s) == BLUETOOTH_ERROR_NONE) {
+                               BT_INFO("TDS Primary Service added in Remote Provider [%s]", address);
+                               /* Set Service changed Watcher */
+                               error_code = bluetooth_gatt_set_service_change_watcher(&addr_hex, true);
+                               if (error_code != BLUETOOTH_ERROR_NONE)
+                                       BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+                       }
+               }
+       }
+       BT_DBG("-");
+}
+
+void _bt_tds_send_complete_transport_data(int result, const char *address, char *data, int data_len)
+{
+       bt_tds_seeker_s *seeker_s = NULL;
+
+       if (!address) {
+               BT_ERR("Abnormal Result!!");
+               return;
+       }
+
+       seeker_s = _bt_tds_seeker_find(address);
+
+       if (seeker_s && (seeker_s)->complete_data_callback) {
+               BT_DBG("Complete TDS Data recv callback is set by app");
+
+               if (result == BT_ERROR_NONE) {
+                       bt_tds_transport_block_list_s *info = g_malloc0(sizeof(bt_tds_transport_block_list_s));
+
+                       if (_bt_tds_parse_transport_blocks(&info, data, data_len) == BT_ERROR_NONE) {
+                               ((bt_tds_seeker_complete_transport_data_cb)((seeker_s)->complete_data_callback))(result,
+                               address, info,
+                               (seeker_s)->complete_data_cb_user_data);
+                       } else {
+                               BT_ERR("Error parsing data blocks");
+                               ((bt_tds_seeker_complete_transport_data_cb)((seeker_s)->complete_data_callback))(result,
+                               address, NULL,
+                               (seeker_s)->complete_data_cb_user_data);
+                       }
+                       __bt_tds_free_transport_data(info);
+               } else {
+                       BT_ERR("TDS Data read failed!!");
+                       ((bt_tds_seeker_complete_transport_data_cb)((seeker_s)->complete_data_callback))(result,
+                       address, NULL,
+                       (seeker_s)->complete_data_cb_user_data);
+               }
+       }
+}
+
+void _bt_tds_control_point_indication_response_update(const char *address, bluetooth_tds_indication_res_t *info)
+{
+       bt_tds_seeker_s *seeker_s = NULL;
+
+       if (!address) {
+               BT_ERR("Abnormal Result!!");
+               return;
+       }
+
+       seeker_s = _bt_tds_seeker_find(address);
+       int result = BT_ERROR_NONE;
+       int k;
+
+       if (seeker_s) {
+               BT_DBG("TDS Control point Activation Indication Response");
+               BT_DBG("Data length [%d]", info->tds_data.length);
+               BT_DBG("Address[%s]", address);
+
+               /* DEBUG */
+               for (k = 0; k < info->tds_data.length; k++)
+                       BT_DBG("Data[%d] [0x%x]", info->tds_data.data[k]);
+
+               if (seeker_s->tds_activation_ongoing == true) {
+                       (seeker_s)->tds_activation_ongoing = false;
+
+                       if (info->tds_data.length < 2)
+                               result = BT_ERROR_OPERATION_FAILED;
+                       else {
+                               if (info->tds_data.data[1] == 0x00) {
+                                       BT_DBG("Provider has enabled transport");
+                                       result = BT_ERROR_NONE;
+                               } else
+                                       result = BT_ERROR_OPERATION_FAILED;
+                       }
+
+                       if ((seeker_s)->control_point_act_cb)
+                               ((bt_tds_control_point_activation_indication_cb)((seeker_s)->control_point_act_cb))(result,
+                               address, info->tds_data.data, info->tds_data.length, (seeker_s)->control_point_act_user_data);
+                       if (seeker_s->activation_data) {
+                               g_free(seeker_s->activation_data);
+                               seeker_s->activation_data = NULL;
+                       }
+               }
+       }
+}
+
+void _bt_tds_control_point_activation_result_update(int result, const char *remote_address)
+{
+       bt_tds_seeker_s *seeker_s = NULL;
+       if (!remote_address) {
+               BT_ERR("Abnormal Result!!");
+               return;
+       }
+       seeker_s = _bt_tds_seeker_find(remote_address);
+
+       if (seeker_s) {
+               BT_DBG("TDS Control point Activation response [%d] address [%s]", result, remote_address);
+
+               if ((seeker_s)->tds_activation_ongoing == true) {
+                       /* Send Pending Activation Request callback with error */
+                       if (result != BT_ERROR_NONE) {
+                               (seeker_s)->tds_activation_ongoing = false;
+                               if ((seeker_s)->control_point_act_cb)
+                                       ((bt_tds_control_point_activation_indication_cb)((seeker_s)->control_point_act_cb))(BT_ERROR_OPERATION_FAILED,
+                                       remote_address, NULL, 0, (seeker_s)->control_point_act_user_data);
+                               if (seeker_s->activation_data) {
+                                       g_free(seeker_s->activation_data);
+                                       seeker_s->activation_data = NULL;
+                               }
+                               return;
+                       } else
+                               BT_DBG("TDS Activation request successfully accepted by Provider, wait for Indication");
+               } else
+                       BT_DBG("TDS Control point activation request is not ongoing");
+       }
+}
+
+void _bt_tds_control_point_enabled_update(int result, const char *remote_address)
+{
+       bt_tds_seeker_s *seeker_s = NULL;
+       if (!remote_address) {
+               BT_ERR("Abnormal Result!!");
+               return;
+       }
+       seeker_s = _bt_tds_seeker_find(remote_address);
+       int ret = BT_ERROR_NONE;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       _bt_convert_address_to_hex(&addr_hex, remote_address);
+
+       if (seeker_s) {
+               BT_DBG("TDS Control point Enable result [%d] address [%s]", result, remote_address);
+
+               /* Send Pending Activation Request callback with error */
+               if (result != BT_ERROR_NONE) {
+                       (seeker_s)->tds_activation_ongoing = false;
+
+                       if ((seeker_s)->control_point_act_cb)
+                               ((bt_tds_control_point_activation_indication_cb)((seeker_s)->control_point_act_cb))(BT_ERROR_OPERATION_FAILED,
+                               remote_address, NULL, 0, (seeker_s)->control_point_act_user_data);
+
+                       if (seeker_s->activation_data) {
+                               g_free(seeker_s->activation_data);
+                               seeker_s->activation_data = NULL;
+                       }
+                       return;
+               } else {
+                       BT_DBG("TDS Control Point enabled successfully!!");
+                       seeker_s->cccd_enabled = true;
+                       ret = _bt_get_error_code(bluetooth_tds_activate_control_point(&addr_hex,
+                                               seeker_s->tds_control_point, seeker_s->activation_data,
+                                               seeker_s->data_len));
+                       if (ret != BT_ERROR_NONE) {
+                               (seeker_s)->tds_activation_ongoing = false;
+
+                               if ((seeker_s)->control_point_act_cb)
+                                       ((bt_tds_control_point_activation_indication_cb)((seeker_s)->control_point_act_cb))(BT_ERROR_OPERATION_FAILED,
+                                       remote_address, NULL, 0, (seeker_s)->control_point_act_user_data);
+
+                               if (seeker_s->activation_data) {
+                                       g_free(seeker_s->activation_data);
+                                       seeker_s->activation_data = NULL;
+                               }
+                       }
+                       BT_DBG("Activation request sent, wait for response and Indication");
+               }
+       }
+}
+
+int _bt_tds_parse_transport_blocks(bt_tds_transport_block_list_s **info,
+               char *data, int data_len)
+{
+       int numblocks = 0;
+       int index = 2;
+       uint8_t flags;
+       int k;
+       GSList *info_list = NULL;
+       GSList *l = NULL;
+
+       if (data_len < 3) {
+               BT_ERR("Invalid TDS data, can not process!!");
+               return BT_ERROR_INVALID_PARAMETER;
+       }
+
+       tds_transport_data_s *td;
+
+       while (index < data_len) {
+
+               /* Check if Provider Role is supported by Remote */
+               flags = data[index-1];
+
+               if (!(flags & 0x02)) {
+                       /* Move to Next Block */
+                       index = index + data[index] + 3;
+                       BT_ERR("TDS Block is not Provider Role");
+                       continue;
+               }
+
+               td = g_malloc(sizeof(tds_transport_data_s));
+               td->length = data[index];
+
+               td->data = g_malloc0(td->length);
+
+               /* Fill Transport Block Data excluding Flag and Org ID */
+               for (k = 0; k < td->length; k++)
+                       td->data[k] = data[k+index+1];
+
+               /* Get Transport Name  */
+               td->transport = data[index -2];
+
+               /* Get Transport Data Block Incomplete status */
+               if (flags & 0x04)
+                       td->is_data_complete = false;
+               else
+                       td->is_data_complete = true;
+
+               /* Get Transport's current state */
+               if (flags & 0x08)
+                       td->state = BT_TDS_TRANSPORT_STATE_ON;
+               else if (flags & 0x10)
+                       td->state = BT_TDS_TRANSPORT_STATE_UNAVAILABLE;
+               else
+                       td->state = BT_TDS_TRANSPORT_STATE_OFF;
+
+               /* Move to Next Block */
+               index = index + data[index] + 3;
+               info_list = g_slist_append(info_list, td);
+
+               (*info)->num_transport_block = ++numblocks;
+               BT_DBG("Transport Block data length [%d] Flags [0x%x] Transport Name [0x%x] Block Num [%d]",
+                               td->length, flags, td->transport, numblocks);
+
+       }
+
+       if (info_list != NULL) {
+               (*info)->data = (tds_transport_data_s**)g_malloc0(g_slist_length(info_list) * sizeof(tds_transport_data_s));
+               for (l = info_list, k = 0; l; l = g_slist_next(l), k++)
+                       (*info)->data[k] = (tds_transport_data_s*)l->data;
+               return BT_ERROR_NONE;
+       }
+       return BT_ERROR_NO_DATA;
+}
+
+static void __bt_tds_reset_seeker_data(bt_tds_seeker_s *seeker)
+{
+       if ((seeker)->tds_control_point) {
+               g_free((seeker)->tds_control_point);
+               (seeker)->tds_control_point = NULL;
+       }
+
+       if ((seeker)->tds_control_point_cccd) {
+               g_free((seeker)->tds_control_point_cccd);
+               (seeker)->tds_control_point_cccd = NULL;
+       }
+
+       if ((seeker)->tds_user_data_desciptor) {
+               g_free((seeker)->tds_user_data_desciptor);
+               (seeker)->tds_user_data_desciptor = NULL;
+       }
+
+       if ((seeker)->tds_service_handle) {
+               g_free((seeker)->tds_service_handle);
+               (seeker)->tds_service_handle = NULL;
+       }
+
+       if ((seeker)->activation_data) {
+               g_free((seeker)->activation_data);
+               (seeker)->activation_data = NULL;
+       }
+
+       /* Reset CCCD */
+       (seeker)->cccd_enabled = false;
+}
+
+void _bt_tds_update_seeker_connection_state_changed(int result,
+               const char *remote_address, bool connected)
+{
+       int error_code = BLUETOOTH_ERROR_NONE;
+       bt_tds_seeker_s *seeker_s = NULL;
+       BT_DBG("TDS Seeker Connection state changed result [%d] connected [%d]", result, connected ? TRUE : FALSE);
+
+       /* GATT Connect Request failed */
+       seeker_s = _bt_tds_seeker_find(remote_address);
+       if (seeker_s) {
+               BT_DBG("Seeker found against address [%s]", remote_address);
+
+               bluetooth_device_address_t addr_hex = { {0,} };
+               _bt_convert_address_to_hex(&addr_hex, remote_address);
+
+               if (result != BT_ERROR_NONE) {
+                       BT_ERR("GATT Connect Request failed Address [%s]", remote_address);
+                       __bt_tds_reset_seeker_data(seeker_s);
+                       bluetooth_gatt_set_service_change_watcher(&addr_hex, false);
+
+                       if ((seeker_s)->connection_callback)
+                               ((bt_tds_seeker_connection_state_changed_cb)(seeker_s)->connection_callback)
+                                       (result, remote_address, seeker_s, connected, (seeker_s)->conn_cb_user_data);
+                       return;
+               }
+               /* Update TDS Control point values */
+               if (connected) {
+                       BT_DBG("Remote Provider connected successfully");
+                       /* Attempt to update TDS Service data */
+                       error_code = __bt_update_tds_transport_data(&addr_hex, seeker_s);
+                       if (error_code != BLUETOOTH_ERROR_NONE)
+                               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+                       /* Set Service changed Watcher */
+                       error_code = bluetooth_gatt_set_service_change_watcher(&addr_hex, true);
+                       if (error_code != BLUETOOTH_ERROR_NONE)
+                               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               } else {
+                       BT_DBG("Remote Provider disconnected successfully");
+                       /* Disconnected */
+                       __bt_tds_reset_seeker_data(seeker_s);
+                       bluetooth_gatt_set_service_change_watcher(&addr_hex, false);
+               }
+               (seeker_s)->connected = connected;
+
+               if ((seeker_s)->connection_callback)
+                       ((bt_tds_seeker_connection_state_changed_cb)(seeker_s)->connection_callback)
+                               (result, remote_address, seeker_s, connected, (seeker_s)->conn_cb_user_data);
+       } else {
+               BT_DBG("TDS Seeker not found!");
+       }
+}
+
+int bt_tds_start_seeking_providers(bt_tds_provider_scan_result_cb cb, void *user_data)
+{
+       int error_code = BT_ERROR_NONE;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(cb);
+       BT_DBG("+");
+
+       /* LE Event handler registered */
+       if (_bt_le_adapter_init() != BLUETOOTH_ERROR_NONE)
+               return BT_ERROR_OPERATION_FAILED;
+
+       /* Start LE discovery with default scan params if already not started */
+       if (bluetooth_is_le_scanning() == false)
+               error_code = _bt_get_error_code(bluetooth_start_le_discovery());
+
+       if (error_code != BT_ERROR_NONE &&
+                       error_code != BT_ERROR_NOW_IN_PROGRESS) {
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+                               error_code);
+       } else {
+               BT_DBG("LE Discovery ON..Wait for TDS Configuration Service from Remote Providers");
+               _bt_set_cb(BT_EVENT_TDS_PROVIDER_FOUND_RESULT, cb, user_data);
+       }
+
+       return error_code;
+}
+
+int bt_tds_stop_seeking_providers(void)
+{
+       int error_code = BT_ERROR_NONE;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_DBG("+");
+
+       if (bluetooth_is_le_scanning() == true)
+               error_code = _bt_get_error_code(bluetooth_stop_le_discovery());
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+                               error_code);
+       }
+
+       _bt_unset_cb(BT_EVENT_TDS_PROVIDER_FOUND_RESULT);
+       return BT_ERROR_NONE;
+}
+
+static int __bt_update_tds_transport_data(bluetooth_device_address_t *address, bt_tds_seeker_s *seeker_s)
+{
+       int ret = BLUETOOTH_ERROR_INTERNAL;
+       bt_gatt_service_property_t service;
+       int count;
+
+       ret = bluetooth_gatt_get_service_from_uuid(address, BT_TDS_SERVICE_UUID, &service);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to find TDS configuration service");
+               return ret;
+       }
+
+       /* Find all characteristics of TDS service and their properties  */
+       for (count = 0; count < service.char_handle.count; count++) {
+               bt_gatt_char_property_t characteristic;
+               memset(&characteristic, 0x00, sizeof(characteristic));
+
+               BT_DBG("Get properties for Char [%s]", service.char_handle.handle[count]);
+
+               ret = bluetooth_gatt_get_characteristics_property(service.char_handle.handle[count],
+                               &characteristic);
+
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("Get characteristic property failed(0x%08x)", ret);
+                       bluetooth_gatt_free_service_property(&service);
+                       bluetooth_gatt_free_char_property(&characteristic);
+                       goto fail;
+               } else {
+                       if (g_strstr_len(characteristic.uuid, -1, BT_TDS_CONTROL_POINT_UUID)) {
+                               BT_DBG("TDS Control point discovered ");
+                               bt_gatt_char_descriptor_property_t desc_property;
+                               memset(&desc_property, 0x00, sizeof(desc_property));
+
+
+                               /* Get CCCD for Control Point */
+                               ret = bluetooth_gatt_get_char_descriptor_property(
+                                               characteristic.char_desc_handle.handle[0], &desc_property);
+
+                               if (ret != BLUETOOTH_ERROR_NONE) {
+                                       BT_ERR("Failed to discover CCCD for TDS Control point");
+                                       bluetooth_gatt_free_service_property(&service);
+                                       bluetooth_gatt_free_char_property(&characteristic);
+                                       bluetooth_gatt_free_desc_property(&desc_property);
+                                       goto fail;
+                               }
+                               if ((seeker_s)->tds_control_point)
+                                       g_free((seeker_s)->tds_control_point);
+                               (seeker_s)->tds_control_point = g_strdup(characteristic.handle);
+
+                               if ((seeker_s)->tds_control_point_cccd)
+                                       g_free((seeker_s)->tds_control_point_cccd);
+                               (seeker_s)->tds_control_point_cccd = g_strdup(desc_property.handle);
+
+                               BT_DBG("TDS Control point handle [%s]", (seeker_s)->tds_control_point);
+                               BT_DBG("TDS Control point CCCD handle [%s]", (seeker_s)->tds_control_point_cccd);
+                       } else {
+                               /* Fetch Descriptors for the discovered characteristic */
+                               int c;
+                               int p;
+
+                               for (c = 0; c < characteristic.char_desc_handle.count; c++) {
+
+                                       bt_gatt_char_descriptor_property_t desc_property;
+                                       memset(&desc_property, 0x00, sizeof(desc_property));
+
+                                       ret = bluetooth_gatt_get_char_descriptor_property(
+                                                       characteristic.char_desc_handle.handle[c], &desc_property);
+
+                                       if (ret != BLUETOOTH_ERROR_NONE) {
+                                               BT_ERR("Failed to discover Descriptor Property for characteristic [%s]",
+                                                               characteristic.handle);
+                                               bluetooth_gatt_free_service_property(&service);
+                                               bluetooth_gatt_free_char_property(&characteristic);
+                                               bluetooth_gatt_free_desc_property(&desc_property);
+                                               goto fail;
+                                       } else {
+                                               /* Descriptor property discovered */
+                                               BT_DBG("Descriptor handle  [%s]", desc_property.handle);
+                                               BT_DBG("Descriptor UUID    [%s]", desc_property.uuid);
+                                               BT_DBG("Descriptor val len [%d]", desc_property.val_len);
+
+                                               if (g_strstr_len(desc_property.uuid, -1, BT_TDS_USER_DATA_DESCRIPTOR)) {
+                                                       BT_DBG("User data descriptor handle discovered");
+                                                       if ((seeker_s)->tds_user_data_desciptor)
+                                                               g_free((seeker_s)->tds_user_data_desciptor);
+                                                       (seeker_s)->tds_user_data_desciptor = g_strdup(desc_property.handle);
+                                               }
+
+                                               for (p = 0; p < desc_property.val_len; p++)
+                                                       BT_DBG("Descriptor data[%d] = [0x%x]", p, desc_property.val[p]);
+                                       } /* Descriptor property get successful */
+                                       bluetooth_gatt_free_desc_property(&desc_property);
+                               } /* Next Descriptor */
+                       } /* Control Point characteristic */
+               } /* Characteristic property get successful */
+               bluetooth_gatt_free_char_property(&characteristic);
+       } /* Next Charatceristic */
+
+       if ((seeker_s)->tds_service_handle)
+               g_free((seeker_s)->tds_service_handle);
+
+       (seeker_s)->tds_service_handle = g_strdup(service.handle);
+       bluetooth_gatt_free_service_property(&service);
+       return ret;
+fail:
+       __bt_tds_reset_seeker_data(seeker_s);
+       return ret;
+}
+
+int bt_tds_seeker_set_connection_state_changed_cb(bt_tds_seeker_h seeker,
+                       bt_tds_seeker_connection_state_changed_cb callback, void *user_data)
+{
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+       BT_CHECK_INPUT_PARAMETER(callback);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("Set TDS Seeker Connection State changed callback");
+       /* register the callback */
+       seeker_s->connection_callback = callback;
+       seeker_s->conn_cb_user_data = user_data;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_tds_seeker_unset_connection_state_changed_cb(bt_tds_seeker_h seeker)
+{
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("UnSet TDS Seeker Connection State changed callback");
+       /* unregister the callback */
+       seeker_s->connection_callback = NULL;
+       seeker_s->conn_cb_user_data = NULL;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_tds_seeker_activate_control_point(bt_tds_seeker_h seeker,
+                               bt_tds_transport_e transport, unsigned char *buffer, int len,
+                               bt_tds_control_point_activation_indication_cb callback, void *user_data)
+{
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       int ret = BT_ERROR_NONE;
+       unsigned char *buf;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+       BT_CHECK_INPUT_PARAMETER(buffer);
+       BT_CHECK_INPUT_PARAMETER(callback);
+
+       if (len > 255)
+               return BT_ERROR_INVALID_PARAMETER;
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (seeker_s->connected == false)
+               return BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED;
+
+       if (seeker_s->tds_activation_ongoing == true)
+               return BT_ERROR_NOW_IN_PROGRESS;
+
+       /* Check if both TDS Control Point char & Control Point CCCD are valid or discovered */
+       if (!(seeker_s->tds_control_point) ||
+                       !(seeker_s->tds_control_point_cccd))
+               return BT_ERROR_OPERATION_FAILED;
+
+       BT_DBG("Activate Control Point [%s] transport [%d] current CCCD state [%d]",
+                               seeker_s->remote_address, transport, seeker_s->cccd_enabled);
+
+       _bt_convert_address_to_hex(&addr_hex, seeker_s->remote_address);
+
+       /* Activate Control Point */
+       buf = g_malloc0(len+2);
+
+       buf[0] = 0x01; /* Activate control point Opcode */
+       buf[1] = transport; /* Activate control point Opcode */
+       memcpy(buf+2, buffer, len);
+
+       /* Check if TDS control Point is already enabled or not */
+       if (seeker_s->cccd_enabled == FALSE) {
+               /* Enable TDS Control point CCCD to enable */
+               BT_DBG("TDS Control point is disabled, enable it");
+               ret = _bt_get_error_code(bluetooth_tds_enable_control_point(&addr_hex, seeker_s->tds_control_point));
+               if (ret != BT_ERROR_NONE) {
+                       BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret);
+                       g_free(buf);
+                       return ret;
+               }
+       } else {
+               BT_DBG("TDS Control point is already enabled");
+               ret = _bt_get_error_code(bluetooth_tds_activate_control_point(&addr_hex, seeker_s->tds_control_point, buf, len));
+               if (ret != BT_ERROR_NONE) {
+                       BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret);
+                       g_free(buf);
+                       return ret;
+               }
+       }
+
+       /* Register the callback */
+       seeker_s->tds_activation_ongoing = true;
+       seeker_s->control_point_act_cb = callback;
+       seeker_s->control_point_act_user_data = user_data;
+
+       /* Save actvation data and trigger when CCCD is actually enabled */
+       seeker_s->activation_data = buf;
+       seeker_s->data_len = len;
+
+       BT_DBG("-");
+       return ret;
+}
+
+int bt_tds_seeker_get_complete_transport_blocks(bt_tds_seeker_h seeker,
+                               bt_tds_seeker_complete_transport_data_cb callback, void *user_data)
+{
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       int ret = BT_ERROR_NONE;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+       BT_CHECK_INPUT_PARAMETER(callback);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (seeker_s->connected == false)
+               return BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED;
+
+       if (!seeker_s->tds_user_data_desciptor)
+               return BT_ERROR_OPERATION_FAILED;
+
+       BT_DBG("Set TDS Seeker Get complete callback");
+       _bt_convert_address_to_hex(&addr_hex, seeker_s->remote_address);
+
+       /* Read Data from Transport Data block desciptor */
+       ret = _bt_get_error_code(bluetooth_tds_read_transport_data(&addr_hex, seeker_s->tds_user_data_desciptor));
+       if (ret != BT_ERROR_NONE) {
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(ret), ret);
+               return ret;
+       }
+       /* register the callback */
+       seeker_s->complete_data_callback = callback;
+       seeker_s->complete_data_cb_user_data = user_data;
+
+       return ret;
+}
+
+int bt_tds_seeker_create(const char *remote_address, bt_tds_seeker_h *seeker)
+{
+       int error_code = BT_ERROR_NONE;
+       bt_tds_seeker_s *seeker_s = NULL;
+       bool connected = false;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       GSList *l;
+       BT_INFO("+");
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(remote_address);
+       BT_CHECK_INPUT_PARAMETER(seeker);
+
+       for (l = tds_seeker_list; l; l = g_slist_next(l)) {
+               bt_tds_seeker_s *c = (bt_tds_seeker_s *)l->data;
+
+               if (!g_ascii_strcasecmp(c->remote_address, remote_address)) {
+                       BT_ERR("TDS Seeker for Remote Provider [%s] is already created",
+                                       remote_address);
+                       *seeker = (bt_tds_seeker_h)c;
+                       return BT_ERROR_ALREADY_DONE;
+               }
+       }
+
+       seeker_s = g_malloc0(sizeof(*seeker_s));
+       if (seeker_s == NULL) {
+               error_code = BT_ERROR_OUT_OF_MEMORY;
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               return error_code;
+       }
+
+       if (bt_device_is_profile_connected(remote_address, BT_PROFILE_GATT,
+                               &connected) != BT_ERROR_NONE)
+               BT_ERR("bt_device_is_profile_connected is failed");
+       seeker_s->connected = connected;
+
+       _bt_convert_address_to_hex(&addr_hex, remote_address);
+
+       if (seeker_s->connected == true) {
+               error_code = __bt_update_tds_transport_data(&addr_hex, seeker_s);
+               if (error_code != BLUETOOTH_ERROR_NONE) {
+                       g_free(seeker_s);
+                       return BT_ERROR_OPERATION_FAILED;
+               }
+               error_code = bluetooth_gatt_set_service_change_watcher(&addr_hex, true);
+               if (error_code != BLUETOOTH_ERROR_NONE) {
+                       g_free(seeker_s);
+                       return BT_ERROR_OPERATION_FAILED;
+               }
+       }
+
+       seeker_s->remote_address = g_strdup(remote_address);
+       if (seeker_s->remote_address == NULL) {
+               free(seeker_s);
+               error_code = BT_ERROR_OUT_OF_MEMORY;
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               return error_code;
+       }
+
+       seeker_s->cccd_enabled = FALSE;
+       seeker_s->activation_data = NULL;
+
+       tds_seeker_list = g_slist_append(tds_seeker_list, seeker_s);
+       *seeker = (bt_tds_seeker_h)seeker_s;
+
+       BT_DBG("TDS Seeker Created");
+       return BT_ERROR_NONE;
+}
+
+int bt_tds_seeker_destroy(bt_tds_seeker_h seeker)
+{
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("TDS Seeker destroy Remote Provider [%s]", seeker_s->remote_address);
+       __bt_tds_reset_seeker_data(seeker_s);
+
+       tds_seeker_list = g_slist_remove(tds_seeker_list, seeker_s);
+       g_free(seeker_s);
+       seeker_s = NULL;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_tds_seeker_connect(bt_tds_seeker_h seeker)
+{
+       int error_code;
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (seeker_s->connected)
+               return BT_ERROR_NONE;
+
+       BT_DBG("TDS Seeker connect Remote Provider [%s]", seeker_s->remote_address);
+       error_code = bt_gatt_connect(seeker_s->remote_address, FALSE);
+
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+       return error_code;
+}
+
+int bt_tds_seeker_disconnect(bt_tds_seeker_h seeker)
+{
+       int error_code;
+       bt_tds_seeker_s *seeker_s = (bt_tds_seeker_s *)seeker;
+
+       BT_CHECK_TDS_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(seeker_s);
+
+       if (_bt_tds_seeker_find(seeker_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (seeker_s->connected == false) {
+               BT_ERR("Remote Provider [%s] is not conencted", seeker_s->remote_address);
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       BT_DBG("TDS Seeker Disconnect Remote Provider [%s]", seeker_s->remote_address);
+       error_code = bt_gatt_disconnect(seeker_s->remote_address);
+
+       if (error_code != BT_ERROR_NONE)
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+       return error_code;
+}
index 82d02741df6430bb3d7f30535184660641e58aae..dffe4c547f18dc38459b8ce875acd171ae781d92 100644 (file)
@@ -125,6 +125,7 @@ bt_scan_filter_h pxp_scan_filter;
 
 bt_tds_provider_h provider;
 char *tds_act_address;
+bt_tds_seeker_h seeker;
 
 #ifdef TIZEN_FEATURE_ENABLE_LEGACY_GATT_CLIENT
 bt_gatt_attribute_h service_clone[MAX_SERVICES];
@@ -186,8 +187,10 @@ tc_table_t tc_main[] = {
 #endif
        {"etc.(Automated test, AppControl)"
                , BT_UNIT_TEST_TABLE_ETC},
-       {"TDS"
-               , BT_UNIT_TEST_TABLE_TDS},
+       {"TDS Provider"
+               , BT_UNIT_TEST_TABLE_TDS_PROVIDER},
+       {"TDS Seeker"
+               , BT_UNIT_TEST_TABLE_TDS_SEEKER},
        {"Initialize All"
                , BT_UNIT_TEST_FUNCTION_INITIALIZE_ALL},
        {"FINISH"
@@ -1098,8 +1101,8 @@ tc_table_t tc_pbap_client[] = {
 };
 #endif
 
-tc_table_t tc_tds[] = {
-       /* TDS functions */
+tc_table_t tc_tds_provider[] = {
+       /* TDS provider functions */
        {"BACK"
                , BT_UNIT_TEST_FUNCTION_BACK},
        {"TDS Provider(Register)"
@@ -1123,6 +1126,34 @@ tc_table_t tc_tds[] = {
        {NULL                                   , 0x0000},
 };
 
+tc_table_t tc_tds_seeker[] = {
+       /* TDS Seeker functions */
+       {"BACK"
+               , BT_UNIT_TEST_FUNCTION_BACK},
+       {"TDS Seeker Start Discovering Provider"
+               , BT_UNIT_TEST_FUNCTION_TDS_START_DISCOVERING_PROVIDER},
+       {"TDS Seeker Stop Discovering Provider"
+               , BT_UNIT_TEST_FUNCTION_TDS_STOP_DISCOVERING_PROVIDER},
+       {"TDS Seeker(Create)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CREATE},
+       {"TDS Seeker(Destroy)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DESTROY},
+       {"TDS Set Seeker Connection cb"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_SET_CONNECTION_CALLBACK},
+       {"TDS Seeker Connect(remote)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CONNECT},
+       {"TDS Seeker DisConnect(remote)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DISCONNECT},
+       {"TDS UnSet Seeker Connection cb"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_UNSET_CONNECTION_CALLBACK},
+       {"TDS Read Complete Transport Data (remote)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_GET_COMPLETE_DATA},
+       {"TDS Activate Control Point (remote)"
+               , BT_UNIT_TEST_FUNCTION_TDS_SEEKER_ACTIVATE_CONTROL_POINT},
+       {NULL                                   , 0x0000},
+};
+
+
 tc_table_t tc_automated_test[] = {
        /* Automated test Functions*/
        {"BACK"                                                         , BT_UNIT_TEST_FUNCTION_BACK},
@@ -1220,8 +1251,11 @@ void tc_usage_print(void)
                __bt_initialize_all();
                TC_PRT("Key 0 : usage BACK");
                return;
-       case BT_UNIT_TEST_TABLE_TDS:
-               tc_table = tc_tds;
+       case BT_UNIT_TEST_TABLE_TDS_PROVIDER:
+               tc_table = tc_tds_provider;
+               break;
+       case BT_UNIT_TEST_TABLE_TDS_SEEKER:
+               tc_table = tc_tds_seeker;
                break;
        case BT_UNIT_TEST_TABLE_MAIN:
        default:
@@ -3075,6 +3109,85 @@ void __bt_repeat_test_adapter_state_changed_cb(int result,
        bt_onoff_cnt++;
 }
 
+/* TDS Seeker Callbacks */
+static  void __bt_tds_provider_scan_result_cb(int result, const char *remote_address,
+                       bt_tds_transport_block_list_s *info, bt_adapter_le_device_scan_result_info_s *scan_info,
+                       void *user_data)
+{
+       int k;
+       int l;
+       TC_PRT("__bt_tds_provider_scan_result_cb");
+       TC_PRT("result: %s", __bt_get_error_message(result));
+
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       TC_PRT("Remote addr [%s]", remote_address);
+       TC_PRT("Number of Transport Block [%d]", info->num_transport_block);
+
+       if (result == BT_ERROR_NONE) {
+               for (k = 0; k < info->num_transport_block; k++) {
+                       TC_PRT("Block Num[%d] Transport Name [%d]", k+1, info->data[k]->transport);
+                       TC_PRT("Block Num[%d] Transport state [%d]", k+1, info->data[k]->state);
+                       TC_PRT("Block Num[%d] Is Data complete [%d]", k+1, info->data[k]->is_data_complete);
+                       TC_PRT("Block Num[%d] Length of TDS Block data [%d]", k+1, info->data[k]->length);
+
+                       for (l = 0; l < info->data[k]->length; l++)
+                               TC_PRT("Transport Specific data [%d] = [0x%x]", l, info->data[k]->data[l]);
+               }
+       }
+}
+
+static void __bt_tds_seeker_connection_state_changed_cb(int result, const char *remote_address,
+                       bt_tds_seeker_h seeker, bool connected, void *user_data)
+{
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       if (result == BT_ERROR_NONE) {
+               if (connected)
+                       TC_PRT("TDS Seeker connected(address = %s)", remote_address);
+               else
+                       TC_PRT("TDS Seeker Disconnected (address = %s)", remote_address);
+       } else
+               BT_ERR("TDS Connection failed!");
+}
+
+static void __bt_tds_seeker_complete_transport_data_cb(int result, const char *remote_address,
+                       bt_tds_transport_block_list_s *info, void *user_data)
+{
+       int k;
+       int l;
+       TC_PRT("__bt_tds_seeker_complete_transport_data_cb");
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       TC_PRT("Remote addr [%s]", remote_address);
+
+       if (result == BT_ERROR_NONE) {
+               TC_PRT("Number of Transport Block [%d]", info->num_transport_block);
+               for (k = 0; k < info->num_transport_block; k++) {
+                       TC_PRT("Block Num[%d] Transport Name [%d]", k+1, info->data[k]->transport);
+                       TC_PRT("Block Num[%d] Transport state [%d]", k+1, info->data[k]->state);
+                       TC_PRT("Block Num[%d] Is Data complete [%d]", k+1, info->data[k]->is_data_complete);
+                       TC_PRT("Block Num[%d] Length of TDS Block data [%d]", k+1, info->data[k]->length);
+
+                       for (l = 0; l < info->data[k]->length; l++)
+                               TC_PRT("Transport Specific data [%d] = [0x%x]", l, info->data[k]->data[l]);
+               }
+       } else
+               BT_ERR("TDS Data receive request failed!");
+}
+
+static void __bt_tds_control_point_activation_result_cb(int result, const char *remote_address,
+                               unsigned char *data, int length, void *user_data)
+{
+       int k;
+       TC_PRT("__bt_tds_control_point_activation_result_cb");
+       TC_PRT("Result [%d]", result);
+       TC_PRT("Address[%s]", remote_address);
+
+       if (result == BT_ERROR_NONE) {
+               TC_PRT("Data length [%d]", length);
+               for (k = 0; k < length; k++)
+                       TC_PRT("Data[%d] [0x%x]", k, data[k]);
+       }
+}
+
 static void __bt_initialize_all(void)
 {
        int ret;
@@ -9626,7 +9739,7 @@ int test_input_callback(void *data)
                break;
        }
 #endif
-       case BT_UNIT_TEST_TABLE_TDS: {
+       case BT_UNIT_TEST_TABLE_TDS_PROVIDER: {
                switch (test_id) {
                case BT_UNIT_TEST_FUNCTION_TDS_PROVIDER_REGISTER: {
                        ret = bt_tds_provider_register();
@@ -9694,6 +9807,85 @@ int test_input_callback(void *data)
                }
                break;
        }
+       case BT_UNIT_TEST_TABLE_TDS_SEEKER: {
+               switch (test_id) {
+               case BT_UNIT_TEST_FUNCTION_TDS_START_DISCOVERING_PROVIDER: {
+                       ret = bt_tds_start_seeking_providers(__bt_tds_provider_scan_result_cb, NULL);
+                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_STOP_DISCOVERING_PROVIDER: {
+                       ret = bt_tds_stop_seeking_providers();
+                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CREATE: {
+                       if (seeker)
+                               seeker = NULL;
+                       ret = bt_tds_seeker_create(remote_addr, &seeker);
+                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DESTROY: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_destroy(seeker);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_SET_CONNECTION_CALLBACK: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_set_connection_state_changed_cb(seeker,
+                                               __bt_tds_seeker_connection_state_changed_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CONNECT: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_connect(seeker);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DISCONNECT: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_disconnect(seeker);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_UNSET_CONNECTION_CALLBACK: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_unset_connection_state_changed_cb(seeker);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_GET_COMPLETE_DATA: {
+                       if (seeker) {
+                               ret = bt_tds_seeker_get_complete_transport_blocks(seeker,
+                                               __bt_tds_seeker_complete_transport_data_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_TDS_SEEKER_ACTIVATE_CONTROL_POINT: {
+                       if (seeker) {
+                               unsigned char buf[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, /* Mac */
+                                       0x0A, 0x0B};    /* Channel Info */
+                               bt_tds_transport_e transport = BT_TDS_TRANSPORT_CUSTOM;
+                               ret = bt_tds_seeker_activate_control_point(seeker, transport, buf, sizeof(buf),
+                                               __bt_tds_control_point_activation_result_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               default:
+                       break;
+               }
+               break;
+       }
        case BT_UNIT_TEST_TABLE_ETC: {
                static unsigned int delay = 0;
                bt_onoff_cnt = 0;
index 537f30cc455a44860b21a0c82dc313c4e5bf85bb..f7548802b57b1c7d523b397ce1189d89b6e0a47f 100644 (file)
@@ -53,7 +53,8 @@ typedef enum {
 #endif
        BT_UNIT_TEST_TABLE_ETC,
        BT_UNIT_TEST_FUNCTION_INITIALIZE_ALL,
-       BT_UNIT_TEST_TABLE_TDS,
+       BT_UNIT_TEST_TABLE_TDS_PROVIDER,
+       BT_UNIT_TEST_TABLE_TDS_SEEKER,
        BT_UNIT_TEST_TABLE_FINISH = 0xFF,
 } bt_unit_test_table_e;
 
@@ -464,6 +465,7 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_PXP_MONITOR_READ_IMMEDIATE_ALERT,
        BT_UNIT_TEST_FUNCTION_PXP_MONITOR_READ_SIGNAL_LEVEL,
 
+       /* TDS Provider */
        BT_UNIT_TEST_FUNCTION_TDS_PROVIDER_REGISTER = 1,
        BT_UNIT_TEST_FUNCTION_TDS_PROVIDER_UNREGISTER,
        BT_UNIT_TEST_FUNCTION_TDS_PROVIDER_SET_ACT_REQ_CB,
@@ -473,6 +475,19 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_TDS_CUSTOM_PROVIDER_SET_TRANSPORT_DATA,
        BT_UNIT_TEST_FUNCTION_TDS_CUSTOM_PROVIDER_SET_MANUF_DATA,
        BT_UNIT_TEST_FUNCTION_TDS_CUSTOM_PROVIDER_SEND_ACTIVATION_RESP,
+
+       /* TDS Seeker */
+       BT_UNIT_TEST_FUNCTION_TDS_START_DISCOVERING_PROVIDER = 1,
+       BT_UNIT_TEST_FUNCTION_TDS_STOP_DISCOVERING_PROVIDER,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CREATE,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DESTROY,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_SET_CONNECTION_CALLBACK,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_CONNECT,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_DISCONNECT,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_UNSET_CONNECTION_CALLBACK,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_GET_COMPLETE_DATA,
+       BT_UNIT_TEST_FUNCTION_TDS_SEEKER_ACTIVATE_CONTROL_POINT,
+
        BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF,
 } bt_unit_test_function_e;