[Bluetooth][OTP] Add object browsing support 34/128834/3
authorGowtham Anandha Babu <gowtham.ab@samsung.com>
Thu, 11 May 2017 13:43:39 +0000 (19:13 +0530)
committerGowtham Anandha Babu <gowtham.ab@samsung.com>
Wed, 17 May 2017 10:17:24 +0000 (15:47 +0530)
Client side changes:
1) Exposed characterstics_write_value BT-API
2) Send "GattValueChanged" indication to otp-application

Server side changes:
1) Change implementation to support both single and
   multiple object(s).

Change-Id: I9fd250505b739b858f26ee7618737e058bc95a8d
Signed-off-by: Gowtham Anandha Babu <gowtham.ab@samsung.com>
bt-api/bt-common.c
bt-api/bt-event-handler.c
bt-api/bt-otp.c
bt-otp/bt-otpserver.c
bt-service/bt-request-handler.c
bt-service/bt-service-event-receiver.c
bt-service/bt-service-event-sender.c
bt-service/bt-service-otp.c
bt-service/include/bt-service-otp.h
include/bluetooth-api.h
include/bt-internal-types.h

index 1ad2171..363f5a2 100644 (file)
@@ -604,6 +604,7 @@ const char *_bt_convert_service_function_to_string(int function)
                {BT_TDS_ACTIVATE_CONTROL_POINT, "BT_TDS_ACTIVATE_CONTROL_POINT"},
                {BT_OTP_READ_VALUE, "BT_OTP_READ_VALUE"},
                {BT_OTP_ENABLE_NOTIFICATION, "BT_OTP_ENABLE_NOTIFICATION"},
+               {BT_OTP_WRITE_VALUE, "BT_OTP_WRITE_VALUE"},
                {-1, ""},
        };
 
index 991094b..67ead44 100644 (file)
@@ -3104,6 +3104,47 @@ static void __bt_otp_event_filter(GDBusConnection *connection,
                _bt_common_event_cb(BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED,
                                result, handle,
                                event_info->cb, event_info->user_data);
+       } else if (strcasecmp(signal_name, BT_OTP_WRITE_CHAR_VAL) == 0) {
+               BT_DBG("OTP Control point Activation result");
+               char *handle = NULL;
+
+               /* Extract data from DBUS params */
+               g_variant_get(parameters, "(i&s)", &result, &handle);
+               BT_DBG("Handle [%s]", handle);
+               BT_DBG("Result  [%d]", result);
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL,
+                               result, handle,
+                               event_info->cb, event_info->user_data);
+       } else if (strcasecmp(signal_name, BT_OTP_INDICATION) == 0) {
+               BT_DBG("OTP Control point Indication Response");
+               bluetooth_otp_resp_info_t *ind_res = NULL;
+               char *buffer = NULL;
+               GVariant *byte_var = NULL;
+               char *handle = NULL;
+
+               g_variant_get(parameters, "(i&s@ay)", &result, &handle, &byte_var);
+
+               ind_res = g_malloc0(sizeof(bluetooth_otp_resp_info_t));
+               ind_res->data_length = g_variant_get_size(byte_var);
+               buffer = (char *)g_variant_get_data(byte_var);
+               ind_res->data = g_memdup(buffer, ind_res->data_length);
+               ind_res->handle = g_strdup(handle);
+
+               _bt_common_event_cb(BLUETOOTH_EVENT_OTP_INDICATION,
+                               result,  ind_res,
+                               event_info->cb, event_info->user_data);
+
+               if (ind_res->handle) {
+                       g_free(ind_res->handle);
+               }
+
+               if (ind_res->data) {
+                       g_free(ind_res->data);
+                       g_free(ind_res);
+               }
+               if (byte_var)
+                       g_variant_unref(byte_var);
        }
 
        BT_DBG("-");
index 23eb5eb..1d0a86c 100644 (file)
@@ -152,4 +152,52 @@ BT_EXPORT_API int bluetooth_otp_enable_notification(const char *handle)
 
        BT_DBG("-");
        return result;
