Apply tizen 3.0 based product patchsets
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-rfcomm-client.c
index abe7a65..099816e 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #include <string.h>
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
 #include <errno.h>
 #include <gio/gunixfdlist.h>
 #endif
 #include "bt-request-sender.h"
 #include "bt-event-handler.h"
 
-#ifdef TIZEN_DPM_ENABLE
+#ifdef TIZEN_FEATURE_BT_DPM
 #include "bt-dpm.h"
 #endif
 
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
 
 #define BT_TIMEOUT_MESSAGE "Did not receive a reply. Possible causes include: " \
                        "the remote application did not send a reply, " \
@@ -53,7 +53,7 @@ static int privilege_token;
 typedef struct {
        char bt_addr[BT_ADDRESS_STRING_SIZE];
        int fd;
-       int watch_id;
+       guint watch_id;
        gboolean disconnected;
 } rfcomm_conn_info_t;
 
@@ -129,12 +129,11 @@ static void __bt_free_conn(rfcomm_conn_info_t *conn)
        if (conn == NULL)
                return;
 
-       if (conn->fd > 0)
-               close(conn->fd);
        if (conn->watch_id > 0) {
                g_source_remove(conn->watch_id);
                conn->watch_id = 0;
        }
+
        g_free(conn);
 
        BT_DBG("-");
