[OTP] Expose Object Write API 27/134627/5
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Mon, 19 Jun 2017 13:30:09 +0000 (19:00 +0530)
committerGowtham Anandha Babu <gowtham.ab@samsung.com>
Tue, 20 Jun 2017 06:35:09 +0000 (12:05 +0530)
Change-Id: Ife975cdd71cd6021ed4cfa450c21891b10d6b321
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 c6e73f6cde61abe6f8fcdecd63d16656dd512687..1361ba68290f10074f5dda03b2e0d03353f27195 100644 (file)
@@ -4116,6 +4116,15 @@ int bt_otp_client_create_object(bt_otp_client_h otp_client,
                                                        const char *file_path,
                                                        bt_otp_client_object_create_cb callback,
                                                        void *user_data);
+/**
+ * @internal
+ * @brief OTP client API to write object contents on remote server
+ */
+int bt_otp_client_write_object(bt_otp_client_h otp_client,
+                                                       const char *file_path,
+                                                       int offset, int length, int mode,
+                                                       bt_otp_client_object_write_cb callback,
+                                                       void *user_data);
 /**
  * @}
  */
index 33193045ad04fe58c68a3a6454d7bbe95313e86d..64ffd47773b640993412438e045e2d0ebde8cb0c 100644 (file)
@@ -987,6 +987,14 @@ typedef void (*bt_otp_client_read_object_complete_cb)
 typedef void (*bt_otp_client_object_create_cb)
                (int result, const char *remote_address, unsigned long long obj_id, void *user_data);
 
+/**
+ * @internal
+ * @since_tizen 4.0
+ * @brief OTP Client profile object create callback
+ */
+typedef void (*bt_otp_client_object_write_cb)
+               (int result, const char *remote_address, unsigned int length, void *user_data);
+
 /**
  * @}
  */
index 26e0127fc394dfef602933abcd85d1ce755371e1..a3b30409d5e6e5df12ed74489b26771e5b94db71 100644 (file)
 #define BT_OTP_IS_OLCP_SUPPORTED(feature)      feature & 0x00000000ffffffff
 #define BT_OTP_IS_OACP_READ_SUPPORTED(feature) feature & 0x0800000000000000
 #define BT_OTP_IS_OACP_CREATE_SUPPORTED(feature)       feature & 0x8000000000000000
+#define BT_OTP_IS_OACP_WRITE_SUPPORTED(feature)        feature & 0x0400000000000000
 
 #define BT_OTP_IS_READ_PERMITTED(props)        props & OBJECT_READ
 
@@ -144,6 +145,7 @@ typedef enum {
        BT_OTP_OBJECT_READ,
        BT_OTP_OBJECT_SELECT,
        BT_OTP_OBJECT_CREATE,
+       BT_OTP_OBJECT_WRITE,
 } bt_otp_api_info_e;
 
 typedef struct {
@@ -207,13 +209,23 @@ typedef struct {
        char *filename;
        char *type_uuid;
        time_t first_created;
-       uint64_t id;
        uint32_t size;
 } bt_otp_client_create_op;
 
+typedef struct {
+       char *file_path;
+       time_t last_modified;
+       uint32_t size;
+       uint32_t offset;
+       uint32_t length;
+       uint8_t mode;
+       FILE *fp;
+} bt_otp_client_write_op;
+
 static bool is_otp_server_initialized = false;
 bt_otp_client_create_op *oacp_create_op = NULL;
 bt_otp_client_read_op *oacp_read_op = NULL;
+bt_otp_client_write_op *oacp_write_op = NULL;
 bool otc_connection_status = FALSE;
 bt_otp_object_list_s *obj_list;
 uint64_t select_obj_id = 0;
@@ -228,8 +240,10 @@ static void _bt_otp_client_notify_read_object_status(int result,
 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);
-static void _bt_otp_send_create_object_callback(int result,
+static void _bt_otp_client_send_create_object_callback(int result,
                                uint64_t id, bt_otp_client_s *otp_client_s);
+static void _bt_otp_client_send_write_object_callback(int result,
+                               unsigned int length, bt_otp_client_s *otp_client_s);
 
 int __bt_check_otp_server_init_status(void)
 {
@@ -574,8 +588,8 @@ static int __bt_update_otp_server_data(bluetooth_device_address_t *address, bt_o
 
                                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));
+                               BT_DBG("Other OTP Characteristic handle [%s]", characteristic.handle);
+                               BT_DBG("UUID [%s]", characteristic.uuid);
                        } /* Control Point characteristic */
                } /* Characteristic property get successful */
                bluetooth_gatt_free_char_property(&characteristic);