-}
\ No newline at end of file
+}
+
+BT_EXPORT_API int bluetooth_otp_write_characteristics_value(const char *handle,
+                                                       unsigned char *buf, int length)
+{
+       char *path;
+       int path_len = 0;
+       bt_user_info_t *user_info;
+       int result = BLUETOOTH_ERROR_INTERNAL;
+       bluetooth_otp_charc_data_t data;
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(handle, return);
+       BT_CHECK_PARAMETER(buf, return);
+       BT_CHECK_ENABLED_LE(return);
+
+       user_info = _bt_get_user_data(BT_COMMON);
+       retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_INIT_PARAMS();
+       BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       memset(&data, 0x00, sizeof(bluetooth_otp_charc_data_t));
+
+       data.length = length;
+       if (length > 0)
+               memcpy(data.data, buf, length);
+
+       path = g_strdup(handle);
+       path_len = _bluetooth_handle_get_len(path);
+
+       /*Fill parameters*/
+       g_array_append_vals(in_param1, path, path_len);
+
+       g_array_append_vals(in_param2, &data, sizeof(bluetooth_otp_charc_data_t));
+
+       int i;
+       for (i = 0; i < length; i++)
+               BT_INFO("Value[%d] = %u", i, buf[i]);
+       result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_WRITE_VALUE,
+                       in_param1, in_param2, in_param3, in_param4,
+                       user_info->cb, user_info->user_data);
+
+       BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
+
+       g_free(path);
+       BT_DBG("-");
+       return result;
+}
index 3eff442..0b7870c 100644 (file)
@@ -95,6 +95,7 @@ static guint obj_curr_index;
 static int adv_handle = 0;
 static gboolean OLCP_indicate = FALSE;
 char *directory = NULL;
+gboolean mutiple_obj_support = false;
 
 static const gchar otp_introspection_xml[] =
 "<node name='/'>"
@@ -111,6 +112,7 @@ static const gchar otp_introspection_xml[] =
 
 void _bt_otp_deinit_event_receiver(void);
 void _bt_otp_unregister_interface(void);
+void update_obj_metadata_charc_value(struct object_metadata *object);
 
 static void delete_all_objects(void)
 {
@@ -347,14 +349,17 @@ int _bt_otp_prepare_ots(void)
        if (ret != BLUETOOTH_ERROR_NONE)
                goto fail;
 
-       /* Characteristic Object ID */
-       props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
-       perms = BLUETOOTH_GATT_PERMISSION_READ;
-       char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_ID_UUID);
-       ret = add_new_characteristic(char_uuid, perms, props,
-                                       &otp_object_id_obj_path);
-       if (ret != BLUETOOTH_ERROR_NONE)
-               goto fail;
+       /* Object ID is mandatory for mutiple object server */
+       if (mutiple_obj_support) {
+               /* Characteristic Object ID */
+               props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
+               perms = BLUETOOTH_GATT_PERMISSION_READ;
+               char_uuid = _otp_convert_uuid_to_uuid128(OTP_OBJECT_ID_UUID);
+               ret = add_new_characteristic(char_uuid, perms, props,
+                                               &otp_object_id_obj_path);
+               if (ret != BLUETOOTH_ERROR_NONE)
+                       goto fail;
+       }
 
        /* Characteristic Object Properties */
        props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_READ;
@@ -386,25 +391,30 @@ int _bt_otp_prepare_ots(void)
                goto fail;
        }
 
-       /* Characteristic OLCP */
-       props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
-               BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
-       perms = BLUETOOTH_GATT_PERMISSION_WRITE;
-       char_uuid = _otp_convert_uuid_to_uuid128(OTP_OLCP_UUID);
-       ret = add_new_characteristic(char_uuid, perms, props,
-                                               &otp_olcp_obj_path);
-       if (ret != BLUETOOTH_ERROR_NONE)
-               goto fail;
+       /* OLCP Characteristics is not required
+        * for single object server
+        */
+       if (mutiple_obj_support) {
+               /* Characteristic OLCP */
+               props = BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_WRITE |
+                       BLUETOOTH_GATT_CHARACTERISTIC_PROPERTY_INDICATE;
+               perms = BLUETOOTH_GATT_PERMISSION_WRITE;
+               char_uuid = _otp_convert_uuid_to_uuid128(OTP_OLCP_UUID);
+               ret = add_new_characteristic(char_uuid, perms, props,
+                                                       &otp_olcp_obj_path);
+               if (ret != BLUETOOTH_ERROR_NONE)
+                       goto fail;
 
-       /* CCCD for OLCP */
-       desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
-       perms = BLUETOOTH_GATT_PERMISSION_READ |
-               BLUETOOTH_GATT_PERMISSION_WRITE;
-       ret = bluetooth_gatt_add_descriptor(otp_olcp_obj_path, desc_uuid,
-                                               perms, &otp_olcp_desc_obj_path);
-       if (ret != BLUETOOTH_ERROR_NONE) {
-               BT_ERR("Failed to add new char descriptor %d", ret);
-               goto fail;
+               /* CCCD for OLCP */
+               desc_uuid = _otp_convert_uuid_to_uuid128(OTP_CP_CCC_DESC_UUID);
+               perms = BLUETOOTH_GATT_PERMISSION_READ |
+                       BLUETOOTH_GATT_PERMISSION_WRITE;
+               ret = bluetooth_gatt_add_descriptor(otp_olcp_obj_path, desc_uuid,
+                                                       perms, &otp_olcp_desc_obj_path);
+               if (ret != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("Failed to add new char descriptor %d", ret);
+                       goto fail;
+               }
        }
 
        /* Register service */
@@ -494,12 +504,17 @@ static void _bt_otp_method(GDBusConnection *connection,
                        list = g_slist_append(list, (gpointer) filename);
                }
 
+               g_dir_close(dir);
+
                if (!list) {
                        BT_DBG("No object found in given directory");
                        status = BLUETOOTH_ERROR_NO_OBJECTS_FOUND;
                        goto fail;
                }
 
+               if (g_slist_length(list) > 1)
+                       mutiple_obj_support = true;
+
                for (l = list; l != NULL; l = l->next) {
                        if (!l->data) continue;
                        snprintf(absolute_path, sizeof(absolute_path), "%s%s", directory,
@@ -530,8 +545,6 @@ static void _bt_otp_method(GDBusConnection *connection,
                        object_id++;
                }
 
-               g_dir_close(dir);
-
                BT_DBG("preparing");
                if (_bt_otp_prepare_ots() != BLUETOOTH_ERROR_NONE) {
                        BT_ERR("Fail to prepare OTP Proxy");
@@ -539,6 +552,15 @@ static void _bt_otp_method(GDBusConnection *connection,
                        goto fail;
                }
 
+               /* If single object is supported, make that as
+                * selected object and update the metadata for the same.
+                */
+               if (!mutiple_obj_support) {
+                       BT_INFO("Server supports single object");
+                       selected_object = (struct object_metadata *) g_slist_nth_data(otp_object_list, 0);
+                       update_obj_metadata_charc_value(selected_object);
+               }
+
                BT_DBG("advertsing");
                if (_bt_otp_set_advertising_data() != BLUETOOTH_ERROR_NONE) {
                        BT_ERR("Fail to set advertising data");
@@ -711,8 +733,11 @@ void update_obj_metadata_charc_value(struct object_metadata *object)
        _bt_otp_set_char_value(otp_object_first_created_obj_path, value, 7);
        _bt_otp_set_char_value(otp_object_last_modified_obj_path, value, 7);
 
-       convert_to_hex(object, "id", value);
-       _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
+       /* Object ID is optonal for single object server */
+       if (mutiple_obj_support) {
+               convert_to_hex(object, "id", value);
+               _bt_otp_set_char_value(otp_object_id_obj_path, value, 6);
+       }
 
        convert_to_hex(object, "props", value);
        _bt_otp_set_char_value(otp_object_prop_obj_path, value, 4);
index 162e94a..cf35d49 100644 (file)
@@ -2407,6 +2407,38 @@ int __bt_bluez_request(int function_name,
                        g_free(handle);
                break;
        }
+       case BT_OTP_WRITE_VALUE: {
+               char *handle;
+               char *data = NULL;
+               guint data_len = 0;
+               char *sender = NULL;
+               bluetooth_otp_charc_data_t otp_charc_data;
+               sender = (char *)g_dbus_method_invocation_get_sender(context);
+
+               data_len = g_variant_get_size(in_param1);
+               data = (char *)g_variant_get_data(in_param1);
+
+               handle = g_strndup(data, data_len);
+               BT_DBG("OTP Write Characteristic value [%s]", handle);
+
+               __bt_service_get_parameters(in_param2,
+                       &otp_charc_data, sizeof(bluetooth_otp_charc_data_t));
+
+               int i;
+               for (i = 0; i < otp_charc_data.length; i++)
+                       BT_DBG("Value[%d] = %u", i, otp_charc_data.data[i]);
+
+               result = _bt_otp_write_characteristic_value(request_id, sender, handle,
+                                                               otp_charc_data.data, otp_charc_data.length);
+
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       BT_ERR("OTP Write Characteristic failed result [%d]", result);
+                       g_array_append_vals(*out_param1, handle, data_len);
+               }
+               if (handle)
+                       g_free(handle);
+               break;
+       }
        default:
                result = BLUETOOTH_ERROR_INTERNAL;
                break;
@@ -3255,6 +3287,7 @@ gboolean __bt_service_check_privilege(int function_name,
        case BT_OTP_SERVER_DEINIT:
        case BT_OTP_READ_VALUE:
        case BT_OTP_ENABLE_NOTIFICATION:
+       case BT_OTP_WRITE_VALUE:
 
        case BT_MAP_CREATE_SESSION:
        case BT_MAP_DESTROY_SESSION:
index c1b7037..153c6ad 100644 (file)
@@ -44,6 +44,7 @@
 #include "bt-service-opp-client.h"
 #include "bt-service-map-client.h"
 #include "bt-service-tds.h"
+#include "bt-service-otp.h"
 
 #ifdef TIZEN_FEATURE_BT_DPM
 #include "bt-service-dpm.h"
@@ -1709,6 +1710,9 @@ void _bt_handle_gatt_event(GVariant *msg, const char *member, const char *path)
        if (strcasecmp(member, "GattValueChanged") == 0) {
                /* Check TDS seekers waiting for Indication  */
                _bt_tds_check_indication(path, msg);
+#ifdef TIZEN_FEATURE_BT_OTP
+               _bt_otp_check_indication(path, msg);
+#endif
        } else {
                BT_INFO("Unhandled event");
        }
index 8ba8847..a5ccbe2 100644 (file)
@@ -559,6 +559,12 @@ int _bt_send_event_to_dest(const char* dest, int event_type,
        case BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED:
                signal = BT_OTP_NOTIFICATION_ENABLED;
                break;
+       case BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL:
+               signal = BT_OTP_WRITE_CHAR_VAL;
+               break;
+       case BLUETOOTH_EVENT_OTP_INDICATION:
+               signal = BT_OTP_INDICATION;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
index 3e49707..e62e809 100644 (file)
 #define GATT_CHAR_INTERFACE             "org.bluez.GattCharacteristic1"
 
 #define GATT_DEFAULT_TIMEOUT  (6 * 1000) /* Dependent on supervision timeout 6 sec */
+#define BT_INDICATION_TIMEOUT_MAX 15000 /* Timeout for Indication from OTP Server in msec */
 
 /* OTP Notification Request structure */
 typedef struct {
        char *handle;
        char *sender;
+       unsigned int notification_timeout_id;
        int req_id;
 } bt_otp_notification_info;
 
@@ -394,8 +396,8 @@ int _bt_otp_read_characteristic_value(int request_id, char *sender, char *handle
 {
        GDBusConnection *conn;
        bt_otp_read_req_info *info = NULL;
-       GVariantBuilder *builder = NULL;
        char *charc_handle = g_strdup(handle);
+       GVariantBuilder *builder = NULL;
        guint16 offset = 0;
 
        BT_CHECK_PARAMETER(handle, return);
@@ -471,6 +473,10 @@ static void __bt_otp_remove_notification_info(bt_otp_notification_info *info)
                g_free(info->handle);
        if (info->sender)
                g_free(info->sender);
+       if (info->notification_timeout_id > 0) {
+               g_source_remove(info->notification_timeout_id);
+               info->notification_timeout_id = 0;
+       }
        g_free(info);
 }
 
@@ -516,9 +522,15 @@ static void __bt_otp_notification_enable_request_cb(GObject *source_object,
        if (info)
                req_info = _bt_get_request_info(info->req_id);
 
-       /* CCCD Enable request failed */
+       /* If CCCD Enable request failed for any reason, reset timer */
        if (result != BLUETOOTH_ERROR_NONE && info != NULL) {
                BT_ERR("Activation Request failed");
+               /* Reset Timer */
+               if (info->notification_timeout_id > 0) {
+                       g_source_remove(info->notification_timeout_id);
+                       info->notification_timeout_id = 0;
+               }
+
                /* Remove Indication Info */
                __bt_otp_remove_notification_info(info);
        } else {
@@ -600,3 +612,218 @@ int _bt_otp_enable_notification(int request_id, char *sender, char *handle)
        BT_DBG("-");
        return BLUETOOTH_ERROR_NONE;
 }
+
+static void __bt_otp_write_request_cb(GObject *source_object,
+                       GAsyncResult *res, gpointer user_data)
+{
+       GError *error = NULL;
+       GDBusConnection *system_gconn = NULL;
+       GVariant *value = NULL;
+       GVariant *param = NULL;
+       GVariant *out_param1 = NULL;
+       int result = BLUETOOTH_ERROR_NONE;
+       char *handle = NULL;
+       bt_otp_notification_info *info = NULL;
+       request_info_t *req_info = NULL;
+       BT_DBG("+");
+
+       system_gconn = _bt_gdbus_get_system_gconn();
+       value = g_dbus_connection_call_finish(system_gconn, res, &error);
+
+       if (error) {
+               BT_ERR("Error : %s \n", error->message);
+               /* Process error->message to narrow down the att_ecode */
+               result = BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       handle = (char *)user_data;
+       info = __bt_otp_get_notification_info(handle);
+       if (info)
+               req_info = _bt_get_request_info(info->req_id);
+
+       /* Is Activation request failed for any reason, reset timer */
+       if (result != BLUETOOTH_ERROR_NONE && info != NULL) {
+               BT_ERR("Activation Request failed");
+               /* Remove Indication Info */
+               __bt_otp_remove_notification_info(info);
+       } else {
+               /* Activation Request successful */
+               if (info) {
+                       param = g_variant_new("(is)", result, handle);
+                       _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
+                                       BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL,
+                                       param);
+               }
+       }
+
+       if (req_info == NULL) {
+               BT_ERR("OTP Write Request is not found!!");
+               goto done;
+       }
+
+       if (req_info->context == NULL)
+               goto done;
+
+       out_param1 = g_variant_new_from_data((const GVariantType*)"ay",
+                       handle, __get_handle_length(handle), TRUE, NULL, NULL);
+       g_dbus_method_invocation_return_value(req_info->context,
+                       g_variant_new("(iv)", result, out_param1));
+
+       _bt_delete_request_list(req_info->req_id);
+
+done:
+       if (value)
+               g_variant_unref(value);
+       if (error)
+               g_clear_error(&error);
+       if (handle)
+               g_free(handle);
+
+       BT_DBG("-");
+       return;
+}
+
+static void __bt_otp_send_indication_event(bt_otp_notification_info *info,
+                                               unsigned char *buffer, int len, int result)
+{
+       GVariant *otp_data;
+       GVariant *param;
+
+       otp_data = g_variant_new_from_data((const GVariantType*)"ay",
+                       buffer, len, TRUE, NULL, NULL);
+
+       BT_DBG("Send Indication event to sender");
+       param = g_variant_new("(is@ay)", result, info->handle, otp_data);
+       _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
+                                       BLUETOOTH_EVENT_OTP_INDICATION,
+                                       param);
+
+       /* Remove info from list */
+       __bt_otp_remove_notification_info(info);
+}
+
+static bool __bt_otp_indication_timeout_cb(gpointer user_data)
+{
+       char *handle = NULL;
+       handle = (char *) user_data;
+       bt_otp_notification_info *info = NULL;
+       /* Indication:Fail*/
+       info = __bt_otp_get_notification_info(handle);
+       BT_DBG("Activation timer Expired [Server] [%s]", info->handle);
+       if (info)
+               __bt_otp_send_indication_event(info, NULL, 0, BLUETOOTH_ERROR_INTERNAL);
+
+       return FALSE;
+}
+
+int _bt_otp_write_characteristic_value(int request_id, char *sender, char *handle,
+                                                       unsigned char *param, int length)
+{
+       GVariantBuilder *builder1;
+       GVariant *val;
+       GVariant *options;
+       GVariantBuilder *builder2;
+       guint16 offset = 0;
+       bt_otp_notification_info *info = NULL;
+       GDBusConnection *conn;
+       char *charc_handle = g_strdup(handle);
+       int i;
+
+       BT_DBG("+");
+
+       BT_CHECK_PARAMETER(handle, return);
+       BT_CHECK_PARAMETER(sender, return);
+       BT_CHECK_PARAMETER(param, return);
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_DBG("OTP Write Characteristic value handle [%s] data length [%d]", handle, length);
+       /* Check if activation is ongoing for the same Remote Server */
+
+       info = __bt_otp_get_notification_info(handle);
+       if (info && info->notification_timeout_id > 0) {
+               BT_ERR("Write Request is already ongoing in remote server");
+               g_free(charc_handle);
+               return BLUETOOTH_ERROR_IN_PROGRESS;
+       }
+
+       builder1 = g_variant_builder_new(G_VARIANT_TYPE("ay"));
+
+       for (i = 0; i < length; i++) {
+               g_variant_builder_add(builder1, "y", param[i]);
+       }
+
+       val = g_variant_new("(ay)", builder1);
+       builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       /*offset*/
+       g_variant_builder_add(builder2, "{sv}", "offset",
+                               g_variant_new_uint16(offset));
+
+       options = g_variant_new("a{sv}", builder2);
+
+       /* Activate Control Point */
+       g_dbus_connection_call(conn,
+                       BT_BLUEZ_NAME,
+                       handle,
+                       GATT_CHAR_INTERFACE,
+                       "WriteValue",
+                       g_variant_new("(@ay@a{sv})",
+                       val, options),
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL,
+                       (GAsyncReadyCallback)__bt_otp_write_request_cb,
+                       (gpointer)charc_handle);
+
+       g_variant_builder_unref(builder1);
+       g_variant_builder_unref(builder2);
+
+       if (info == NULL) {
+               info = g_malloc0(sizeof(bt_otp_notification_info));
+               info->handle = g_strdup(handle);
+               info->sender = g_strdup(sender);
+               otp_notification_info_list = g_slist_append(otp_notification_info_list, info);
+       }
+       info->req_id = request_id;
+       info->notification_timeout_id = g_timeout_add(BT_INDICATION_TIMEOUT_MAX,
+                       (GSourceFunc)__bt_otp_indication_timeout_cb, (gpointer)info->handle);
+
+       BT_DBG("-");
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_otp_check_indication(const char *path, GVariant *msg)
+{
+       bt_otp_notification_info *info = NULL;
+       unsigned char *buffer = NULL;
+       int len = 0;
+       int i;
+       GVariant *value = NULL;
+       BT_DBG("+");
+
+       info = __bt_otp_get_notification_info((char *)path);
+
+       if (info) {
+               g_variant_get(msg, "(is@ay)", NULL, NULL, &value);
+               len = g_variant_get_size(value);
+               BT_DBG("Indication data from Server len[%d]", len);
+               if (len > 0) {
+                       buffer = (unsigned char *)g_variant_get_data(value);
+                       /* DEBUG */
+                       for (i = 0; i < len; i++)
+                               BT_DBG("%.2x", buffer[i]);
+               }
+
+               /* Reset Timer */
+               if (info->notification_timeout_id > 0)
+                       g_source_remove(info->notification_timeout_id);
+
+               /* Send Indication & info removed internally */
+               __bt_otp_send_indication_event(info, buffer, len, BLUETOOTH_ERROR_NONE);
+
+               if (value)
+                       g_variant_unref(value);
+       }
+       BT_DBG("-");
+}
index b525e18..64d4026 100644 (file)
@@ -34,6 +34,11 @@ int _bt_otp_read_characteristic_value(int request_id, char *sender, char *handle
 
 int _bt_otp_enable_notification(int request_id, char *sender, char *handle);
 
+int _bt_otp_write_characteristic_value(int request_id, char *sender, char *handle,
+                                                                                                       unsigned char *param, int length);
+
+void _bt_otp_check_indication(const char *path, GVariant *msg);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index 3eab8cb..153f324 100644 (file)
@@ -86,6 +86,8 @@ extern "C" {
  */
 #define BLUETOOTH_MAX_OTP_SERVER_DIR_NAME 100
 
+#define BLUETOOTH_OTP_CHARC_VAL_MAX_LENGTH   500 /**< OTP Characteristics Value Max length */
+
 /**
  * This is Bluetooth error code
  */
@@ -506,6 +508,14 @@ typedef struct {
 } bluetooth_tds_transport_data_info_t;
 
 /**
+* OTP Characteristics Value
+*/
+typedef struct {
+       int length;                                                     /**< Characteristics value length */
+       guint8 data[BLUETOOTH_OTP_CHARC_VAL_MAX_LENGTH];        /**< Characteristics data */
+} bluetooth_otp_charc_data_t;
+
+/**
 * Structure to hold the OTP response data from remote OTP server
 */
 typedef struct {
@@ -833,6 +843,8 @@ typedef enum {
        BLUETOOTH_EVENT_OTP_SERVER_STATE_CHANGED,       /* OTP Server Status **/
        BLUETOOTH_EVENT_OTP_READ_CHAR_VAL,      /* OTP Read Value Response */
        BLUETOOTH_EVENT_OTP_NOTIFICATION_ENABLED,       /* OTP Notification Enabled Response */
+       BLUETOOTH_EVENT_OTP_WRITE_CHAR_VAL,     /* OTP Write Value Response */
+       BLUETOOTH_EVENT_OTP_INDICATION, /* OTP Indication */
 } bluetooth_event_type_t;
 
  /**
@@ -7580,8 +7592,57 @@ int bluetooth_otp_server_init(const char *directory);
  */
 int bluetooth_otp_server_deinit();
 
+/**
+ * @fn int bluetooth_otp_enable_notification(const char *handle);
+ *
+ * @brief Enable notification for remote OACP & OLCP characteristics.
+ *
+ * This function is a synchronous call.
+ *
+ * @return
+ *
+ * @exception  None
+ * @param[in] None
+ * @param[out] None
+ *
+ * @remark     None
+ */
 int bluetooth_otp_enable_notification(const char *handle);
 
+/**
+ * @fn int bluetooth_otp_write_characteristics_value( const char *handle,
+ *                                             unsigned char *buf, int length);
+ *
+ * @brief Write value on remote characteristics.
+ *
+ * This function is a synchronous call.
+ *
+ * @return
+ *
+ * @exception  None
+ * @param[in] None
+ * @param[out] None
+ *
+ * @remark     None
+ */
+int bluetooth_otp_write_characteristics_value( const char *handle,
+                                       unsigned char *buf, int length);
+
+/**
+ * @fn int bluetooth_otp_read_characteristic_value(const char *handle);
+ *
+ * @brief Read value for remote characteristics.
+ *
+ * This function is a synchronous call.
+ *
+ * @return
+ *
+ * @exception  None
+ * @param[in] None
+ * @param[out] None
+ *
+ * @remark     None
+ */
 int bluetooth_otp_read_characteristic_value(const char *handle);
 
 /**
index c5469cd..23d8917 100644 (file)
@@ -385,6 +385,7 @@ typedef enum {
        BT_OTP_SERVER_DEINIT,
        BT_OTP_READ_VALUE,
        BT_OTP_ENABLE_NOTIFICATION,
+       BT_OTP_WRITE_VALUE,
 } bt_function_t;
 
 typedef struct {
@@ -565,6 +566,8 @@ typedef struct {
 #define BT_OTP_SERVER_STATE_CHANGED "OtpServerStateChanged"
 #define BT_OTP_READ_CHAR_VAL "OtpReadCharVal"
 #define BT_OTP_NOTIFICATION_ENABLED "OtpNotificationEnabled"
+#define BT_OTP_WRITE_CHAR_VAL "OtpWriteCharVal"
+#define BT_OTP_INDICATION "OtpIndication"
 
 typedef enum {
        _PROFILE_UNKNOWN = 0,