[Bluetooth][OTP-Client] Expose OTP client APIs 66/127966/2
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Tue, 2 May 2017 15:58:21 +0000 (21:28 +0530)
committerGowtham Anandha Babu <gowtham.ab@samsung.com>
Wed, 3 May 2017 05:58:36 +0000 (11:28 +0530)
Exposed below mentioned APIs for OTP client:
1) Create client
2) Destroy client
3) Set client connection state changed callback
4) Unset client connection state changed callback
5) Client connect
6) Client disconnect

Change-Id: Ief69c8838d096fa8d98514e54ecf8674310641b8
Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
include/bluetooth_internal.h
include/bluetooth_private.h
include/bluetooth_type_internal.h
src/bluetooth-common.c
src/bluetooth-otp.c
test/bt_unit_test.c
test/bt_unit_test.h

index a7c7027bdd06ca6bebec8037384ac916a95370a7..99d7ec83d15b4965ede584b53065e2e53a330a04 100644 (file)
@@ -4052,6 +4052,43 @@ int bt_otp_set_server_state_changed_cb(bt_otp_server_state_changed_cb callback,
  */
 int bt_otp_unset_server_state_changed_cb(void);
 
+/**
+ * @internal
+ * @brief OTP Client Profile API to create Client Role associated with Remote OTP Server
+ */
+int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client);
+
+/**
+ * @internal
+ * @brief OTP Client Profile API to destroy Client Role associated with Remote OTP Server
+ */
+int bt_otp_client_destroy(bt_otp_client_h otp_client);
+
+/**
+ * @internal
+ * @brief OTP Client Profile API to set connection state changed event associated with Remote OTP Server
+ */
+int bt_otp_client_set_connection_state_changed_cb(bt_otp_client_h otp_client,
+                                               bt_otp_client_state_changed_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief OTP Client Profile API to unset connection state changed event associated with Remote OTP Server
+ */
+int bt_otp_client_unset_connection_state_changed_cb(bt_otp_client_h otp_client);
+
+/**
+ * @internal
+ * @brief OTP client API to connect to Remote OTP Server
+ */
+int bt_otp_client_connect(bt_otp_client_h otp_client);
+
+/**
+ * @internal
+ * @brief OTP client API to disconnect to Remote OTP Server
+ */
+int bt_otp_client_disconnect(bt_otp_client_h otp_client);
+
 /**
  * @}
  */
index 193e0f1621d29b43f0a66291a005d5ae6d1e8c46..b8ad8adc6db1677895d7724929705ce05533b2b2 100644 (file)
@@ -864,6 +864,25 @@ void _bt_tds_control_point_indication_response_update(const char *address, bluet
  */
 void _bt_tds_check_service_changed(char *address, bt_gatt_service_change_t *service_change);
 
+/**
+ * @internal
+ * @brief Send GATT connection state changed status with remote OTP Server.
+ */
+void _bt_otp_client_connection_state_changed(int result, const char *remote_address, bool connected);
+
+/**
+ * @internal
+ * @brief Send GATT Read Response status got from remote OTP Server.
+ */
+void _bt_otp_client_read_value_response(int result, char *char_path,
+                                                                       char *char_value, int val_len);
+
+/**
+ * @internal
+ * @brief Send GATT Notification Enabled Response status got from remote OTP Server.
+ */
+void _bt_otp_client_notification_enabled(int result, char *handle);
+
 typedef enum {
        _PROFILE_UNKNOWN = 0,
        _PROFILE_MOBILE = 0x1,
index 67770e16975521b51d0550c9c8a926bfa39c0d65..c7d83a1f3c1503997dcef8ee352635d4a38a902b 100644 (file)
@@ -917,6 +917,22 @@ typedef void (*bt_tds_control_point_activation_indication_cb)
  */
 typedef void (*bt_otp_server_state_changed_cb)(int result, bool connected);
 
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_ADAPTER_LE_MODULE
+ * @brief The handle of a OTP client which is associated with a remote OTP Server
+ * @since_tizen 3.0
+ */
+typedef void *bt_otp_client_h;
+
+/**
+ * @internal
+ * @since_tizen 3.0
+ * @brief OTP Client profile Connection State changed callback which is associated with a remote OTP Server
+ */
+typedef void (*bt_otp_client_state_changed_cb)
+               (int result, const char *remote_address, bt_otp_client_h otp_client, bool connected, void *user_data);
+
 /**
  * @}
  */
index 08e4a0ff9cf462fb09d48f3c70f002f0db1aab66..5e3c5c1eac3bb1bfde515f7bc8b313a5c9e9badf 100644 (file)
@@ -1053,6 +1053,8 @@ static bool __bt_need_to_handle(int event)
        case BLUETOOTH_EVENT_TDS_ACTIVATION_RESULT:
        case BLUETOOTH_EVENT_TDS_CONTROL_POINT_ENABLED:
        case BLUETOOTH_EVENT_TDS_ACTIVATION_INDICATION:
+       case BLUETOOTH_EVENT_OTP_READ_CHAR_VAL:
+       case BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED:
                return true;
        default:
                break;
@@ -1992,6 +1994,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                /* TDS Seeker */
                _bt_tds_update_seeker_connection_state_changed(param->result, device_addr, TRUE);
 
+               /* OTP Client */
+               _bt_otp_client_connection_state_changed(param->result, device_addr, TRUE);
+
                g_free(device_addr);
                device_addr = NULL;
                break;
@@ -2019,6 +2024,9 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                /* TDS Seeker */
                _bt_tds_update_seeker_connection_state_changed(param->result, device_addr, FALSE);
 
+               /* OTP Client */
+               _bt_otp_client_connection_state_changed(param->result, device_addr, FALSE);
+
                g_free(device_addr);
                device_addr = NULL;
                break;
@@ -2918,7 +2926,8 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                if (device_addr != NULL)
                        free(device_addr); /* LCOV_EXCL_STOP */
                break;
-       } case BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED: {
+       }
+       case BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED: {
                bt_otp_server_state_changed_cb cb = bt_event_slot_container[event_index].callback;
                bool *status = (bool *)(param->param_data);
 
@@ -2927,6 +2936,31 @@ static void __bt_event_proxy(int event, bluetooth_event_param_t *param, void *us
                cb(_bt_get_error_code(param->result), *status ? true : false);
                break;
        }
+       case BLUETOOTH_EVENT_OTP_READ_CHAR_VAL: {
+               BT_DBG("BLUETOOTH_EVENT_OTP_READ_CHAR_VAL"); /* LCOV_EXCL_LINE */
+               bluetooth_otp_resp_info_t *info = NULL;
+               char *handle = NULL;
+
+               if (_bt_get_error_code(param->result) == BT_ERROR_NONE) {
+                       info = (bluetooth_otp_resp_info_t *)(param->param_data);
+                       BT_ERR("Read Success Handle [%s]", info->handle);
+                       _bt_otp_client_read_value_response(_bt_get_error_code(param->result),
+                                                                               info->handle, info->data, info->data_length);
+               } else {
+                       handle = (char *)(param->param_data);
+                       BT_ERR("Read Fail Handle [%s]", handle);
+                       _bt_otp_client_read_value_response(_bt_get_error_code(param->result),
+                                                                               handle, NULL, 0);
+               }
+               break;
+       }
+       case BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED: {
+               BT_DBG("BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED"); /* LCOV_EXCL_LINE */
+               char *handle = (char *)(param->param_data);
+               BT_ERR("Handle [%s]", handle);
+               _bt_otp_client_notification_enabled(_bt_get_error_code(param->result), handle);
+               break;
+       }
        default:
                BT_INFO("Unknown function");
                break;
index 464c5a5a67f418824352f09cfc5b8e7f3f490589..4da35f3f07e306b81460d01cebe6f290191296b9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 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.
                return BT_ERROR_NOT_INITIALIZED; \
        }
 
+#define BT_OTP_SERVICE_UUID                    "00001825-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_FEATURE_UUID                    "00002abd-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OACP_CONTROL_POINT_UUID         "00002ac5-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OLCP_CONTROL_POINT_UUID         "00002ac6-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_NAME_UUID                        "00002abe-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_TYPE_UUID                        "00002abf-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_SIZE_UUID                        "00002ac0-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_FIRST_CREATED_UUID       "00002ac1-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_LAST_MODIFIED_UUID       "00002ac2-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_ID_UUID                  "00002ac3-0000-1000-8000-00805f9b34fb"
+#define BT_OTP_OBJECT_PROP_UUID                        "00002ac4-0000-1000-8000-00805f9b34fb"
+
+#define BT_ADDR_LENGTH 18
+#define BT_OTP_FEATURE_LENGTH 8
+
+#define IS_OACP_SUPPORTED(feature) feature & 0xffffffff00000000
+#define IS_OLCP_SUPPORTED(feature) feature & 0x00000000ffffffff
+
+typedef struct {
+       char *remote_address;
+       bool connected;
+
+       const void *connection_callback;
+       void *conn_cb_user_data;
+
+       char *otp_service_handle;               /* OTP Service Handle */
+       char *otp_feature_obj_path;             /* OTP feature characteristic handle */
+       uint64_t otp_feature;                   /* OTP feature value */
+       char *otp_oacp_control_point;           /* OTP OACP Control Point characteristic handle */
+       char *otp_oacp_cccd;                    /* OTP OACP Control Point CCCD handle */
+       char *otp_olcp_control_point;           /* OTP OLCP Control Point characteristic handle */
+       char *otp_olcp_cccd;                    /* OTP OLCP Control Point CCCD handle */
+
+       /* Object Metadata paths */
+       char *otp_name_obj_path;                /* OTP Object Name characteristic handle */
+       char *otp_type_obj_path;                /* OTP Object Type characteristic handle */
+       char *otp_size_obj_path;                /* OTP Object Size characteristic handle */
+       char *otp_first_created_obj_path;       /* OTP Object Frist Created characteristic handle */
+       char *otp_last_modified_obj_path;       /* OTP Object Last Modified characteristic handle */
+       char *otp_id_obj_path;                  /* OTP Object ID characteristic handle */
+       char *otp_props_obj_path;               /* OTP Object Properties characteristic handle */
+
+       bool oacp_cccd_enabled;                 /* OTP OACP Control Point CCCD is enabled or not */
+       bool olcp_cccd_enabled;                 /* OTP OLCP Control Point CCCD is enabled or not */
+} bt_otp_client_s;
+
+GSList *otp_client_list;
 static bool is_otp_server_initialized = false;
 
 int __bt_check_otp_server_init_status(void)
@@ -119,4 +166,534 @@ int bt_otp_unset_server_state_changed_cb(void)
        if (_bt_check_cb(BT_EVENT_OTP_SERVER_STATE_CHANGED) == true)
                _bt_unset_cb(BT_EVENT_OTP_SERVER_STATE_CHANGED);
        return BT_ERROR_NONE;
-}
\ No newline at end of file
+}
+
+static bt_otp_client_s *_bt_otp_client_find(const char *remote_address)
+{
+       GSList *l;
+
+       for (l = otp_client_list; l; l = g_slist_next(l)) {
+
+               if (!g_ascii_strcasecmp(((bt_otp_client_s *)l->data)->remote_address, remote_address))
+                       return ((bt_otp_client_s *)l->data);
+       }
+       return NULL;
+}
+
+char *free_object_path(char *path)
+{
+       if (path)
+               g_free(path);
+       return NULL;
+}
+
+static void __bt_otp_client_reset_server_data(bt_otp_client_s *otp_client_s)
+{
+       otp_client_s->otp_service_handle =
+                       free_object_path(otp_client_s->otp_service_handle);
+       otp_client_s->otp_feature_obj_path =
+                       free_object_path(otp_client_s->otp_feature_obj_path);
+       otp_client_s->otp_oacp_control_point =
+                       free_object_path(otp_client_s->otp_oacp_control_point);
+       otp_client_s->otp_oacp_cccd =
+                       free_object_path(otp_client_s->otp_oacp_cccd);
+       otp_client_s->otp_olcp_control_point =
+                       free_object_path(otp_client_s->otp_olcp_control_point);
+       otp_client_s->otp_olcp_cccd =
+                       free_object_path(otp_client_s->otp_olcp_cccd);
+       otp_client_s->otp_name_obj_path =
+                       free_object_path(otp_client_s->otp_name_obj_path);
+       otp_client_s->otp_type_obj_path =
+                       free_object_path(otp_client_s->otp_type_obj_path);
+       otp_client_s->otp_size_obj_path =
+                       free_object_path(otp_client_s->otp_size_obj_path);
+       otp_client_s->otp_first_created_obj_path =
+                       free_object_path(otp_client_s->otp_first_created_obj_path);
+       otp_client_s->otp_last_modified_obj_path =
+                       free_object_path(otp_client_s->otp_last_modified_obj_path);
+       otp_client_s->otp_id_obj_path =
+                       free_object_path(otp_client_s->otp_id_obj_path);
+       otp_client_s->otp_props_obj_path =
+                       free_object_path(otp_client_s->otp_props_obj_path);
+
+       /* Reset CCCD */
+       otp_client_s->oacp_cccd_enabled = FALSE;
+       otp_client_s->olcp_cccd_enabled = FALSE;
+}
+
+int bt_otp_client_set_connection_state_changed_cb(bt_otp_client_h otp_client,
+                       bt_otp_client_state_changed_cb callback, void *user_data)
+{
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+       BT_CHECK_INPUT_PARAMETER(callback);
+
+       if (_bt_otp_client_find(otp_client_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("Set OTP Client Connection State changed callback");
+       /* register the callback */
+       otp_client_s->connection_callback = callback;
+       otp_client_s->conn_cb_user_data = user_data;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_otp_client_unset_connection_state_changed_cb(bt_otp_client_h otp_client)
+{
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+
+       if (_bt_otp_client_find(otp_client_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("UnSet OTP Client Connection State changed callback");
+       /* unregister the callback */
+       otp_client_s->connection_callback = NULL;
+       otp_client_s->conn_cb_user_data = NULL;
+
+       return BT_ERROR_NONE;
+}
+
+static int __bt_update_otp_server_data(bluetooth_device_address_t *address, bt_otp_client_s *otp_client_s)
+{
+       int ret = BLUETOOTH_ERROR_INTERNAL;
+       bt_gatt_service_property_t service;
+       int count;
+
+       ret = bluetooth_gatt_get_service_from_uuid(address, BT_OTP_SERVICE_UUID, &service);
+       if (ret != BLUETOOTH_ERROR_NONE) {
+               BT_ERR("Failed to find OTP service on the remote device [%s]", address);
+               return ret;
+       }
+
+       /* Discover all charc & desc of OTP service */
+       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_OTP_FEATURE_UUID)) {
+                               BT_DBG("OTP feature characteristic discovered");
+
+                               if (otp_client_s->otp_feature_obj_path)
+                                       g_free(otp_client_s->otp_feature_obj_path);
+                               otp_client_s->otp_feature_obj_path = g_strdup(characteristic.handle);
+
+                               ret = _bt_get_error_code(bluetooth_otp_read_characteristic_value(otp_client_s->otp_feature_obj_path));
+                               if (ret != BT_ERROR_NONE)
+                                       BT_ERR("Failed to read OTP Feature : %s(0x%08x)", _bt_convert_error_to_string(ret), ret);
+
+                               BT_DBG("OTP feature handle [%s]", otp_client_s->otp_feature_obj_path);
+                       } else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OACP_CONTROL_POINT_UUID)) {
+                               BT_DBG("OTP OACP 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 OACP Control point");
+                                       bluetooth_gatt_free_service_property(&service);
+                                       bluetooth_gatt_free_char_property(&characteristic);
+                                       bluetooth_gatt_free_desc_property(&desc_property);
+                                       goto fail;
+                               }
+                               if (otp_client_s->otp_oacp_control_point)
+                                       g_free(otp_client_s->otp_oacp_control_point);
+                               otp_client_s->otp_oacp_control_point = g_strdup(characteristic.handle);
+
+                               if (otp_client_s->otp_oacp_cccd)
+                                       g_free(otp_client_s->otp_oacp_cccd);
+                               otp_client_s->otp_oacp_cccd = g_strdup(desc_property.handle);
+
+                               BT_DBG("OACP Control point handle [%s]", otp_client_s->otp_oacp_control_point);
+                               BT_DBG("OACP Control point CCCD handle [%s]", otp_client_s->otp_oacp_cccd);
+                       } else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OLCP_CONTROL_POINT_UUID)) {
+                               BT_DBG("OTP OLCP 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 OLCP Control point");
+                                       bluetooth_gatt_free_service_property(&service);
+                                       bluetooth_gatt_free_char_property(&characteristic);
+                                       bluetooth_gatt_free_desc_property(&desc_property);
+                                       goto fail;
+                               }
+                               if (otp_client_s->otp_olcp_control_point)
+                                       g_free(otp_client_s->otp_olcp_control_point);
+                               otp_client_s->otp_olcp_control_point = g_strdup(characteristic.handle);
+
+                               if (otp_client_s->otp_olcp_cccd)
+                                       g_free(otp_client_s->otp_olcp_cccd);
+                               otp_client_s->otp_olcp_cccd = g_strdup(desc_property.handle);
+
+                               BT_DBG("OLCP Control point handle [%s]", otp_client_s->otp_olcp_control_point);
+                               BT_DBG("OLCP Control point CCCD handle [%s]", otp_client_s->otp_olcp_cccd);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_NAME_UUID)) {
+                               BT_DBG("OTP Object Name characteristic discovered");
+
+                               if (otp_client_s->otp_name_obj_path)
+                                       g_free(otp_client_s->otp_name_obj_path);
+                               otp_client_s->otp_name_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object Name handle [%s]", otp_client_s->otp_name_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_TYPE_UUID)) {
+                               BT_DBG("OTP Object Type characteristic discovered");
+
+                               if (otp_client_s->otp_type_obj_path)
+                                       g_free(otp_client_s->otp_type_obj_path);
+                               otp_client_s->otp_type_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object Type handle [%s]", otp_client_s->otp_type_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_SIZE_UUID)) {
+                               BT_DBG("OTP Object Size characteristic discovered");
+
+                               if (otp_client_s->otp_size_obj_path)
+                                       g_free(otp_client_s->otp_size_obj_path);
+                               otp_client_s->otp_size_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object Size handle [%s]", otp_client_s->otp_size_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_FIRST_CREATED_UUID)) {
+                               BT_DBG("OTP Object First Created characteristic discovered");
+
+                               if (otp_client_s->otp_first_created_obj_path)
+                                       g_free(otp_client_s->otp_first_created_obj_path);
+                               otp_client_s->otp_first_created_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object First Created handle [%s]", otp_client_s->otp_first_created_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_LAST_MODIFIED_UUID)) {
+                               BT_DBG("OTP Object Last Modified characteristic discovered");
+
+                               if (otp_client_s->otp_last_modified_obj_path)
+                                       g_free(otp_client_s->otp_last_modified_obj_path);
+                               otp_client_s->otp_last_modified_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object Last Modified handle [%s]", otp_client_s->otp_last_modified_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_ID_UUID)) {
+                               BT_DBG("OTP Object ID characteristic discovered");
+
+                               if (otp_client_s->otp_id_obj_path)
+                                       g_free(otp_client_s->otp_id_obj_path);
+                               otp_client_s->otp_id_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object ID handle [%s]", otp_client_s->otp_id_obj_path);
+                       }  else if (g_strstr_len(characteristic.uuid, -1, BT_OTP_OBJECT_PROP_UUID)) {
+                               BT_DBG("OTP Object Properties characteristic discovered");
+
+                               if (otp_client_s->otp_props_obj_path)
+                                       g_free(otp_client_s->otp_props_obj_path);
+                               otp_client_s->otp_props_obj_path = g_strdup(characteristic.handle);
+
+                               BT_DBG("OTP Object Properties handle [%s]", otp_client_s->otp_props_obj_path);
+                       }       else {
+                               BT_DBG("Other OTP Characteristic handle [%s]", g_strdup(characteristic.handle));
+                               BT_DBG("UUID [%s]", g_strdup(characteristic.uuid));
+                       } /* Control Point characteristic */
+               } /* Characteristic property get successful */
+               bluetooth_gatt_free_char_property(&characteristic);
+       } /* Next Charatceristic */
+
+       if (otp_client_s->otp_service_handle)
+               g_free(otp_client_s->otp_service_handle);
+
+       otp_client_s->otp_service_handle = g_strdup(service.handle);
+       bluetooth_gatt_free_service_property(&service);
+       return ret;
+fail:
+       __bt_otp_client_reset_server_data(otp_client_s);
+       return ret;
+}
+
+void _bt_otp_client_connection_state_changed(int result,
+               const char *remote_address, bool connected)
+{
+       bt_otp_client_s *otp_client_s = NULL;
+       BT_DBG("OTP Client Connection state changed result [%d] connected [%d]", result, connected ? TRUE : FALSE);
+
+       otp_client_s = _bt_otp_client_find(remote_address);
+       if (otp_client_s) {
+               BT_DBG("OTP Client 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_otp_client_reset_server_data(otp_client_s);
+
+                       if (otp_client_s->connection_callback)
+                               ((bt_otp_client_state_changed_cb)otp_client_s->connection_callback)
+                                       (result, remote_address, otp_client_s, connected, otp_client_s->conn_cb_user_data);
+                       return;
+               }
+               /* Update OTP Service values */
+               if (connected) {
+                       int error_code = BLUETOOTH_ERROR_NONE;
+                       BT_DBG("Remote device connected successfully");
+                       /* Attempt to update OTP Service data */
+                       error_code = __bt_update_otp_server_data(&addr_hex, otp_client_s);
+                       if (error_code != BLUETOOTH_ERROR_NONE)
+                               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+               } else {
+                       BT_DBG("Remote device disconnected successfully");
+                       /* Disconnected */
+                       __bt_otp_client_reset_server_data(otp_client_s);
+               }
+               otp_client_s->connected = connected;
+
+               if (otp_client_s->connection_callback)
+                       ((bt_otp_client_state_changed_cb)otp_client_s->connection_callback)
+                               (result, remote_address, otp_client_s, connected, otp_client_s->conn_cb_user_data);
+       } else {
+               BT_DBG("OTP client not found!");
+       }
+}
+
+int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client)
+{
+       int error_code = BT_ERROR_NONE;
+       bt_otp_client_s *otp_client_s = NULL;
+       bool connected = false;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       GSList *l;
+       BT_INFO("+");
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(remote_address);
+       BT_CHECK_INPUT_PARAMETER(otp_client);
+
+       for (l = otp_client_list; l; l = g_slist_next(l)) {
+               bt_otp_client_s *c = (bt_otp_client_s *)l->data;
+
+               if (!g_ascii_strcasecmp(c->remote_address, remote_address)) {
+                       BT_ERR("OTP Client for Remote device [%s] is already created",
+                                       remote_address);
+                       *otp_client = (bt_otp_client_h)c;
+                       return BT_ERROR_ALREADY_DONE;
+               }
+       }
+
+       otp_client_s = g_malloc0(sizeof(*otp_client_s));
+       if (otp_client_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");
+       otp_client_s->connected = connected;
+
+       _bt_convert_address_to_hex(&addr_hex, remote_address);
+
+       if (otp_client_s->connected == true) {
+               /* Update all serv & charc */
+               error_code = __bt_update_otp_server_data(&addr_hex, otp_client_s);
+               if (error_code != BLUETOOTH_ERROR_NONE) {
+                       g_free(otp_client_s);
+                       return BT_ERROR_OPERATION_FAILED;
+               }
+       }
+
+       otp_client_s->remote_address = g_strdup(remote_address);
+       if (otp_client_s->remote_address == NULL) {
+               free(otp_client_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;
+       }
+
+       otp_client_s->olcp_cccd_enabled = FALSE;
+       otp_client_s->oacp_cccd_enabled = FALSE;
+
+       otp_client_list = g_slist_append(otp_client_list, otp_client_s);
+       *otp_client = (bt_otp_client_h)otp_client_s;
+
+       BT_DBG("OTP Client Created");
+       return BT_ERROR_NONE;
+}
+
+int bt_otp_client_destroy(bt_otp_client_h otp_client)
+{
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+
+       if (_bt_otp_client_find(otp_client_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       BT_DBG("OTP client Remote device [%s]", otp_client_s->remote_address);
+       __bt_otp_client_reset_server_data(otp_client_s);
+
+       otp_client_list = g_slist_remove(otp_client_list, otp_client_s);
+       g_free(otp_client_s);
+       otp_client_s = NULL;
+
+       return BT_ERROR_NONE;
+}
+
+int bt_otp_client_connect(bt_otp_client_h otp_client)
+{
+       int error_code;
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+
+       if (_bt_otp_client_find(otp_client_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (otp_client_s->connected)
+               return BT_ERROR_NONE;
+
+       BT_DBG("OTP client connect Remote device [%s]", otp_client_s->remote_address);
+       error_code = bt_gatt_connect(otp_client_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_otp_client_disconnect(bt_otp_client_h otp_client)
+{
+       int error_code;
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+
+       if (_bt_otp_client_find(otp_client_s->remote_address) == NULL)
+               return BT_ERROR_NOT_INITIALIZED;
+
+       if (otp_client_s->connected == false) {
+               BT_ERR("Remote device [%s] is not conencted", otp_client_s->remote_address);
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       BT_DBG("OTP client Disconnect Remote device [%s]", otp_client_s->remote_address);
+       error_code = bt_gatt_disconnect(otp_client_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;
+}
+
+void _bt_otp_get_remote_address(char *handle, char *remote_address)
+{
+       char *dev_path;
+       dev_path = strstr(handle, "dev_");
+       dev_path += 4;
+       /* 18 -> Length of BT ADDR in path */
+       g_strlcpy(remote_address, dev_path, BT_ADDR_LENGTH);
+       g_strdelimit(remote_address, "_", ':');
+       BT_INFO("[%s] --> [%s]", handle, remote_address);
+}
+
+void _bt_otp_client_read_value_response(int result, char *char_path,
+                                                                       char *value, int len)
+{
+       bt_otp_client_s *otp_client_s = NULL;
+       char remote_address[BT_ADDR_LENGTH];
+
+       _bt_otp_get_remote_address(char_path, remote_address);
+
+       BT_DBG("OTP client Read Value Response [%d] [%s] [%s] [%d]", result,
+                                                                                       char_path, value, len);
+       if (result != BLUETOOTH_ERROR_NONE)
+               BT_INFO("Read failed for [%s]", char_path);
+
+       otp_client_s = _bt_otp_client_find(remote_address);
+       if (otp_client_s == NULL)
+               return;
+
+       if (!g_strcmp0(otp_client_s->otp_feature_obj_path, char_path)) {
+               int error_code;
+                       uint64_t feature =      (uint64_t)(value[0] & 0xFF) << 56       |
+                                                               (uint64_t)(value[1] & 0xFF) << 48       |
+                                                               (uint64_t)(value[2] & 0xFF) << 40       |
+                                                               (uint64_t)(value[3] & 0xFF) << 32       |
+                                                               (uint64_t)(value[4] & 0xFF) << 24       |
+                                                               (uint64_t)(value[5] & 0xFF) << 16       |
+                                                               (uint64_t)(value[6] & 0xFF) << 8        |
+                                                               (uint64_t)(value[7] & 0xFF);
+                       otp_client_s->otp_feature = feature;
+                       BT_INFO("OTP Feature [%lld]", feature);
+
+                       if (IS_OACP_SUPPORTED(otp_client_s->otp_feature)
+                                                               && !otp_client_s->oacp_cccd_enabled) {
+
+                               error_code = bluetooth_otp_enable_notification(otp_client_s->otp_oacp_control_point);
+                               if (error_code != BT_ERROR_NONE)
+                                       BT_ERR("OACP Notification enable failed %s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+                       }
+
+                       if (IS_OLCP_SUPPORTED(otp_client_s->otp_feature)
+                                                       && !otp_client_s->olcp_cccd_enabled) {
+                               error_code = bluetooth_otp_enable_notification(otp_client_s->otp_olcp_control_point);
+                               if (error_code != BT_ERROR_NONE)
+                                       BT_ERR("OLCP Notification enable failed %s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+                       }
+       } else {
+               /* Handle other Object Metadata read response */
+       }
+}
+
+void _bt_otp_client_notification_enabled(int result, char *handle)
+{
+       bt_otp_client_s *otp_client_s = NULL;
+       char remote_address[BT_ADDR_LENGTH];
+       BT_DBG("OTP notificaton [%d] [%s]", result, handle);
+       _bt_otp_get_remote_address(handle, remote_address);
+
+       otp_client_s = _bt_otp_client_find(remote_address);
+       if (otp_client_s == NULL)
+               return;
+
+       if (!g_strcmp0(otp_client_s->otp_oacp_control_point, handle)) {
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       otp_client_s->oacp_cccd_enabled = FALSE;
+                       BT_ERR("Failed to enable OACP notification : %s(0x%08x)", _bt_convert_error_to_string(result), result);
+               } else {
+                       otp_client_s->oacp_cccd_enabled = TRUE;
+               }
+       } else if (!g_strcmp0(otp_client_s->otp_olcp_control_point, handle)) {
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       otp_client_s->olcp_cccd_enabled = FALSE;
+                       BT_ERR("Failed to enable OLCP notification : %s(0x%08x)", _bt_convert_error_to_string(result), result);
+               } else {
+                       otp_client_s->olcp_cccd_enabled = TRUE;
+               }
+       }
+}
index 0e11664d2e84b086e9398c205f76c02e018f9009..bbe31747390beae443ca9e066f2152c214a3fde1 100644 (file)
@@ -125,6 +125,8 @@ bt_tds_provider_h provider;
 char *tds_act_address;
 bt_tds_seeker_h seeker;
 
+bt_otp_client_h otp_client;
+
 bt_gatt_attribute_h service_clone[MAX_SERVICES];
 bt_gatt_attribute_h characteristics[MAX_SERVICES];
 bt_gatt_attribute_h characteristics_services[MAX_SERVICES];
@@ -1162,6 +1164,18 @@ tc_table_t tc_otp[] = {
                , BT_UNIT_TEST_FUNCTION_OTP_SET_SERVER_STATE_CHANGED_CB},
        {"bt_otp_unset_server_state_changed_cb"
                , BT_UNIT_TEST_FUNCTION_OTP_UNSET_SERVER_STATE_CHANGED_CB},
+       {"bt_otp_client_create"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CREATE},
+       {"bt_otp_client_destroy"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DESTROY},
+       {"bt_otp_client_set_connection_state_changed_cb"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SET_CONNECTION_CALLBACK},
+       {"bt_otp_client_unset_connection_state_changed_cb"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_UNSET_CONNECTION_CALLBACK},
+       {"bt_otp_client_connect"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CONNECT},
+       {"bt_otp_client_disconnect"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCONNECT},
        {NULL                                   , 0x0000},
 };
 
@@ -3221,6 +3235,19 @@ void __bt_otp_server_state_changed_cb(int result, bool status)
        TC_PRT("Server Status: %s", status ? "enabled" : "disabled");
 }
 
+static void __bt_otp_client_connection_state_changed_cb(int result, const char *remote_address,
+                       bt_otp_client_h otp_client, bool connected, void *user_data)
+{
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       if (result == BT_ERROR_NONE) {
+               if (connected)
+                       TC_PRT("OTP Client connected(address = %s)", remote_address);
+               else
+                       TC_PRT("OTP Client Disconnected (address = %s)", remote_address);
+       } else
+               BT_ERR("OTP Connection failed!");
+}
+
 static void __bt_initialize_all(void)
 {
        int ret;
@@ -10195,6 +10222,49 @@ int test_input_callback(void *data)
                        TC_PRT("returns %s\n", __bt_get_error_message(ret));
                        break;
                }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CREATE: {
+                       if (otp_client)
+                               otp_client = NULL;
+                       ret = bt_otp_client_create(remote_addr, &otp_client);
+                       TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DESTROY: {
+                       if (otp_client) {
+                               ret = bt_otp_client_destroy(otp_client);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SET_CONNECTION_CALLBACK: {
+                       if (otp_client) {
+                               ret = bt_otp_client_set_connection_state_changed_cb(otp_client,
+                                               __bt_otp_client_connection_state_changed_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CONNECT: {
+                       if (otp_client) {
+                               ret = bt_otp_client_connect(otp_client);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCONNECT: {
+                       if (otp_client) {
+                               ret = bt_otp_client_disconnect(otp_client);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_UNSET_CONNECTION_CALLBACK: {
+                       if (otp_client) {
+                               ret = bt_otp_client_unset_connection_state_changed_cb(otp_client);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
                case BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS:
                        need_to_set_params = true;
                        TC_PRT("Select the function again");
index 35a06a5fb52af504a24c7124fd6ca9b76413a46f..30920cca16314e8ccb993ac8b1c420ed82d99d98 100644 (file)
@@ -487,6 +487,12 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_OTP_SERVER_DEINIT,
        BT_UNIT_TEST_FUNCTION_OTP_SET_SERVER_STATE_CHANGED_CB,
        BT_UNIT_TEST_FUNCTION_OTP_UNSET_SERVER_STATE_CHANGED_CB,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CREATE,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DESTROY,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SET_CONNECTION_CALLBACK,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_UNSET_CONNECTION_CALLBACK,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CONNECT,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCONNECT,
 
        BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF,
 } bt_unit_test_function_e;