@@ -682,6 +696,7 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
                /* Update all serv & charc */
                error_code = __bt_update_otp_server_data(&addr_hex, otp_client_s);
                if (error_code != BLUETOOTH_ERROR_NONE) {
+                       __bt_otp_client_reset_server_data(otp_client_s);
                        g_free(otp_client_s);
                        return BT_ERROR_OPERATION_FAILED;
                }
@@ -689,10 +704,11 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
 
        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;
+               BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code),
+                                                                       error_code);
+               __bt_otp_client_reset_server_data(otp_client_s);
+               g_free(otp_client_s);
+               return BT_ERROR_OUT_OF_MEMORY;
        }
 
        otp_client_s->otp_olcp_control_point = NULL;
@@ -816,7 +832,7 @@ void _bt_otp_send_discovery_callback(int result, bt_otp_client_s *otp_client_s)
        }
        obj_list = g_malloc0(sizeof(bt_otp_object_list_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);
+       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; l = g_slist_next(l)) {
                metadata = l->data;
@@ -825,6 +841,7 @@ void _bt_otp_send_discovery_callback(int result, bt_otp_client_s *otp_client_s)
                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);
+               obj_list->data[k] = (otp_object_metadata_s *)g_malloc0(sizeof(otp_object_metadata_s));
                obj_list->data[k] = m_data;
                k++;
        }
@@ -843,15 +860,16 @@ void _bt_otp_client_read_value_response(int result, char *char_path,
 
        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);
-               goto read_fail;
-       }
 
        otp_client_s = _bt_otp_client_find(remote_address);
        if (otp_client_s == NULL)
                return;
 
