[OTP] Expose Object Select API 02/132802/3 accepted/tizen/unified/20170613.194511 submit/tizen/20170613.061617
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Wed, 7 Jun 2017 15:04:47 +0000 (20:34 +0530)
committerGowtham Anandha Babu <gowtham.ab@samsung.com>
Fri, 9 Jun 2017 11:21:38 +0000 (16:51 +0530)
Change-Id: I7cb2de1136ddf7f681f2744ac31eed8c947bc4ea
Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
include/bluetooth_internal.h
include/bluetooth_type_internal.h
src/bluetooth-otp.c
test/bt_unit_test.c
test/bt_unit_test.h

index ecc491a466dca533dd223756bc7ce62a40f801bc..d9a8e323f4cd8527ccbc5e131cbf87ee96ff6460 100644 (file)
@@ -4096,6 +4096,12 @@ int bt_otp_client_disconnect(bt_otp_client_h otp_client);
 int bt_otp_client_discover_all_objects(bt_otp_client_h otp_client,
                                                bt_otp_client_object_discovery_cb callback, void *user_data);
 
+/**
+ * @internal
+ * @brief OTP client API to select object in Remote OTP Server
+ */
+int bt_otp_client_select_object(bt_otp_client_h otp_client, unsigned long long id,
+                                                       bt_otp_client_object_select_cb callback, void *user_data);
 /**
  * @internal
  * @brief OTP client API to read remote objects contents
index d7a473f0bf8ab7eda0430d9c873c709a71dcf28a..8438238d9a9466217ef72c95491904b0e26c1684 100644 (file)
@@ -914,6 +914,7 @@ typedef void (*bt_tds_control_point_activation_indication_cb)
 
 /**
  * @internal
+ * @since_tizen 4.0
  * @brief  Called when OTP Server is Enabled or Disabled.
  */
 typedef void (*bt_otp_server_state_changed_cb)(int result, bool connected);
