Initial code to have support to listen over a RFCOMM socket for incoming
connections.
---
Makefile.am | 1 +
plugins/bluetooth.c | 165
+++++++++++++++++++++++++++++++++++++++++++++++++++
plugins/bluetooth.h | 11 ++++
3 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index a38fcb9..77b1453 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -321,6 +321,7 @@ builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
builtin_modules += hfp
builtin_sources += plugins/hfp.c plugins/bluetooth.h
+builtin_sources += $(btio_sources)
builtin_cflags += @BLUEZ_CFLAGS@
builtin_libadd += @BLUEZ_LIBS@
endif
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 93dd7a1..dcf75e6 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -35,13 +35,58 @@
#include<ofono/dbus.h>
+#include<btio.h>
#include "bluetooth.h"
static DBusConnection *connection;
static GHashTable *uuid_hash = NULL;
static GHashTable *adapter_address_hash = NULL;
+static GSList *server_list = NULL;
static gint bluetooth_refcount;
+struct server {
+ guint16 service;
+ gchar *name;
+ guint8 channel;
+ GIOChannel *io;
+ char *adapter;
+ guint handle;
+ ConnectFunc connect_cb;
+ gpointer user_data;
+};
+
+typedef struct {
+ guint8 b[6];
+} __attribute__((packed)) bdaddr_t;
+
+static void baswap(bdaddr_t *dst, const bdaddr_t *src)
+{
+ register unsigned char *d = (unsigned char *) dst;
+ register const unsigned char *s = (const unsigned char *) src;
+ register int i;
+
+ for (i = 0; i< 6; i++)
+ d[i] = s[5-i];
+}
+
+static int str2ba(const char *str, bdaddr_t *ba)
+{
+ guint8 b[6];
+ const char *ptr = str;
+ int i;
+
+ for (i = 0; i< 6; i++) {
+ b[i] = (guint8) strtol(ptr, NULL, 16);
+ if (i != 5&& !(ptr = strchr(ptr, ':')))
+ ptr = ":00:00:00:00:00";
+ ptr++;
+ }
+
+ baswap(ba, (bdaddr_t *) b);
+
+ return 0;
+}
+
void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
{
@@ -371,6 +416,70 @@ static gboolean property_changed(DBusConnection
*connection, DBusMessage *msg,
return TRUE;
}
+static void server_stop(gpointer data)
+{
+ struct server *server = data;
+
+ if (server->handle> 0) {
+ DBusMessage *msg;
+
+ msg = dbus_message_new_method_call(BLUEZ_SERVICE,
+ server->adapter,
+ BLUEZ_SERVICE_INTERFACE,
+ "RemoveRecord");
+ dbus_message_append_args(msg, DBUS_TYPE_UINT32,&server->handle,
+ DBUS_TYPE_INVALID);
+ g_dbus_send_message(connection, msg);
+
+ server->handle = 0;
+ }
+
+ if (server->io != NULL) {
+ g_io_channel_shutdown(server->io, TRUE, NULL);
+ g_io_channel_unref(server->io);
+ server->io = NULL;
+ }
+
+ g_free(server->adapter);
+ server->adapter = NULL;
+}
+
+static void new_connection(GIOChannel *io, gpointer user_data)
+{
+ struct server *server = user_data;
+
+ DBG("%p", server);
+}
+
+static void server_start(gpointer data, gpointer user_data)
+{
+ struct server *server = data;
+ char *addr, *path = user_data;
+ bdaddr_t baddr;
+ GError *err = NULL;
+
+ if (server->handle != 0)
+ return;
+
+ addr = g_hash_table_lookup(adapter_address_hash, path);
+ str2ba(addr,&baddr);
+ server->io = bt_io_listen(BT_IO_RFCOMM, NULL, new_connection,
+ server, NULL,&err,
+ BT_IO_OPT_SOURCE_BDADDR,&baddr,
+ BT_IO_OPT_CHANNEL, server->channel,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+ if (server->io == NULL) {
+ ofono_error("Bluetooth %s register failed: %s",
+ server->name, err->message);
+ g_error_free(err);
+ server_stop(server);
+ return;
+ }
+
+ server->adapter = g_strdup(path);
+}
+