[Adapt: HAL] Implement rfcomm socket connect 71/80071/1
authorAtul Rai <a.rai@samsung.com>
Wed, 13 Jul 2016 10:23:03 +0000 (19:23 +0900)
committerAtul Rai <a.rai@samsung.com>
Thu, 14 Jul 2016 10:02:38 +0000 (19:02 +0900)
This patch adds dbus based implementation to handle rfcomm outgoing
socket connection request in HAL.

Change-Id: I1bd0ef13bb25e1b4ca4ac95ca3f4e137fda27f62
Signed-off-by: Atul Rai <a.rai@samsung.com>
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-socket.c

index d37b579..4d96cf2 100644 (file)
@@ -13,6 +13,7 @@ SET(SRCS
 ./src/bt-hal-hidhost.c
 ./src/bt-hal-hid-dbus-handler.c
 ./src/bt-hal-socket.c
+./src/bt-hal-rfcomm-dbus-handler.c
 )
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
index 974960c..36b8f50 100644 (file)
@@ -233,5 +233,12 @@ struct hal_ev_hidhost_handshake {
        uint8_t  status;
 } __attribute__((packed));
 
+/* Bluetooth Socket HAL events */
+struct hal_ev_sock_connect {
+       short   size;
+       uint8_t bdaddr[6];
+       int     channel;
+       int     status;
+} __attribute__((packed));
 #endif //_BT_HAL_MSG_H_
 
diff --git a/bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.c
new file mode 100644 (file)
index 0000000..d6eea7c
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-rfcomm-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+
+#define BT_HAL_RFCOMM_ID_MAX 245
+#define BT_HAL_RFCOMM_MAX_BUFFER_SIZE 1024
+
+typedef struct {
+       char uuid[BT_HAL_UUID_STRING_LEN];
+       char *device_path;
+       char *obj_path;
+       int object_id;
+       int id;
+       GSList *rfcomm_conns;
+} rfcomm_cb_data_t;
+
+typedef struct {
+       char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
+       int hal_fd;
+       unsigned int hal_watch;
+       int stack_fd;
+       unsigned int bt_watch;
+} rfcomm_conn_info_t;
+
+static GSList *rfcomm_clients;
+static int latest_id = -1;
+static gboolean id_used[BT_HAL_RFCOMM_ID_MAX];
+
+int __rfcomm_assign_id(void)
+{
+       int index;
+
+       DBG("latest_id: %d", latest_id);
+
+       index = latest_id + 1;
+       if (index >= BT_HAL_RFCOMM_ID_MAX)
+               index = 0;
+
+       DBG("index: %d", index);
+
+       while (id_used[index] == TRUE) {
+               if (index == latest_id) {
+                       /* No available ID */
+                       ERR("All request ID is used");
+                       return -1;
+               }
+
+               index++;
+               if (index >= BT_HAL_RFCOMM_ID_MAX)
+                       index = 0;
+       }
+
+       latest_id = index;
+       id_used[index] = TRUE;
+       DBG("Assigned Id: %d", latest_id);
+
+       return latest_id;
+}
+
+void __rfcomm_delete_id(int id)
+{
+       if (id >= BT_HAL_RFCOMM_ID_MAX || id < 0) {
+               ERR("Invalid id %d", id);
+               return;
+       }
+
+       id_used[id] = FALSE;
+       latest_id = id - 1;
+       DBG("id: %d, latest_id: %d", id, latest_id);
+}
+
+static rfcomm_cb_data_t *__find_rfcomm_info_from_uuid(const char *uuid)
+{
+       GSList *l;
+
+       for (l = rfcomm_clients; l != NULL; l = l->next) {
+               rfcomm_cb_data_t *info = l->data;
+
+               if (g_strcmp0(info->uuid, uuid) == 0)
+                       return info;
+       }
+
+       return NULL;
+}
+
+static rfcomm_cb_data_t *__find_rfcomm_info_from_path(const char *path)
+{
+       GSList *l;
+
+       for (l = rfcomm_clients; l != NULL; l = l->next) {
+               rfcomm_cb_data_t *info = l->data;
+
+               if (info != NULL)
+                       if (g_strcmp0(info->obj_path, path) == 0)
+                               return info;
+       }
+
+       return NULL;
+}
+
+static void __bt_free_cb_data(rfcomm_cb_data_t *cb_data)
+{
+       DBG("+");
+
+       if (cb_data->id >= 0)
+               __rfcomm_delete_id(cb_data->id);
+
+       if (cb_data->object_id > 0)
+               _bt_unregister_gdbus_object(cb_data->object_id);
+
+       if (cb_data->obj_path) {
+               INFO("Unregister profile");
+               _bt_unregister_profile(cb_data->obj_path);
+       }
+
+       g_free(cb_data->obj_path);
+
+       g_free(cb_data->device_path);
+       g_free(cb_data);
+
+       DBG("-");
+}
+
+static void __rfcomm_cb_data_remove(rfcomm_cb_data_t *info)
+{
+       if (!info) {
+               ERR("info == NULL");
+               return;
+       }
+
+       if (info->rfcomm_conns == NULL) {
+               INFO("No more device connected remove info");
+               rfcomm_clients = g_slist_remove(rfcomm_clients, info);
+               __bt_free_cb_data(info);
+       }
+}
+
+static rfcomm_conn_info_t *__find_conn_info_with_stack_fd(rfcomm_cb_data_t *info, int fd)
+{
+       GSList *l;
+
+       for (l = info->rfcomm_conns; l != NULL; l = l->next) {
+               rfcomm_conn_info_t *conn_info = l->data;
+
+               if (conn_info && (conn_info->stack_fd == fd))
+                       return conn_info;
+       }
+
+       return NULL;
+}
+
+static rfcomm_conn_info_t *__find_conn_info_with_hal_fd(rfcomm_cb_data_t *info, int fd)
+{
+       GSList *l;
+       for (l = info->rfcomm_conns; l != NULL; l = l->next) {
+               rfcomm_conn_info_t *conn_info = l->data;
+
+               if (conn_info && (conn_info->hal_fd == fd))
+                       return conn_info;
+       }
+
+       return NULL;
+}
+
+static gint compare(gpointer *a, gpointer *b)
+{
+       rfcomm_conn_info_t *node = (rfcomm_conn_info_t *)a;
+       char *address = (char *)b;
+       return g_strcmp0(node->remote_addr, address);
+}
+
+static rfcomm_conn_info_t *__get_conn_info_from_address(rfcomm_cb_data_t *info,
+               char *dev_address)
+{
+       GSList *l = NULL;
+       rfcomm_conn_info_t *conn_info = NULL;
+       l = g_slist_find_custom(info->rfcomm_conns, dev_address,
+                       (GCompareFunc)compare);
+       if (l)
+               conn_info = l->data;
+       return conn_info;
+}
+
+static void __bt_free_conn(rfcomm_conn_info_t *conn)
+{
+       DBG("+");
+
+       if (conn == NULL)
+               return;
+
+       if (0 < conn->hal_fd)
+               close(conn->hal_fd);
+
+       if (conn->hal_watch > 0) {
+               g_source_remove(conn->hal_watch);
+               conn->hal_watch = 0;
+       }
+
+       if (0 < conn->stack_fd)
+               close(conn->stack_fd);
+
+       if (conn->bt_watch > 0) {
+               g_source_remove(conn->bt_watch);
+               conn->bt_watch = 0;
+       }
+
+       g_free(conn);
+       DBG("-");
+}
+
+static void __rfcomm_remove_conn_info_t(rfcomm_cb_data_t *info, char *address)
+{
+       rfcomm_conn_info_t *conn_info;
+
+       conn_info = __get_conn_info_from_address(info, address);
+       if (conn_info) {
+               info->rfcomm_conns = g_slist_remove(info->rfcomm_conns, conn_info);
+               __bt_free_conn(conn_info);
+       }
+}
+
+static int write_all(int fd, unsigned char *buf, int len)
+{
+       int sent = 0;
+
+       while (len > 0) {
+               int written;
+
+               written = write(fd, buf, len);
+               if (written < 0) {
+                       if (errno == EINTR || errno == EAGAIN)
+                               continue;
+                       return -1;
+               }
+
+               if (!written)
+                       return 0;
+
+               len -= written; buf += written; sent += written;
+       }
+
+       return sent;
+}
+
+static gboolean app_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
+{
+       gsize len;
+       unsigned int sent;
+       rfcomm_cb_data_t *info = data;
+       rfcomm_conn_info_t *conn_info;
+       unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
+       GError *err = NULL;
+       int fd;
+
+       DBG("+");
+       fd = g_io_channel_unix_get_fd(io);
+       conn_info = __find_conn_info_with_hal_fd(info, fd);
+
+       if (cond & G_IO_HUP) {
+               ERR("Socket %d hang up", fd);
+               goto fail;
+       }
+
+       if (cond & (G_IO_ERR | G_IO_NVAL)) {
+               ERR("Socket %d error", fd);
+               goto fail;
+       }
+
+       if (!conn_info) {
+               ERR("conn_info is NULL");
+               return TRUE;
+       }
+
+       /* Read data from application */
+       if (g_io_channel_read_chars(io, (gchar *)buff,
+                       BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
+                       &len, &err) == G_IO_STATUS_ERROR) {
+               if( err )
+                       ERR("IO Channel read error: %s", err->message);
+               else
+                       ERR("IO Channel read error client");
+               goto fail;
+       }
+
+       DBG("len: %d", len);
+       if (0 == len) {
+               ERR("Other end of socket is closed");
+               goto fail;
+       }
+
+       /* Send data to remote device */
+       sent = write_all(conn_info->stack_fd, buff, len);
+       if (sent < 0) {
+               ERR("write(): %s", strerror(errno));
+               goto fail;
+       }
+
+       DBG("-");
+       return TRUE;
+fail:
+       __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
+       __rfcomm_cb_data_remove(info);
+       return FALSE;
+}
+
+static gboolean stack_event_cb(GIOChannel *io, GIOCondition cond, gpointer data)
+{
+       unsigned int len;
+       unsigned int sent;
+       rfcomm_cb_data_t *info = data;
+       rfcomm_conn_info_t *conn_info;
+       unsigned char buff[BT_HAL_RFCOMM_MAX_BUFFER_SIZE];
+       GError *err = NULL;
+       int fd;
+
+       DBG("+");
+
+       fd = g_io_channel_unix_get_fd(io);
+       conn_info = __find_conn_info_with_stack_fd(info, fd);
+
+       if (cond & G_IO_HUP) {
+               ERR("Socket %d hang up", fd);
+               goto fail;
+       }
+
+       if (cond & (G_IO_ERR | G_IO_NVAL)) {
+               ERR("Socket %d error", fd);
+               goto fail;
+       }
+
+       if (!conn_info) {
+               ERR("conn_info is NULL");
+               return TRUE;
+       }
+
+       /* Read data from remote device */
+       if (g_io_channel_read_chars(io, (gchar *)buff,
+                       BT_HAL_RFCOMM_MAX_BUFFER_SIZE,
+                       &len, &err) == G_IO_STATUS_ERROR) {
+               if( err )
+                       ERR("IO Channel read error: %s", err->message);
+               else
+                       ERR("IO Channel read error client");
+               goto fail;
+       }
+
+       DBG("len: %d", len);
+       if (0 == len) {
+               ERR("Other end of socket is closed");
+               goto fail;
+       }
+
+       /* Send data to application */
+       sent = write_all(conn_info->hal_fd, buff, len);
+       if (sent < 0) {
+               ERR("write(): %s", strerror(errno));
+               goto fail;
+       }
+
+       DBG("-");
+       return TRUE;
+fail:
+       __rfcomm_remove_conn_info_t(info, conn_info->remote_addr);
+       __rfcomm_cb_data_remove(info);
+       return FALSE;
+}
+
+static int __new_connection(const char *path, int fd, bt_bdaddr_t *addr)
+{
+       char address[BT_HAL_ADDRESS_STRING_SIZE];
+       rfcomm_cb_data_t *info;
+       rfcomm_conn_info_t *conn_info;
+       struct hal_ev_sock_connect ev;
+       GIOCondition cond;
+       int len;
+       GIOChannel *io;
+
+       /* TODO: Temperary, later need to fill correct channel form correct place */
+       int chan = 0;
+
+       if (NULL == path || NULL == addr) {
+               ERR("NULL == path || NULL = addr");
+               return -1;
+       }
+
+       _bt_convert_addr_type_to_string(address, addr->address);
+       info = __find_rfcomm_info_from_path(path);
+       if (info == NULL)
+               return -1;
+
+       conn_info = __get_conn_info_from_address(info, address);
+       if (conn_info == NULL) {
+               ERR("Device Address %s not found in connection list", address);
+               return -1;
+       }
+
+       if (write(conn_info->hal_fd, &chan, sizeof(chan)) != sizeof(chan)) {
+               ERR("Error sending RFCOMM channel");
+               goto fail;
+       }
+
+       conn_info->stack_fd = fd;
+       DBG("Remote address: %s, RFCOMM fd: %d", address, conn_info->stack_fd);
+
+       /* Send rfcomm connected event */
+       memset(&ev, 0, sizeof(ev));
+       ev.size = sizeof(ev);
+       memcpy(ev.bdaddr, addr->address, 6);
+       ev.status = BT_STATUS_SUCCESS;
+       len = write_all(conn_info->hal_fd, (unsigned char *)&ev, sizeof(ev));
+       if (len < 0) {
+               ERR("%s", strerror(errno));
+               goto fail;
+       }
+
+       if (len != sizeof(ev)) {
+               ERR("Error sending connect event");
+               goto fail;;
+       }
+
+       /* Handle events from App */
+       cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
+       io = g_io_channel_unix_new(conn_info->hal_fd);
+       conn_info->hal_watch = g_io_add_watch(io, cond, app_event_cb, info);
+       g_io_channel_unref(io);
+
+       /* Handle rfcomm events from bluez */
+       cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+       io = g_io_channel_unix_new(conn_info->stack_fd);
+       conn_info->bt_watch = g_io_add_watch(io, cond, stack_event_cb, info);
+       g_io_channel_unref(io);
+
+       return 0;
+fail:
+       __rfcomm_remove_conn_info_t(info, address);
+       __rfcomm_cb_data_remove(info);
+       return -1;
+}
+
+static void __bt_connect_response_cb(GDBusProxy *proxy,
+               GAsyncResult *res, gpointer user_data)
+{
+       GError *error = NULL;
+       rfcomm_cb_data_t *cb_data;
+       char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
+       const char *path;
+
+       DBG("+");
+
+       cb_data = user_data;
+       if (cb_data == NULL) {
+               ERR("cb_data == NULL");
+               return;
+       }
+
+       if (!g_dbus_proxy_call_finish(proxy, res, &error)) {
+               ERR("Error : %s \n", error->message);
+               path = g_dbus_proxy_get_object_path(proxy);
+               _bt_convert_device_path_to_address(path, dev_address);
+               __rfcomm_remove_conn_info_t(cb_data, dev_address);
+               __rfcomm_cb_data_remove(cb_data);
+               g_error_free(error);
+       }
+
+       if (proxy)
+               g_object_unref(proxy);
+
+       DBG("-");
+}
+
+static void __bt_discover_service_response_cb(GDBusProxy *proxy,
+               GAsyncResult *res, gpointer user_data)
+{
+       rfcomm_cb_data_t *cb_data;
+       int ret = 0;
+       GError *err = NULL;
+       bt_hal_register_profile_info_t info = {0};
+       char dev_address[BT_HAL_ADDRESS_STRING_SIZE];
+       const char *path;
+
+       DBG("+");
+
+       cb_data = user_data;
+       if (!cb_data) {
+               ERR("cb_data == NULL");
+               return;
+       }
+
+       path = g_dbus_proxy_get_object_path(proxy);
+       _bt_convert_device_path_to_address(path, dev_address);
+       DBG("Device Adress [%s]", dev_address);
+
+       g_dbus_proxy_call_finish(proxy, res, &err);
+       if (proxy)
+               g_object_unref(proxy);
+       if (err != NULL) {
+               ERR("Error occured in Proxy call [%s]\n", err->message);
+               __rfcomm_remove_conn_info_t(cb_data, dev_address);
+               __rfcomm_cb_data_remove(cb_data);
+               goto done;
+       } else {
+               INFO("Services are Updated checking required uuid is there");
+               /* Check here for uuid present */
+               ret = _bt_discover_service_uuids(dev_address, cb_data->uuid);
+               if (ret == BT_STATUS_SUCCESS) {
+                       info.uuid = (char *)cb_data->uuid;
+                       info.obj_path = cb_data->obj_path;
+                       info.role = "client";
+
+                       ret = _bt_register_profile(&info, FALSE);
+                       if (ret < 0)
+                               DBG("Error: register profile");
+                       ret = _bt_connect_profile(dev_address, cb_data->uuid,
+                                       __bt_connect_response_cb, cb_data);
+                       if (ret != BT_STATUS_SUCCESS) {
+                               ERR("ConnectProfile failed");
+                               __rfcomm_remove_conn_info_t(cb_data, dev_address);
+                               __rfcomm_cb_data_remove(cb_data);
+                               goto done;
+                       }
+               } else {
+                       ERR("remote uuid not found");
+                       __rfcomm_remove_conn_info_t(cb_data, dev_address);
+                       __rfcomm_cb_data_remove(cb_data);
+               }
+       }
+done:
+       if (err)
+               g_clear_error(&err);
+}
+
+static rfcomm_cb_data_t *__get_rfcomm_cb_data(char *remote_uuid)
+{
+       int id;
+       int object_id;
+       char *path;
+       rfcomm_cb_data_t *cb_data;
+
+       DBG("+");
+
+       cb_data = __find_rfcomm_info_from_uuid(remote_uuid);
+       if (!cb_data) {
+               id = __rfcomm_assign_id();
+               if (id < 0) {
+                       ERR("__rfcomm_assign_id failed");
+                       return NULL;
+               }
+
+               path = g_strdup_printf("/org/socket/client/%d/%d", getpid(), id);
+               object_id = _bt_register_new_gdbus_object(path, __new_connection);
+               if (object_id < 0) {
+                       ERR("_bt_register_new_gdbus_object failed");
+                       __rfcomm_delete_id(id);
+                       return NULL;
+               }
+
+               cb_data = g_malloc0(sizeof(rfcomm_cb_data_t));
+               g_strlcpy(cb_data->uuid, remote_uuid, BT_HAL_UUID_STRING_LEN);
+               cb_data->obj_path = path;
+               cb_data->object_id = object_id;
+               cb_data->id = id;
+       }
+
+       DBG("-");
+       return cb_data;
+}
+
+static rfcomm_conn_info_t *__rfcomm_create_conn_info(char *addr, int *sock)
+{
+       int fds[2] = {-1, -1};
+       rfcomm_conn_info_t *conn;
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
+               ERR("socketpair(): %s", strerror(errno));
+               *sock = -1;
+               return NULL;
+       }
+
+       conn = g_malloc0(sizeof(rfcomm_conn_info_t));
+       g_strlcpy(conn->remote_addr, addr, BT_HAL_ADDRESS_STRING_SIZE);
+       conn->hal_fd = fds[0];
+       conn->stack_fd = -1;
+       *sock = fds[1];
+
+       DBG("hal_fd: %d, sock: %d", conn->hal_fd, *sock);
+
+       return conn;
+}
+
+int _bt_hal_dbus_handler_rfcomm_connect(unsigned char *addr, unsigned char *uuid, int *sock)
+{
+       int ret;
+       rfcomm_cb_data_t *cb_data;
+       rfcomm_conn_info_t *conn;
+       char remote_addr[BT_HAL_ADDRESS_STRING_SIZE];
+       char remote_uuid[BT_HAL_UUID_SIZE];
+
+       if (!addr) {
+               ERR("remote_addr is NULL");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       if (!uuid) {
+               ERR("remote_uuid is NULL");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       if (!sock) {
+               ERR("sock is NULL");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       _bt_convert_uuid_type_to_string(remote_uuid, uuid);
+       cb_data = __get_rfcomm_cb_data(remote_uuid);
+       if (!cb_data)
+               return BT_STATUS_FAIL;
+
+       _bt_convert_addr_type_to_string(remote_addr, addr);
+       DBG("Connecting to %s, uuid %s", remote_addr, remote_uuid);
+       conn = __rfcomm_create_conn_info(remote_addr, sock);
+       if (!conn)
+               return BT_STATUS_FAIL;
+
+       cb_data->rfcomm_conns = g_slist_append(cb_data->rfcomm_conns, conn);
+       ret = _bt_discover_services(remote_addr, (char *)remote_uuid,
+                       __bt_discover_service_response_cb, cb_data);
+       if (ret != BT_STATUS_SUCCESS) {
+               ERR("Error returned while service discovery");
+               __rfcomm_remove_conn_info_t(cb_data, conn->remote_addr);
+               __rfcomm_cb_data_remove(cb_data);
+               return BT_STATUS_FAIL;
+       }
+
+       if (g_slist_find(rfcomm_clients, cb_data) == NULL) {
+               INFO("Adding callback information to rfcomm_clients");
+               rfcomm_clients = g_slist_append(rfcomm_clients, cb_data);
+       } else
+               INFO("Callback information is already added");
+
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-rfcomm-dbus-handler.h
new file mode 100644 (file)
index 0000000..4ba1ac1
--- /dev/null
@@ -0,0 +1,42 @@
+/* Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef _BT_HAL_SOCKET_DBUS_HANDLER_H_
+#define _BT_HAL_SOCKET_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _bt_hal_dbus_handler_rfcomm_connect(
+       unsigned char *addr, unsigned char *uuid, int *sock);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_SOCKET_DBUS_HANDLER_H_ */
index 21f5586..b8b3d86 100644 (file)
@@ -29,6 +29,7 @@
 #include "bt-hal-log.h"
 #include "bt-hal-msg.h"
 #include "bt-hal-utils.h"
+#include "bt-hal-rfcomm-dbus-handler.h"
 
 static bt_status_t listen(btsock_type_t type, const char *service_name,
                const uint8_t *uuid, int channel, int *sock_fd, int flags)
@@ -59,9 +60,11 @@ static bt_status_t connect(const bt_bdaddr_t *bd_addr, btsock_type_t type,
 
        switch (type) {
        case BTSOCK_RFCOMM:
-               ERR("bt rfcomm socket type not supported");
-               status = BT_STATUS_UNSUPPORTED;
-               goto failed;
+               /* Call rfcomm dbus handler to connect rfcomm client */
+               status = _bt_hal_dbus_handler_rfcomm_connect(
+                               (unsigned char *)bd_addr->address,
+                               (unsigned char *)uuid, sock_fd);
+               break;
        case BTSOCK_L2CAP:
                ERR("bt l2cap socket type not supported");
                status = BT_STATUS_UNSUPPORTED;