[OTP] Add support for OACP Read
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-otp.c
index e62e809..dc8716d 100644 (file)
@@ -41,7 +41,7 @@
 #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 */
+#define BT_INDICATION_TIMEOUT_MAX 30000 /* Timeout for Indication from OTP Server in msec */
 
 /* OTP Notification Request structure */
 typedef struct {
@@ -312,7 +312,7 @@ static void __bt_otp_read_char_cb(GObject *source_object,
        char *otp_data = NULL;
        GVariant *out_param1;
        GError *error = NULL;
-       guint8 g_byte;
+       guint8 g_byte, att_error_code;
        char *handle;
 
        BT_DBG("+");
@@ -325,17 +325,21 @@ static void __bt_otp_read_char_cb(GObject *source_object,
 
        if (error) {
                BT_ERR("Error : %s \n", error->message);
-               g_free(handle);
-               if (info) {
-                       req_info = _bt_get_request_info(info->req_id);
-                       __bt_otp_remove_read_info(info);
-               }
+               att_value.val_len = 0;
                result = BLUETOOTH_ERROR_INTERNAL;
                goto dbus_return;
        }
 
+       g_variant_get(value, "(yay)", &att_error_code, &iter);
+
+       if (att_error_code != 0) {
+               BT_ERR("ATT err code : [%d]", att_error_code);
+               att_value.val_len = 0;
+               result = att_error_code;
+               goto dbus_return;
+       }
+
        gp_byte_array = g_byte_array_new();
-       g_variant_get(value, "(ay)", &iter);
 
        while (g_variant_iter_loop(iter, "y",  &g_byte))
                g_byte_array_append(gp_byte_array, &g_byte, 1);
@@ -347,6 +351,7 @@ static void __bt_otp_read_char_cb(GObject *source_object,
 
        otp_data = (char *)g_memdup(att_value.val, att_value.val_len);
 
+dbus_return:
        var_data = g_variant_new_from_data((const GVariantType*)"ay",
                        otp_data, att_value.val_len, TRUE, NULL, NULL);
 
@@ -355,11 +360,11 @@ static void __bt_otp_read_char_cb(GObject *source_object,
                _bt_send_event_to_dest(info->sender, BT_OTP_EVENT,
                                BLUETOOTH_EVENT_OTP_READ_CHAR_VAL,
                                param);
-               req_info = _bt_get_request_info(info->req_id);
-               __bt_otp_remove_read_info(info);
        }
 
-dbus_return:
+       req_info = _bt_get_request_info(info->req_id);
+       __bt_otp_remove_read_info(info);
+
        if (req_info == NULL) {
                BT_ERR("OTP data read Request not found!!");
                goto done;
@@ -426,7 +431,7 @@ int _bt_otp_read_characteristic_value(int request_id, char *sender, char *handle
                        GATT_CHAR_INTERFACE,
                        "ReadValue",
                        g_variant_new("(a{sv})", builder),
-                       G_VARIANT_TYPE("(ay)"),
+                       G_VARIANT_TYPE("(yay)"),
                        G_DBUS_CALL_FLAGS_NONE,
                        -1,
                        NULL,
@@ -625,6 +630,7 @@ static void __bt_otp_write_request_cb(GObject *source_object,
        char *handle = NULL;
        bt_otp_notification_info *info = NULL;
        request_info_t *req_info = NULL;
+       guint8 att_ecode = 0;
        BT_DBG("+");
 
        system_gconn = _bt_gdbus_get_system_gconn();
@@ -634,6 +640,12 @@ static void __bt_otp_write_request_cb(GObject *source_object,
                BT_ERR("Error : %s \n", error->message);
                /* Process error->message to narrow down the att_ecode */
                result = BLUETOOTH_ERROR_INTERNAL;
+       } else {
+               g_variant_get(value, "(y)", &att_ecode);
+               if (att_ecode) {
+                       result =  att_ecode;
+                       BT_ERR("ATT Error code: %d \n", att_ecode);
+               }
        }
 
        handle = (char *)user_data;
@@ -646,14 +658,14 @@ static void __bt_otp_write_request_cb(GObject *source_object,
                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);
-               }
+       }
+
+       /* 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) {
@@ -709,9 +721,10 @@ static bool __bt_otp_indication_timeout_cb(gpointer 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)
+       if (info) {
+               BT_DBG("Activation timer Expired [Server] [%s]", info->handle);
                __bt_otp_send_indication_event(info, NULL, 0, BLUETOOTH_ERROR_INTERNAL);
+       }
 
        return FALSE;
 }
@@ -754,7 +767,7 @@ int _bt_otp_write_characteristic_value(int request_id, char *sender, char *handl
                g_variant_builder_add(builder1, "y", param[i]);
        }
 
-       val = g_variant_new("(ay)", builder1);
+       val = g_variant_new("ay", builder1);
        builder2 = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
        /*offset*/
        g_variant_builder_add(builder2, "{sv}", "offset",
@@ -827,3 +840,122 @@ void _bt_otp_check_indication(const char *path, GVariant *msg)
        }
        BT_DBG("-");
 }
+
+int _bt_otp_connect_otc(int req_id, const bluetooth_device_address_t *bd_addr)
+{
+       char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+       gchar *device_path = NULL;
+       GDBusProxy *device_proxy = NULL;
+       GDBusConnection *conn;
+       int ret = BLUETOOTH_ERROR_NONE;
+       GVariant *result = NULL;
+       GError *err = NULL;
+
+       BT_CHECK_PARAMETER(bd_addr, return);
+
+       _bt_convert_addr_type_to_string(device_address,
+                       (unsigned char *)bd_addr->addr);
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       device_path = _bt_get_device_object_path(device_address);
+       if (device_path == NULL) {
+               BT_DBG("device_path NULL");
+               ret = BLUETOOTH_ERROR_INTERNAL;
+               goto fail;
+       }
+
+       retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       device_proxy = g_dbus_proxy_new_sync(conn,
+                                       G_DBUS_PROXY_FLAGS_NONE,
+                                       NULL, BT_BLUEZ_NAME,
+                                       device_path, BT_DEVICE_INTERFACE,
+                                       NULL, NULL);
+       g_free(device_path);
+       retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       result = g_dbus_proxy_call_sync(device_proxy, "ConnectOtc",
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               &err);
+
+       if (result == NULL) {
+               if (err != NULL) {
+                       g_dbus_error_strip_remote_error(err);
+                       BT_ERR("OTC Connect Error: %s\n", err->message);
+                       if (g_strcmp0(err->message, "Already Exists") == 0)
+                               ret = BLUETOOTH_ERROR_ALREADY_INITIALIZED;
+                       else
+                               ret = BLUETOOTH_ERROR_INTERNAL;
+                       g_error_free(err);
+               }
+       }
+       g_variant_unref(result);
+
+fail:
+       g_object_unref(device_proxy);
+       return ret;
+}
+
+int _bt_otp_disconnect_otc(const bluetooth_device_address_t *bd_addr)
+{
+       char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
+       gchar *device_path = NULL;
+       GError *error = NULL;
+       GDBusProxy *device_proxy = NULL;
+       GDBusProxy *adapter_proxy;
+       GDBusConnection *conn;
+       int ret = BLUETOOTH_ERROR_NONE;
+
+       BT_CHECK_PARAMETER(bd_addr, return);
+
+       _bt_convert_addr_type_to_string(device_address,
+                       (unsigned char *)bd_addr->addr);
+
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       adapter_proxy = _bt_get_adapter_proxy();
+       retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       device_path = _bt_get_device_object_path(device_address);
+       if (device_path == NULL) {
+               BT_DBG("device_path NULL");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       retv_if(device_path == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       device_proxy = g_dbus_proxy_new_sync(conn,
+                                       G_DBUS_PROXY_FLAGS_NONE,
+                                       NULL, BT_BLUEZ_NAME,
+                                       device_path,
+                                       BT_DEVICE_INTERFACE,
+                                       NULL, NULL);
+       g_free(device_path);
+       retv_if(device_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       g_dbus_proxy_call_sync(device_proxy, "DisconnectOtc",
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               &error);
+
+       if (error) {
+               BT_ERR("DisconnectOtc Call Error %s[%s]",
+                               error->message, device_address);
+               g_error_free(error);
+               g_object_unref(device_proxy);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       if (device_proxy)
+               g_object_unref(device_proxy);
+
+       return ret;
+}