linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] oFono patches for BT DUN server
@ 2010-07-29  7:18 Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 1/6] bluetooth: Add reference count for bluetooth utils Zhenhua Zhang
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

Hi Johan and Luiz,

This series of patches are for BT DUN server support in oFono. Could
you please to review them especially the btio.[ch] changes in patch
2/6.

oFono git: git://git.kernel.org/pub/scm/network/ofono/ofono.git

Thanks.
Zhenhua


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] bluetooth: Add reference count for bluetooth utils
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  2010-07-31 23:25   ` Gustavo F. Padovan
  2010-07-29  7:18 ` [PATCH 2/6] bluetooth: Add Btio library for DUN Zhenhua Zhang
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

Add bluetooth_ref()/bluetooth_unref() to support reference count in
bluetooth utils.
---
 plugins/bluetooth.c |   62 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 5a85eaa..10cc49d 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -39,6 +39,7 @@
 static DBusConnection *connection;
 static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
+static gint ref_count;
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
 				char *buf, int size)
@@ -503,13 +504,10 @@ static guint adapter_added_watch;
 static guint adapter_removed_watch;
 static guint property_watch;
 
-int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
+static int bluetooth_init()
 {
 	int err;
 
-	if (uuid_hash)
-		goto done;
-
 	connection = ofono_dbus_get_connection();
 
 	bluetooth_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE,
@@ -542,13 +540,6 @@ int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
 	adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
 						g_free, g_free);
 
-done:
-	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile);
-
-	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties",
-				manager_properties_cb, NULL, NULL, -1,
-				DBUS_TYPE_INVALID);
-
 	return 0;
 
 remove:
@@ -556,14 +547,27 @@ remove:
 	g_dbus_remove_watch(connection, adapter_added_watch);
 	g_dbus_remove_watch(connection, adapter_removed_watch);
 	g_dbus_remove_watch(connection, property_watch);
+
 	return err;
 }
 
-void bluetooth_unregister_uuid(const char *uuid)
+static int bluetooth_ref()
 {
-	g_hash_table_remove(uuid_hash, uuid);
+	g_atomic_int_inc(&ref_count);
+
+	if (ref_count > 1)
+		return 0;
+
+	return bluetooth_init();
+}
+
+static void bluetooth_unref()
+{
+	gboolean is_zero;
+
+	is_zero = g_atomic_int_dec_and_test(&ref_count);
 
-	if (g_hash_table_size(uuid_hash))
+	if (is_zero == FALSE)
 		return;
 
 	g_dbus_remove_watch(connection, bluetooth_watch);
@@ -571,9 +575,33 @@ void bluetooth_unregister_uuid(const char *uuid)
 	g_dbus_remove_watch(connection, adapter_removed_watch);
 	g_dbus_remove_watch(connection, property_watch);
 
-	g_hash_table_destroy(uuid_hash);
-	g_hash_table_destroy(adapter_address_hash);
-	uuid_hash = NULL;
+	if (uuid_hash)
+		g_hash_table_destroy(uuid_hash);
+
+	if (adapter_address_hash)
+		g_hash_table_destroy(adapter_address_hash);
+}
+
+int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
+{
+	int err = bluetooth_ref();
+
+	if (err != 0)
+		return err;
+
+	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile);
+
+	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties",
+				manager_properties_cb, NULL, NULL, -1,
+				DBUS_TYPE_INVALID);
+	return 0;
+}
+
+void bluetooth_unregister_uuid(const char *uuid)
+{
+	g_hash_table_remove(uuid_hash, uuid);
+
+	bluetooth_unref();
 }
 
 OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] bluetooth: Add Btio library for DUN
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 1/6] bluetooth: Add reference count for bluetooth utils Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 3/6] bluetooth: Add bluetooth server support " Zhenhua Zhang
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

Btio library is the low level socket API for BT RFCOMM connection.
---
 plugins/btio.c |  479 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/btio.h |  118 ++++++++++++++
 2 files changed, 597 insertions(+), 0 deletions(-)
 create mode 100644 plugins/btio.c
 create mode 100644 plugins/btio.h

