summaryrefslogtreecommitdiffstats
path: root/plugins/hfp_hf_bluez5.c
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2013-01-28 18:11:03 -0300
committerDenis Kenzior <denkenz@gmail.com>2013-01-29 09:01:26 -0600
commite05b3dfb4d37b71a2b8354b5011dccb0748e52aa (patch)
tree9e8d50b842c186c98ac5eb19a5f7644c7e2929cc /plugins/hfp_hf_bluez5.c
parent5e84f788695c88afff1eb248e8f0190629d11df7 (diff)
downloadofono-e05b3dfb4d37b71a2b8354b5011dccb0748e52aa.tar.bz2
hfp_hf_bluez5: Add SCO listen socket
This patch adds the initial SCO server socket handling. BtIO and BlueZ functions should not be used, with the new Profile API the objetive is to get rid of these dependencies.
Diffstat (limited to 'plugins/hfp_hf_bluez5.c')
-rw-r--r--plugins/hfp_hf_bluez5.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/plugins/hfp_hf_bluez5.c b/plugins/hfp_hf_bluez5.c
index 0e496ee4..d2cca055 100644
--- a/plugins/hfp_hf_bluez5.c
+++ b/plugins/hfp_hf_bluez5.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <fcntl.h>
#include <sys/socket.h>
#include <glib.h>
@@ -64,6 +65,7 @@ struct hfp {
static GHashTable *modem_hash = NULL;
static GHashTable *devices_proxies = NULL;
static GDBusClient *bluez = NULL;
+static guint sco_watch = 0;
static void hfp_debug(const char *str, void *user_data)
{
@@ -378,6 +380,71 @@ static const GDBusMethodTable profile_methods[] = {
{ }
};
+static gboolean sco_accept(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ struct sockaddr_sco saddr;
+ socklen_t alen;
+ int sk, nsk;
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
+ return FALSE;
+
+ sk = g_io_channel_unix_get_fd(io);
+
+ memset(&saddr, 0, sizeof(saddr));
+ alen = sizeof(saddr);
+
+ nsk = accept(sk, (struct sockaddr *) &saddr, &alen);
+ if (nsk < 0)
+ return TRUE;
+
+ /* TODO: Verify if the device has a modem */
+
+ return TRUE;
+}
+
+static int sco_init(void)
+{
+ GIOChannel *sco_io;
+ struct sockaddr_sco saddr;
+ int sk, defer_setup = 1;
+
+ sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET | O_NONBLOCK | SOCK_CLOEXEC,
+ BTPROTO_SCO);
+ if (sk < 0)
+ return -errno;
+
+ /* Bind to local address */
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sco_family = AF_BLUETOOTH;
+ bt_bacpy(&saddr.sco_bdaddr, BDADDR_ANY);
+
+ if (bind(sk, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
+ close(sk);
+ return -errno;
+ }
+
+ if (setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP,
+ &defer_setup, sizeof(defer_setup)) < 0)
+ ofono_warn("Can't enable deferred setup: %s (%d)",
+ strerror(errno), errno);
+
+ if (listen(sk, 5) < 0) {
+ close(sk);
+ return -errno;
+ }
+
+ sco_io = g_io_channel_unix_new(sk);
+ sco_watch = g_io_add_watch(sco_io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ sco_accept, NULL);
+
+ g_io_channel_unref(sco_io);
+
+ return 0;
+}
+
static void connect_handler(DBusConnection *conn, void *user_data)
{
DBG("Registering External Profile handler ...");
@@ -500,6 +567,12 @@ static int hfp_init(void)
if (DBUS_TYPE_UNIX_FD < 0)
return -EBADF;
+ err = sco_init();
+ if (err < 0) {
+ ofono_error("SCO: %s(%d)", strerror(-err), -err);
+ return err;
+ }
+
/* Registers External Profile handler */
if (!g_dbus_register_interface(conn, HFP_EXT_PROFILE_PATH,
BLUEZ_PROFILE_INTERFACE,
@@ -550,6 +623,9 @@ static void hfp_exit(void)
g_hash_table_destroy(modem_hash);
g_hash_table_destroy(devices_proxies);
+
+ if (sco_watch > 0)
+ g_source_remove(sco_watch);
}
OFONO_PLUGIN_DEFINE(hfp_bluez5, "External Hands-Free Profile Plugin", VERSION,