@@ -922,14 +923,14 @@ 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
+ * @since_tizen 4.0
  */
 typedef void *bt_otp_client_h;
 
 /**
  * @internal
  * @brief The structure type of OTP object metadata
- * @since_tizen 3.0
+ * @since_tizen 4.0
  */
 typedef struct {
        unsigned long long id;
@@ -939,7 +940,7 @@ typedef struct {
 /**
  * @internal
  * @brief The structure type of list of OTP discovered objects
- * @since_tizen 3.0
+ * @since_tizen 4.0
  */
 typedef struct {
        int num_objects;            /**< Number of Objects Discovered */
@@ -948,7 +949,7 @@ typedef struct {
 
 /**
  * @internal
- * @since_tizen 3.0
+ * @since_tizen 4.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)
@@ -956,7 +957,7 @@ typedef void (*bt_otp_client_state_changed_cb)
 
 /**
  * @internal
- * @since_tizen 3.0
+ * @since_tizen 4.0
  * @brief OTP Client profile remote object discovery callback
  */
 typedef void (*bt_otp_client_object_discovery_cb)
@@ -964,7 +965,15 @@ typedef void (*bt_otp_client_object_discovery_cb)
 
 /**
  * @internal
- * @since_tizen 3.0
+ * @since_tizen 4.0
+ * @brief OTP Client profile select object callback
+ */
+typedef void (*bt_otp_client_object_select_cb)
+               (int result, const char *remote_address, unsigned long long obj_id, void *user_data);
+
+/**
+ * @internal
+ * @since_tizen 4.0
  * @brief OTP Client profile remote object read complete callback
  */
 typedef void (*bt_otp_client_read_object_complete_cb)
index 05fbb3def4be521a032d0a900b0b56c9c71de650..b2755e183785f1ae497753499997239acd9dd6a2 100644 (file)
@@ -133,6 +133,7 @@ typedef enum {
        BT_OTP_NO_OPERATION = 0,
        BT_OTP_OBJECT_DISCOVERY,
        BT_OTP_OBJECT_READ,
+       BT_OTP_OBJECT_SELECT,
 } bt_otp_api_info_e;
 
 typedef struct {
@@ -196,6 +197,7 @@ static bool is_otp_server_initialized = false;
 bt_otp_client_read_op *oacp_read_op = NULL;
 bool otc_connection_status = FALSE;
 bt_otp_object_list_s *obj_list;
+uint64_t select_obj_id = 0;
 object_metadata *metadata;
 GSList *otp_client_list;
 unsigned int timeout_id;
@@ -205,6 +207,8 @@ object_metadata *_bt_otp_client_find_object(GSList *list, uint64_t id);
 static void _bt_otp_client_notify_read_object_status(int result,
                        char *file_path, bt_otp_client_s *otp_client_s);
 void __bt_otp_reset_api_info(bt_otp_client_s *otp_client_s);
+static void _bt_otp_client_send_select_object_callback(int result,
+                                       bt_otp_client_s *otp_client_s);
 
 int __bt_check_otp_server_init_status(void)
 {
@@ -279,11 +283,13 @@ int bt_otp_unset_server_state_changed_cb(void)
 static bt_otp_client_s *_bt_otp_client_find(const char *remote_address)
 {
        GSList *l;
+       bt_otp_client_s *info;
 
        for (l = otp_client_list; l; l = g_slist_next(l)) {
+               info = l->data;
 
-               if (!g_ascii_strcasecmp(((bt_otp_client_s *)l->data)->remote_address, remote_address))
-                       return ((bt_otp_client_s *)l->data);
+               if (info && !g_ascii_strcasecmp(info->remote_address, remote_address))
+                       return info;
        }
        return NULL;
 }
@@ -602,6 +608,7 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
        bt_otp_client_s *otp_client_s = NULL;
        bool connected = false;
        bluetooth_device_address_t addr_hex = { {0,} };
+       bt_otp_client_s *info;
        GSList *l;
        BT_INFO("+");
 
@@ -612,12 +619,12 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
        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;
+               info = l->data;
 
-               if (!g_ascii_strcasecmp(c->remote_address, remote_address)) {
+               if (info && !g_ascii_strcasecmp(info->remote_address, remote_address)) {
                        BT_ERR("OTP Client for Remote device [%s] is already created",
                                        remote_address);
-                       *otp_client = (bt_otp_client_h)c;
+                       *otp_client = (bt_otp_client_h)info;
                        return BT_ERROR_ALREADY_DONE;
                }
        }
@@ -753,6 +760,7 @@ void _bt_otp_get_remote_address(char *handle, char *remote_address)
 
 void _bt_otp_send_discovery_callback(int result, bt_otp_client_s *otp_client_s)
 {
+       object_metadata *metadata;
        GSList *l;
        int k;
        if (result != BLUETOOTH_ERROR_NONE) {
@@ -775,8 +783,10 @@ void _bt_otp_send_discovery_callback(int result, bt_otp_client_s *otp_client_s)
        obj_list->num_objects = g_slist_length(otp_client_s->object_list);
        obj_list->data = (otp_object_metadata_s **)g_malloc0(sizeof(otp_object_metadata_s)*obj_list->num_objects);
        k = 0;
-       for (l = otp_client_s->object_list; l != NULL; l = g_slist_next(l)) {
-               object_metadata *metadata = l->data;
+       for (l = otp_client_s->object_list; l; l = g_slist_next(l)) {
+               metadata = l->data;
+               if (metadata == NULL)
+                       continue;
                otp_object_metadata_s *m_data = g_malloc0(sizeof(otp_object_metadata_s));
                m_data->id = metadata->id;
                m_data->name = g_strdup(metadata->name);
@@ -1066,11 +1076,13 @@ void _bt_otp_client_write_value_response(int result, char *handle)
                if (otp_client_s->curr_op == BT_OTP_OBJECT_DISCOVERY) {
                        _bt_otp_send_discovery_callback(result, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
-               }
-               if (otp_client_s->curr_op == BT_OTP_OBJECT_READ) {
+               } else if (otp_client_s->curr_op == BT_OTP_OBJECT_READ) {
                        _bt_otp_client_notify_read_object_status(result,
                                                                NULL, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
+               } else  if (otp_client_s->curr_op == BT_OTP_OBJECT_SELECT) {
+                       _bt_otp_client_send_select_object_callback(result, otp_client_s);
+                       __bt_otp_reset_api_info(otp_client_s);
                }
        }
 }
@@ -1129,13 +1141,13 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                if (resp_code != OACP_RESPONSE) {
                        BT_INFO("Indication Response Failed : Wrong Response Code");
                        result = BLUETOOTH_ERROR_INTERNAL;
-                       goto oacp_fail;
+                       goto oacp_done;
                }
 
                if (result_code != OACP_SUCCESS) {
                        BT_INFO("Indication Response Fail [0x%x]", result_code);
                        result = BLUETOOTH_ERROR_INTERNAL;
-                       goto oacp_fail;
+                       goto oacp_done;
                }
 
                switch (req_opcode) {
@@ -1157,7 +1169,7 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                                BT_INFO("OTC Connection Failed %s(0x%08x)",
                                        _bt_convert_error_to_string(error_code), error_code);
                                result = error_code;
-                               goto oacp_fail;
+                               goto oacp_done;
                        }
                        break;
                case OACP_WRITE:
@@ -1167,11 +1179,11 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                        BT_INFO("Indication Failed : Wrong Req Opcode [0x%x], Reason [0x%x]",
                                                                        req_opcode, result_code);
                        result = BLUETOOTH_ERROR_INTERNAL;
-                       goto oacp_fail;
+                       goto oacp_done;
                        break;
                }
                return;
-oacp_fail:
+oacp_done:
                if (otp_client_s->curr_op == BT_OTP_OBJECT_READ) {
                        _bt_otp_client_notify_read_object_status(result, NULL, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
@@ -1183,7 +1195,7 @@ oacp_fail:
 
                /* Indication failed/timeout occured */
                if (result != BLUETOOTH_ERROR_NONE)
-                       goto olcp_fail;
+                       goto olcp_done;
 
                BT_INFO("Resp_code [0x%x], Req_opcode [0x%x], result_code [0x%x]",
                                                        resp_code, req_opcode, result_code);
@@ -1191,7 +1203,7 @@ oacp_fail:
                if (resp_code != OLCP_RESPONSE) {
                        BT_INFO("Indication Response Failed : Wrong Response Code");
                        result = BLUETOOTH_ERROR_INTERNAL;
-                       goto olcp_fail;
+                       goto olcp_done;
                }
 
                if (result_code != OLCP_SUCCESS) {
@@ -1213,7 +1225,7 @@ oacp_fail:
                                result = BLUETOOTH_ERROR_INTERNAL;
                                break;
                        }
-                       goto olcp_fail;
+                       goto olcp_done;
                }
 
                switch (req_opcode) {
@@ -1232,23 +1244,30 @@ oacp_fail:
                        if (error_code != BLUETOOTH_ERROR_NONE) {
                                BT_INFO("Read Charc Value Failed %s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
                                result = error_code;
-                               goto olcp_fail;
+                               goto olcp_done;
                        }
                        } break;
-               case OLCP_GOTO: /* TODO: */
+               case OLCP_GOTO:
+                               /* Update the object id & notify client app*/
+                               otp_client_s->object_id = select_obj_id;
+                               select_obj_id = 0;
+                               goto olcp_done;
                        break;
                default:
                        BT_INFO("Indication Response Failed : Wrong Req Opcode [0x%x], Reason [0x%x]",
                                                                                        req_opcode, result_code);
                        result = BLUETOOTH_ERROR_INTERNAL;
-                       goto olcp_fail;
+                       goto olcp_done;
                        break;
                }
                return;
-olcp_fail:
+olcp_done:
                if (otp_client_s->curr_op == BT_OTP_OBJECT_DISCOVERY) {
                        _bt_otp_send_discovery_callback(result, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
+               } else if (otp_client_s->curr_op == BT_OTP_OBJECT_SELECT) {
+                       _bt_otp_client_send_select_object_callback(result, otp_client_s);
+                       __bt_otp_reset_api_info(otp_client_s);
                }
        }
 }
@@ -1309,7 +1328,6 @@ int bt_otp_client_discover_all_objects(bt_otp_client_h otp_client,
                error_code = bluetooth_otp_write_characteristics_value(otp_client_s->otp_olcp_control_point, value, 1);
                if (error_code != BT_ERROR_NONE) {
                        BT_ERR("Failed to write control point : %s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
-                       error_code = BT_ERROR_OPERATION_FAILED;
                        __bt_otp_reset_api_info(otp_client_s);
                }
        }
@@ -1317,6 +1335,68 @@ int bt_otp_client_discover_all_objects(bt_otp_client_h otp_client,
        return error_code;
 }
 
+static void _bt_otp_client_send_select_object_callback(int result,
+                               bt_otp_client_s *otp_client_s)
+{
+       ((bt_otp_client_object_select_cb)otp_client_s->callback)(
+                               result, otp_client_s->remote_address,
+                               otp_client_s->object_id, otp_client_s->user_data);
+}
+
+int bt_otp_client_select_object(bt_otp_client_h otp_client, unsigned long long id,
+                               bt_otp_client_object_select_cb callback, void *user_data)
+{
+       int error_code;
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_OTP_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;
+       }
+
+       if (otp_client_s->object_id == id) {
+               BT_INFO("Object already selected");
+               return BLUETOOTH_ERROR_NONE;
+       }
+       if (otp_client_s->curr_op != BT_OTP_NO_OPERATION) {
+               BT_DBG("OTP client is busy");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       BT_DBG("OTP client select object [%llu] from Remote device [%s]", id, otp_client_s->remote_address);
+       otp_client_s->curr_op = BT_OTP_OBJECT_SELECT;
+       otp_client_s->callback = callback;
+       otp_client_s->user_data = user_data;
+
+       select_obj_id = id;
+
+       uint8_t value[7] = {0x00};
+       value[0] = OLCP_GOTO;
+       value[1] = select_obj_id & 0xFF;
+       value[2] = (select_obj_id >> 8) & 0xFF;
+       value[3] = (select_obj_id >> 16) & 0xFF;
+       value[4] = (select_obj_id >> 24) & 0xFF;
+       value[5] = (select_obj_id >> 32) & 0xFF;
+       value[6] = (select_obj_id >> 40) & 0xFF;
+
+       error_code = bluetooth_otp_write_characteristics_value(otp_client_s->otp_olcp_control_point,
+                                                                                               value, 7);
+       if (error_code != BT_ERROR_NONE) {
+               BT_ERR("Failed to write control point : %s(0x%08x)",
+                               _bt_convert_error_to_string(error_code), error_code);
+               __bt_otp_reset_api_info(otp_client_s);
+       }
+
+       return error_code;
+}
 
 static bool __bt_otc_connection_timeout_cb(gpointer user_data)
 {
@@ -1498,11 +1578,13 @@ void _bt_otc_connection_state_changed(int result, bluetooth_otc_info_t *otc_info
 object_metadata *_bt_otp_client_find_object(GSList *list, uint64_t id)
 {
        GSList *l;
+       object_metadata *info;
 
        for (l = list; l; l = g_slist_next(l)) {
+               info = l->data;
 
-               if (((object_metadata *)l->data)->id == id)
-                       return ((object_metadata *)l->data);
+               if (info && (info->id == id))
+                       return info;
        }
        return NULL;
 }
index 10ecf09fcc7f41aabcef3679d37d2f9157f189d6..53ea8320e5bf927c82e29687b58365353d312035 100644 (file)
@@ -1178,6 +1178,8 @@ tc_table_t tc_otp[] = {
                , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCONNECT},
        {"bt_otp_client_discover_all_objects"
                , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCOVER_ALL_OBJECTS},
+       {"bt_otp_client_select_object"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SELECT_OBJ},
        {"bt_otp_client_read_object_contents"
                , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_READ_OBJ_CONTENTS},
        {NULL                                   , 0x0000},
@@ -3269,6 +3271,19 @@ static void __bt_otp_client_object_discovery_cb(int result, const char *remote_a
                BT_ERR("Object discovery failed!");
 }
 
+static void __bt_otp_client_object_select_cb(int result, const char *remote_address,
+                       unsigned long long obj_id, void *user_data)
+{
+       TC_PRT("__bt_otp_client_object_select_cb");
+       TC_PRT("Result: %s", __bt_get_error_message(result));
+       TC_PRT("Remote addr [%s]", remote_address);
+
+       if (result == BT_ERROR_NONE)
+               TC_PRT("Object selected successfully! Current object[%llu]", obj_id);
+       else
+               BT_ERR("Object selection failed! Current object[%llu]", obj_id);
+}
+
 static void __bt_otp_client_read_object_complete_cb(int result, const char *remote_address,
                        char *file_path, void *user_data)
 {
@@ -4901,6 +4916,42 @@ int test_set_params(int test_id, char *param)
 
                        break;
                }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SELECT_OBJ: {
+                       if (param_index == 0) {
+                               g_test_param.param_count = 1;
+                               g_test_param.params = g_malloc0(sizeof(char *) *g_test_param.param_count);
+                               param_type = BT_UNIT_TEST_PARAM_TYPE_INT;
+                       }
+
+                       if (param_index > 0) {
+                               int len = strlen(param);
+                               g_test_param.params[param_index - 1] = g_malloc0(len + 1);
+                               /* Remove new line character */
+                               param[len - 1] = '\0';
+                               strncpy(g_test_param.params[param_index - 1], param, strlen(param));
+                       }
+
+                       if (param_index == g_test_param.param_count) {
+                               need_to_set_params = false;
+#ifdef ARCH64
+                               test_input_callback((void *)(uintptr_t)test_id);
+#else
+                               test_input_callback((void *)test_id);
+#endif
+                               param_index = 0;
+                               return 0;
+                       }
+
+                       switch (param_index) {
+                       case 0:
+                               TC_PRT("Input Value in uint64_t");
+                               break;
+                       }
+
+                       param_index++;
+
+                       break;
+               }
                default:
                        TC_PRT("There is no param to set\n");
                        need_to_set_params = false;
@@ -10303,6 +10354,22 @@ int test_input_callback(void *data)
                        }
                        break;
                }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SELECT_OBJ:       {
+                       if (otp_client) {
+                               unsigned long long id;
+                               if (g_test_param.param_count < 1) {
+                                               TC_PRT("Input parameters first");
+                                               break;
+                               }
+
+                               id = atoi(g_test_param.params[0]);
+                               TC_PRT("Object ID[%llu]", id);
+                               ret = bt_otp_client_select_object(otp_client, id,
+                                                       __bt_otp_client_object_select_cb, NULL);
+                               TC_PRT("returns %s\n", __bt_get_error_message(ret));
+                       }
+                       break;
+               }
                case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_READ_OBJ_CONTENTS:        {
                        if (otp_client) {
                                ret = bt_otp_client_read_object_contents(otp_client,
index 91729226ea4b8019acfdab0f2f049ed6e4a76799..e591e11812d0e9aeda9522e2994c1e60ee5c9440 100644 (file)
@@ -494,6 +494,7 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CONNECT,
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCONNECT,
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_DISCOVER_ALL_OBJECTS,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SELECT_OBJ,
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_READ_OBJ_CONTENTS,
 
        BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF,