summaryrefslogtreecommitdiff
path: root/src/bluetooth-otp.c
diff options
context:
space:
mode:
authorGowtham Anandha Babu <gowtham.ab@samsung.com>2017-05-24 13:53:15 +0530
committerGowtham Anandha Babu <gowtham.ab@samsung.com>2017-05-26 13:10:39 +0530
commit5cf2bc6d96baec8c23370f463076022f0ff17c9f (patch)
tree23dd9467a5330f8a05a2f3be28f79f6d18200caf /src/bluetooth-otp.c
parent2cccb83302b562de9c50aa1c4192ef07efc72c63 (diff)
downloadbluetooth-5cf2bc6d96baec8c23370f463076022f0ff17c9f.tar.gz
bluetooth-5cf2bc6d96baec8c23370f463076022f0ff17c9f.tar.bz2
bluetooth-5cf2bc6d96baec8c23370f463076022f0ff17c9f.zip
[OTP] Expose APIs for read object contents
Change-Id: I2011fc945b6f4e0ce859b34d8ea95a519d5526cc Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
Diffstat (limited to 'src/bluetooth-otp.c')
-rw-r--r--src/bluetooth-otp.c458
1 files changed, 431 insertions, 27 deletions
diff --git a/src/bluetooth-otp.c b/src/bluetooth-otp.c
index 020491e..3224664 100644
--- a/src/bluetooth-otp.c
+++ b/src/bluetooth-otp.c
@@ -82,13 +82,52 @@
#define OLCP_NO_OBJ 0x07
#define OLCP_OJECT_ID_NOT_FOUND 0x08
+/* OACP opcodes */
+#define OACP_CREATE 0x01
+#define OACP_DELETE 0x02
+#define OACP_CALC_CHECKSUM 0x03
+#define OACP_EXECUTE 0x04
+#define OACP_READ 0x05
+#define OACP_WRITE 0x06
+#define OACP_ABORT 0x07
+#define OACP_RESPONSE 0x60
+
+/* OACP error codes */
+#define OACP_SUCCESS 0x01
+#define OACP_OPCODE_NOT_SUPPORTED 0x02
+#define OACP_INVALID_PARAM 0x03
+#define OACP_INSUFFICIENT_RESOURCES 0x04
+#define OACP_INVALID_OBJ 0x05
+#define OACP_CHANNEL_UNAVAILABLE 0x06
+#define OACP_UNSUPPORTED_TYPE 0x07
+#define OACP_PROCEDURE_NOT_SUPPORTED 0x08
+#define OACP_OBJECT_LOCKED 0x09
+#define OACP_OPERATION_FAILED 0x0A
+
+/* Object Properties */
+#define OBJECT_DELETE 0x00000001
+#define OBJECT_EXECUTE 0x00000002
+#define OBJECT_READ 0x00000004
+#define OBJECT_WRITE 0x00000008
+#define OBJECT_APPEND 0x00000010
+#define OBJECT_TRUNCATE 0x00000020
+#define OBJECT_PATCH 0x00000040
+#define OBJECT_MARK 0x00000080
+
#define BT_OTP_CLIENT_BASE_DIR "/home/owner/media/otp-client/"
#define BT_FILE_PATH_MAX_LEN 262
#define BT_OTP_FEATURE_LENGTH 8
#define BT_ADDR_LENGTH 18
-#define IS_OACP_SUPPORTED(feature) feature & 0xffffffff00000000
-#define IS_OLCP_SUPPORTED(feature) feature & 0x00000000ffffffff
+#define BT_OTC_CONNECTION_MAX_TIMEOUT 30000 /* Timeout for OTC Connection in msec */
+
+#define BT_L2CAP_BUFFER_LEN 672
+
+#define BT_OTP_IS_OACP_SUPPORTED(feature) feature & 0xffffffff00000000
+#define BT_OTP_IS_OLCP_SUPPORTED(feature) feature & 0x00000000ffffffff
+#define BT_OTP_IS_OACP_READ_SUPPORTED(feature) feature & 0x0800000000000000
+
+#define BT_OTP_IS_READ_PERMITTED(props) props & OBJECT_READ
typedef struct {
char *name;
@@ -111,6 +150,9 @@ typedef struct {
const void *object_discovery_complete_cb;
void *discovery_user_data;
+ const void *object_read_complete_cb;
+ void *read_object_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 */
@@ -134,17 +176,31 @@ typedef struct {
bool multiple_obj_supp; /* Indicates whether remote server supports
* multiple-objects or not
*/
-
+ bool oacp_read_status; /* Indicate whether oacp read is completed or not */
GSList *object_list; /* List of server objects */
uint64_t object_id; /* ID of current object */
} bt_otp_client_s;
-GSList *otp_client_list;
+typedef struct {
+ uint32_t offset;
+ uint32_t length;
+ uint32_t size;
+ char *file_path;
+ FILE *fp;
+} bt_otp_client_read_op;
+
static bool is_otp_server_initialized = false;
-object_metadata *metadata;
+bt_otp_client_read_op *oacp_read_op = NULL;
+bool otc_connection_status = FALSE;
bt_otp_object_list_s *obj_list;
+object_metadata *metadata;
+GSList *otp_client_list;
+unsigned int timeout_id;
+guint id;
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);
int __bt_check_otp_server_init_status(void)
{
@@ -288,6 +344,7 @@ int bt_otp_client_set_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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
BT_CHECK_INPUT_PARAMETER(callback);
@@ -308,6 +365,7 @@ 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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
@@ -544,6 +602,7 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
BT_INFO("+");
BT_CHECK_LE_SUPPORT();
+ BT_CHECK_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(remote_address);
BT_CHECK_INPUT_PARAMETER(otp_client);
@@ -595,6 +654,7 @@ int bt_otp_client_create(const char *remote_address, bt_otp_client_h *otp_client
otp_client_s->oacp_cccd_enabled = FALSE;
otp_client_s->object_discovery = FALSE;
otp_client_s->multiple_obj_supp = FALSE;
+ otp_client_s->oacp_read_status = FALSE;
otp_client_list = g_slist_append(otp_client_list, otp_client_s);
*otp_client = (bt_otp_client_h)otp_client_s;
@@ -608,6 +668,7 @@ 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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
@@ -630,6 +691,7 @@ int bt_otp_client_connect(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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
@@ -654,6 +716,7 @@ int bt_otp_client_disconnect(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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
@@ -722,7 +785,7 @@ void _bt_otp_send_discovery_callback(int result, bt_otp_client_s *otp_client_s)
}
void _bt_otp_client_read_value_response(int result, char *char_path,
- char *value, int len)
+ char *value, int len)
{
bt_otp_client_s *otp_client_s = NULL;
char remote_address[BT_ADDR_LENGTH];
@@ -731,7 +794,7 @@ void _bt_otp_client_read_value_response(int result, char *char_path,
_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);
+ char_path, value, len);
if (result != BLUETOOTH_ERROR_NONE)
BT_INFO("Read failed for [%s]", char_path);
@@ -751,7 +814,7 @@ void _bt_otp_client_read_value_response(int result, char *char_path,
otp_client_s->otp_feature = feature;
BT_INFO("OTP Feature [%lld]", feature);
- if (IS_OACP_SUPPORTED(otp_client_s->otp_feature)
+ if (BT_OTP_IS_OACP_SUPPORTED(otp_client_s->otp_feature)
&& !otp_client_s->oacp_cccd_enabled
&& otp_client_s->otp_oacp_control_point) {
@@ -760,7 +823,7 @@ void _bt_otp_client_read_value_response(int result, char *char_path,
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)
+ if (BT_OTP_IS_OLCP_SUPPORTED(otp_client_s->otp_feature)
&& !otp_client_s->olcp_cccd_enabled
&& otp_client_s->otp_olcp_control_point) {
error_code = bluetooth_otp_enable_notification(otp_client_s->otp_olcp_control_point);
@@ -980,8 +1043,15 @@ void _bt_otp_client_write_value_response(int result, char *handle)
if (result != BLUETOOTH_ERROR_NONE) {
BT_DBG("OTP Write Failed");
- otp_client_s->object_discovery = FALSE;
- _bt_otp_send_discovery_callback(result, otp_client_s);
+ if (otp_client_s->object_discovery) {
+ _bt_otp_send_discovery_callback(result, otp_client_s);
+ otp_client_s->object_discovery = FALSE;
+ }
+ if (otp_client_s->oacp_read_status) {
+ _bt_otp_client_notify_read_object_status(result,
+ NULL, otp_client_s);
+ otp_client_s->oacp_read_status = FALSE;
+ }
}
}
@@ -999,14 +1069,16 @@ void _bt_otp_client_notification_enabled(int result, char *handle)
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);
+ 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);
+ 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;
}
@@ -1027,45 +1099,101 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
return;
if (!g_strcmp0(otp_client_s->otp_oacp_control_point, info->handle)) {
- /* TODO: Handle OACP Indication response */
- } else if (!g_strcmp0(otp_client_s->otp_olcp_control_point, info->handle)) {
uint8_t resp_code = info->data[0];
uint8_t req_opcode = info->data[1];
uint8_t result_code = info->data[2];
- if (result != BLUETOOTH_ERROR_NONE) {
- /* Indication failed/timeout occured */
- if (otp_client_s->object_discovery)
- _bt_otp_send_discovery_callback(result, otp_client_s);
+ BT_INFO("Resp_code [0x%x], Req_opcode [0x%x], result_code [0x%x]",
+ resp_code, req_opcode, result_code);
+
+ if (resp_code != OACP_RESPONSE) {
+ BT_INFO("Indication Response Failed : Wrong Response Code");
+ result = BLUETOOTH_ERROR_INTERNAL;
+ goto oacp_fail;
}
+ if (result_code != OACP_SUCCESS) {
+ BT_INFO("Indication Response Fail [0x%x]", result_code);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ goto oacp_fail;
+ }
+
+ switch (req_opcode) {
+ case OACP_CREATE:
+ case OACP_DELETE:
+ case OACP_CALC_CHECKSUM:
+ case OACP_EXECUTE:
+ break;
+ case OACP_READ:
+ BT_INFO("OACP_READ Indication Response received");
+ bluetooth_device_address_t addr_hex = { {0,} };
+ _bt_convert_address_to_hex(&addr_hex, otp_client_s->remote_address);
+ if (otc_connection_status) {
+ BT_INFO("OTC Connected already");
+ break;
+ }
+ error_code = bluetooth_otp_connect_otc(&addr_hex);
+ if (error_code != BLUETOOTH_ERROR_NONE) {
+ BT_INFO("OTC Connection Failed %s(0x%08x)",
+ _bt_convert_error_to_string(error_code), error_code);
+ result = error_code;
+ goto oacp_fail;
+ }
+ break;
+ case OACP_WRITE:
+ case OACP_ABORT:
+ break;
+ default:
+ BT_INFO("Indication Failed : Wrong Req Opcode [0x%x], Reason [0x%x]",
+ req_opcode, result_code);
+ result = BLUETOOTH_ERROR_INTERNAL;
+ goto oacp_fail;
+ break;
+ }
+ return;
+oacp_fail:
+ if (otp_client_s->oacp_read_status) {
+ _bt_otp_client_notify_read_object_status(result, NULL, otp_client_s);
+ otp_client_s->oacp_read_status = FALSE;
+ }
+ } else if (!g_strcmp0(otp_client_s->otp_olcp_control_point, info->handle)) {
+ uint8_t resp_code = info->data[0];
+ uint8_t req_opcode = info->data[1];
+ uint8_t result_code = info->data[2];
+
+ /* Indication failed/timeout occured */
+ if (result != BLUETOOTH_ERROR_NONE)
+ goto olcp_fail;
+
BT_INFO("Resp_code [0x%x], Req_opcode [0x%x], result_code [0x%x]",
- resp_code, req_opcode, result_code);
+ resp_code, req_opcode, result_code);
if (resp_code != OLCP_RESPONSE) {
- otp_client_s->object_discovery = FALSE;
BT_INFO("Indication Response Failed : Wrong Response Code");
- return;
+ result = BLUETOOTH_ERROR_INTERNAL;
+ goto olcp_fail;
}
if (result_code != OLCP_SUCCESS) {
- otp_client_s->object_discovery = FALSE;
switch (result_code) {
case OLCP_NO_OBJ:
BT_INFO("No Object Found on server");
+ result = BLUETOOTH_ERROR_INTERNAL;
break;
case OLCP_OUT_OF_BOUNDS:
- /* All object discovered, notify application via callback */
- _bt_otp_send_discovery_callback(BLUETOOTH_ERROR_NONE, otp_client_s);
+ /* All object discovered succesfully, notify application via callback */
+ result = BLUETOOTH_ERROR_NONE;
break;
case OLCP_OJECT_ID_NOT_FOUND:
BT_INFO("Object ID not found");
+ result = BLUETOOTH_ERROR_INTERNAL;
break;
default:
BT_INFO("Indication Response Fail [0x%x]", result_code);
+ result = BLUETOOTH_ERROR_INTERNAL;
break;
}
- return;
+ goto olcp_fail;
}
switch (req_opcode) {
@@ -1083,7 +1211,8 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
error_code = bluetooth_otp_read_characteristic_value(otp_client_s->otp_name_obj_path);
if (error_code != BLUETOOTH_ERROR_NONE) {
BT_INFO("Read Charc Value Failed %s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
- otp_client_s->object_discovery = FALSE;
+ result = error_code;
+ goto olcp_fail;
}
} break;
case OLCP_GOTO: /* TODO: */
@@ -1091,8 +1220,16 @@ void _bt_otp_client_indication(int result, bluetooth_otp_resp_info_t *info)
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;
break;
}
+ return;
+olcp_fail:
+ if (otp_client_s->object_discovery) {
+ _bt_otp_send_discovery_callback(result, otp_client_s);
+ otp_client_s->object_discovery = FALSE;
+ }
}
}
@@ -1103,6 +1240,7 @@ int bt_otp_client_discover_all_objects(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_OTP_SUPPORT();
BT_CHECK_INIT_STATUS();
BT_CHECK_INPUT_PARAMETER(otp_client_s);
@@ -1146,3 +1284,269 @@ int bt_otp_client_discover_all_objects(bt_otp_client_h otp_client,
fail:
return error_code;
}
+
+
+static bool __bt_otc_connection_timeout_cb(gpointer user_data)
+{
+ bluetooth_otc_info_t *otc_info = (bluetooth_otc_info_t *)user_data;
+ char *address = otc_info->address;
+ bluetooth_device_address_t addr_hex = { {0,} };
+
+ /* TODO: Write OACP Abort opcode, then disconnect */
+
+ BT_DBG("OTC Connection timer Expired [%s]", address);
+ _bt_convert_address_to_hex(&addr_hex, address);
+ bluetooth_otp_disconnect_otc(&addr_hex);
+
+ return FALSE;
+}
+
+static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
+ gpointer data)
+{
+ bluetooth_otc_info_t *otc_info = (bluetooth_otc_info_t *)data;
+ char *remote_addr = otc_info->address;
+ GIOStatus status = G_IO_STATUS_NORMAL;
+ GError *err = NULL;
+ char *buffer = NULL;
+ gsize len = 0;
+ int written;
+ int fd;
+
+ BT_DBG("");
+
+ fd = g_io_channel_unix_get_fd(chan);
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+ otc_connection_status = FALSE;
+ BT_ERR("OTC Client disconnected: %d", fd);
+ close(fd);
+ g_source_remove(id);
+ return FALSE;
+ }
+
+ buffer = g_malloc0(BT_L2CAP_BUFFER_LEN + 1);
+
+ status = g_io_channel_read_chars(chan, buffer,
+ BT_L2CAP_BUFFER_LEN,
+ &len, &err);
+ if (status != G_IO_STATUS_NORMAL) {
+ BT_ERR("IO Channel read is failed with %d", status);
+
+ g_free(buffer);
+ if (err) {
+ otc_connection_status = FALSE;
+ BT_ERR("IO Channel read error [%s]", err->message);
+ if (status == G_IO_STATUS_ERROR) {
+ BT_ERR("cond : %d", cond);
+ g_error_free(err);
+ close(fd);
+ g_source_remove(id);
+ return FALSE;
+ }
+ g_error_free(err);
+ }
+ return TRUE;
+ }
+
+ BT_DBG("Received data length %d, remote_addr = %s", len, remote_addr);
+
+ if (!oacp_read_op) {
+ char file_path[BT_FILE_PATH_MAX_LEN] = {0, };
+ bt_otp_client_s *otp_client_s = NULL;
+ object_metadata *object_info;
+ uint64_t obj_id;
+ FILE *fp = NULL;
+
+ otp_client_s = _bt_otp_client_find(remote_addr);
+ obj_id = otp_client_s->object_id;
+
+ 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;
+ }
+
+ snprintf(file_path, sizeof(file_path), "%s%s",
+ BT_OTP_CLIENT_BASE_DIR, object_info->name);
+ BT_DBG("file_path = [%s]", file_path);
+
+ fp = fopen(file_path, "w");
+ if (!fp) {
+ BT_DBG("fopen() failed : %s", strerror(errno));
+ return TRUE;
+ }
+
+ oacp_read_op = g_malloc0(sizeof(bt_otp_client_read_op));
+ oacp_read_op->offset = 0;
+ oacp_read_op->length = 0;
+ oacp_read_op->fp = fp;
+ oacp_read_op->size = object_info->curr_size;
+ oacp_read_op->file_path = g_strdup(file_path);
+ } else {
+ oacp_read_op->offset += (oacp_read_op->length - oacp_read_op->offset);
+ }
+
+ fseek(oacp_read_op->fp, oacp_read_op->offset, SEEK_SET);
+ written = fwrite(buffer, 1, len, oacp_read_op->fp);
+ oacp_read_op->length += len;
+ BT_DBG("written [%d], offset [%lu], length [%lu], size [%lu]",
+ written, oacp_read_op->offset,
+ oacp_read_op->length, oacp_read_op->size);
+ if (timeout_id > 0) {
+ g_source_remove(timeout_id);
+ timeout_id = g_timeout_add(BT_OTC_CONNECTION_MAX_TIMEOUT,
+ (GSourceFunc)__bt_otc_connection_timeout_cb, (gpointer)otc_info);
+ }
+
+ g_free(buffer);
+ return TRUE;
+}
+
+static void _bt_otp_client_notify_read_object_status(int result,
+ char *file_path, bt_otp_client_s *otp_client_s)
+{
+
+ ((bt_otp_client_read_object_complete_cb)otp_client_s->object_read_complete_cb)(
+ result, otp_client_s->remote_address,
+ file_path, otp_client_s->read_object_user_data);
+}
+
+void _bt_otc_connection_state_changed(int result, bluetooth_otc_info_t *otc_info)
+{
+ GIOChannel *data_io;
+ char *file_path = NULL;
+
+ 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);
+ /*
+ * Remove request in both connected/disconnected case.
+ * So that new request can proceed.
+ */
+ fclose(oacp_read_op->fp);
+ g_free(oacp_read_op->file_path);
+ g_free(oacp_read_op);
+ oacp_read_op = NULL;
+ }
+
+ if (otc_info->connected) {
+ BT_DBG("OTC Connected");
+ otc_connection_status = TRUE;
+
+ data_io = g_io_channel_unix_new(otc_info->fd);
+
+ 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,
+ 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);
+ } else {
+ BT_DBG("OTC Disconnected");
+ otc_connection_status = FALSE;
+ if (timeout_id > 0) {
+ 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->oacp_read_status) {
+ _bt_otp_client_notify_read_object_status(BLUETOOTH_ERROR_NONE,
+ file_path, otp_client_s);
+ otp_client_s->oacp_read_status = FALSE;
+ }
+ }
+}
+
+object_metadata *_bt_otp_client_find_object(GSList *list, uint64_t id)
+{
+ GSList *l;
+
+ for (l = list; l; l = g_slist_next(l)) {
+
+ if (((object_metadata *)l->data)->id == id)
+ return ((object_metadata *)l->data);
+ }
+ return NULL;
+}
+
+int bt_otp_client_read_object_contents(bt_otp_client_h otp_client,
+ bt_otp_client_read_object_complete_cb callback,
+ void *user_data)
+{
+ bt_otp_client_s *otp_client_s = (bt_otp_client_s *)otp_client;
+ object_metadata *object_info = NULL;
+ uint64_t obj_id;
+ int error_code;
+
+ 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;
+ }
+
+ obj_id = otp_client_s->object_id;
+
+ BT_DBG("OTP client Read objects Contents from Remote device [%s] for Object [%llu]",
+ otp_client_s->remote_address, obj_id);
+
+ 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 BT_ERROR_OPERATION_FAILED;
+ }
+
+ if (~BT_OTP_IS_OACP_READ_SUPPORTED(otp_client_s->otp_feature)) {
+ BT_INFO("OACP Read not supported");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ if (~BT_OTP_IS_READ_PERMITTED(object_info->props)) {
+ BT_INFO("Read not permitted");
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ otp_client_s->object_read_complete_cb = callback;
+ otp_client_s->read_object_user_data = user_data;
+ otp_client_s->oacp_read_status = TRUE;
+
+ uint32_t offset = 0;
+ uint32_t length = object_info->curr_size;
+
+ BT_INFO("Object ID [%llu],Offset [%lu], Length [%lu], curr_soze [%lu]",
+ obj_id, offset, length, object_info->curr_size);
+ uint8_t value[9] = {0x00};
+
+ value[0] = OACP_READ;
+ 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;
+
+ error_code = bluetooth_otp_write_characteristics_value(otp_client_s->otp_oacp_control_point,
+ value, 9);
+ 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);
+ otp_client_s->oacp_read_status = FALSE;
+ }
+
+ return error_code;
+}