diff --git a/plugins/btio.c b/plugins/btio.c
new file mode 100644
index 0000000..6156027
--- /dev/null
+++ b/plugins/btio.c
@@ -0,0 +1,479 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009  Nokia Corporation
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <glib.h>
+
+#include "btio.h"
+
+#define ERROR_FAILED(gerr, str, err) \
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED, \
+				str ": %s (%d)", strerror(err), err)
+
+#define DEFAULT_DEFER_TIMEOUT 30
+
+struct set_opts {
+	bdaddr_t src;
+	int defer;
+	int sec_level;
+	uint8_t channel;
+	int master;
+};
+
+struct connect {
+	BtIOConnect connect;
+	gpointer user_data;
+	GDestroyNotify destroy;
+};
+
+struct accept {
+	BtIOConnect connect;
+	gpointer user_data;
+	GDestroyNotify destroy;
+};
+
+struct server {
+	BtIOConnect connect;
+	BtIOConfirm confirm;
+	gpointer user_data;
+	GDestroyNotify destroy;
+};
+
+static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
+{
+	memcpy(dst, src, sizeof(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 ba2str(const bdaddr_t *ba, char *str)
+{
+	uint8_t b[6];
+
+	baswap((bdaddr_t *) b, ba);
+	return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
+		b[0], b[1], b[2], b[3], b[4], b[5]);
+}
+
+static void server_remove(struct server *server)
+{
+	if (server->destroy)
+		server->destroy(server->user_data);
+	g_free(server);
+}
+
+static void accept_remove(struct accept *accept)
+{
+	if (accept->destroy)
+		accept->destroy(accept->user_data);
+	g_free(accept);
+}
+
+static gboolean accept_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct accept *accept = user_data;
+	GError *err = NULL;
+
+	/* If the user aborted this accept attempt */
+	if (cond & G_IO_NVAL)
+		return FALSE;
+
+	if (cond & (G_IO_HUP | G_IO_ERR))
+		g_set_error(&err, BT_IO_ERROR, BT_IO_ERROR_DISCONNECTED,
+				"HUP or ERR on socket");
+
+	accept->connect(io, err, accept->user_data);
+
+	g_clear_error(&err);
+
+	return FALSE;
+}
+
+static gboolean server_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct server *server = user_data;
+	int srv_sock, cli_sock;
+	GIOChannel *cli_io;
+
+	/* If the user closed the server */
+	if (cond & G_IO_NVAL)
+		return FALSE;
+
+	srv_sock = g_io_channel_unix_get_fd(io);
+
+	cli_sock = accept(srv_sock, NULL, NULL);
+	if (cli_sock < 0)
+		return TRUE;
+
+	cli_io = g_io_channel_unix_new(cli_sock);
+
+	g_io_channel_set_close_on_unref(cli_io, TRUE);
+	g_io_channel_set_flags(cli_io, G_IO_FLAG_NONBLOCK, NULL);
+
+	if (server->confirm)
+		server->confirm(cli_io, server->user_data);
+	else
+		server->connect(cli_io, NULL, server->user_data);
+
+	g_io_channel_unref(cli_io);
+
+	return TRUE;
+}
+
+static void server_add(GIOChannel *io, BtIOConnect connect,
+				BtIOConfirm confirm, gpointer user_data,
+				GDestroyNotify destroy)
+{
+	struct server *server;
+	GIOCondition cond;
+
+	server = g_new0(struct server, 1);
+	server->connect = connect;
+	server->confirm = confirm;
+	server->user_data = user_data;
+	server->destroy = destroy;
+
+	cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, server_cb, server,
+					(GDestroyNotify) server_remove);
+}
+
+static void accept_add(GIOChannel *io, BtIOConnect connect, gpointer user_data,
+							GDestroyNotify destroy)
+{
+	struct accept *accept;
+	GIOCondition cond;
+
+	accept = g_new0(struct accept, 1);
+	accept->connect = connect;
+	accept->user_data = user_data;
+	accept->destroy = destroy;
+
+	cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT, cond, accept_cb, accept,
+					(GDestroyNotify) accept_remove);
+}
+
+static int rfcomm_set_lm(int sock, int level)
+{
+	int lm_map[] = {
+		0,
+		RFCOMM_LM_AUTH,
+		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT,
+		RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE,
+	}, opt = lm_map[level];
+
+	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static gboolean set_sec_level(int sock, BtIOType type, int level, GError **err)
+{
+	struct bt_security sec;
+	int ret;
+
+	if (level < BT_SECURITY_LOW || level > BT_SECURITY_HIGH) {
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Valid security level range is %d-%d",
+				BT_SECURITY_LOW, BT_SECURITY_HIGH);
+		return FALSE;
+	}
+
+	memset(&sec, 0, sizeof(sec));
+	sec.level = level;
+
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec,
+							sizeof(sec)) == 0)
+		return TRUE;
+
+	if (errno != ENOPROTOOPT) {
+		ERROR_FAILED(err, "setsockopt(BT_SECURITY)", errno);
+		return FALSE;
+	}
+
+	ret = rfcomm_set_lm(sock, level);
+	if (ret < 0) {
+		ERROR_FAILED(err, "setsockopt(LM)", -ret);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int rfcomm_bind(int sock, const bdaddr_t *src, uint8_t channel)
+{
+	struct sockaddr_rc addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, src);
+	addr.rc_channel = channel;
+
+	return bind(sock, (struct sockaddr *) &addr, sizeof(addr));
+}
+
+static gboolean rfcomm_set(int sock, int sec_level, int master, GError **err)
+{
+	if (sec_level && !set_sec_level(sock, BT_IO_RFCOMM, sec_level, err))
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean parse_set_opts(struct set_opts *opts, GError **err,
+						BtIOOption opt1, va_list args)
+{
+	BtIOOption opt = opt1;
+
+	memset(opts, 0, sizeof(*opts));
+
+	/* Set defaults */
+	opts->defer = DEFAULT_DEFER_TIMEOUT;
+	opts->master = -1;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_CHANNEL:
+			opts->channel = va_arg(args, int);
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			opts->sec_level = va_arg(args, int);
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static gboolean get_peers(int sock, struct sockaddr *src, struct sockaddr *dst,
+				socklen_t len, GError **err)
+{
+	socklen_t olen;
+
+	memset(src, 0, len);
+	olen = len;
+	if (getsockname(sock, src, &olen) < 0) {
+		ERROR_FAILED(err, "getsockname", errno);
+		return FALSE;
+	}
+
+	memset(dst, 0, len);
+	olen = len;
+	if (getpeername(sock, dst, &olen) < 0) {
+		ERROR_FAILED(err, "getpeername", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
+								va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_rc src, dst;
+
+	if (!get_peers(sock, (struct sockaddr *) &src,
+				(struct sockaddr *) &dst, sizeof(src), err))
+		return FALSE;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			ba2str(&src.rc_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.rc_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_CHANNEL:
+			*(va_arg(args, uint8_t *)) = src.rc_channel ?
+					src.rc_channel : dst.rc_channel;
+			break;
+		default:
+			g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+					"Unknown option %d", opt);
+			return FALSE;
+		}
+
+		opt = va_arg(args, int);
+	}
+
+	return TRUE;
+}
+
+static gboolean get_valist(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, va_list args)
+{
+	int sock = g_io_channel_unix_get_fd(io);
+
+	if (type != BT_IO_RFCOMM) {
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Unknown BtIO type %d", type);
+		return FALSE;
+	}
+
+	return rfcomm_get(sock, err, opt1, args);
+}
+
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
+					GDestroyNotify destroy, GError **err)
+{
+	int sock;
+	char c;
+	struct pollfd pfd;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	memset(&pfd, 0, sizeof(pfd));
+	pfd.fd = sock;
+	pfd.events = POLLOUT;
+
+	if (poll(&pfd, 1, 0) < 0) {
+		ERROR_FAILED(err, "poll", errno);
+		return FALSE;
+	}
+
+	if (!(pfd.revents & POLLOUT)) {
+		int ret;
+		ret = read(sock, &c, 1);
+	}
+
+	accept_add(io, connect, user_data, destroy);
+
+	return TRUE;
+}
+
+gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
+							BtIOOption opt1, ...)
+{
+	va_list args;
+	gboolean ret;
+
+	va_start(args, opt1);
+	ret = get_valist(io, type, err, opt1, args);
+	va_end(args);
+
+	return ret;
+}
+
+static GIOChannel *create_io(BtIOType type, gboolean server,
+					struct set_opts *opts, GError **err)
+{
+	int sock;
+	GIOChannel *io;
+
+	if (type != BT_IO_RFCOMM)
+		return NULL;
+
+	sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (sock < 0) {
+		ERROR_FAILED(err, "socket(STREAM, RFCOMM)", errno);
+		return NULL;
+	}
+
+	if (rfcomm_bind(sock, &opts->src,
+				server ? opts->channel : 0) < 0) {
+		ERROR_FAILED(err, "rfcomm_bind", errno);
+		return NULL;
+	}
+
+	if (!rfcomm_set(sock, opts->sec_level, opts->master, err))
+		return NULL;
+
+	io = g_io_channel_unix_new(sock);
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+	g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
+
+	return io;
+}
+
+GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
+				BtIOConfirm confirm, gpointer user_data,
+				GDestroyNotify destroy, GError **err,
+				BtIOOption opt1, ...)
+{
+	GIOChannel *io;
+	va_list args;
+	struct set_opts opts;
+	int sock;
+	gboolean ret;
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, err, opt1, args);
+	va_end(args);
+
+	if (ret == FALSE)
+		return NULL;
+
+	io = create_io(type, TRUE, &opts, err);
+	if (io == NULL)
+		return NULL;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	if (confirm)
+		setsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, &opts.defer,
+							sizeof(opts.defer));
+
+	if (listen(sock, 5) < 0) {
+		ERROR_FAILED(err, "listen", errno);
+		g_io_channel_unref(io);
+		return NULL;
+	}
+
+	server_add(io, connect, confirm, user_data, destroy);
+
+	return io;
+}
+
+GQuark bt_io_error_quark(void)
+{
+	return g_quark_from_static_string("bt-io-error-quark");
+}
diff --git a/plugins/btio.h b/plugins/btio.h
new file mode 100644
index 0000000..78d5961
--- /dev/null
+++ b/plugins/btio.h
@@ -0,0 +1,118 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009  Nokia Corporation
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <glib.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#ifndef AF_BLUETOOTH
+#define AF_BLUETOOTH	31
+#define PF_BLUETOOTH	AF_BLUETOOTH
+#endif
+
+#define BTPROTO_RFCOMM		3
+#define SOL_RFCOMM		18
+#define SOL_BLUETOOTH		274
+
+struct bt_security {
+	uint8_t level;
+};
+#define BT_SECURITY_SDP		0
+#define BT_SECURITY_LOW		1
+#define BT_SECURITY_MEDIUM	2
+#define BT_SECURITY_HIGH	3
+#define BT_SECURITY		4
+
+#define BT_DEFER_SETUP		7
+
+/* BD Address */
+typedef struct {
+	uint8_t b[6];
+} __attribute__((packed)) bdaddr_t;
+
+#define RFCOMM_LM       	0x03
+#define RFCOMM_LM_AUTH		0x0002
+#define RFCOMM_LM_ENCRYPT	0x0004
+#define RFCOMM_LM_TRUSTED	0x0008
+#define RFCOMM_LM_RELIABLE	0x0010
+#define RFCOMM_LM_SECURE	0x0020
+
+#include <sys/socket.h>
+
+/* RFCOMM socket address */
+struct sockaddr_rc {
+	sa_family_t	rc_family;
+	bdaddr_t	rc_bdaddr;
+	uint8_t		rc_channel;
+};
+
+typedef enum {
+	BT_IO_ERROR_DISCONNECTED,
+	BT_IO_ERROR_CONNECT_FAILED,
+	BT_IO_ERROR_FAILED,
+	BT_IO_ERROR_INVALID_ARGS,
+} BtIOError;
+
+#define BT_IO_ERROR bt_io_error_quark()
+
+GQuark bt_io_error_quark(void);
+
+typedef enum {
+	BT_IO_RFCOMM,
+} BtIOType;
+
+typedef enum {
+	BT_IO_OPT_INVALID = 0,
+	BT_IO_OPT_SOURCE,
+	BT_IO_OPT_DEST,
+	BT_IO_OPT_SEC_LEVEL,
+	BT_IO_OPT_CHANNEL,
+} BtIOOption;
+
+typedef enum {
+	BT_IO_SEC_SDP = 0,
+	BT_IO_SEC_LOW,
+	BT_IO_SEC_MEDIUM,
+	BT_IO_SEC_HIGH,
+} BtIOSecLevel;
+
+typedef void (*BtIOConfirm)(GIOChannel *io, gpointer user_data);
+
+typedef void (*BtIOConnect)(GIOChannel *io, GError *err, gpointer user_data);
+
+gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data,
+					GDestroyNotify destroy, GError **err);
+
+gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
+					BtIOOption opt1, ...);
+
+GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
+					BtIOConfirm confirm, gpointer user_data,
+					GDestroyNotify destroy, GError **err,
+					BtIOOption opt1, ...);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] bluetooth: Add bluetooth server support for DUN
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 1/6] bluetooth: Add reference count for bluetooth utils Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 2/6] bluetooth: Add Btio library for DUN Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 4/6] modem: Add method to get modem by path Zhenhua Zhang
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

It watches Bluetooth adapter property changes and addes DUN record to
listen DUN client connection request.
---
 plugins/bluetooth.c |  379 +++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/bluetooth.h |   14 ++
 2 files changed, 393 insertions(+), 0 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 10cc49d..5890161 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -35,12 +35,71 @@
 #include <ofono/dbus.h>
 
 #include "bluetooth.h"
+#include "btio.h"
 
 static DBusConnection *connection;
 static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
+static GSList *server_list = NULL;
 static gint ref_count;
 
+static const gchar *dun_record = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>	\
+<record>									\
+  <attribute id=\"0x0001\">							\
+    <sequence>									\
+      <uuid value=\"0x1103\"/>							\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0004\">							\
+    <sequence>									\
+      <sequence>								\
+        <uuid value=\"0x0100\"/>						\
+      </sequence>								\
+      <sequence>								\
+        <uuid value=\"0x0003\"/>						\
+        <uint8 value=\"%u\" name=\"channel\"/>					\
+      </sequence>								\
+      <sequence>								\
+        <uuid value=\"0x0008\"/>						\
+      </sequence>								\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0009\">							\
+    <sequence>									\
+      <sequence>								\
+        <uuid value=\"0x1103\"/>						\
+        <uint16 value=\"0x0100\" name=\"version\"/>				\
+      </sequence>								\
+    </sequence>									\
+  </attribute>									\
+										\
+  <attribute id=\"0x0100\">							\
+    <text value=\"%s\" name=\"name\"/>						\
+  </attribute>									\
+</record>";
+
+#define TIMEOUT (60*1000) /* Timeout for user response (miliseconds) */
+
+struct client {
+	GIOChannel	*io;
+	guint		watch;
+};
+
+struct server {
+	guint16		service;
+	gchar		*name;
+	guint8		channel;
+	GIOChannel	*io;
+	gchar		*adapter;
+	guint		handle;
+	ConnectFunc	connect_cb;
+	gpointer	user_data;
+
+	struct client	client;
+};
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
 				char *buf, int size)
 {
@@ -370,6 +429,253 @@ static gboolean property_changed(DBusConnection *connection, DBusMessage *msg,
 	return TRUE;
 }
 
+static void disconnect(struct server *server)
+{
+	struct client *client = &server->client;
+
+	if (!client->io)
+		return;
+
+	g_io_channel_unref(client->io);
+	client->io = NULL;
+
+	if (client->watch > 0) {
+		g_source_remove(client->watch);
+		client->watch = 0;
+	}
+
+	return;
+}
+
+static void server_stop(gpointer data, gpointer user_data)
+{
+	struct server *server = data;
+
+	disconnect(server);
+
+	if (server->handle) {
+		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) {
+		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 gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	struct server *server = data;
+
+	disconnect(server);
+
+	return FALSE;
+}
+
+static void cancel_authorization(struct server *server)
+{
+	DBusMessage *msg;
+
+	if (!server->adapter)
+		return;
+
+	msg = dbus_message_new_method_call(BLUEZ_SERVICE, server->adapter,
+						BLUEZ_SERVICE_INTERFACE,
+						"CancelAuthorization");
+
+	g_dbus_send_message(connection, msg);
+}
+
+static void auth_cb(DBusPendingCall *call, gpointer user_data)
+{
+	struct server *server = user_data;
+	struct client *client = &server->client;
+	GIOChannel *io = client->io;
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+	GError *err = NULL;
+
+	dbus_error_init(&derr);
+
+	if (dbus_set_error_from_message(&derr, reply)) {
+		ofono_error("RequestAuthorization error: %s, %s",
+				derr.name, derr.message);
+
+		if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
+			cancel_authorization(server);
+
+		dbus_error_free(&derr);
+		goto failed;
+	}
+
+	ofono_info("RequestAuthorization succeeded");
+
+	if (!bt_io_accept(io, server->connect_cb, server->user_data,
+						NULL, &err)) {
+		ofono_error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	g_source_remove(client->watch);
+
+	client->watch = g_io_add_watch(client->io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					client_event, server);
+
+	dbus_message_unref(reply);
+
+	return;
+
+failed:
+	dbus_message_unref(reply);
+	disconnect(server);
+}
+
+static gboolean auth_watch(GIOChannel *io, GIOCondition cond,
+						gpointer user_data)
+{
+	struct server *server = user_data;
+
+	cancel_authorization(server);
+	disconnect(server);
+
+	return FALSE;
+}
+
+static void confirm_event(GIOChannel *io, gpointer user_data)
+{
+	struct server *server = user_data;
+	struct client *client = &server->client;
+	GError *err = NULL;
+	char address[18];
+	const char *addr;
+	guint8 channel;
+	int ret;
+
+	if (client->io) {
+		ofono_error("Rejecting connection since one client already \
+				connected");
+		return;
+	}
+
+	bt_io_get(io, BT_IO_RFCOMM, &err, BT_IO_OPT_DEST, address,
+					BT_IO_OPT_CHANNEL, &channel,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		ofono_error("%s", err->message);
+		g_error_free(err);
+		return;
+	}
+
+	ofono_info("New connection from: %s, channel %u", address, channel);
+
+	addr = address;
+	ret = bluetooth_send_with_reply(server->adapter,
+					BLUEZ_SERVICE_INTERFACE,
+					"RequestAuthorization",
+					auth_cb, server, NULL, TIMEOUT,
+					DBUS_TYPE_STRING, &addr,
+					DBUS_TYPE_UINT32, &server->handle,
+					DBUS_TYPE_INVALID);
+	if (ret < 0) {
+		ofono_error("Request Bluetooth authorization failed");
+		return;
+	}
+
+	ofono_info("RequestAuthorization(%s, 0x%x)", address, server->handle);
+
+	client->io = g_io_channel_ref(io);
+	client->watch = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					auth_watch, server);
+
+	return;
+}
+
+static void add_record_cb(DBusPendingCall *call, gpointer user_data)
+{
+	struct server *server = user_data;
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	DBusError derr;
+	guint32 handle;
+
+	dbus_error_init(&derr);
+
+	if (dbus_set_error_from_message(&derr, reply)) {
+		ofono_error("Replied with an error: %s, %s",
+					derr.name, derr.message);
+		dbus_error_free(&derr);
+		server_stop(server, NULL);
+		goto done;
+	}
+
+	dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32, &handle,
+					DBUS_TYPE_INVALID);
+	server->handle = handle;
+
+	ofono_info("Registered: %s, handle: 0x%x", server->name, handle);
+
+done:
+	dbus_message_unref(reply);
+}
+
+static void server_start(gpointer data, gpointer user_data)
+{
+	struct server *server = data;
+	gchar *path = user_data;
+	GError *err = NULL;
+	gchar *xml;
+
+	if (server->handle != 0)
+		return;
+
+	if (server->service != DUN_GW)
+		goto failed;
+
+	server->io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event,
+					server, NULL, &err,
+					BT_IO_OPT_CHANNEL, server->channel,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+					BT_IO_OPT_INVALID);
+	if (!server->io) {
+		ofono_error("Bluetooth %s register failed: %s",
+					server->name, err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	server->adapter = g_strdup(path);
+
+	xml = g_markup_printf_escaped(dun_record, server->channel,
+					server->name);
+
+	bluetooth_send_with_reply(path, BLUEZ_SERVICE_INTERFACE, "AddRecord",
+					add_record_cb, server, NULL, -1,
+					DBUS_TYPE_STRING, &xml,
+					DBUS_TYPE_INVALID);
+
+	g_free(xml);
+
+	return;
+
+failed:
+	server_stop(server, NULL);
+}
+
 static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data)
 {
 	const char *path = user_data;
@@ -394,6 +700,9 @@ static void adapter_properties_cb(DBusPendingCall *call, gpointer user_data)
 	g_hash_table_insert(adapter_address_hash,
 				g_strdup(path), g_strdup(addr));
 
+	if (server_list)
+		g_slist_foreach(server_list, server_start, (gpointer)path);
+
 	for (l = device_list; l; l = l->next) {
 		const char *device = l->data;
 
@@ -428,11 +737,26 @@ static gboolean adapter_removed(DBusConnection *connection,
 				DBusMessage *message, void *user_data)
 {
 	const char *path;
+	GSList *l;
 
 	if (dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
 				DBUS_TYPE_INVALID) == TRUE)
 		g_hash_table_remove(adapter_address_hash, path);
 
+	for (l = server_list; l; l = l->next) {
+		struct server *server = l->data;
+
+		if (!server->adapter)
+			continue;
+
+		if (!g_str_equal(path, server->adapter))
+			continue;
+
+		/* Don't remove handle if the adapter has been removed */
+		server->handle = 0;
+		server_stop(server, NULL);
+	}
+
 	return TRUE;
 }
 
@@ -564,6 +888,7 @@ static int bluetooth_ref()
 static void bluetooth_unref()
 {
 	gboolean is_zero;
+	GSList *l;
 
 	is_zero = g_atomic_int_dec_and_test(&ref_count);
 
@@ -580,6 +905,20 @@ static void bluetooth_unref()
 
 	if (adapter_address_hash)
 		g_hash_table_destroy(adapter_address_hash);
+
+	if (server_list == NULL)
+		return;
+
+	for (l = server_list; l; l = l->next) {
+		struct server *server = l->data;
+
+		server_stop(server, NULL);
+		g_free(server->name);
+		g_free(server);
+	}
+
+	g_slist_free(server_list);
+	server_list = NULL;
 }
 
 int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
@@ -604,5 +943,45 @@ void bluetooth_unregister_uuid(const char *uuid)
 	bluetooth_unref();
 }
 
+struct server *bluetooth_register_server(guint16 service, char *name,
+						guint8 channel, ConnectFunc cb,
+						gpointer user_data)
+{
+	struct server *server;
+	int err = bluetooth_ref();
+
+	if (err != 0)
+		return NULL;
+
+	server = g_try_new0(struct server, 1);
+	if (!server)
+		return NULL;
+
+	server->service = service;
+	server->name = g_strdup(name);
+	server->channel = channel;
+	server->connect_cb = cb;
+	server->user_data = user_data;
+
+	server_list = g_slist_prepend(server_list, server);
+
+	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties",
+					manager_properties_cb, NULL, NULL, -1,
+					DBUS_TYPE_INVALID);
+
+	return server;
+}
+
+void bluetooth_unregister_server(struct server *server)
+{
+	server_list = g_slist_remove(server_list, server);
+
+	server_stop(server, NULL);
+	g_free(server->name);
+	g_free(server);
+
+	bluetooth_unref();
+}
+
 OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
 			OFONO_PLUGIN_PRIORITY_DEFAULT, NULL, NULL)
diff --git a/plugins/bluetooth.h b/plugins/bluetooth.h
index fb0d841..ab42c99 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -2,6 +2,7 @@
  *  oFono - Open Source Telephony
  *
  *  Copyright (C) 2010 Gustavo F. Padovan <gustavo@padovan.org>
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -22,12 +23,16 @@
 #define	BLUEZ_MANAGER_INTERFACE		BLUEZ_SERVICE ".Manager"
 #define	BLUEZ_ADAPTER_INTERFACE		BLUEZ_SERVICE ".Adapter"
 #define	BLUEZ_DEVICE_INTERFACE		BLUEZ_SERVICE ".Device"
+#define	BLUEZ_SERVICE_INTERFACE		BLUEZ_SERVICE ".Service"
 
 #define HFP_AG_UUID	"0000111F-0000-1000-8000-00805F9B34FB"
 
 /* Profiles bitfield */
 #define HFP_AG 0x01
 
+/* Service bitfield */
+#define DUN_GW 0x01
+
 struct bluetooth_profile {
 	const char *name;
 	int (*create)(const char *device, const char *dev_addr,
@@ -36,10 +41,19 @@ struct bluetooth_profile {
 	void (*set_alias)(const char *device, const char *);
 };
 
+typedef void (*ConnectFunc)(GIOChannel *io, GError *err, gpointer user_data);
+
+struct server;
+
 int bluetooth_register_uuid(const char *uuid,
 				struct bluetooth_profile *profile);
 void bluetooth_unregister_uuid(const char *uuid);
 
+struct server *bluetooth_register_server(guint16 service, char *name,
+						guint8 channel, ConnectFunc cb,
+						gpointer user_data);
+void bluetooth_unregister_server(struct server *server);
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
 							char *buf, int size);
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] modem: Add method to get modem by path
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
                   ` (2 preceding siblings ...)
  2010-07-29  7:18 ` [PATCH 3/6] bluetooth: Add bluetooth server support " Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 5/6] dun_gw: Add DUN server plugin for oFono Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 6/6] emulator: Add emulator atom in oFono Zhenhua Zhang
  5 siblings, 0 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

Return modem instance by searching modem path.
---
 include/modem.h |    1 +
 src/modem.c     |   15 +++++++++++++++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/modem.h b/include/modem.h
index e1cd049..34c3fbf 100644
--- a/include/modem.h
+++ b/include/modem.h
@@ -36,6 +36,7 @@ void ofono_modem_remove_interface(struct ofono_modem *modem,
 					const char *interface);
 
 const char *ofono_modem_get_path(struct ofono_modem *modem);
+struct ofono_modem *ofono_modem_get_modem_by_path(const char *path);
 
 void ofono_modem_set_data(struct ofono_modem *modem, void *data);
 void *ofono_modem_get_data(struct ofono_modem *modem);
diff --git a/src/modem.c b/src/modem.c
index f89d609..6907a5e 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -157,6 +157,21 @@ const char *ofono_modem_get_path(struct ofono_modem *modem)
 	return NULL;
 }
 
+struct ofono_modem *ofono_modem_get_modem_by_path(const char *path)
+{
+	GSList *l;
+	struct ofono_modem *modem = NULL;
+
+	for (l = g_modem_list; l; l = l->next) {
+		modem = l->data;
+
+		if (g_str_equal(modem->path, path))
+			break;
+	}
+
+	return modem;
+}
+
 struct ofono_atom *__ofono_modem_add_atom(struct ofono_modem *modem,
 					enum ofono_atom_type type,
 					void (*destruct)(struct ofono_atom *),
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] dun_gw: Add DUN server plugin for oFono
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
                   ` (3 preceding siblings ...)
  2010-07-29  7:18 ` [PATCH 4/6] modem: Add method to get modem by path Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  2010-07-29  7:18 ` [PATCH 6/6] emulator: Add emulator atom in oFono Zhenhua Zhang
  5 siblings, 0 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

DUN server plug-in watches ofono modem status. When the modem comes to
ONLINE state, it registers itself on Bluetooth adapter and want for
incoming DUN connection.
---
 Makefile.am      |    4 ++
 plugins/dun_gw.c |  143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+), 0 deletions(-)
 create mode 100644 plugins/dun_gw.c

diff --git a/Makefile.am b/Makefile.am
index e256841..2e08ff2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -242,6 +242,10 @@ builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
 builtin_modules += hfp
 builtin_sources += plugins/hfp.c plugins/bluetooth.h
 
+builtin_modules += dun_gw
+builtin_sources += plugins/dun_gw.c plugins/bluetooth.h plugins/btio.c \
+			plugins/btio.h
+
 builtin_modules += palmpre
 builtin_sources += plugins/palmpre.c
 
diff --git a/plugins/dun_gw.c b/plugins/dun_gw.c
new file mode 100644
index 0000000..56bd03d
--- /dev/null
+++ b/plugins/dun_gw.c
@@ -0,0 +1,143 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <ofono.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+
+#include <ofono/dbus.h>
+
+#include "gdbus.h"
+#include "bluetooth.h"
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+#define DUN_GW_CHANNEL	1
+
+static struct server *server;
+static int modem_watch;
+
+static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+	DBG("");
+
+	if (err) {
+		DBG("%s", err->message);
+		goto failed;
+	}
+
+	return;
+
+failed:
+	g_io_channel_shutdown(io, TRUE, NULL);
+	bluetooth_unregister_server(server);
+	server = NULL;
+}
+
+static gboolean property_changed(DBusConnection *connection, DBusMessage *msg,
+					void *user_data)
+{
+	const char *property;
+	DBusMessageIter iter, var;
+
+	dbus_message_iter_init(msg, &iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		return FALSE;
+
+	dbus_message_iter_get_basic(&iter, &property);
+
+	if (g_str_equal(property, "Online") == TRUE) {
+		const char *path = dbus_message_get_path(msg);
+		struct ofono_modem *modem;
+		struct ofono_atom *gprs;
+		gboolean online;
+
+		if (!dbus_message_iter_next(&iter))
+			return FALSE;
+
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+			return FALSE;
+
+		dbus_message_iter_recurse(&iter, &var);
+
+		dbus_message_iter_get_basic(&var, &online);
+
+		if (online == FALSE) {
+			bluetooth_unregister_server(server);
+			server = NULL;
+			goto done;
+		}
+
+		/* Create DUN server */
+		modem = ofono_modem_get_modem_by_path(path);
+		gprs = __ofono_modem_find_atom(modem,
+						OFONO_ATOM_TYPE_GPRS);
+		/* Make sure the modem has GPRS atom */
+		if (!gprs)
+			goto done;
+
+		server = bluetooth_register_server(DUN_GW,
+				"Dial-Up Networking", DUN_GW_CHANNEL,
+				dun_gw_connect_cb, modem);
+	}
+
+done:
+	return TRUE;
+}
+
+static int dun_gw_init()
+{
+	DBusConnection *connection = ofono_dbus_get_connection();
+
+	if (DBUS_TYPE_UNIX_FD < 0)
+		return -EBADF;
+
+	modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+						OFONO_MODEM_INTERFACE,
+						"PropertyChanged",
+						property_changed, NULL, NULL);
+
+	return 0;
+}
+
+static void dun_gw_exit()
+{
+	if (server)
+		bluetooth_unregister_server(server);
+
+	if (modem_watch)
+		g_source_remove(modem_watch);
+}
+
+OFONO_PLUGIN_DEFINE(dun_gw, "Dial-up Networking Profile Plugins", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT, dun_gw_init, dun_gw_exit)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] emulator: Add emulator atom in oFono
  2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
                   ` (4 preceding siblings ...)
  2010-07-29  7:18 ` [PATCH 5/6] dun_gw: Add DUN server plugin for oFono Zhenhua Zhang
@ 2010-07-29  7:18 ` Zhenhua Zhang
  5 siblings, 0 replies; 9+ messages in thread
From: Zhenhua Zhang @ 2010-07-29  7:18 UTC (permalink / raw)
  To: linux-bluetooth

DUN server could create emulator and use GAtServer to talk AT commands
to DUN client side.
---
 Makefile.am        |    4 +-
 include/emulator.h |   41 ++++++++++++++++++
 plugins/dun_gw.c   |    8 +++
 src/emulator.c     |  121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ofono.h        |    3 +
 5 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 include/emulator.h
 create mode 100644 src/emulator.c

diff --git a/Makefile.am b/Makefile.am
index 2e08ff2..1ec04f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,7 @@ include_HEADERS = include/log.h include/plugin.h include/history.h \
 			include/cbs.h include/call-volume.h \
 			include/gprs.h include/gprs-context.h \
 			include/radio-settings.h include/stk.h \
-			include/nettime.h
+			include/nettime.h include/emulator.h
 
 nodist_include_HEADERS = include/version.h
 
@@ -274,7 +274,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) \
 			src/storage.c src/cbs.c src/watch.c src/call-volume.c \
 			src/gprs.c src/idmap.h src/idmap.c \
 			src/radio-settings.c src/stkutil.h src/stkutil.c \
-			src/nettime.c
+			src/nettime.c src/emulator.c
 
 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
 
diff --git a/include/emulator.h b/include/emulator.h
new file mode 100644
index 0000000..1033e59
--- /dev/null
+++ b/include/emulator.h
@@ -0,0 +1,41 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __OFONO_EMULATOR_H
+#define __OFONO_EMULATOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ofono/types.h>
+
+struct ofono_emulator;
+
+struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
+						enum ofono_atom_type type,
+						GIOChannel *io);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OFONO_EMULATOR_H */
diff --git a/plugins/dun_gw.c b/plugins/dun_gw.c
index 56bd03d..840d22d 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw.c
@@ -48,6 +48,9 @@ static int modem_watch;
 
 static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
+	struct ofono_modem *modem = user_data;
+	struct ofono_emulator *emulator;
+
 	DBG("");
 
 	if (err) {
@@ -55,6 +58,11 @@ static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 		goto failed;
 	}
 
+	emulator = ofono_emulator_create(modem, OFONO_ATOM_TYPE_EMULATOR_DUN,
+						io);
+	if (!emulator)
+		goto failed;
+
 	return;
 
 failed:
diff --git a/src/emulator.c b/src/emulator.c
new file mode 100644
index 0000000..6219bb1
--- /dev/null
+++ b/src/emulator.c
@@ -0,0 +1,121 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2010  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <gdbus.h>
+
+#include "ofono.h"
+#include "common.h"
+#include "gatserver.h"
+
+struct ofono_emulator {
+	struct ofono_modem *modem;
+	struct ofono_atom *atom;
+	enum ofono_atom_type type;
+	unsigned int id;
+	GAtServer *server;
+};
+
+static unsigned int ofono_emulator_ids;
+
+static void ofono_emulator_debug(const char *str, void *data)
+{
+	g_print("%s: %s\n", (char *)data, str);
+}
+
+static unsigned int ofono_emulator_next_id()
+{
+	unsigned int i;
+
+	for (i = 1; i < sizeof(ofono_emulator_ids) * 8; i++) {
+		if (ofono_emulator_ids & (0x1 << i))
+			continue;
+
+		ofono_emulator_ids |= (0x1 << i);
+
+		return i;
+	}
+
+	return 0;
+}
+
+static void ofono_emulator_release_id(int id)
+{
+	ofono_emulator_ids &= ~(0x1 << id);
+}
+
+static void emulator_remove(struct ofono_atom *atom)
+{
+	struct ofono_emulator *e =  __ofono_atom_get_data(atom);
+
+	DBG("");
+
+	g_at_server_shutdown(e->server);
+	g_at_server_unref(e->server);
+	e->server = NULL;
+
+	ofono_emulator_release_id(e->id);
+	g_free(e);
+	e = NULL;
+}
+
+static void emulator_disconnect(gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	__ofono_atom_free(e->atom);
+}
+
+struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
+						enum ofono_atom_type type,
+						GIOChannel *channel)
+{
+	struct ofono_emulator *e;
+
+	DBG("");
+
+	e = g_try_new0(struct ofono_emulator, 1);
+	if (!e)
+		return NULL;
+
+	e->server = g_at_server_new(channel);
+	if (!e->server) {
+		g_free(e);
+		return NULL;
+	}
+
+	g_at_server_set_debug(e->server, ofono_emulator_debug, "Server");
+	g_at_server_set_disconnect_function(e->server, emulator_disconnect, e);
+
+	e->modem = modem;
+	e->type = type;
+	e->id = ofono_emulator_next_id();
+	e->atom = __ofono_modem_add_atom(modem, type, emulator_remove, e);
+
+	return e;
+}
diff --git a/src/ofono.h b/src/ofono.h
index aaa01d9..8982a95 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -117,6 +117,7 @@ enum ofono_atom_type {
 	OFONO_ATOM_TYPE_RADIO_SETTINGS = 18,
 	OFONO_ATOM_TYPE_STK = 19,
 	OFONO_ATOM_TYPE_NETTIME = 20,
+	OFONO_ATOM_TYPE_EMULATOR_DUN = 21,
 };
 
 enum ofono_atom_watch_condition {
@@ -289,3 +290,5 @@ void __ofono_nettime_probe_drivers(struct ofono_modem *modem);
 
 void __ofono_nettime_info_received(struct ofono_modem *modem,
 					struct ofono_network_time *info);
+
+#include <ofono/emulator.h>
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/6] bluetooth: Add reference count for bluetooth utils
  2010-07-29  7:18 ` [PATCH 1/6] bluetooth: Add reference count for bluetooth utils Zhenhua Zhang
@ 2010-07-31 23:25   ` Gustavo F. Padovan
  2010-08-02  0:20     ` Zhang, Zhenhua
  0 siblings, 1 reply; 9+ messages in thread
From: Gustavo F. Padovan @ 2010-07-31 23:25 UTC (permalink / raw)
  To: Zhenhua Zhang; +Cc: linux-bluetooth

Hi Zhenhua,

* Zhenhua Zhang <zhenhua.zhang@intel.com> [2010-07-29 15:18:16 +0800]:

> Add bluetooth_ref()/bluetooth_unref() to support reference count in
> bluetooth utils.
> ---
>  plugins/bluetooth.c |   62 +++++++++++++++++++++++++++++++++++++--------------
>  1 files changed, 45 insertions(+), 17 deletions(-)
> 
> diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
> index 5a85eaa..10cc49d 100644
> --- a/plugins/bluetooth.c
> +++ b/plugins/bluetooth.c
> @@ -39,6 +39,7 @@
>  static DBusConnection *connection;
>  static GHashTable *uuid_hash = NULL;
>  static GHashTable *adapter_address_hash = NULL;
> +static gint ref_count;
>  
>  void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
>  				char *buf, int size)
> @@ -503,13 +504,10 @@ static guint adapter_added_watch;
>  static guint adapter_removed_watch;
>  static guint property_watch;
>  
> -int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
> +static int bluetooth_init()
>  {
>  	int err;
>  
> -	if (uuid_hash)
> -		goto done;
> -
>  	connection = ofono_dbus_get_connection();
>  
>  	bluetooth_watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE,
> @@ -542,13 +540,6 @@ int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
>  	adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
>  						g_free, g_free);
>  
> -done:
> -	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile);
> -
> -	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties",
> -				manager_properties_cb, NULL, NULL, -1,
> -				DBUS_TYPE_INVALID);
> -
>  	return 0;
>  
>  remove:
> @@ -556,14 +547,27 @@ remove:
>  	g_dbus_remove_watch(connection, adapter_added_watch);
>  	g_dbus_remove_watch(connection, adapter_removed_watch);
>  	g_dbus_remove_watch(connection, property_watch);
> +
>  	return err;
>  }
>  
> -void bluetooth_unregister_uuid(const char *uuid)
> +static int bluetooth_ref()
>  {
> -	g_hash_table_remove(uuid_hash, uuid);
> +	g_atomic_int_inc(&ref_count);
> +
> +	if (ref_count > 1)
> +		return 0;
> +
> +	return bluetooth_init();
> +}
> +
> +static void bluetooth_unref()
> +{
> +	gboolean is_zero;
> +
> +	is_zero = g_atomic_int_dec_and_test(&ref_count);
>  
> -	if (g_hash_table_size(uuid_hash))
> +	if (is_zero == FALSE)
>  		return;

We can remove the is_zero variable, and test g_atomic_int_dec_and_test()
directly. What do you think?

>  
>  	g_dbus_remove_watch(connection, bluetooth_watch);
> @@ -571,9 +575,33 @@ void bluetooth_unregister_uuid(const char *uuid)
>  	g_dbus_remove_watch(connection, adapter_removed_watch);
>  	g_dbus_remove_watch(connection, property_watch);
>  
> -	g_hash_table_destroy(uuid_hash);
> -	g_hash_table_destroy(adapter_address_hash);
> -	uuid_hash = NULL;
> +	if (uuid_hash)
> +		g_hash_table_destroy(uuid_hash);
> +
> +	if (adapter_address_hash)
> +		g_hash_table_destroy(adapter_address_hash);
> +}
> +
> +int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile *profile)
> +{
> +	int err = bluetooth_ref();
> +
> +	if (err != 0)
> +		return err;
> +
> +	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile);
> +
> +	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE, "GetProperties",
> +				manager_properties_cb, NULL, NULL, -1,
> +				DBUS_TYPE_INVALID);
> +	return 0;
> +}
> +
> +void bluetooth_unregister_uuid(const char *uuid)
> +{
> +	g_hash_table_remove(uuid_hash, uuid);
> +
> +	bluetooth_unref();
>  }
>  
>  OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
> -- 
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH 1/6] bluetooth: Add reference count for bluetooth utils
  2010-07-31 23:25   ` Gustavo F. Padovan
