Get local IRK value
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-dbus-common-utils.c
index 730fde4..66340c6 100644 (file)
@@ -52,9 +52,6 @@
 #define RFCOMM_DEFAULT_PROFILE_CHANNEL 0
 #define BT_AUDIO_SOURCE_MAX 2
 
-static char *avrcp_control_path = NULL;
-static char *avrcp_transport_path = NULL;
-
 static GDBusConnection *system_conn;
 static GDBusConnection *session_conn;
 static GDBusProxy *manager_gproxy = NULL;
@@ -70,10 +67,10 @@ struct avrcp_proxy {
        bt_bdaddr_t bd_addr;
 };
 
-struct avrcp_proxy proxy_array[BT_AUDIO_SOURCE_MAX];
+static struct avrcp_proxy proxy_array[BT_AUDIO_SOURCE_MAX];
 
 static guint bus_id;
-GDBusNodeInfo *new_conn_node;
+static GDBusNodeInfo *new_conn_node;
 static const gchar rfcomm_agent_xml[] =
 "<node name='/'>"
 " <interface name='org.bluez.Profile1'>"
@@ -88,6 +85,17 @@ static const gchar rfcomm_agent_xml[] =
 "  </interface>"
 "</node>";
 
+static GDBusNodeInfo *new_l2cap_le_conn_node;
+static const gchar l2cap_le_agent_xml[] =
+"<node name='/'>"
+" <interface name='org.bluez.l2cap_le'>"
+"     <method name='NewConnection'>"
+"          <arg type='o' name='object' direction='in'/>"
+"          <arg type='h' name='fd' direction='in'/>"
+"     </method>"
+"  </interface>"
+"</node>";
+
 static GDBusConnection *__bt_hal_init_session_conn(void)
 {
        if (session_conn == NULL)
@@ -396,8 +404,7 @@ char *_bt_hal_get_control_device_path(bt_bdaddr_t *bd_addr)
        char *control_path;
        char connected_address[BT_HAL_ADDRESS_STRING_SIZE];
 
-       if (avrcp_control_path != NULL)
-               return avrcp_control_path;
+       /* We can add the cache to get transport path for each device */
 
        _bt_hal_convert_addr_type_to_string(connected_address, bd_addr->address);
 
@@ -405,7 +412,6 @@ char *_bt_hal_get_control_device_path(bt_bdaddr_t *bd_addr)
        if (control_path == NULL)
                return NULL;
 
-       avrcp_control_path = control_path;
        DBG("control_path = %s", control_path);
        return control_path;
 }
@@ -415,8 +421,7 @@ char *_bt_hal_get_transport_device_path(bt_bdaddr_t *bd_addr)
        char *transport_path;
        char connected_address[BT_HAL_ADDRESS_STRING_SIZE];
 
-       if (avrcp_transport_path != NULL)
-               return avrcp_transport_path;
+       /* We can add the cache to get transport path for each device */
 
        _bt_hal_convert_addr_type_to_string(connected_address, bd_addr->address);
 
@@ -424,7 +429,6 @@ char *_bt_hal_get_transport_device_path(bt_bdaddr_t *bd_addr)
        if (transport_path == NULL)
                return NULL;
 
-       avrcp_transport_path = transport_path;
        DBG("transport_path = %s", transport_path);
        return transport_path;
 }
@@ -1206,21 +1210,6 @@ char * _bt_hal_convert_disc_reason_to_string(int reason)
        }
 }
 