+       if (result != BLUETOOTH_ERROR_NONE) {
+               BT_INFO("Read failed for [%s]", char_path);
+               goto read_fail;
+       }
+
        if (!g_strcmp0(otp_client_s->otp_feature_obj_path, char_path)) {
                        uint64_t feature =      (uint64_t)(value[0] & 0xFF) << 56       |
                                                                (uint64_t)(value[1] & 0xFF) << 48       |
@@ -1108,7 +1126,7 @@ read_fail:
                        }
                }
                if (otp_client_s->curr_op == BT_OTP_OBJECT_CREATE) {
-                       _bt_otp_send_create_object_callback(result,
+                       _bt_otp_client_send_create_object_callback(result,
                                        otp_client_s->object_id, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
                }
@@ -1191,7 +1209,11 @@ fail:
                __bt_otp_reset_api_info(otp_client_s);
                break;
        case BT_OTP_OBJECT_CREATE:
-               _bt_otp_send_create_object_callback(result, 0, otp_client_s);
+               _bt_otp_client_send_create_object_callback(result, 0, otp_client_s);
+               __bt_otp_reset_api_info(otp_client_s);
+               break;
+       case BT_OTP_OBJECT_WRITE:
+               _bt_otp_client_send_write_object_callback(result, 0, otp_client_s);
                __bt_otp_reset_api_info(otp_client_s);
                break;
        case BT_OTP_NO_OPERATION:
@@ -1266,9 +1288,12 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                case OACP_CREATE:
                        BT_INFO("OACP_CREATE Indication received");
                        if ((otp_client_s->curr_op == BT_OTP_OBJECT_CREATE) && oacp_create_op) {
-                               int len = strlen(oacp_create_op->filename);
-                               uint8_t *value = (uint8_t *)malloc(len * sizeof(uint8_t));
+                               int len;
+                               uint8_t value[BT_FILE_PATH_MAX_LEN];
+
+                               len = strlen(oacp_create_op->filename) + 1;
                                memcpy(value, oacp_create_op->filename, len);
+
                                error_code = bluetooth_otp_write_characteristics_value(otp_client_s->otp_name_obj_path,
                                                                                                                value, len);
                                if (error_code != BT_ERROR_NONE) {
@@ -1284,7 +1309,8 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                case OACP_EXECUTE:
                        break;
                case OACP_READ:
-                       BT_INFO("OACP_READ Indication Response received");
+               case OACP_WRITE:
+                       BT_INFO("OACP Read/Write Indication received");
                         bluetooth_device_address_t addr_hex = { {0,} };
                        _bt_convert_address_to_hex(&addr_hex, otp_client_s->remote_address);
                        if (otc_connection_status) {
@@ -1299,7 +1325,6 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
                                goto oacp_done;
                        }
                        break;
-               case OACP_WRITE:
                case OACP_ABORT:
                        break;
                default:
@@ -1315,7 +1340,10 @@ oacp_done:
                        _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_CREATE) {
-                       _bt_otp_send_create_object_callback(result, 0, otp_client_s);
+                       _bt_otp_client_send_create_object_callback(result, 0, otp_client_s);
+                       __bt_otp_reset_api_info(otp_client_s);
+               } else  if (otp_client_s->curr_op == BT_OTP_OBJECT_WRITE) {
+                       _bt_otp_client_send_write_object_callback(result, 0, otp_client_s);
                        __bt_otp_reset_api_info(otp_client_s);
                }
        } else if (!g_strcmp0(otp_client_s->otp_olcp_control_point, info->handle)) {
@@ -1494,6 +1522,7 @@ int bt_otp_client_select_object(bt_otp_client_h otp_client, unsigned long long i
 
        if (otp_client_s->object_id == id) {
                BT_INFO("Object already selected");
+               _bt_otp_client_send_select_object_callback(BLUETOOTH_ERROR_NONE, otp_client_s);
                return BLUETOOTH_ERROR_NONE;
        }
        if (otp_client_s->curr_op != BT_OTP_NO_OPERATION) {
@@ -1605,7 +1634,7 @@ static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
                object_info = _bt_otp_client_find_object(otp_client_s->object_list, obj_id);
                if (!object_info) {
                        BT_INFO("Object Not Found [%llu]", obj_id);
-                       return TRUE;
+                       goto fail;
                }
 
                snprintf(file_path, sizeof(file_path), "%s%s",
@@ -1615,7 +1644,7 @@ static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
                fp = fopen(file_path, "w");
                if (!fp) {
                        BT_DBG("fopen() failed : %s", strerror(errno));
-                       return TRUE;
+                       goto fail;
                }
 
                oacp_read_op = g_malloc0(sizeof(bt_otp_client_read_op));
@@ -1638,7 +1667,7 @@ static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
                timeout_id = g_timeout_add(BT_OTC_CONNECTION_MAX_TIMEOUT,
                        (GSourceFunc)__bt_otc_connection_timeout_cb, (gpointer)otc_info);
        }
-
+fail:
        g_free(buffer);
        return TRUE;
 }
@@ -1652,16 +1681,107 @@ static void _bt_otp_client_notify_read_object_status(int result,
                                file_path, otp_client_s->user_data);
 }
 
+static void _bt_otp_client_write_on_fd(bluetooth_otc_info_t *otc_info)
+{
+       char buf[BT_L2CAP_BUFFER_LEN];
+       int written, read, len;
+       FILE *fp = NULL;
+       int length;
+       unsigned int byteswritten = 0;
+       int fd = otc_info->fd;
+       char *address = otc_info->address;
+       int result = BLUETOOTH_ERROR_NONE;
+       bt_otp_client_s *otp_client_s = NULL;
+       bluetooth_device_address_t addr_hex = { {0,} };
+       struct tm fc_tm;
+       uint8_t value[7];
+
+       if (!oacp_write_op) {
+               result = BLUETOOTH_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       BT_DBG("file_path = [%s]", oacp_write_op->file_path);
+
+       fp = fopen(oacp_write_op->file_path, "r");
+       if (!fp) {
+               BT_DBG("fopen() failed : %s", strerror(errno));
+               result = BLUETOOTH_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       if (oacp_write_op->offset > 0)
+               fseek(fp, oacp_write_op->offset, SEEK_SET);
+
+       BT_DBG("length [%d]", oacp_write_op->length);
+       length = oacp_write_op->length;
+
+       while (length > 0) {
+               if (length < BT_L2CAP_BUFFER_LEN)
+                       len = length;
+               else
+                       len = BT_L2CAP_BUFFER_LEN;
+
+               read = fread(buf, 1, len, fp);
+               written = write(fd, buf, len);
+
+               if (written < 0) {
+                       result = BLUETOOTH_ERROR_INTERNAL;
+                       goto fail;
+               }
+
+               length -= written;
+               byteswritten += written;
+
+               BT_DBG("read [%d], written [%d], rem_len [%d]",
+                                               read, written, length);
+       }
+
+fail:
+       if (fp)
+               fclose(fp);
+
+       /* Disconnect and notify application */
+       _bt_convert_address_to_hex(&addr_hex, address);
+       bluetooth_otp_disconnect_otc(&addr_hex);
+
+       otp_client_s = _bt_otp_client_find(address);
+
+       if (result == BLUETOOTH_ERROR_NONE) {
+               /* Write Last-modified */
+               memset(value, 0, 7);
+               localtime_r(&(oacp_write_op->last_modified), &fc_tm);
+
+               value[1] = ((fc_tm.tm_year+1900) >> 8) & 0xFF;
+               value[0] = (fc_tm.tm_year+1900) & 0xFF;
+               value[2] = (fc_tm.tm_mon+1) & 0xFF;
+               value[3] = fc_tm.tm_mday & 0xFF;
+               value[4] = fc_tm.tm_hour & 0xFF;
+               value[5] = fc_tm.tm_min & 0xFF;
+               value[6] = fc_tm.tm_sec & 0xFF;
+               result = bluetooth_otp_write_characteristics_value(otp_client_s->otp_last_modified_obj_path,
+                                                                                                       value, 7);
+       }
+
+       _bt_otp_client_send_write_object_callback(result,
+                                                                       byteswritten, otp_client_s);
+       __bt_otp_reset_api_info(otp_client_s);
+}
+
 void _bt_otc_connection_state_changed(int result, bluetooth_otc_info_t *otc_info)
 {
        GIOChannel *data_io;
-       char *file_path = NULL;
+       char file_path[BT_FILE_PATH_MAX_LEN];
+       bt_otp_client_s *otp_client_s = NULL;
+
+       otp_client_s = _bt_otp_client_find(otc_info->address);
 
        BT_DBG("OTC Channel status [%d], fd [%d]", otc_info->connected, otc_info->fd);
 
        if (oacp_read_op) {
                if (!otc_info->connected)
-                       file_path = g_strdup(oacp_read_op->file_path);
+                       memcpy(file_path, oacp_read_op->file_path,
+                                               strlen(oacp_read_op->file_path) + 1);
                /*
                 * Remove request in both connected/disconnected case.
                 * So that new request can proceed.
@@ -1681,12 +1801,16 @@ void _bt_otc_connection_state_changed(int result, bluetooth_otc_info_t *otc_info
                g_io_channel_set_encoding(data_io, NULL, NULL);
                g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
 
-               id = g_io_add_watch(data_io,
+               if (otp_client_s->curr_op == BT_OTP_OBJECT_WRITE) {
+                       _bt_otp_client_write_on_fd(otc_info);
+               } else if (otp_client_s->curr_op == BT_OTP_OBJECT_READ) {
+                       id = g_io_add_watch(data_io,
                                G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                __client_data_received_cb, (gpointer)otc_info);
 
-               timeout_id = g_timeout_add(BT_OTC_CONNECTION_MAX_TIMEOUT,
-                       (GSourceFunc)__bt_otc_connection_timeout_cb, (gpointer)otc_info);
+                       timeout_id = g_timeout_add(BT_OTC_CONNECTION_MAX_TIMEOUT,
+                               (GSourceFunc)__bt_otc_connection_timeout_cb, (gpointer)otc_info);
+               }
        } else {
                BT_DBG("OTC Disconnected");
                otc_connection_status = FALSE;
@@ -1694,8 +1818,6 @@ void _bt_otc_connection_state_changed(int result, bluetooth_otc_info_t *otc_info
                        g_source_remove(timeout_id);
                        timeout_id = 0;
                }
-               bt_otp_client_s *otp_client_s = NULL;
-               otp_client_s = _bt_otp_client_find(otc_info->address);
 
                if (otp_client_s && (otp_client_s->curr_op == BT_OTP_OBJECT_READ)) {
                        _bt_otp_client_notify_read_object_status(BLUETOOTH_ERROR_NONE,
@@ -1799,7 +1921,7 @@ int bt_otp_client_read_object_contents(bt_otp_client_h otp_client,
        return error_code;
 }
 
-static void _bt_otp_send_create_object_callback(int result,
+static void _bt_otp_client_send_create_object_callback(int result,
                                uint64_t id, bt_otp_client_s *otp_client_s)
 {
 
@@ -1850,10 +1972,6 @@ int bt_otp_client_create_object(bt_otp_client_h otp_client,
                return BT_ERROR_OPERATION_FAILED;
        }
 
-       otp_client_s->callback = callback;
-       otp_client_s->user_data = user_data;
-       otp_client_s->curr_op = BT_OTP_OBJECT_CREATE;
-
        BT_DBG("OTP client create object [%s] in Remote device [%s]",
                                                        file_path, otp_client_s->remote_address);
 
@@ -1863,6 +1981,10 @@ int bt_otp_client_create_object(bt_otp_client_h otp_client,
                return BLUETOOTH_ERROR_INTERNAL;
        }
 
+       otp_client_s->callback = callback;
+       otp_client_s->user_data = user_data;
+       otp_client_s->curr_op = BT_OTP_OBJECT_CREATE;
+
        size = (uint32_t)st.st_size;
        last_token = strrchr(file_path, '/');
        file_name = last_token + 1;
@@ -1901,3 +2023,110 @@ int bt_otp_client_create_object(bt_otp_client_h otp_client,
        g_free(type_uuid);
        return error_code;
 }
+
+static void _bt_otp_client_send_write_object_callback(int result,
+                                       unsigned int length, bt_otp_client_s *otp_client_s)
+{
+       ((bt_otp_client_object_write_cb)otp_client_s->callback)(
+                               result, otp_client_s->remote_address,
+                               length, otp_client_s->user_data);
+
+       if (oacp_write_op) {
+               g_free(oacp_write_op->file_path);
+               g_free(oacp_write_op);
+               oacp_write_op = NULL;
+       }
+}
+
+int bt_otp_client_write_object(bt_otp_client_h otp_client,
+                                                       const char *file_path,
+                                                       int offset, int length, int mode,
+                                                       bt_otp_client_object_write_cb callback,
+                                                       void *user_data)
+{
+       int error_code;
+       bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+       struct stat st;
+       uint32_t size;
+       time_t curr_time;
+
+       BT_CHECK_LE_SUPPORT();
+       BT_CHECK_INIT_STATUS();
+       BT_CHECK_INPUT_PARAMETER(otp_client_s);
+       BT_CHECK_INPUT_PARAMETER(file_path);
+
+       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->curr_op != BT_OTP_NO_OPERATION) {
+               BT_DBG("OTP Client is busy");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       if (~BT_OTP_IS_OACP_WRITE_SUPPORTED(otp_client_s->otp_feature)) {
+               BT_INFO("OACP Write not supported");
+               return BT_ERROR_OPERATION_FAILED;
+       }
+
+       BT_DBG("OTP client wirte object [%s] in Remote device [%s]",
+                                               file_path, otp_client_s->remote_address);
+
+       /* Get file_name & size from file_path */
+       if (stat(file_path, &st) == -1) {
+               BT_INFO("stat failed: %s (%d)\n", strerror(errno), errno);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       size = (uint32_t)st.st_size;
+
+       BT_INFO("Filepath [%s], Size[%llu]",
+                                                       file_path, size);
+       BT_INFO("offset[%llu], length[%llu], mode[%u]",
+                                                               offset, length, mode);
+
+       oacp_write_op = g_malloc0(sizeof(bt_otp_client_write_op));
+       oacp_write_op->size = size;
+       oacp_write_op->file_path = g_strdup(file_path);
+       oacp_write_op->offset = offset;
+       oacp_write_op->length = length;
+       oacp_write_op->mode = mode;
+
+       time(&curr_time);
+       oacp_write_op->last_modified = curr_time;
+
+       if (offset < 0 && (offset > size || (length - offset) > size)) {
+               /* Invalid param */
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       otp_client_s->callback = callback;
+       otp_client_s->user_data = user_data;
+       otp_client_s->curr_op = BT_OTP_OBJECT_WRITE;
+
+       uint8_t value[10] = {0x00};
+       value[0] = OACP_WRITE;
+       value[1] = offset & 0xFF;
+       value[2] = (offset >> 8) & 0xFF;
+       value[3] = (offset >> 16) & 0xFF;
+       value[4] = (offset >> 24) & 0xFF;
+       value[5] = length & 0xFF;
+       value[6] = (length >> 8) & 0xFF;
+       value[7] = (length >> 16) & 0xFF;
+       value[8] = (length >> 24) & 0xFF;
+       value[9] = mode & 0xFF;
+
+       error_code = bluetooth_otp_write_characteristics_value(otp_client_s->otp_oacp_control_point,
+                                                                                               value, 10);
+       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;
+}
\ No newline at end of file
index 9ff394c46ce40dc922d369986a4791632fa2cc85..2eabe3fb96d2f48d8e55e5a8b0e3c6a7700c2b8e 100644 (file)
@@ -1184,6 +1184,8 @@ tc_table_t tc_otp[] = {
                , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_READ_OBJ_CONTENTS},
        {"bt_otp_client_create_object"
                , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CREATE_OBJ},
+       {"bt_otp_client_write_object"
+               , BT_UNIT_TEST_FUNCTION_OTP_CLIENT_WRITE_OBJ},
        {NULL                                   , 0x0000},
 };
 
@@ -3304,6 +3306,15 @@ static void __bt_otp_client_object_create_cb(int result, const char *remote_addr
                BT_ERR("Object creation failed!");
 }
 
+static void __bt_otp_client_object_write_cb(int result, const char *remote_address,
+                       unsigned int length, void *user_data)
+{
+       if (result == BT_ERROR_NONE)
+               TC_PRT("Object write success!, [%u] bytes written", length);
+       else
+               BT_ERR("Object write failed!, [%u] bytes written", length);
+}
+
 static void __bt_initialize_all(void)
 {
        int ret;
@@ -4998,6 +5009,51 @@ int test_set_params(int test_id, char *param)
 
                        break;
                }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_WRITE_OBJ: {
+                       if (param_index == 0) {
+                               g_test_param.param_count = 4;
+                               g_test_param.params = g_malloc0(sizeof(char *) *g_test_param.param_count);
+                       }
+
+                       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 file path");
+                               break;
+                       case 1:
+                               TC_PRT("Input offset");
+                               break;
+                       case 2:
+                               TC_PRT("Input Length");
+                               break;
+                       case 3:
+                               TC_PRT("Input mode");
+                               break;
+                       }
+
+                       param_index++;
+
+                       break;
+               }
                default:
                        TC_PRT("There is no param to set\n");
                        need_to_set_params = false;
@@ -10408,7 +10464,7 @@ int test_input_callback(void *data)
                                                break;
                                }
 
-                               id = atoi(g_test_param.params[0]);
+                               id = (unsigned long long)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);
@@ -10445,6 +10501,34 @@ int test_input_callback(void *data)
                        __bt_free_test_param(&g_test_param);
                        break;
                }
+               case BT_UNIT_TEST_FUNCTION_OTP_CLIENT_WRITE_OBJ: {
+                       char *file_path = NULL;
+                       int offset, length, mode;
+
+                       if (g_test_param.param_count < 4) {
+                                       TC_PRT("Input parameters first");
+                                       break;
+                       }
+
+                       file_path = g_test_param.params[0];
+                       TC_PRT("%s", file_path);
+
+                       offset = strtoul(g_test_param.params[1], NULL, 10);
+                       length = strtoul(g_test_param.params[2], NULL, 10);
+                       mode = strtoul(g_test_param.params[3], NULL, 10);
+
+                       if (otp_client) {
+                               ret = bt_otp_client_write_object(otp_client,
+                                               file_path, offset, length, mode,
+                                               __bt_otp_client_object_write_cb, NULL);
+                               if (ret < BT_ERROR_NONE)
+                                       TC_PRT("failed with [0x%04x]", ret);
+                               else if (ret == BT_ERROR_NONE)
+                                       TC_PRT("Success");
+                       }
+                       __bt_free_test_param(&g_test_param);
+                       break;
+               }
                case BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS:
                        need_to_set_params = true;
                        TC_PRT("Select the function again");
index 4f09eba477b970f858ad3cf5fe8b16db59c84933..7f1692dd9a007adb6239bd796abfac764aaa09f1 100644 (file)
@@ -497,6 +497,7 @@ typedef enum {
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_SELECT_OBJ,
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_READ_OBJ_CONTENTS,
        BT_UNIT_TEST_FUNCTION_OTP_CLIENT_CREATE_OBJ,
+       BT_UNIT_TEST_FUNCTION_OTP_CLIENT_WRITE_OBJ,
 
        BT_UNIT_TEST_FUNCTION_ACTIVATE_FLAG_TO_SET_PARAMETERS = 0XFF,
 } bt_unit_test_function_e;