@@ -158,9 +157,9 @@ static rfcomm_conn_info_t *__get_conn_info_from_fd(rfcomm_cb_data_t *info,
 {
        GSList *l;
        rfcomm_conn_info_t *device_node = NULL;
-       for(l = info->rfcomm_conns; l != NULL; l = l->next) {
+       for (l = info->rfcomm_conns; l != NULL; l = l->next) {
                device_node = l->data;
-               if ( device_node && device_node->fd == fd)
+               if (device_node && device_node->fd == fd)
                        return device_node;
        }
        return NULL;
@@ -181,6 +180,11 @@ static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info,
 static void __rfcomm_client_connected_cb(rfcomm_cb_data_t *info,
        char *dev_address, int result)
 {
+       if (g_slist_find(rfcomm_clients, info) == NULL) {
+               BT_INFO("rfcomm resource is already freed");
+               return;
+       }
+
        __client_connected_cb(info, dev_address, result);
        __rfcomm_remove_conn_info_t(info, dev_address);
 
@@ -240,21 +244,26 @@ static void _bt_rfcomm_disconnect_conn_info(rfcomm_conn_info_t *conn_info,
 
        bluetooth_rfcomm_disconnection_t disconn_info;
        bt_event_info_t *event_info = NULL;
+
        if (conn_info->disconnected == FALSE)
                return;
+
        event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT);
        if (event_info == NULL) {
+               __rfcomm_remove_conn_info_t(info, conn_info->bt_addr);
+
                if (info->rfcomm_conns == NULL)
                        rfcomm_cb_data_remove(info);
                return;
        }
+
        memset(&disconn_info, 0x00, sizeof(bluetooth_rfcomm_disconnection_t));
        disconn_info.device_role = RFCOMM_ROLE_CLIENT;
        g_strlcpy(disconn_info.uuid, info->uuid, BLUETOOTH_UUID_STRING_MAX);
-       BT_DBG("Disconnected FD [%d]", conn_info->fd);
        _bt_convert_addr_string_to_type(disconn_info.device_addr.addr,
                                        conn_info->bt_addr);
 
+       BT_DBG("Disconnected FD [%d]", conn_info->fd);
        disconn_info.socket_fd = conn_info->fd;
 
        BT_DBG("Disconnection Result[%d] BT_ADDRESS[%s] UUID[%s] FD[%d]",
@@ -264,10 +273,8 @@ static void _bt_rfcomm_disconnect_conn_info(rfcomm_conn_info_t *conn_info,
                        BLUETOOTH_ERROR_NONE, &disconn_info,
                        event_info->cb, event_info->user_data);
 
-       if(conn_info) {
-               BT_DBG("List is present deleting it");
-               __rfcomm_remove_conn_info_t(info, conn_info->bt_addr);
-       }
+       __rfcomm_remove_conn_info_t(info, conn_info->bt_addr);
+
        if (info->rfcomm_conns == NULL)
                rfcomm_cb_data_remove(info);
 
@@ -276,8 +283,10 @@ static void _bt_rfcomm_disconnect_conn_info(rfcomm_conn_info_t *conn_info,
 
 static gboolean __rfcomm_client_disconnect(gpointer user_data)
 {
-       rfcomm_cb_data_t *info = (rfcomm_cb_data_t *) user_data;
-       BT_INFO_C("Disconnected [RFCOMM Client]");
+       rfcomm_cb_data_t *info = (rfcomm_cb_data_t *)user_data;
+
+       BT_INFO_C("### Disconnected [RFCOMM Client]");
+
        retv_if(info == NULL, FALSE);
 
        if (g_slist_find(rfcomm_clients, info) == NULL) {
@@ -285,8 +294,10 @@ static gboolean __rfcomm_client_disconnect(gpointer user_data)
                return FALSE;
        }
        info->idle_id = 0;
+
        g_slist_foreach(info->rfcomm_conns,
-               (GFunc) _bt_rfcomm_disconnect_conn_info, info);
+               (GFunc)_bt_rfcomm_disconnect_conn_info, info);
+
        BT_DBG("-");
        return FALSE;
 }
@@ -317,12 +328,17 @@ static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
        fd = g_io_channel_unix_get_fd(chan);
        if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
                BT_ERR_C("RFComm Client  disconnected: %d", fd);
+
                conn_info = __get_conn_info_from_fd(info, fd);
                if (conn_info == NULL) {
                        BT_ERR("No Connection info found with FD [%d]", fd);
                        return FALSE;
                }
-               conn_info->disconnected = TRUE;
+
+               if (conn_info->disconnected == FALSE) {
+                       close(conn_info->fd);
+                       conn_info->disconnected = TRUE;
+               }
                __rfcomm_client_disconnect(info);
                return FALSE;
        }
@@ -341,12 +357,17 @@ static gboolean __client_data_received_cb(GIOChannel *chan, GIOCondition cond,
                                        __is_error_by_disconnect(err)) {
                                BT_ERR("cond : %d", cond);
                                g_error_free(err);
+
                                conn_info = __get_conn_info_from_fd(info, fd);
                                if (conn_info == NULL) {
                                        BT_ERR("No Connection info found with FD [%d]", fd);
                                        return FALSE;
                                }
-                               conn_info->disconnected = TRUE;
+
+                               if (conn_info->disconnected == FALSE) {
+                                       close(conn_info->fd);
+                                       conn_info->disconnected = TRUE;
+                               }
                                __rfcomm_client_disconnect(info);
                                return FALSE;
                        }
@@ -379,7 +400,9 @@ static void __client_connected_cb(rfcomm_cb_data_t *cb_data, char *dev_address,
        bluetooth_rfcomm_connection_t conn_info;
        bt_event_info_t *event_info;
        rfcomm_conn_info_t *conn_list_info = NULL;
-       BT_INFO_C("Connected [RFCOMM Client]");
+
+       if (result == BLUETOOTH_ERROR_NONE)
+               BT_INFO_C("### Connected [RFCOMM Client]");
 
        event_info = _bt_event_get_cb_data(BT_RFCOMM_CLIENT_EVENT);
        if (event_info == NULL)
@@ -406,6 +429,38 @@ static void __client_connected_cb(rfcomm_cb_data_t *cb_data, char *dev_address,
        BT_DBG("-");
 }
 
+void _bt_rfcomm_client_disconnect_all(void)
+{
+       GSList *client;
+       GSList *conn;
+
+       BT_INFO_C("### Disconnect all RFCOMM client connections");
+
+       for (client = rfcomm_clients; client; ) {
+               rfcomm_cb_data_t *info = client->data;
+
+               for (conn = info->rfcomm_conns; conn; conn = conn->next) {
+                       rfcomm_conn_info_t *conn_info = conn->data;
+
+                       if (conn_info == NULL)
+                               continue;
+
+                       if (conn_info->watch_id == 0 || conn_info->disconnected)
+                               continue;
+
+                       close(conn_info->fd);
+                       conn_info->disconnected = TRUE;
+
+                       _bt_disconnect_ext_profile(conn_info->bt_addr,
+                                                  info->obj_path);
+               }
+
+               client = client->next;
+               __rfcomm_client_disconnect(info);
+       }
+
+       return;
+}
 #endif
 
 int new_connection(const char *path, int fd, bluetooth_device_address_t *addr)
@@ -413,31 +468,39 @@ int new_connection(const char *path, int fd, bluetooth_device_address_t *addr)
        rfcomm_cb_data_t *info;
        GIOChannel *data_io;
        rfcomm_conn_info_t *conn_info = NULL;
-       BT_DBG("%s %d", path, fd);
        char address[BT_ADDRESS_STRING_SIZE];
+
+       BT_INFO("%s %d", path, fd);
+
        _bt_convert_addr_type_to_string(address,
                                (unsigned char *)addr);
+
        info = __find_rfcomm_info_from_path(path);
-       if (info == NULL)
+       if (info == NULL) {
+               BT_ERR("rfcomm info is NULL");
                return -1;
-       conn_info = __get_conn_info_from_address(info, address);
+       }
 
+       conn_info = __get_conn_info_from_address(info, address);
        if (conn_info == NULL) {
-               BT_ERR("Device Address %s not found in connection list", address);
+               BT_ERR("connection info is NULL");
                return -1;
        }
+
        conn_info->fd = fd;
-       BT_DBG("connection info fd %d", conn_info->fd);
+
        data_io = g_io_channel_unix_new(fd);
+
        g_io_channel_set_encoding(data_io, NULL, NULL);
        g_io_channel_set_flags(data_io, G_IO_FLAG_NONBLOCK, NULL);
+
        conn_info->watch_id = g_io_add_watch(data_io,
                                G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
                                __client_data_received_cb, info);
 
        g_io_channel_unref(data_io);
 
-       __client_connected_cb(info, address,BLUETOOTH_ERROR_NONE);
+       __client_connected_cb(info, address, BLUETOOTH_ERROR_NONE);
 
        return 0;
 }
@@ -447,6 +510,7 @@ static void __bt_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
 
 {
        GError *error = NULL;
+       GVariant *value;
        rfcomm_cb_data_t *cb_data;
        char dev_address[BT_ADDRESS_STRING_SIZE];
        const char *path;
@@ -456,7 +520,8 @@ static void __bt_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
 
        cb_data = user_data;
 
-       if (!g_dbus_proxy_call_finish(proxy, res, &error)) {
+       value = g_dbus_proxy_call_finish(proxy, res, &error);
+       if (value == NULL) {
                int result;
                g_dbus_error_strip_remote_error(error);
                BT_ERR("Error : %s \n", error->message);
@@ -470,7 +535,10 @@ static void __bt_connect_response_cb(GDBusProxy *proxy, GAsyncResult *res,
                __rfcomm_client_connected_cb(cb_data, dev_address, result);
 
                g_error_free(error);
+       } else {
+               g_variant_unref(value);
        }
+
        if (proxy)
                g_object_unref(proxy);
 
@@ -483,6 +551,7 @@ static void __bt_discover_service_response_cb(GDBusProxy *proxy,
        rfcomm_cb_data_t *cb_data;
        int ret = 0;
        GError *err = NULL;
+       GVariant *value;
        bt_register_profile_info_t info = {0};
        int result = BLUETOOTH_ERROR_NONE;
        char dev_address[BT_ADDRESS_STRING_SIZE];
@@ -498,9 +567,11 @@ static void __bt_discover_service_response_cb(GDBusProxy *proxy,
 
        _bt_convert_device_path_to_address(path, dev_address);
        BT_DBG("Device Adress [%s]", dev_address);
-       g_dbus_proxy_call_finish(proxy, res, &err);
+       value = g_dbus_proxy_call_finish(proxy, res, &err);
        if (proxy)
                g_object_unref(proxy);
+       if (value)
+               g_variant_unref(value);
 
        if (err != NULL) {
                g_dbus_error_strip_remote_error(err);
@@ -558,7 +629,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
                const char *remote_uuid)
 {
 
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
        rfcomm_cb_data_t *cb_data = NULL;
        rfcomm_conn_info_t *conn = NULL;
 #else
@@ -571,7 +642,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
        BT_CHECK_PARAMETER(remote_uuid, return);
        BT_CHECK_ENABLED(return);
 
-#ifdef TIZEN_DPM_ENABLE
+#ifdef TIZEN_FEATURE_BT_DPM
        if (_bt_check_dpm(BT_DPM_ADDRESS, (void *)remote_bt_address) == BT_DPM_RESTRICTED) {
                BT_ERR("Blacklist device");
                return BLUETOOTH_ERROR_DEVICE_POLICY_RESTRICTION;
@@ -597,8 +668,8 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
        }
 #endif
 
-#ifdef RFCOMM_DIRECT
-       BT_INFO_C("<<<<<<<<< RFCOMM Connect request from app >>>>>>>>>>>");
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
+       BT_INFO_C("### Connect RFCOMM");
        int ret;
        int id, object_id;
        char *path;
@@ -620,6 +691,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
                object_id = _bt_register_new_conn(path, new_connection);
                if (object_id < 0) {
                        __rfcomm_delete_id(id);
+                       g_free(path);
                        return BLUETOOTH_ERROR_INTERNAL;
                }
 
@@ -629,6 +701,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
                cb_data->object_id = object_id;
                cb_data->id = id;
        }
+
        conn = g_new0(rfcomm_conn_info_t, 1);
        conn->fd = -1;
        _bt_convert_addr_type_to_string(conn->bt_addr,
@@ -636,6 +709,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
 
        BT_DBG("Connecting to %s uuid %s", conn->bt_addr, remote_uuid);
        cb_data->rfcomm_conns = g_slist_append(cb_data->rfcomm_conns, conn);
+
        ret = _bt_discover_services(conn->bt_addr, (char *)remote_uuid,
                                __bt_discover_service_response_cb, cb_data);
        if (ret != BLUETOOTH_ERROR_NONE) {
@@ -645,6 +719,7 @@ BT_EXPORT_API int bluetooth_rfcomm_connect(
                        rfcomm_cb_data_remove(cb_data);
                return BLUETOOTH_ERROR_INTERNAL;
        }
+
        if (g_slist_find(rfcomm_clients, cb_data) == NULL) {
                BT_INFO("Adding callback information to rfcomm_clients");
                rfcomm_clients = g_slist_append(rfcomm_clients, cb_data);
@@ -709,10 +784,10 @@ BT_EXPORT_API int bluetooth_rfcomm_client_is_connected(const bluetooth_device_ad
                client_info = l->data;
                if (client_info == NULL)
                        continue;
-               for(conn_list = client_info->rfcomm_conns;
+               for (conn_list = client_info->rfcomm_conns;
                        conn_list != NULL; conn_list = conn_list->next) {
                        conn_info = conn_list->data;
-                       if(conn_info == NULL)
+                       if (conn_info == NULL)
                                continue;
 
                        if (g_strcmp0(address, conn_info->bt_addr) == 0) {
@@ -756,10 +831,12 @@ BT_EXPORT_API gboolean bluetooth_rfcomm_is_client_connected(void)
 
 BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
 {
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
        rfcomm_cb_data_t *info;
        rfcomm_conn_info_t *conn_info;
-       BT_INFO_C("<<<<<<<<< RFCOMM Disconnect request from app >>>>>>>>");
+
+       BT_INFO_C("### Disconnect RFCOMM");
+
        BT_CHECK_ENABLED(return);
 
        if (_bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT)
@@ -768,6 +845,7 @@ BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
                return BLUETOOTH_ERROR_PERMISSION_DEINED;
        }
 
+       BT_DBG("Requested FD %d", socket_fd);
        if (socket_fd < 0) {
                BT_ERR("Invalid FD");
                return BLUETOOTH_ERROR_INVALID_PARAM;
@@ -779,26 +857,30 @@ BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
                BT_DBG("Could not find in client, so check in server");
                return bluetooth_rfcomm_server_disconnect(socket_fd);
        }
+
        conn_info = __get_conn_info_from_fd(info, socket_fd);
        if (conn_info == NULL) {
-               BT_ERR("FATAL Error");
+               BT_ERR("Could not find connection info");
                return BLUETOOTH_ERROR_INTERNAL;
        }
-       if (conn_info->watch_id <= 0) {
+
+       if (conn_info->watch_id == 0 || conn_info->disconnected) {
                BT_ERR("Invalid state");
                return BLUETOOTH_ERROR_NOT_CONNECTED;
        }
+
+       close(conn_info->fd);
        conn_info->disconnected = TRUE;
-       close(socket_fd);
+
        BT_INFO("conn_info %s", conn_info->bt_addr);
-       _bt_disconnect_profile(conn_info->bt_addr, info->uuid, NULL,NULL);
+       _bt_disconnect_ext_profile(conn_info->bt_addr, info->obj_path);
+
        if (info->idle_id == 0)
                info->idle_id = g_idle_add(__rfcomm_client_disconnect, info);
 
        return BLUETOOTH_ERROR_NONE;
 #else
        int result;
-       int service_function;
 
        BT_CHECK_ENABLED(return);
 
@@ -808,15 +890,14 @@ BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
        /* Support the OSP */
        if (socket_fd == -1) {
                /* Cancel connect */
-               service_function = BT_RFCOMM_CLIENT_CANCEL_CONNECT;
+               result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_CLIENT_CANCEL_CONNECT,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
        } else {
                g_array_append_vals(in_param1, &socket_fd, sizeof(int));
-               service_function = BT_RFCOMM_SOCKET_DISCONNECT;
+               result = _bt_send_request(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_DISCONNECT,
+                       in_param1, in_param2, in_param3, in_param4, &out_param);
        }
 
-       result = _bt_send_request(BT_BLUEZ_SERVICE, service_function,
-               in_param1, in_param2, in_param3, in_param4, &out_param);
-
        BT_DBG("result: %x", result);
 
        BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
@@ -827,7 +908,7 @@ BT_EXPORT_API int bluetooth_rfcomm_disconnect(int socket_fd)
 
 BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length)
 {
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
        int written;
 #else
        char *buffer;
@@ -840,14 +921,12 @@ BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length)
                return BLUETOOTH_ERROR_INVALID_PARAM;
        }
 
-       BT_DBG("FD : %d", fd);
-
-#ifndef RFCOMM_DIRECT
+#ifndef TIZEN_FEATURE_BT_RFCOMM_DIRECT
        BT_CHECK_ENABLED(return);
 #endif
        retv_if(length <= 0, BLUETOOTH_ERROR_INVALID_PARAM);
 
-#ifdef TIZEN_DPM_ENABLE
+#ifdef TIZEN_FEATURE_BT_DPM
        if (_bt_check_dpm(BT_DPM_SPP, NULL) == BT_DPM_RESTRICTED ||
                _bt_check_dpm(BT_DPM_HF_ONLY, NULL) == BT_DPM_RESTRICTED) {
                BT_ERR("Not allow to write RFCOMM data");
@@ -855,7 +934,7 @@ BT_EXPORT_API int bluetooth_rfcomm_write(int fd, const char *buf, int length)
        }
 #endif
 
-#ifdef RFCOMM_DIRECT
+#ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
        switch (privilege_token) {
        case 0:
                result = _bt_check_privilege(BT_BLUEZ_SERVICE, BT_RFCOMM_SOCKET_WRITE);