-int _bt_hal_convert_disc_reason_to_status(int reason)
-{
-       switch (reason) {
-       case 1:
-               return BT_STATUS_CONN_TOUT; //"Link loss"
-       case 2:
-               return BT_STATUS_CONN_TERM_LOCAL_HOST; //"Connection terminated by local host";
-       case 3:
-               return BT_STATUS_CONN_TERM_RMT_HOST; //"Connection terminated by local host";
-       case 0:
-       default:
-               return BT_STATUS_FAIL;
-       }
-}
-
 void _bt_hal_logging_connection(gboolean connect, int addr_type)
 {
        static int le_conn = 0;
@@ -1297,6 +1286,7 @@ int _bt_hal_connect_profile(char *address, char *uuid,
        GDBusConnection *conn;
        GDBusProxy *adapter_proxy;
        GError *error = NULL;
+       GVariant *result;
 
        conn = _bt_hal_get_system_gconn();
        if (conn == NULL)
@@ -1310,16 +1300,19 @@ int _bt_hal_connect_profile(char *address, char *uuid,
                if (adapter_proxy == NULL)
                        return  BT_HAL_ERROR_INTERNAL;
 
-               g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
+               result = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
                                g_variant_new("(s)", address),
                                G_DBUS_CALL_FLAGS_NONE,
                                -1,
                                NULL,
                                &error);
-
-               if (error != NULL) {
-                       ERR("CreateDevice Fail: %s", error->message);
-                       g_error_free(error);
+               if (!result) {
+                       if (error) {
+                               ERR("CreateDevice Fail: %s", error->message);
+                               g_error_free(error);
+                       }
+               } else {
+                       g_variant_unref(result);
                }
 
                object_path = _bt_hal_get_device_object_path(address);
@@ -1535,6 +1528,251 @@ static void __hal_new_connection_method(GDBusConnection *connection,
        }
 }
 
+int _bt_hal_connect_l2cap_le(char *address,
+                       bt_hal_l2cap_le_profile_info_t *info, void *cb, gpointer func_data)
+{
+       GVariantBuilder *option_builder;
+       char *object_path;
+       GDBusProxy *proxy;
+       GDBusConnection *conn;
+       GDBusProxy *adapter_proxy;
+       GError *error = NULL;
+       GVariant *result;
+
+       DBG("+");
+       conn = _bt_hal_get_system_gconn();
+       if (conn == NULL)
+               return  BT_HAL_ERROR_INTERNAL;
+
+       object_path = _bt_hal_get_device_object_path(address);
+       if (object_path == NULL) {
+               ERR("No searched device");
+
+               adapter_proxy = _bt_hal_get_adapter_proxy();
+               if (adapter_proxy == NULL)
+                       return  BT_HAL_ERROR_INTERNAL;
+
+               result = g_dbus_proxy_call_sync(adapter_proxy, "CreateDevice",
+                               g_variant_new("(s)", address), G_DBUS_CALL_FLAGS_NONE,
+                               -1, NULL, &error);
+
+               if (!result) {
+                       if (error) {
+                               ERR("CreateDevice Fail: %s", error->message);
+                               g_error_free(error);
+                       }
+               } else
+                       g_variant_unref(result);
+
+               object_path = _bt_hal_get_device_object_path(address);
+       }
+
+       if (object_path == NULL) {
+               INFO("Not able to find device object");
+               return BT_HAL_ERROR_INTERNAL;
+       }
+
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME,
+                       object_path, BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
+       g_free(object_path);
+
+       if (proxy == NULL) {
+               INFO("proxy is null");
+               return BT_HAL_ERROR_INTERNAL;
+       }
+
+       option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       if (info->authentication)
+               g_variant_builder_add(option_builder, "{sv}",
+                               "RequireAuthentication",
+                               g_variant_new_boolean(TRUE));
+
+       if (info->authorization)
+               g_variant_builder_add(option_builder, "{sv}",
+                               "RequireAuthorization",
+                               g_variant_new_boolean(TRUE));
+
+       g_dbus_proxy_call(proxy, "ConnectL2capLESocket",
+                       g_variant_new("(oia{sv})", info->obj_path,
+                               info->psm, option_builder),
+                       G_DBUS_CALL_FLAGS_NONE, BT_HAL_MAX_DBUS_TIMEOUT, NULL,
+                       (GAsyncReadyCallback)cb, func_data);
+
+       g_variant_builder_unref(option_builder);
+
+       DBG("-");
+       return BT_HAL_ERROR_NONE;
+}
+
+int _bt_hal_listen_l2cap_le(bt_hal_l2cap_le_profile_info_t *info)
+{
+       GVariantBuilder *option_builder;
+       GVariant *ret;
+       GDBusProxy *proxy;
+       GError *err = NULL;
+       int result = BT_STATUS_SUCCESS;
+
+       DBG("+");
+       proxy = _bt_hal_get_adapter_proxy();
+       if (proxy == NULL) {
+               ERR("Getting adapter profile proxy failed");
+               return BT_STATUS_FAIL;
+       }
+
+       option_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+       if (info->authentication)
+               g_variant_builder_add(option_builder, "{sv}",
+                               "RequireAuthentication",
+                               g_variant_new_boolean(TRUE));
+
+       if (info->authorization)
+               g_variant_builder_add(option_builder, "{sv}",
+                               "RequireAuthorization",
+                               g_variant_new_boolean(TRUE));
+
+       ret = g_dbus_proxy_call_sync(proxy, "ListenL2capLESocket",
+                       g_variant_new("(oia{sv})", info->obj_path, info->psm,
+                               option_builder),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
+
+       if (err) {
+               ERR("Listen L2cap_LE failed: %s", err->message);
+
+               if (g_strrstr(err->message, BT_HAL_ACCESS_DENIED_MSG))
+                       result = BT_STATUS_AUTH_REJECTED;
+               else
+                       result = BT_STATUS_FAIL;
+
+               g_clear_error(&err);
+       }
+
+       g_variant_builder_unref(option_builder);
+
+       if (ret)
+               g_variant_unref(ret);
+
+       DBG("-");
+       return result;
+}
+
+void _bt_hal_remove_l2cap_le_socket(char *path)
+{
+       GVariant *ret;
+       GDBusProxy *proxy;
+       GError *err = NULL;
+
+       proxy = _bt_hal_get_adapter_proxy();
+       if (proxy == NULL) {
+               ERR("Getting adapter profile proxy failed");
+               return;
+       }
+
+       ret = g_dbus_proxy_call_sync(proxy, "RemoveL2capLESocket",
+                       g_variant_new("(o)", path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &err);
+       if (err) {
+               ERR("Remove socket l2cap le failed : %s", err->message);
+               g_clear_error(&err);
+       }
+
+       if (ret)
+               g_variant_unref(ret);
+
+       return;
+}
+
+int _bt_hal_get_psm_l2cap_le(bt_hal_l2cap_le_profile_info_t *info, uint32_t *psm)
+{
+       GVariant *ret;
+       GDBusProxy *proxy;
+       GError *err = NULL;
+       int result = BT_STATUS_SUCCESS;
+
+       proxy = _bt_hal_get_adapter_proxy();
+       if (proxy == NULL) {
+               ERR("Getting adapter profile proxy failed");
+               return BT_STATUS_FAIL;
+       }
+
+       ret = g_dbus_proxy_call_sync(proxy, "GetPSML2capLE",
+                       g_variant_new("(o)", info->obj_path),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &err);
+       if (err) {
+               ERR("Get PSM L2cap_LE failed: %s", err->message);
+               result = BT_STATUS_FAIL;
+               g_clear_error(&err);
+               return result;
+       }
+
+       g_variant_get(ret, "(u)", psm);
+       INFO("PSM: %d", *psm);
+
+       if (ret)
+               g_variant_unref(ret);
+
+       return result;
+}
+
+static void __hal_l2cap_le_new_connection_method(GDBusConnection *connection,
+               const gchar *sender,
+               const gchar *object_path,
+               const gchar *interface_name,
+               const gchar *method_name,
+               GVariant *parameters,
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
+{
+       INFO("method %s", method_name);
+       if (g_strcmp0(method_name, "NewConnection") == 0) {
+               INFO("L2cap_LE New connection method");
+               int index;
+               int fd;
+               GUnixFDList *fd_list;
+               GDBusMessage *msg;
+               char *obj_path;
+               bt_bdaddr_t remote_addr1;
+               char addr[BT_HAL_ADDRESS_STRING_SIZE];
+               bt_hal_new_connection_cb cb = user_data;
+
+               g_variant_get(parameters, "(oh)", &obj_path, &index);
+
+               msg = g_dbus_method_invocation_get_message(invocation);
+               fd_list = g_dbus_message_get_unix_fd_list(msg);
+               if (fd_list == NULL) {
+                       ERR("No fd in message");
+                       GQuark quark = g_quark_from_string("l2cap_le-app");
+                       GError *err = g_error_new(quark, 0, "No fd in message");
+                       g_dbus_method_invocation_return_gerror(invocation, err);
+                       g_error_free(err);
+                       return;
+               }
+
+               fd = g_unix_fd_list_get(fd_list, index, NULL);
+               if (fd == -1) {
+                       ERR("Invalid fd return");
+                       GQuark quark = g_quark_from_string("l2cap_le-app");
+                       GError *err = g_error_new(quark, 0, "Invalid FD return");
+                       g_dbus_method_invocation_return_gerror(invocation, err);
+                       g_error_free(err);
+                       return;
+               }
+
+               _bt_hal_convert_device_path_to_address(obj_path, addr);
+               _bt_hal_convert_addr_string_to_type(remote_addr1.address, (const char *)addr);
+               INFO("Object path %s, fd: %d, address %s", obj_path, fd, addr);
+
+               g_dbus_method_invocation_return_value(invocation, NULL);
+
+               if (cb)
+                       cb(object_path, fd, &remote_addr1);
+               else
+                       close(fd);
+       }
+}
+
 static GDBusNodeInfo *_bt_hal_get_gdbus_node(const gchar *xml_data)
 {
        if (bus_id == 0) {
@@ -1561,6 +1799,12 @@ static const GDBusInterfaceVTable method_table = {
        NULL,
 };
 
+static const GDBusInterfaceVTable l2cap_le_method_table = {
+       __hal_l2cap_le_new_connection_method,
+       NULL,
+       NULL,
+};
+
 int _bt_hal_register_new_gdbus_object(const char *path, bt_hal_new_connection_cb cb)
 {
        GDBusConnection *gconn;
@@ -1603,6 +1847,49 @@ void _bt_hal_unregister_gdbus_object(int object_id)
        g_dbus_connection_unregister_object(gconn, object_id);
 }
 
+int _bt_hal_register_new_l2cap_le_gdbus_object(const char *path,
+                                               bt_hal_new_connection_cb cb)
+{
+       GDBusConnection *gconn;
+       int id;
+       GError *error = NULL;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return -1;
+
+       if (new_l2cap_le_conn_node == NULL)
+               new_l2cap_le_conn_node = _bt_hal_get_gdbus_node(l2cap_le_agent_xml);
+
+       if (new_l2cap_le_conn_node == NULL)
+               return -1;
+
+       id = g_dbus_connection_register_object(gconn, path,
+                       new_l2cap_le_conn_node->interfaces[0],
+                       &l2cap_le_method_table,
+                       cb, NULL, &error);
+       if (id == 0) {
+               ERR("Failed to register: %s", error->message);
+               g_error_free(error);
+               return -1;
+       }
+
+       INFO("L2CAP_LE NEW CONNECTION ID %d", id);
+
+       return id;
+}
+
+void _bt_hal_unregister_l2cap_le_gdbus_object(int object_id)
+{
+       GDBusConnection *gconn;
+
+       gconn = _bt_hal_get_system_gconn();
+       if (gconn == NULL)
+               return;
+
+       g_dbus_connection_unregister_object(gconn, object_id);
+}
+
 int _bt_hal_discover_services(char *address, char *uuid, void *cb, gpointer func_data)
 {
        char *object_path;
@@ -1676,6 +1963,7 @@ int _bt_hal_cancel_discovers(char *address)
        GDBusProxy *adapter_proxy;
        GError *err = NULL;
        GDBusConnection *conn;
+       GVariant *ret = NULL;
 
        conn = _bt_hal_get_system_gconn();
        if (conn == NULL)
@@ -1683,7 +1971,6 @@ int _bt_hal_cancel_discovers(char *address)
 
        object_path = _bt_hal_get_device_object_path(address);
        if (object_path == NULL) {
-               GVariant *ret = NULL;
                INFO("No searched device");
                adapter_proxy = _bt_hal_get_adapter_proxy();
                if (adapter_proxy == NULL) {
@@ -1696,13 +1983,14 @@ int _bt_hal_cancel_discovers(char *address)
                                G_DBUS_CALL_FLAGS_NONE,
                                BT_HAL_MAX_DBUS_TIMEOUT, NULL,
                                &err);
-               if (err != NULL) {
-                       ERR("CreateDevice Failed: %s", err->message);
-                       g_clear_error(&err);
-               }
-
-               if (ret)
+               if (!ret) {
+                       if (err) {
+                               ERR("CreateDevice Failed: %s", err->message);
+                               g_clear_error(&err);
+                       }
+               } else {
                        g_variant_unref(ret);
+               }
 
                g_object_unref(adapter_proxy);
 
@@ -1716,15 +2004,19 @@ int _bt_hal_cancel_discovers(char *address)
                        BT_HAL_BLUEZ_NAME, object_path,
                        BT_HAL_DEVICE_INTERFACE,  NULL, NULL);
        g_free(object_path);
-       g_dbus_proxy_call_sync(proxy, "CancelDiscovery",
+       ret = g_dbus_proxy_call_sync(proxy, "CancelDiscovery",
                        NULL,
                        G_DBUS_CALL_FLAGS_NONE,
                        BT_HAL_MAX_DBUS_TIMEOUT, NULL,
                        &err);
-       if (err) {
-               ERR("DBus Error message: [%s]", err->message);
-               g_clear_error(&err);
-               return BT_STATUS_FAIL;
+       if (!ret) {
+               if (err) {
+                       ERR("DBus Error message: [%s]", err->message);
+                       g_clear_error(&err);
+                       return BT_STATUS_FAIL;
+               }
+       } else {
+               g_variant_unref(ret);
        }
 
        if (proxy)