@ 2010-08-02  0:20     ` Zhang, Zhenhua
  0 siblings, 0 replies; 9+ messages in thread
From: Zhang, Zhenhua @ 2010-08-02  0:20 UTC (permalink / raw)
  To: Gustavo F. Padovan; +Cc: linux-bluetooth@vger.kernel.org

Hi Padovan,

Gustavo F. Padovan wrote:
> Hi Zhenhua,
> 
> * Zhenhua Zhang <zhenhua.zhang@intel.com> [2010-07-29 15:18:16 +0800]:
> 
>> Add bluetooth_ref()/bluetooth_unref() to support reference count in
>> bluetooth utils.
>> ---
>>  plugins/bluetooth.c |   62
>>  +++++++++++++++++++++++++++++++++++++-------------- 1 files
>> changed, 45 insertions(+), 17 deletions(-) 
>> 
>> diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
>> index 5a85eaa..10cc49d 100644
>> --- a/plugins/bluetooth.c
>> +++ b/plugins/bluetooth.c
>> @@ -39,6 +39,7 @@
>>  static DBusConnection *connection;
>>  static GHashTable *uuid_hash = NULL;
>>  static GHashTable *adapter_address_hash = NULL;
>> +static gint ref_count;
>> 
>>  void bluetooth_create_path(const char *dev_addr, const char
>> *adapter_addr,  				char *buf, int size) @@ -503,13 +504,10 @@
>>  static guint adapter_added_watch; static guint
>>  adapter_removed_watch; static guint property_watch;
>> 
>> -int bluetooth_register_uuid(const char *uuid, struct
>>  bluetooth_profile *profile) +static int bluetooth_init() {
>>  	int err;
>> 
>> -	if (uuid_hash)
>> -		goto done;
>> -
>>  	connection = ofono_dbus_get_connection();
>> 
>>  	bluetooth_watch = g_dbus_add_service_watch(connection,
>> BLUEZ_SERVICE, @@ -542,13 +540,6 @@ int
>>  	bluetooth_register_uuid(const char *uuid, struct bluetooth_profile
>> *profile) adapter_address_hash = g_hash_table_new_full(g_str_hash,
>> g_str_equal,  						g_free, g_free);  
>> 
>> -done:
>> -	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); -
>> -	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE,
>> "GetProperties", 
>> -				manager_properties_cb, NULL, NULL, -1,
>> -				DBUS_TYPE_INVALID);
>> -
>>  	return 0;
>> 
>>  remove:
>> @@ -556,14 +547,27 @@ remove:
>>  	g_dbus_remove_watch(connection, adapter_added_watch);
>>  	g_dbus_remove_watch(connection, adapter_removed_watch);
>>  	g_dbus_remove_watch(connection, property_watch);
>> +
>>  	return err;
>>  }
>> 
>> -void bluetooth_unregister_uuid(const char *uuid)
>> +static int bluetooth_ref()
>>  {
>> -	g_hash_table_remove(uuid_hash, uuid);
>> +	g_atomic_int_inc(&ref_count);
>> +
>> +	if (ref_count > 1)
>> +		return 0;
>> +
>> +	return bluetooth_init();
>> +}
>> +
>> +static void bluetooth_unref()
>> +{
>> +	gboolean is_zero;
>> +
>> +	is_zero = g_atomic_int_dec_and_test(&ref_count);
>> 
>> -	if (g_hash_table_size(uuid_hash))
>> +	if (is_zero == FALSE)
>>  		return;
> 
> We can remove the is_zero variable, and test
> g_atomic_int_dec_and_test() directly. What do you think?

Actually I think it's ok to keep this variable. We also have it in gatchat and gatppp.

Thanks,
Zhenhua

>> 
>>  	g_dbus_remove_watch(connection, bluetooth_watch);
>> @@ -571,9 +575,33 @@ void bluetooth_unregister_uuid(const char *uuid)
>>  	g_dbus_remove_watch(connection, adapter_removed_watch);
>>  	g_dbus_remove_watch(connection, property_watch);
>> 
>> -	g_hash_table_destroy(uuid_hash);
>> -	g_hash_table_destroy(adapter_address_hash);
>> -	uuid_hash = NULL;
>> +	if (uuid_hash)
>> +		g_hash_table_destroy(uuid_hash);
>> +
>> +	if (adapter_address_hash)
>> +		g_hash_table_destroy(adapter_address_hash);
>> +}
>> +
>> +int bluetooth_register_uuid(const char *uuid, struct
>> bluetooth_profile *profile) +{ +	int err = bluetooth_ref();
>> +
>> +	if (err != 0)
>> +		return err;
>> +
>> +	g_hash_table_insert(uuid_hash, g_strdup(uuid), profile); +
>> +	bluetooth_send_with_reply("/", BLUEZ_MANAGER_INTERFACE,
>> "GetProperties", +				manager_properties_cb, NULL, NULL, -1,
>> +				DBUS_TYPE_INVALID);
>> +	return 0;
>> +}
>> +
>> +void bluetooth_unregister_uuid(const char *uuid)
>> +{
>> +	g_hash_table_remove(uuid_hash, uuid);
>> +
>> +	bluetooth_unref();
>>  }
>> 
>>  OFONO_PLUGIN_DEFINE(bluetooth, "Bluetooth Utils Plugins", VERSION,
>> -- 
>> 1.7.0.4
>> 
>> --
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-bluetooth" in 
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html



Regards,
Zhenhua

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-08-02  0:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-29  7:18 [PATCH 0/6] oFono patches for BT DUN server Zhenhua Zhang
2010-07-29  7:18 ` [PATCH 1/6] bluetooth: Add reference count for bluetooth utils Zhenhua Zhang
2010-07-31 23:25   ` Gustavo F. Padovan
2010-08-02  0:20     ` Zhang, Zhenhua
2010-07-29  7:18 ` [PATCH 2/6] bluetooth: Add Btio library for DUN Zhenhua Zhang
2010-07-29  7:18 ` [PATCH 3/6] bluetooth: Add bluetooth server support " Zhenhua Zhang
2010-07-29  7:18 ` [PATCH 4/6] modem: Add method to get modem by path Zhenhua Zhang
2010-07-29  7:18 ` [PATCH 5/6] dun_gw: Add DUN server plugin for oFono Zhenhua Zhang
2010-07-29  7:18 ` [PATCH 6/6] emulator: Add emulator atom in oFono Zhenhua Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).