All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
@ 2011-01-12 17:15 =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 01/21] bluetooth: Add reference count for bluetooth utils =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (22 more replies)
  0 siblings, 23 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2435 bytes --]

This is rebased as of head of today

Zhenhua Zhang (21):
  bluetooth: Add reference count for bluetooth utils
  bluetooth: Add Btio library for DUN
  bluetooth: Add bluetooth server support for DUN
  emulator: Add emulator atom in oFono
  dun_gw: Add DUN server plugin for oFono
  gprs: Rename status_watch to netreg_status_watch
  emulator: Add status watches for ofono emulator
  emulator: Add emulator status watches in gprs atom
  emulator: Add APIs to send GAtServer result
  emulator: Implement dialing up for DUN
  gprs: Make gprs_proto_to/from_string non-static
  gprs: ignore the case of proto str when comparing
  emulator: Register mandatory AT command handlers
  gprs: Refactor to share remove_context method
  gprs: Add DUN +CGATT support in gprs atom
  gprs: Add DUN +CGDCONT support in gprs atom
  gprs: Add DUN server GPRS connect support
  gprs: Add status watch functions
  gprs: Add gprs_get_status
  emulator: Watch GPRS status changes
  emulator: Watch netreg status changes

 Makefile.am            |   15 +-
 btio/btio.c            | 1299 ++++++++++++++++++++++++++++++++++++++++++++++++
 btio/btio.h            |   97 ++++
 configure.ac           |    5 +
 include/emulator.h     |   94 ++++
 include/gprs-context.h |    4 +
 include/gprs.h         |   11 +
 plugins/bluetooth.c    |  441 ++++++++++++++++-
 plugins/bluetooth.h    |   15 +
 plugins/dun_gw.c       |  115 +++++
 src/emulator.c         | 1072 +++++++++++++++++++++++++++++++++++++++
 src/gprs.c             |  500 +++++++++++++++++--
 src/modem.c            |    1 +
 src/ofono.h            |   31 ++
 14 files changed, 3636 insertions(+), 64 deletions(-)
 create mode 100644 btio/btio.c
 create mode 100644 btio/btio.h
 create mode 100644 include/emulator.h
 create mode 100644 plugins/dun_gw.c
 create mode 100644 src/emulator.c

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 01/21] bluetooth: Add reference count for bluetooth utils
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 02/21] bluetooth: Add Btio library for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 3864 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

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 602c6da..fe1eaa9 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -40,6 +40,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)
@@ -504,13 +505,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,
@@ -543,13 +541,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:
@@ -557,14 +548,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);
@@ -572,9 +576,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.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 02/21] bluetooth: Add Btio library for DUN
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 01/21] bluetooth: Add reference count for bluetooth utils =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-13 23:31   ` Denis Kenzior
  2011-01-12 17:15 ` [PATCH 03/21] bluetooth: Add bluetooth server support " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 37762 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Btio library is the low level socket API for BT RFCOMM connection. We
share the same library among BlueZ, Obex and oFono. So make sure you
synchronize to other two projects when you make changes to btio.[ch].
---
 Makefile.am  |    8 +-
 btio/btio.c  | 1299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 btio/btio.h  |   97 +++++
 configure.ac |    5 +
 4 files changed, 1407 insertions(+), 2 deletions(-)
 create mode 100644 btio/btio.c
 create mode 100644 btio/btio.h

diff --git a/Makefile.am b/Makefile.am
index 4dec90a..2a9f340 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -82,6 +82,8 @@ gisi_sources = gisi/client.c gisi/client.h gisi/common.h \
 				gisi/server.c gisi/server.h \
 				gisi/socket.c gisi/socket.h
 
+btio_sources = btio/btio.h btio/btio.c
+
 udev_files = plugins/ofono.rules
 
 if UDEV
@@ -342,7 +344,8 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
 			src/smsagent.c src/smsagent.h src/ctm.c \
 			src/cdma-voicecall.c
 
-src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
+src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ \
+			@BLUEZ_LIBS@ -ldl
 
 src_ofonod_LDFLAGS = -Wl,--export-dynamic \
 				-Wl,--version-script=$(srcdir)/src/ofono.ver
@@ -365,7 +368,8 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ @USB_CFLAGS@ \
 					-DPLUGINDIR=\""$(build_plugindir)"\"
 
 INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/src \
-			-I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat
+			-I$(srcdir)/gdbus -I$(srcdir)/gisi -I$(srcdir)/gatchat \
+			-I$(srcdir)/btio
 
 doc_files = doc/overview.txt doc/ofono-paper.txt doc/release-faq.txt \
 		doc/manager-api.txt doc/modem-api.txt doc/network-api.txt \
diff --git a/btio/btio.c b/btio/btio.c
new file mode 100644
index 0000000..574e224
--- /dev/null
+++ b/btio/btio.c
@@ -0,0 +1,1299 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009-2010  Nokia Corporation
+ *
+ *
+ *  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 <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sco.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.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;
+	bdaddr_t dst;
+	int defer;
+	int sec_level;
+	uint8_t channel;
+	uint16_t psm;
+	uint16_t mtu;
+	uint16_t imtu;
+	uint16_t omtu;
+	int master;
+	uint8_t mode;
+};
+
+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 void server_remove(struct server *server)
+{
+	if (server->destroy)
+		server->destroy(server->user_data);
+	g_free(server);
+}
+
+static void connect_remove(struct connect *conn)
+{
+	if (conn->destroy)
+		conn->destroy(conn->user_data);
+	g_free(conn);
+}
+
+static void accept_remove(struct accept *accept)
+{
+	if (accept->destroy)
+		accept->destroy(accept->user_data);
+	g_free(accept);
+}
+
+static gboolean check_nval(GIOChannel *io)
+{
+	struct pollfd fds;
+
+	memset(&fds, 0, sizeof(fds));
+	fds.fd = g_io_channel_unix_get_fd(io);
+	fds.events = POLLNVAL;
+
+	if (poll(&fds, 1, 0) > 0 && (fds.revents & POLLNVAL))
+		return TRUE;
+
+	return FALSE;
+}
+
+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) || check_nval(io))
+		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 connect_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct connect *conn = user_data;
+	GError *gerr = NULL;
+
+	/* If the user aborted this connect attempt */
+	if ((cond & G_IO_NVAL) || check_nval(io))
+		return FALSE;
+
+	if (cond & G_IO_OUT) {
+		int err = 0, sock = g_io_channel_unix_get_fd(io);
+		socklen_t len = sizeof(err);
+
+		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
+			err = errno;
+
+		if (err)
+			g_set_error(&gerr, BT_IO_ERROR,
+					BT_IO_ERROR_CONNECT_FAILED, "%s (%d)",
+					strerror(err), err);
+	} else if (cond & (G_IO_HUP | G_IO_ERR))
+		g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
+				"HUP or ERR on socket");
+
+	conn->connect(io, gerr, conn->user_data);
+
+	if (gerr)
+		g_error_free(gerr);
+
+	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) || check_nval(io))
+		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 connect_add(GIOChannel *io, BtIOConnect connect,
+				gpointer user_data, GDestroyNotify destroy)
+{
+	struct connect *conn;
+	GIOCondition cond;
+
+	conn = g_new0(struct connect, 1);
+	conn->connect = connect;
+	conn->user_data = user_data;
+	conn->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, connect_cb, conn,
+					(GDestroyNotify) connect_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 l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, GError **err)
+{
+	struct sockaddr_l2 addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, src);
+	addr.l2_psm = htobs(psm);
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "l2cap_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int l2cap_connect(int sock, const bdaddr_t *dst, uint16_t psm)
+{
+	int err;
+	struct sockaddr_l2 addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.l2_family = AF_BLUETOOTH;
+	bacpy(&addr.l2_bdaddr, dst);
+	addr.l2_psm = htobs(psm);
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static int l2cap_set_master(int sock, int master)
+{
+	int flags;
+	socklen_t len;
+
+	len = sizeof(flags);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, &len) < 0)
+		return -errno;
+
+	if (master) {
+		if (flags & L2CAP_LM_MASTER)
+			return 0;
+		flags |= L2CAP_LM_MASTER;
+	} else {
+		if (!(flags & L2CAP_LM_MASTER))
+			return 0;
+		flags &= ~L2CAP_LM_MASTER;
+	}
+
+	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags, sizeof(flags)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static int rfcomm_set_master(int sock, int master)
+{
+	int flags;
+	socklen_t len;
+
+	len = sizeof(flags);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, &len) < 0)
+		return -errno;
+
+	if (master) {
+		if (flags & RFCOMM_LM_MASTER)
+			return 0;
+		flags |= RFCOMM_LM_MASTER;
+	} else {
+		if (!(flags & RFCOMM_LM_MASTER))
+			return 0;
+		flags &= ~RFCOMM_LM_MASTER;
+	}
+
+	if (setsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags, sizeof(flags)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+static int l2cap_set_lm(int sock, int level)
+{
+	int lm_map[] = {
+		0,
+		L2CAP_LM_AUTH,
+		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT,
+		L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | L2CAP_LM_SECURE,
+	}, opt = lm_map[level];
+
+	if (setsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0)
+		return -errno;
+
+	return 0;
+}
+
+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;
+	}
+
+	if (type == BT_IO_L2CAP)
+		ret = l2cap_set_lm(sock, level);
+	else
+		ret = rfcomm_set_lm(sock, level);
+
+	if (ret < 0) {
+		ERROR_FAILED(err, "setsockopt(LM)", -ret);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int l2cap_get_lm(int sock, int *sec_level)
+{
+	int opt;
+	socklen_t len;
+
+	len = sizeof(opt);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &opt, &len) < 0)
+		return -errno;
+
+	*sec_level = 0;
+
+	if (opt & L2CAP_LM_AUTH)
+		*sec_level = BT_SECURITY_LOW;
+	if (opt & L2CAP_LM_ENCRYPT)
+		*sec_level = BT_SECURITY_MEDIUM;
+	if (opt & L2CAP_LM_SECURE)
+		*sec_level = BT_SECURITY_HIGH;
+
+	return 0;
+}
+
+static int rfcomm_get_lm(int sock, int *sec_level)
+{
+	int opt;
+	socklen_t len;
+
+	len = sizeof(opt);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &opt, &len) < 0)
+		return -errno;
+
+	*sec_level = 0;
+
+	if (opt & RFCOMM_LM_AUTH)
+		*sec_level = BT_SECURITY_LOW;
+	if (opt & RFCOMM_LM_ENCRYPT)
+		*sec_level = BT_SECURITY_MEDIUM;
+	if (opt & RFCOMM_LM_SECURE)
+		*sec_level = BT_SECURITY_HIGH;
+
+	return 0;
+}
+
+static gboolean get_sec_level(int sock, BtIOType type, int *level,
+								GError **err)
+{
+	struct bt_security sec;
+	socklen_t len;
+	int ret;
+
+	memset(&sec, 0, sizeof(sec));
+	len = sizeof(sec);
+	if (getsockopt(sock, SOL_BLUETOOTH, BT_SECURITY, &sec, &len) == 0) {
+		*level = sec.level;
+		return TRUE;
+	}
+
+	if (errno != ENOPROTOOPT) {
+		ERROR_FAILED(err, "getsockopt(BT_SECURITY)", errno);
+		return FALSE;
+	}
+
+	if (type == BT_IO_L2CAP)
+		ret = l2cap_get_lm(sock, level);
+	else
+		ret = rfcomm_get_lm(sock, level);
+
+	if (ret < 0) {
+		ERROR_FAILED(err, "getsockopt(LM)", -ret);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean l2cap_set(int sock, int sec_level, uint16_t imtu, uint16_t omtu,
+					uint8_t mode, int master, GError **err)
+{
+	if (imtu || omtu || mode) {
+		struct l2cap_options l2o;
+		socklen_t len;
+
+		memset(&l2o, 0, sizeof(l2o));
+		len = sizeof(l2o);
+		if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
+								&len) < 0) {
+			ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
+			return FALSE;
+		}
+
+		if (imtu)
+			l2o.imtu = imtu;
+		if (omtu)
+			l2o.omtu = omtu;
+		if (mode)
+			l2o.mode = mode;
+
+		if (setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o,
+							sizeof(l2o)) < 0) {
+			ERROR_FAILED(err, "setsockopt(L2CAP_OPTIONS)", errno);
+			return FALSE;
+		}
+	}
+
+	if (master >= 0 && l2cap_set_master(sock, master) < 0) {
+		ERROR_FAILED(err, "l2cap_set_master", errno);
+		return FALSE;
+	}
+
+	if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err))
+		return FALSE;
+
+	return TRUE;
+}
+
+static int rfcomm_bind(int sock,
+		const bdaddr_t *src, uint8_t channel, GError **err)
+{
+	struct sockaddr_rc addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, src);
+	addr.rc_channel = channel;
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "rfcomm_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int rfcomm_connect(int sock, const bdaddr_t *dst, uint8_t channel)
+{
+	int err;
+	struct sockaddr_rc addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.rc_family = AF_BLUETOOTH;
+	bacpy(&addr.rc_bdaddr, dst);
+	addr.rc_channel = channel;
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+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;
+
+	if (master >= 0 && rfcomm_set_master(sock, master) < 0) {
+		ERROR_FAILED(err, "rfcomm_set_master", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int sco_bind(int sock, const bdaddr_t *src, GError **err)
+{
+	struct sockaddr_sco addr;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sco_family = AF_BLUETOOTH;
+	bacpy(&addr.sco_bdaddr, src);
+
+	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		ERROR_FAILED(err, "sco_bind", errno);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int sco_connect(int sock, const bdaddr_t *dst)
+{
+	struct sockaddr_sco addr;
+	int err;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sco_family = AF_BLUETOOTH;
+	bacpy(&addr.sco_bdaddr, dst);
+
+	err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
+	if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
+		return err;
+
+	return 0;
+}
+
+static gboolean sco_set(int sock, uint16_t mtu, GError **err)
+{
+	struct sco_options sco_opt;
+	socklen_t len;
+
+	if (!mtu)
+		return TRUE;
+
+	len = sizeof(sco_opt);
+	memset(&sco_opt, 0, len);
+	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	sco_opt.mtu = mtu;
+	if (setsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt,
+						sizeof(sco_opt)) < 0) {
+		ERROR_FAILED(err, "setsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean parse_set_opts(struct set_opts *opts, GError **err,
+						BtIOOption opt1, va_list args)
+{
+	BtIOOption opt = opt1;
+	const char *str;
+
+	memset(opts, 0, sizeof(*opts));
+
+	/* Set defaults */
+	opts->defer = DEFAULT_DEFER_TIMEOUT;
+	opts->master = -1;
+	opts->sec_level = BT_IO_SEC_MEDIUM;
+	opts->mode = L2CAP_MODE_BASIC;
+
+	while (opt != BT_IO_OPT_INVALID) {
+		switch (opt) {
+		case BT_IO_OPT_SOURCE:
+			str = va_arg(args, const char *);
+			if (strncasecmp(str, "hci", 3) == 0)
+				hci_devba(atoi(str + 3), &opts->src);
+			else
+				str2ba(str, &opts->src);
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(&opts->src, va_arg(args, const bdaddr_t *));
+			break;
+		case BT_IO_OPT_DEST:
+			str2ba(va_arg(args, const char *), &opts->dst);
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(&opts->dst, va_arg(args, const bdaddr_t *));
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			opts->defer = va_arg(args, int);
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			opts->sec_level = va_arg(args, int);
+			break;
+		case BT_IO_OPT_CHANNEL:
+			opts->channel = va_arg(args, int);
+			break;
+		case BT_IO_OPT_PSM:
+			opts->psm = va_arg(args, int);
+			break;
+		case BT_IO_OPT_MTU:
+			opts->mtu = va_arg(args, int);
+			opts->imtu = opts->mtu;
+			opts->omtu = opts->mtu;
+			break;
+		case BT_IO_OPT_OMTU:
+			opts->omtu = va_arg(args, int);
+			if (!opts->mtu)
+				opts->mtu = opts->omtu;
+			break;
+		case BT_IO_OPT_IMTU:
+			opts->imtu = va_arg(args, int);
+			if (!opts->mtu)
+				opts->mtu = opts->imtu;
+			break;
+		case BT_IO_OPT_MASTER:
+			opts->master = va_arg(args, gboolean);
+			break;
+		case BT_IO_OPT_MODE:
+			opts->mode = 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 int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct l2cap_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
+								va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_l2 src, dst;
+	struct l2cap_options l2o;
+	int flags;
+	uint8_t dev_class[3];
+	uint16_t handle;
+	socklen_t len;
+
+	len = sizeof(l2o);
+	memset(&l2o, 0, len);
+	if (getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(L2CAP_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	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.l2_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.l2_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.l2_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.l2_bdaddr);
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			len = sizeof(int);
+			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
+					va_arg(args, int *), &len) < 0) {
+				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
+									errno);
+				return FALSE;
+			}
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			if (!get_sec_level(sock, BT_IO_L2CAP,
+						va_arg(args, int *), err))
+				return FALSE;
+			break;
+		case BT_IO_OPT_PSM:
+			*(va_arg(args, uint16_t *)) = src.l2_psm ?
+						src.l2_psm : dst.l2_psm;
+			break;
+		case BT_IO_OPT_OMTU:
+			*(va_arg(args, uint16_t *)) = l2o.omtu;
+			break;
+		case BT_IO_OPT_IMTU:
+			*(va_arg(args, uint16_t *)) = l2o.imtu;
+			break;
+		case BT_IO_OPT_MASTER:
+			len = sizeof(flags);
+			if (getsockopt(sock, SOL_L2CAP, L2CAP_LM, &flags,
+								&len) < 0) {
+				ERROR_FAILED(err, "getsockopt(L2CAP_LM)",
+									errno);
+				return FALSE;
+			}
+			*(va_arg(args, gboolean *)) =
+				(flags & L2CAP_LM_MASTER) ? TRUE : FALSE;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (l2cap_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			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 int rfcomm_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct rfcomm_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_RFCOMM, RFCOMM_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
+								va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_rc src, dst;
+	int flags;
+	socklen_t len;
+	uint8_t dev_class[3];
+	uint16_t handle;
+
+	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_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.rc_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.rc_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.rc_bdaddr);
+			break;
+		case BT_IO_OPT_DEFER_TIMEOUT:
+			len = sizeof(int);
+			if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP,
+					va_arg(args, int *), &len) < 0) {
+				ERROR_FAILED(err, "getsockopt(DEFER_SETUP)",
+									errno);
+				return FALSE;
+			}
+			break;
+		case BT_IO_OPT_SEC_LEVEL:
+			if (!get_sec_level(sock, BT_IO_RFCOMM,
+						va_arg(args, int *), err))
+				return FALSE;
+			break;
+		case BT_IO_OPT_CHANNEL:
+			*(va_arg(args, uint8_t *)) = src.rc_channel ?
+					src.rc_channel : dst.rc_channel;
+			break;
+		case BT_IO_OPT_SOURCE_CHANNEL:
+			*(va_arg(args, uint8_t *)) = src.rc_channel;
+			break;
+		case BT_IO_OPT_DEST_CHANNEL:
+			*(va_arg(args, uint8_t *)) = dst.rc_channel;
+			break;
+		case BT_IO_OPT_MASTER:
+			len = sizeof(flags);
+			if (getsockopt(sock, SOL_RFCOMM, RFCOMM_LM, &flags,
+								&len) < 0) {
+				ERROR_FAILED(err, "getsockopt(RFCOMM_LM)",
+									errno);
+				return FALSE;
+			}
+			*(va_arg(args, gboolean *)) =
+				(flags & RFCOMM_LM_MASTER) ? TRUE : FALSE;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			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 int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+	struct sco_conninfo info;
+	socklen_t len;
+
+	len = sizeof(info);
+	if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0)
+		return -errno;
+
+	if (handle)
+		*handle = info.hci_handle;
+
+	if (dev_class)
+		memcpy(dev_class, info.dev_class, 3);
+
+	return 0;
+}
+
+static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
+{
+	BtIOOption opt = opt1;
+	struct sockaddr_sco src, dst;
+	struct sco_options sco_opt;
+	socklen_t len;
+	uint8_t dev_class[3];
+	uint16_t handle;
+
+	len = sizeof(sco_opt);
+	memset(&sco_opt, 0, len);
+	if (getsockopt(sock, SOL_SCO, SCO_OPTIONS, &sco_opt, &len) < 0) {
+		ERROR_FAILED(err, "getsockopt(SCO_OPTIONS)", errno);
+		return FALSE;
+	}
+
+	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.sco_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_SOURCE_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &src.sco_bdaddr);
+			break;
+		case BT_IO_OPT_DEST:
+			ba2str(&dst.sco_bdaddr, va_arg(args, char *));
+			break;
+		case BT_IO_OPT_DEST_BDADDR:
+			bacpy(va_arg(args, bdaddr_t *), &dst.sco_bdaddr);
+			break;
+		case BT_IO_OPT_MTU:
+		case BT_IO_OPT_IMTU:
+		case BT_IO_OPT_OMTU:
+			*(va_arg(args, uint16_t *)) = sco_opt.mtu;
+			break;
+		case BT_IO_OPT_HANDLE:
+			if (sco_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			*(va_arg(args, uint16_t *)) = handle;
+			break;
+		case BT_IO_OPT_CLASS:
+			if (sco_get_info(sock, &handle, dev_class) < 0) {
+				ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+				return FALSE;
+			}
+			memcpy(va_arg(args, uint8_t *), dev_class, 3);
+			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;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+	case BT_IO_L2CAP:
+		return l2cap_get(sock, err, opt1, args);
+	case BT_IO_RFCOMM:
+		return rfcomm_get(sock, err, opt1, args);
+	case BT_IO_SCO:
+		return sco_get(sock, err, opt1, args);
+	}
+
+	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+			"Unknown BtIO type %d", type);
+	return FALSE;
+}
+
+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_set(GIOChannel *io, BtIOType type, GError **err,
+							BtIOOption opt1, ...)
+{
+	va_list args;
+	gboolean ret;
+	struct set_opts opts;
+	int sock;
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, err, opt1, args);
+	va_end(args);
+
+	if (!ret)
+		return ret;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+	case BT_IO_L2CAP:
+		return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu,
+						opts.mode, opts.master, err);
+	case BT_IO_RFCOMM:
+		return rfcomm_set(sock, opts.sec_level, opts.master, err);
+	case BT_IO_SCO:
+		return sco_set(sock, opts.mtu, err);
+	}
+
+	g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+			"Unknown BtIO type %d", type);
+	return FALSE;
+}
+
+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;
+
+	switch (type) {
+	case BT_IO_L2RAW:
+		sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(RAW, L2CAP)", errno);
+			return NULL;
+		}
+		if (l2cap_bind(sock, &opts->src,
+					server ? opts->psm : 0, err) < 0)
+			goto failed;
+		if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
+			goto failed;
+		break;
+	case BT_IO_L2CAP:
+		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno);
+			return NULL;
+		}
+		if (l2cap_bind(sock, &opts->src,
+					server ? opts->psm : 0, err) < 0)
+			goto failed;
+		if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
+						opts->mode, opts->master, err))
+			goto failed;
+		break;
+	case BT_IO_RFCOMM:
+		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, err) < 0)
+			goto failed;
+		if (!rfcomm_set(sock, opts->sec_level, opts->master, err))
+			goto failed;
+		break;
+	case BT_IO_SCO:
+		sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
+		if (sock < 0) {
+			ERROR_FAILED(err, "socket(SEQPACKET, SCO)", errno);
+			return NULL;
+		}
+		if (sco_bind(sock, &opts->src, err) < 0)
+			goto failed;
+		if (!sco_set(sock, opts->mtu, err))
+			goto failed;
+		break;
+	default:
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Unknown BtIO type %d", type);
+		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;
+
+failed:
+	close(sock);
+
+	return NULL;
+}
+
+GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
+				gpointer user_data, GDestroyNotify destroy,
+				GError **gerr, BtIOOption opt1, ...)
+{
+	GIOChannel *io;
+	va_list args;
+	struct set_opts opts;
+	int err, sock;
+	gboolean ret;
+
+	va_start(args, opt1);
+	ret = parse_set_opts(&opts, gerr, opt1, args);
+	va_end(args);
+
+	if (ret == FALSE)
+		return NULL;
+
+	io = create_io(type, FALSE, &opts, gerr);
+	if (io == NULL)
+		return NULL;
+
+	sock = g_io_channel_unix_get_fd(io);
+
+	switch (type) {
+	case BT_IO_L2RAW:
+		err = l2cap_connect(sock, &opts.dst, 0);
+		break;
+	case BT_IO_L2CAP:
+		err = l2cap_connect(sock, &opts.dst, opts.psm);
+		break;
+	case BT_IO_RFCOMM:
+		err = rfcomm_connect(sock, &opts.dst, opts.channel);
+		break;
+	case BT_IO_SCO:
+		err = sco_connect(sock, &opts.dst);
+		break;
+	default:
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+						"Unknown BtIO type %d", type);
+		return NULL;
+	}
+
+	if (err < 0) {
+		g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED,
+				"connect: %s (%d)", strerror(-err), -err);
+		g_io_channel_unref(io);
+		return NULL;
+	}
+
+	connect_add(io, connect, user_data, destroy);
+
+	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;
+
+	if (type == BT_IO_L2RAW) {
+		g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
+				"Server L2CAP RAW sockets not supported");
+		return NULL;
+	}
+
+	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/btio/btio.h b/btio/btio.h
new file mode 100644
index 0000000..a039b85
--- /dev/null
+++ b/btio/btio.h
@@ -0,0 +1,97 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2009-2010  Nokia Corporation
+ *
+ *
+ *  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
+ *
+ */
+#ifndef BT_IO_H
+#define BT_IO_H
+
+#include <glib.h>
+
+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_L2RAW,
+	BT_IO_L2CAP,
+	BT_IO_RFCOMM,
+	BT_IO_SCO,
+} BtIOType;
+
+typedef enum {
+	BT_IO_OPT_INVALID = 0,
+	BT_IO_OPT_SOURCE,
+	BT_IO_OPT_SOURCE_BDADDR,
+	BT_IO_OPT_DEST,
+	BT_IO_OPT_DEST_BDADDR,
+	BT_IO_OPT_DEFER_TIMEOUT,
+	BT_IO_OPT_SEC_LEVEL,
+	BT_IO_OPT_CHANNEL,
+	BT_IO_OPT_SOURCE_CHANNEL,
+	BT_IO_OPT_DEST_CHANNEL,
+	BT_IO_OPT_PSM,
+	BT_IO_OPT_MTU,
+	BT_IO_OPT_OMTU,
+	BT_IO_OPT_IMTU,
+	BT_IO_OPT_MASTER,
+	BT_IO_OPT_HANDLE,
+	BT_IO_OPT_CLASS,
+	BT_IO_OPT_MODE,
+} 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_set(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, ...);
+
+gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err,
+						BtIOOption opt1, ...);
+
+GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
+				gpointer user_data, GDestroyNotify destroy,
+				GError **err, BtIOOption opt1, ...);
+
+GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect,
+				BtIOConfirm confirm, gpointer user_data,
+				GDestroyNotify destroy, GError **err,
+				BtIOOption opt1, ...);
+
+#endif
diff --git a/configure.ac b/configure.ac
index 7a2ca79..2a650b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,11 @@ else
 fi
 AC_SUBST(DBUS_CONFDIR)
 
+PKG_CHECK_MODULES(BLUEZ, bluez, dummy=yes,
+				AC_MSG_ERROR(libbluetooth is required))
+AC_SUBST(BLUEZ_CFLAGS)
+AC_SUBST(BLUEZ_LIBS)
+
 AC_ARG_WITH(dbusdatadir, AC_HELP_STRING([--with-dbusdatadir=PATH],
 	[path to D-Bus data directory]), [path_dbusdata=${withval}],
 		[path_dbusdata="`$PKG_CONFIG --variable=datadir dbus-1`"])
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 03/21] bluetooth: Add bluetooth server support for DUN
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 01/21] bluetooth: Add reference count for bluetooth utils =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 02/21] bluetooth: Add Btio library for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 04/21] emulator: Add emulator atom in oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 13555 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

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

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index fe1eaa9..c20728e 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -35,13 +35,72 @@
 
 #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 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)
 {
@@ -371,6 +430,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;
@@ -395,6 +701,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;
 
@@ -429,11 +738,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;
 }
 
@@ -565,6 +889,7 @@ static int bluetooth_ref()
 static void bluetooth_unref()
 {
 	gboolean is_zero;
+	GSList *l;
 
 	is_zero = g_atomic_int_dec_and_test(&ref_count);
 
@@ -581,6 +906,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)
@@ -605,5 +944,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 f187529..945da6a 100644
--- a/plugins/bluetooth.h
+++ b/plugins/bluetooth.h
@@ -3,6 +3,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
@@ -23,6 +24,7 @@
 #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 DBUS_TIMEOUT 15
 
@@ -31,6 +33,9 @@
 /* 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,
@@ -39,10 +44,20 @@ 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.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 04/21] emulator: Add emulator atom in oFono
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (2 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 03/21] bluetooth: Add bluetooth server support " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 05/21] dun_gw: Add DUN server plugin for oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 9223 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Create emulator atom when modem state changes to online. The emulator
driver probes each driver to create specific emulator like DUN, HFP AG,
etc. Once get client connection request, create GAtServer to talk AT
commands with client side.
---
 Makefile.am        |    4 +-
 include/emulator.h |   54 +++++++++++++++
 src/emulator.c     |  189 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/modem.c        |    1 +
 src/ofono.h        |    5 ++
 5 files changed, 251 insertions(+), 2 deletions(-)
 create mode 100644 include/emulator.h
 create mode 100644 src/emulator.c

diff --git a/Makefile.am b/Makefile.am
index 2a9f340..5dcf253 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,7 @@ include_HEADERS = include/log.h include/plugin.h include/history.h \
 			include/radio-settings.h include/stk.h \
 			include/audio-settings.h include/nettime.h \
 			include/ctm.h include/cdma-voicecall.h \
-			include/cdma-sms.h
+			include/cdma-sms.h include/emulator.h
 
 nodist_include_HEADERS = include/version.h
 
@@ -342,7 +342,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \
 			src/nettime.c src/stkagent.c src/stkagent.h \
 			src/simfs.c src/simfs.h src/audio-settings.c \
 			src/smsagent.c src/smsagent.h src/ctm.c \
-			src/cdma-voicecall.c
+			src/cdma-voicecall.c src/emulator.c
 
 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ \
 			@BLUEZ_LIBS@ -ldl
diff --git a/include/emulator.h b/include/emulator.h
new file mode 100644
index 0000000..2691928
--- /dev/null
+++ b/include/emulator.h
@@ -0,0 +1,54 @@
+/*
+ *
+ *  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_driver {
+	const char *name;
+	enum ofono_atom_type type;
+	int (*probe)(struct ofono_emulator *emulator,
+			struct ofono_modem *modem);
+	void (*remove)();
+};
+
+int ofono_emulator_enable(struct ofono_emulator *emulator, GIOChannel *channel);
+void ofono_emulator_remove(gpointer user_data);
+struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
+					struct ofono_emulator_driver *driver);
+
+int ofono_emulator_driver_register(const struct ofono_emulator_driver *driver);
+void ofono_emulator_driver_unregister(
+				const struct ofono_emulator_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OFONO_EMULATOR_H */
diff --git a/src/emulator.c b/src/emulator.c
new file mode 100644
index 0000000..1ede79a
--- /dev/null
+++ b/src/emulator.c
@@ -0,0 +1,189 @@
+/*
+ *
+ *  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;
+	unsigned int id;
+	GAtServer *server;
+	struct ofono_emulator_driver *driver;
+};
+
+static GSList *emulator_drivers = NULL;
+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;
+}
+
+void ofono_emulator_remove(gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	if (e == NULL)
+		return;
+
+	__ofono_atom_free(e->atom);
+}
+
+static void ofono_emulator_release_id(int id)
+{
+	ofono_emulator_ids &= ~(0x1 << id);
+}
+
+int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
+{
+	if (channel == NULL)
+		return -1;
+
+	e->server = g_at_server_new(channel);
+	if (!e->server) {
+		g_free(e);
+		return -1;
+	}
+
+	g_at_server_set_debug(e->server, ofono_emulator_debug, "Server");
+	g_at_server_set_disconnect_function(e->server, ofono_emulator_remove,
+						e);
+
+	return 0;
+}
+
+static void emulator_disable(struct ofono_emulator *e)
+{
+	DBG("");
+
+	g_at_server_shutdown(e->server);
+	g_at_server_unref(e->server);
+	e->server = NULL;
+}
+
+static void emulator_remove(struct ofono_atom *atom)
+{
+	struct ofono_emulator *e =  __ofono_atom_get_data(atom);
+
+	DBG("");
+
+	if (e->server)
+		emulator_disable(e);
+
+	ofono_emulator_release_id(e->id);
+
+	if (e->driver->remove)
+		e->driver->remove();
+
+	g_free(e);
+	e = NULL;
+}
+
+struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
+					struct ofono_emulator_driver *driver)
+{
+	struct ofono_emulator *e;
+
+	DBG("");
+
+	if (driver->probe == NULL)
+		return NULL;
+
+	e = g_try_new0(struct ofono_emulator, 1);
+	if (!e)
+		return NULL;
+
+	e->modem = modem;
+	e->driver = driver;
+
+	if (driver->probe(e, modem) < 0) {
+		g_free(e);
+		return NULL;
+	}
+
+	e->id = ofono_emulator_next_id();
+
+	return e;
+}
+
+void __ofono_emulator_probe_drivers(struct ofono_modem *modem)
+{
+	struct ofono_emulator_driver *driver;
+	GSList *l;
+
+	for (l = emulator_drivers; l; l = l->next) {
+		struct ofono_emulator *e;
+
+		driver = l->data;
+
+		e = ofono_emulator_create(modem, driver);
+		if (!e)
+			continue;
+
+		e->atom = __ofono_modem_add_atom(modem, driver->type,
+							emulator_remove, e);
+	}
+}
+
+int ofono_emulator_driver_register(const struct ofono_emulator_driver *driver)
+{
+	DBG("driver: %p name: %s", driver, driver->name);
+
+	emulator_drivers = g_slist_prepend(emulator_drivers, (void *)driver);
+
+	return 0;
+}
+
+void ofono_emulator_driver_unregister(
+				const struct ofono_emulator_driver *driver)
+{
+	DBG("driver: %p name: %s", driver, driver->name);
+
+	emulator_drivers = g_slist_remove(emulator_drivers, driver);
+}
diff --git a/src/modem.c b/src/modem.c
index 953d6c3..f117e5e 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -434,6 +434,7 @@ static void modem_change_state(struct ofono_modem *modem,
 			driver->post_online(modem);
 
 		notify_online_watches(modem);
+		__ofono_emulator_probe_drivers(modem);
 		break;
 	}
 }
diff --git a/src/ofono.h b/src/ofono.h
index cab70cd..64ea625 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -127,6 +127,7 @@ enum ofono_atom_type {
 	OFONO_ATOM_TYPE_NETTIME = 21,
 	OFONO_ATOM_TYPE_CTM = 22,
 	OFONO_ATOM_TYPE_CDMA_VOICECALL_MANAGER = 23,
+	OFONO_ATOM_TYPE_EMULATOR_DUN = 24,
 };
 
 enum ofono_atom_watch_condition {
@@ -418,3 +419,7 @@ void __ofono_nettime_info_received(struct ofono_modem *modem,
 					struct ofono_network_time *info);
 
 #include <ofono/cdma-voicecall.h>
+
+#include <ofono/emulator.h>
+
+void __ofono_emulator_probe_drivers(struct ofono_modem *modem);
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 05/21] dun_gw: Add DUN server plugin for oFono
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (3 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 04/21] emulator: Add emulator atom in oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 06/21] gprs: Rename status_watch to netreg_status_watch =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4381 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

DUN server is probed when modem state changes to online. It registers
DUN record to Bluetooth adapter and wait for incoming DUN connection.
---
 Makefile.am      |    3 +
 plugins/dun_gw.c |  115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 0 deletions(-)
 create mode 100644 plugins/dun_gw.c

diff --git a/Makefile.am b/Makefile.am
index 5dcf253..58bf6c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -291,6 +291,9 @@ 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 += $(btio_sources) plugins/dun_gw.c plugins/bluetooth.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..803ae32
--- /dev/null
+++ b/plugins/dun_gw.c
@@ -0,0 +1,115 @@
+/*
+ *  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 <gdbus.h>
+
+#include "bluetooth.h"
+
+#define DUN_GW_CHANNEL	1
+
+static struct server *server;
+
+static void dun_gw_connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+	struct ofono_emulator *emulator = user_data;
+
+	DBG("");
+
+	if (err) {
+		DBG("%s", err->message);
+		goto failed;
+	}
+
+	if (ofono_emulator_enable(emulator, io) < 0)
+		goto failed;
+
+	return;
+
+failed:
+	g_io_channel_shutdown(io, TRUE, NULL);
+	ofono_emulator_remove(emulator);
+	bluetooth_unregister_server(server);
+	server = NULL;
+}
+
+static int dun_gw_probe(struct ofono_emulator *emulator,
+				struct ofono_modem *modem)
+{
+	struct ofono_atom *gprs;
+
+	if (server)
+		return -1;
+
+	DBG("");
+
+	gprs = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+	/* Make sure the modem has GPRS atom */
+	if (!gprs)
+		return -1;
+
+	server = bluetooth_register_server(DUN_GW, "Dial-Up Networking",
+				DUN_GW_CHANNEL, dun_gw_connect_cb, emulator);
+
+	return 0;
+}
+
+static void dun_gw_remove()
+{
+	if (server == NULL)
+		return;
+
+	DBG("");
+
+	bluetooth_unregister_server(server);
+	server = NULL;
+}
+
+static struct ofono_emulator_driver emulator_driver = {
+	.name = "Dial-Up Networking",
+	.type = OFONO_ATOM_TYPE_EMULATOR_DUN,
+	.probe = dun_gw_probe,
+	.remove = dun_gw_remove,
+};
+
+static int dun_gw_init()
+{
+	return ofono_emulator_driver_register(&emulator_driver);
+}
+
+static void dun_gw_exit()
+{
+	ofono_emulator_driver_unregister(&emulator_driver);
+}
+
+OFONO_PLUGIN_DEFINE(dun_gw, "Dial-up Networking Profile Plugins", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT, dun_gw_init, dun_gw_exit)
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 06/21] gprs: Rename status_watch to netreg_status_watch
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (4 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 05/21] dun_gw: Add DUN server plugin for oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 07/21] emulator: Add status watches for ofono emulator =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2257 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

To be more precise and avoid name conflict with dun_status_watch.
---
 src/gprs.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 0e86bdf..4cb5eaf 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -74,7 +74,7 @@ struct ofono_gprs {
 	int netreg_status;
 	struct ofono_netreg *netreg;
 	unsigned int netreg_watch;
-	unsigned int status_watch;
+	unsigned int netreg_status_watch;
 	GKeyFile *settings;
 	char *imsi;
 	DBusMessage *pending;
@@ -2164,10 +2164,10 @@ static void gprs_unregister(struct ofono_atom *atom)
 	}
 
 	if (gprs->netreg_watch) {
-		if (gprs->status_watch) {
+		if (gprs->netreg_status_watch) {
 			__ofono_netreg_remove_status_watch(gprs->netreg,
-							gprs->status_watch);
-			gprs->status_watch = 0;
+						gprs->netreg_status_watch);
+			gprs->netreg_status_watch = 0;
 		}
 
 		__ofono_modem_remove_atom_watch(modem, gprs->netreg_watch);
@@ -2250,15 +2250,16 @@ static void netreg_watch(struct ofono_atom *atom,
 	struct ofono_gprs *gprs = data;
 
 	if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
-		gprs->status_watch = 0;
+		gprs->netreg_status_watch = 0;
 		gprs->netreg = NULL;
 		return;
 	}
 
 	gprs->netreg = __ofono_atom_get_data(atom);
 	gprs->netreg_status = ofono_netreg_get_status(gprs->netreg);
-	gprs->status_watch = __ofono_netreg_add_status_watch(gprs->netreg,
-					netreg_status_changed, gprs, NULL);
+	gprs->netreg_status_watch = __ofono_netreg_add_status_watch(
+					gprs->netreg, netreg_status_changed,
+					gprs, NULL);
 
 	gprs_netreg_update(gprs);
 }
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 07/21] emulator: Add status watches for ofono emulator
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (5 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 06/21] gprs: Rename status_watch to netreg_status_watch =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 08/21] emulator: Add emulator status watches in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4592 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

The status watches monitor the emulator activities. Other atoms like
gprs, netreg could register notification to watch emulator status
changes.
---
 include/emulator.h |    6 +++++
 src/emulator.c     |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ofono.h        |   11 ++++++++++
 3 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 2691928..99ae218 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -30,6 +30,12 @@ extern "C" {
 
 struct ofono_emulator;
 
+enum ofono_emulator_status {
+	OFONO_EMULATOR_STATUS_IDLE = 0,
+	OFONO_EMULATOR_STATUS_CREATE,
+	OFONO_EMULATOR_STATUS_DESTROY,
+};
+
 struct ofono_emulator_driver {
 	const char *name;
 	enum ofono_atom_type type;
diff --git a/src/emulator.c b/src/emulator.c
index 1ede79a..c68dbf8 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -39,6 +39,8 @@ struct ofono_emulator {
 	unsigned int id;
 	GAtServer *server;
 	struct ofono_emulator_driver *driver;
+	enum ofono_emulator_status status;
+	struct ofono_watchlist *status_watches;
 };
 
 static GSList *emulator_drivers = NULL;
@@ -80,6 +82,20 @@ static void ofono_emulator_release_id(int id)
 	ofono_emulator_ids &= ~(0x1 << id);
 }
 
+static void notify_status_watches(struct ofono_emulator *e, void *data)
+{
+	struct ofono_watchlist_item *item;
+	ofono_emulator_status_notify_cb_t notify;
+	GSList *l;
+
+	for (l = e->status_watches->items; l; l = l->next) {
+		item = l->data;
+		notify = item->notify;
+
+		notify(e, e->status, data, item->notify_data);
+	}
+}
+
 int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 {
 	if (channel == NULL)
@@ -116,6 +132,11 @@ static void emulator_remove(struct ofono_atom *atom)
 	if (e->server)
 		emulator_disable(e);
 
+	e->status = OFONO_EMULATOR_STATUS_DESTROY;
+	notify_status_watches(e, NULL);
+
+	__ofono_watchlist_free(e->status_watches);
+
 	ofono_emulator_release_id(e->id);
 
 	if (e->driver->remove)
@@ -125,6 +146,37 @@ static void emulator_remove(struct ofono_atom *atom)
 	e = NULL;
 }
 
+unsigned int __ofono_emulator_add_status_watch(struct ofono_emulator *e,
+				ofono_emulator_status_notify_cb_t notify,
+				void *data, ofono_destroy_func destroy)
+{
+	struct ofono_watchlist_item *item;
+
+	DBG("%p", e);
+
+	if (e == NULL)
+		return 0;
+
+	if (notify == NULL)
+		return 0;
+
+	item = g_new0(struct ofono_watchlist_item, 1);
+
+	item->notify = notify;
+	item->destroy = destroy;
+	item->notify_data = data;
+
+	return __ofono_watchlist_add_item(e->status_watches, item);
+}
+
+gboolean __ofono_emulator_remove_status_watch(struct ofono_emulator *e,
+						unsigned int id)
+{
+	DBG("%p", e);
+
+	return __ofono_watchlist_remove_item(e->status_watches, id);
+}
+
 struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
 					struct ofono_emulator_driver *driver)
 {
@@ -148,6 +200,8 @@ struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
 	}
 
 	e->id = ofono_emulator_next_id();
+	e->status_watches = __ofono_watchlist_new(g_free);
+	e->status = OFONO_EMULATOR_STATUS_CREATE;
 
 	return e;
 }
diff --git a/src/ofono.h b/src/ofono.h
index 64ea625..247152b 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -423,3 +423,14 @@ void __ofono_nettime_info_received(struct ofono_modem *modem,
 #include <ofono/emulator.h>
 
 void __ofono_emulator_probe_drivers(struct ofono_modem *modem);
+
+typedef void (*ofono_emulator_status_notify_cb_t)(struct ofono_emulator *e,
+					enum ofono_emulator_status status,
+					void *data, void *user_data);
+
+unsigned int __ofono_emulator_add_status_watch(struct ofono_emulator *e,
+				ofono_emulator_status_notify_cb_t notify,
+				void *data, ofono_destroy_func destroy);
+
+gboolean __ofono_emulator_remove_status_watch(struct ofono_emulator *e,
+						unsigned int id);
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 08/21] emulator: Add emulator status watches in gprs atom
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (6 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 07/21] emulator: Add status watches for ofono emulator =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 09/21] emulator: Add APIs to send GAtServer result =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 3694 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Add dun_watch to watch emulator status update in gprs atom. So that gprs
atom could get notified when we get request to create new PPP connection
from DUN client;
---
 src/gprs.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 4cb5eaf..c7793ea 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -82,6 +82,9 @@ struct ofono_gprs {
 	const struct ofono_gprs_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ofono_emulator *dun;
+	unsigned int dun_watch;
+	unsigned int dun_status_watch;
 };
 
 struct ofono_gprs_context {
@@ -2014,6 +2017,39 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
 	}
 }
 
+static void dun_status_watch(struct ofono_emulator *e,
+					enum ofono_emulator_status status,
+					void *data, void *user_data)
+{
+	if (e == NULL)
+		return;
+
+	switch (status) {
+	default:
+		break;
+	}
+}
+
+static void dun_watch(struct ofono_atom *atom,
+					enum ofono_atom_watch_condition cond,
+					void *data)
+{
+	struct ofono_gprs *gprs = data;
+	struct ofono_emulator *e = __ofono_atom_get_data(atom);
+
+	if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+		gprs->dun_status_watch = 0;
+		gprs->dun = NULL;
+		return;
+	}
+
+	DBG("");
+
+	gprs->dun = e;
+	gprs->dun_status_watch = __ofono_emulator_add_status_watch(e,
+						dun_status_watch, gprs, NULL);
+}
+
 int ofono_gprs_context_driver_register(const struct ofono_gprs_context_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -2175,6 +2211,18 @@ static void gprs_unregister(struct ofono_atom *atom)
 		gprs->netreg = NULL;
 	}
 
+	if (gprs->dun_watch) {
+		if (gprs->dun_status_watch) {
+			__ofono_emulator_remove_status_watch(gprs->dun,
+							gprs->dun_status_watch);
+			gprs->dun_status_watch = 0;
+		}
+
+		__ofono_modem_remove_atom_watch(modem, gprs->dun_watch);
+		gprs->dun_watch = 0;
+		gprs->dun = NULL;
+	}
+
 	ofono_modem_remove_interface(modem,
 					OFONO_CONNECTION_MANAGER_INTERFACE);
 	g_dbus_unregister_interface(conn, path,
@@ -2464,6 +2512,7 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
 	const char *path = __ofono_atom_get_path(gprs->atom);
 	struct ofono_atom *netreg_atom;
 	struct ofono_atom *sim_atom;
+	struct ofono_atom *dun_atom;
 
 	if (!g_dbus_register_interface(conn, path,
 					OFONO_CONNECTION_MANAGER_INTERFACE,
@@ -2500,6 +2549,17 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
 		netreg_watch(netreg_atom,
 				OFONO_ATOM_WATCH_CONDITION_REGISTERED, gprs);
 
+	gprs->dun_watch = __ofono_modem_add_atom_watch(modem,
+						OFONO_ATOM_TYPE_EMULATOR_DUN,
+						dun_watch, gprs, NULL);
+
+	dun_atom = __ofono_modem_find_atom(modem,
+						OFONO_ATOM_TYPE_EMULATOR_DUN);
+
+	if (dun_atom && __ofono_atom_get_registered(dun_atom))
+		dun_watch(dun_atom,
+				OFONO_ATOM_WATCH_CONDITION_REGISTERED, gprs);
+
 	__ofono_atom_register(gprs->atom, gprs_unregister);
 }
 
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 09/21] emulator: Add APIs to send GAtServer result
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (7 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 08/21] emulator: Add emulator status watches in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 10/21] emulator: Implement dialing up for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 3206 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Defines APIs to send final/intermediate/unsolicited result to DUN
client.
 Please enter the commit message for your changes. Lines starting
---
 include/emulator.h |    2 ++
 src/emulator.c     |   28 ++++++++++++++++++++++++++++
 src/ofono.h        |   15 +++++++++++++++
 3 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 99ae218..0d5568c 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -36,6 +36,8 @@ enum ofono_emulator_status {
 	OFONO_EMULATOR_STATUS_DESTROY,
 };
 
+enum _GAtServerResult;
+
 struct ofono_emulator_driver {
 	const char *name;
 	enum ofono_atom_type type;
diff --git a/src/emulator.c b/src/emulator.c
index c68dbf8..455af11 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -82,6 +82,34 @@ static void ofono_emulator_release_id(int id)
 	ofono_emulator_ids &= ~(0x1 << id);
 }
 
+void ofono_emulator_send_final(struct ofono_emulator *e, GAtServerResult result)
+{
+	g_at_server_send_final(e->server, result);
+}
+
+void ofono_emulator_send_ext_final(struct ofono_emulator *e, const char *result)
+{
+	g_at_server_send_ext_final(e->server, result);
+}
+
+void ofono_emulator_send_intermediate(struct ofono_emulator *e,
+						const char *result)
+{
+	g_at_server_send_intermediate(e->server, result);
+}
+
+void ofono_emulator_send_unsolicited(struct ofono_emulator *e,
+						const char *result)
+{
+	g_at_server_send_unsolicited(e->server, result);
+}
+
+void ofono_emulator_send_info(struct ofono_emulator *e, const char *line,
+						gboolean last)
+{
+	g_at_server_send_info(e->server, line, last);
+}
+
 static void notify_status_watches(struct ofono_emulator *e, void *data)
 {
 	struct ofono_watchlist_item *item;
diff --git a/src/ofono.h b/src/ofono.h
index 247152b..4c11e1f 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -434,3 +434,18 @@ unsigned int __ofono_emulator_add_status_watch(struct ofono_emulator *e,
 
 gboolean __ofono_emulator_remove_status_watch(struct ofono_emulator *e,
 						unsigned int id);
+
+void ofono_emulator_send_final(struct ofono_emulator *e,
+					enum _GAtServerResult result);
+
+void ofono_emulator_send_ext_final(struct ofono_emulator *e,
+					const char *result);
+
+void ofono_emulator_send_intermediate(struct ofono_emulator *e,
+					const char *result);
+
+void ofono_emulator_send_unsolicited(struct ofono_emulator *e,
+					const char *result);
+
+void ofono_emulator_send_info(struct ofono_emulator *e, const char *line,
+					gboolean last);
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 10/21] emulator: Implement dialing up for DUN
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (8 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 09/21] emulator: Add APIs to send GAtServer result =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 11/21] gprs: Make gprs_proto_to/from_string non-static =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 8639 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

It handles client ATD*99# request and complete GPRS connection. Pass
client IP address through IPCP packet to client side.
---
 include/emulator.h |   30 +++++++
 src/emulator.c     |  221 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 251 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 0d5568c..e6eeb06 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -34,6 +34,9 @@ enum ofono_emulator_status {
 	OFONO_EMULATOR_STATUS_IDLE = 0,
 	OFONO_EMULATOR_STATUS_CREATE,
 	OFONO_EMULATOR_STATUS_DESTROY,
+	OFONO_EMULATOR_STATUS_DUN_CONNECT,
+	OFONO_EMULATOR_STATUS_DUN_CONNECTED,
+	OFONO_EMULATOR_STATUS_DUN_DISCONNECTED,
 };
 
 enum _GAtServerResult;
@@ -46,6 +49,33 @@ struct ofono_emulator_driver {
 	void (*remove)();
 };
 
+typedef void (*ofono_emulator_cb_t)(enum _GAtServerResult res, void *data);
+
+struct ofono_emulator_req {
+	void *data;
+	ofono_emulator_cb_t cb;
+	void *cb_data;
+};
+
+typedef void (*ofono_emulator_gprs_connect_cb)(const struct ofono_error *error,
+						const char *interface,
+						const char *local,
+						const char *peer,
+						const char **dns, void *data);
+
+struct ofono_emulator_gprs_connect_req {
+	const char *dial_str;
+	ofono_emulator_gprs_connect_cb cb;
+	void *cb_data;
+};
+
+struct ofono_emulator_gprs_context_req {
+	const char *proto;
+	const char *apn;
+	ofono_emulator_cb_t cb;
+	void *cb_data;
+};
+
 int ofono_emulator_enable(struct ofono_emulator *emulator, GIOChannel *channel);
 void ofono_emulator_remove(gpointer user_data);
 struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
diff --git a/src/emulator.c b/src/emulator.c
index 455af11..3329b36 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -32,12 +32,30 @@
 #include "ofono.h"
 #include "common.h"
 #include "gatserver.h"
+#include "gatppp.h"
+
+struct context_settings {
+	char *interface;
+	gboolean static_ip;
+	char *ip;
+	char *netmask;
+	char *gateway;
+	char **dns;
+};
+
+struct dun_context {
+	ofono_bool_t active;
+	struct context_settings settings;
+	struct ofono_gprs_primary_context pri_ctx;
+};
 
 struct ofono_emulator {
 	struct ofono_modem *modem;
 	struct ofono_atom *atom;
 	unsigned int id;
 	GAtServer *server;
+	GAtPPP *ppp;
+	struct dun_context context;
 	struct ofono_emulator_driver *driver;
 	enum ofono_emulator_status status;
 	struct ofono_watchlist *status_watches;
@@ -124,6 +142,201 @@ static void notify_status_watches(struct ofono_emulator *e, void *data)
 	}
 }
 
+static struct ofono_emulator_req *ofono_emulator_req_new(void *cb,
+							void *cb_data)
+{
+	struct ofono_emulator_req *req;
+
+	req = g_try_new0(struct ofono_emulator_req, 1);
+	if (!req)
+		return req;
+
+	req->cb = cb;
+	req->cb_data = cb_data;
+
+	return req;
+}
+
+static void ppp_connect(const char *interface, const char *local,
+			const char *remote,
+			const char *dns1, const char *dns2,
+			gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct dun_context *ctx = &e->context;
+	struct context_settings *settings = &ctx->settings;
+
+	e->status = OFONO_EMULATOR_STATUS_DUN_CONNECTED;
+	ctx->active = TRUE;
+
+	DBG("DUN server connected!\n");
+
+	DBG("Network Device: %s\n", settings->interface);
+	DBG("IP Address: %s\n", settings->ip);
+	DBG("Remote IP Address: %s\n", settings->gateway);
+	DBG("Primary DNS Server: %s\n", settings->dns[0]);
+	DBG("Secondary DNS Server: %s\n", settings->dns[1]);
+}
+
+static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct dun_context *ctx = &e->context;
+	struct context_settings *settings = &ctx->settings;
+	struct ofono_emulator_req *req;
+
+	DBG("");
+
+	g_at_ppp_unref(e->ppp);
+	e->ppp = NULL;
+
+	g_at_server_resume(e->server);
+
+	ctx->active = FALSE;
+
+	g_free(settings->interface);
+	g_free(settings->ip);
+	g_free(settings->netmask);
+	g_free(settings->gateway);
+	g_strfreev(settings->dns);
+
+	req = ofono_emulator_req_new(NULL, NULL);
+	if (!req)
+		return;
+
+	e->status = OFONO_EMULATOR_STATUS_DUN_DISCONNECTED;
+	notify_status_watches(e, req);
+
+	g_free(req);
+}
+
+static gboolean setup_ppp(gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	GAtServer *server = e->server;
+	GAtIO *io;
+	struct context_settings *settings = &e->context.settings;
+
+	DBG("");
+
+	io = g_at_server_get_io(server);
+
+	/* suspend server port */
+	g_at_server_suspend(server);
+
+	/* open ppp */
+	e->ppp = g_at_ppp_server_new_from_io(io, settings->ip);
+	if (e->ppp == NULL) {
+		g_at_server_resume(server);
+		return FALSE;
+	}
+
+	g_at_ppp_set_server_info(e->ppp, settings->gateway,
+					settings->dns[0], settings->dns[1]);
+	g_at_ppp_set_credentials(e->ppp, "", "");
+	g_at_ppp_set_debug(e->ppp, ofono_emulator_debug, "PPP");
+
+	/* set connect and disconnect callbacks */
+	g_at_ppp_set_connect_function(e->ppp, ppp_connect, e);
+	g_at_ppp_set_disconnect_function(e->ppp, ppp_disconnect, e);
+
+	return FALSE;
+}
+
+static void gprs_connect_cb(const struct ofono_error *error,
+				const char *interface,
+				const char *local,
+				const char *peer,
+				const char **dns, void *data)
+{
+	struct ofono_emulator *e = data;
+	struct context_settings *settings = &e->context.settings;
+	const char *netmask = "255.255.255.255";
+
+	DBG("");
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		goto error;
+
+	if (!dns[0] || !dns[1])
+		goto error;
+
+	settings->interface = g_strdup(interface);
+	settings->static_ip = FALSE;
+	settings->ip = g_strdup(local);
+	settings->netmask = g_strdup(netmask);
+	settings->gateway = g_strdup(peer);
+	settings->dns = g_strdupv((char **)dns);
+
+	g_at_server_send_intermediate(e->server, "CONNECT");
+
+	g_idle_add(setup_ppp, e);
+
+	return;
+
+error:
+	g_at_server_send_final(e->server, G_AT_SERVER_RESULT_NO_CARRIER);
+}
+
+static gboolean dial_call(struct ofono_emulator *e, const char *dial_str)
+{
+	char c = *dial_str;
+
+	DBG("dial call %s", dial_str);
+
+	if (c == '*' || c == '#' || c == 'T' || c == 't') {
+		struct ofono_emulator_gprs_connect_req *req;
+
+		req = g_try_new0(struct ofono_emulator_gprs_connect_req, 1);
+		if (!req)
+			return FALSE;
+
+		req->cb = gprs_connect_cb;
+		req->cb_data = e;
+		req->dial_str = dial_str;
+
+		e->status = OFONO_EMULATOR_STATUS_DUN_CONNECT;
+		notify_status_watches(e, req);
+
+		g_free(req);
+	}
+
+	return TRUE;
+}
+
+static void dial_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	GAtServer *server = e->server;
+	GAtServerResult res = G_AT_SERVER_RESULT_ERROR;
+	GAtResultIter iter;
+	const char *dial_str;
+
+	if (type != G_AT_SERVER_REQUEST_TYPE_SET)
+		goto error;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "D"))
+		goto error;
+
+	dial_str = g_at_result_iter_raw_line(&iter);
+	if (!dial_str)
+		goto error;
+
+	if (e->context.active == TRUE)
+		goto error;
+
+	if (!dial_call(e, dial_str))
+		goto error;
+
+	return;
+
+error:
+	g_at_server_send_final(server, res);
+}
+
 int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 {
 	if (channel == NULL)
@@ -139,6 +352,8 @@ int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 	g_at_server_set_disconnect_function(e->server, ofono_emulator_remove,
 						e);
 
+	g_at_server_register(e->server, "D", dial_cb, e, NULL);
+
 	return 0;
 }
 
@@ -146,6 +361,12 @@ static void emulator_disable(struct ofono_emulator *e)
 {
 	DBG("");
 
+	if (e->ppp) {
+		g_at_ppp_shutdown(e->ppp);
+		g_at_ppp_unref(e->ppp);
+		e->ppp = NULL;
+	}
+
 	g_at_server_shutdown(e->server);
 	g_at_server_unref(e->server);
 	e->server = NULL;
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 11/21] gprs: Make gprs_proto_to/from_string non-static
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (9 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 10/21] emulator: Implement dialing up for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 12/21] gprs: ignore the case of proto str when comparing =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2088 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

So DUN server could share gprs_proto_to_string and
gprs_proto_from_string.
---
 include/gprs-context.h |    4 ++++
 src/gprs.c             |    4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/gprs-context.h b/include/gprs-context.h
index c29c0dc..19c1b98 100644
--- a/include/gprs-context.h
+++ b/include/gprs-context.h
@@ -95,6 +95,10 @@ struct ofono_modem *ofono_gprs_context_get_modem(struct ofono_gprs_context *gc);
 void ofono_gprs_context_set_type(struct ofono_gprs_context *gc,
 					enum ofono_gprs_context_type type);
 
+gboolean gprs_proto_from_string(const char *str, enum ofono_gprs_proto *proto);
+
+const char *gprs_proto_to_string(enum ofono_gprs_proto proto);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gprs.c b/src/gprs.c
index c7793ea..9e8fae3 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -184,7 +184,7 @@ static gboolean gprs_context_string_to_type(const char *str,
 	return FALSE;
 }
 
-static const char *gprs_proto_to_string(enum ofono_gprs_proto proto)
+const char *gprs_proto_to_string(enum ofono_gprs_proto proto)
 {
 	switch (proto) {
 	case OFONO_GPRS_PROTO_IP:
@@ -196,7 +196,7 @@ static const char *gprs_proto_to_string(enum ofono_gprs_proto proto)
 	return NULL;
 }
 
-static gboolean gprs_proto_from_string(const char *str,
+gboolean gprs_proto_from_string(const char *str,
 					enum ofono_gprs_proto *proto)
 {
 	if (g_str_equal(str, "ip")) {
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 12/21] gprs: ignore the case of proto str when comparing
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (10 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 11/21] gprs: Make gprs_proto_to/from_string non-static =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 13/21] emulator: Register mandatory AT command handlers =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Use g_ascii_strcasecmp in gprs_proto_from_string when getting the GPRS
protocol from string.
---
 src/gprs.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 9e8fae3..830e143 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -199,10 +199,10 @@ const char *gprs_proto_to_string(enum ofono_gprs_proto proto)
 gboolean gprs_proto_from_string(const char *str,
 					enum ofono_gprs_proto *proto)
 {
-	if (g_str_equal(str, "ip")) {
+	if (g_ascii_strcasecmp(str, "ip")) {
 		*proto = OFONO_GPRS_PROTO_IP;
 		return TRUE;
-	} else if (g_str_equal(str, "ipv6")) {
+	} else if (g_ascii_strcasecmp(str, "ipv6")) {
 		*proto = OFONO_GPRS_PROTO_IPV6;
 		return TRUE;
 	}
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 13/21] emulator: Register mandatory AT command handlers
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (11 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 12/21] gprs: ignore the case of proto str when comparing =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 14/21] gprs: Refactor to share remove_context method =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 11353 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Register mandatory AT command handlers for DUN server.
---
 include/emulator.h |    2 +
 src/emulator.c     |  380 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 382 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index e6eeb06..71ed78a 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -37,6 +37,8 @@ enum ofono_emulator_status {
 	OFONO_EMULATOR_STATUS_DUN_CONNECT,
 	OFONO_EMULATOR_STATUS_DUN_CONNECTED,
 	OFONO_EMULATOR_STATUS_DUN_DISCONNECTED,
+	OFONO_EMULATOR_STATUS_SET_CGATT,
+	OFONO_EMULATOR_STATUS_SET_CGDCONT,
 };
 
 enum _GAtServerResult;
diff --git a/src/emulator.c b/src/emulator.c
index 3329b36..2a089a1 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -49,6 +49,14 @@ struct dun_context {
 	struct ofono_gprs_primary_context pri_ctx;
 };
 
+struct modem_settings {
+	int mode;
+	int creg;
+	int cgreg;
+	int cops;
+	int attached;
+};
+
 struct ofono_emulator {
 	struct ofono_modem *modem;
 	struct ofono_atom *atom;
@@ -57,6 +65,7 @@ struct ofono_emulator {
 	GAtPPP *ppp;
 	struct dun_context context;
 	struct ofono_emulator_driver *driver;
+	struct modem_settings settings;
 	enum ofono_emulator_status status;
 	struct ofono_watchlist *status_watches;
 };
@@ -157,6 +166,370 @@ static struct ofono_emulator_req *ofono_emulator_req_new(void *cb,
 	return req;
 }
 
+static void generic_cb(GAtServerResult res, void *user_data)
+{
+	struct ofono_emulator *e = user_data;
+	GAtServer *server = e->server;
+
+	g_at_server_send_final(server, res);
+
+	e->status = OFONO_EMULATOR_STATUS_IDLE;
+
+	notify_status_watches(e, NULL);
+}
+
+static gboolean send_ok(gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+
+	return FALSE;
+}
+
+static void cfun_cb(GAtServerRequestType type, GAtResult *cmd,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	char buf[50];
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_info(e, "+CFUN: (0-1)", TRUE);
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		snprintf(buf, sizeof(buf), "+CFUN: %d", e->settings.mode);
+		ofono_emulator_send_info(e, buf, TRUE);
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		int mode;
+
+		g_at_result_iter_init(&iter, cmd);
+		g_at_result_iter_next(&iter, "+CFUN=");
+
+		if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
+			goto error;
+
+		if (mode != 0 && mode != 1)
+			goto error;
+
+		DBG("set CFUN to %d", mode);
+
+		e->settings.mode = mode;
+		g_timeout_add_seconds(1, send_ok, e);
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void cpin_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+		/* not implement yet*/
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void creg_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		int mode;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+CREG=");
+
+		if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
+			goto error;
+
+		if (mode < 0 || mode > 2)
+			goto error;
+
+		DBG("set netreg status %d", mode);
+
+		e->settings.creg = mode;
+
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void cgreg_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		int mode;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+CGREG=");
+
+		if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
+			goto error;
+
+		if (mode < 0 || mode > 2)
+			goto error;
+
+		DBG("set GPRS cgreg status %d", mode);
+
+		e->settings.cgreg = mode;
+
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void cops_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	char buf[50];
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		snprintf(buf, sizeof(buf), "+COPS: %d", e->settings.cops);
+		ofono_emulator_send_info(e, buf, TRUE);
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		int mode;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+COPS=");
+
+		if (g_at_result_iter_next_number(&iter, &mode) == FALSE)
+			goto error;
+
+		if (mode < 0 || mode > 2)
+			goto error;
+
+		DBG("set GPRS cops status %d", mode);
+
+		e->settings.cops = mode;
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void cgatt_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct ofono_emulator_req *req;
+	char buf[12];
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		snprintf(buf, sizeof(buf), "+CGATT: %d", e->settings.attached);
+		ofono_emulator_send_info(e, buf, TRUE);
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		int attached;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+CGATT=");
+
+		if (g_at_result_iter_next_number(&iter, &attached) == FALSE)
+			goto error;
+
+		if (attached != 0 && attached != 1)
+			goto error;
+
+		DBG("set GPRS attach status %d", attached);
+
+		req = ofono_emulator_req_new(generic_cb, e);
+		if (!req)
+			goto error;
+
+		req->data = &attached;
+
+		e->status = OFONO_EMULATOR_STATUS_SET_CGATT;
+
+		notify_status_watches(e, req);
+
+		e->settings.attached = attached;
+		g_free(req);
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
+static void cgdcont_cb(GAtServerRequestType type, GAtResult *result,
+					gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct ofono_emulator_gprs_context_req *req;
+	struct dun_context *context = &e->context;
+	struct ofono_gprs_primary_context *ctx = &context->pri_ctx;
+	char buf[256];
+
+	switch (type) {
+	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+	{
+		const char *proto = gprs_proto_to_string(ctx->proto);
+
+		snprintf(buf, sizeof(buf), "+CGDCONT: %d, \"%s\", \"%s\"",
+						ctx->cid, proto, ctx->apn);
+		ofono_emulator_send_info(e, buf, TRUE);
+		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
+		break;
+	}
+	case G_AT_SERVER_REQUEST_TYPE_SET:
+	{
+		GAtResultIter iter;
+		unsigned int cid;
+		const char *proto;
+		const char *apn;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+CGDCONT=");
+
+		if (g_at_result_iter_next_number(&iter, (gint *)&cid) == FALSE)
+			goto error;
+
+		if (g_at_result_iter_next_string(&iter, &proto) == FALSE)
+			goto error;
+
+		if (g_at_result_iter_next_string(&iter, &apn) == FALSE)
+			goto error;
+
+		DBG("set CGDCONT %d %s %s", cid, proto, apn);
+
+		if (cid <= 0 || proto == NULL || apn == NULL)
+			goto error;
+
+		if (cid == ctx->cid)
+			goto error;
+
+		if (context->active)
+			goto error;
+
+		ctx->cid = cid;
+		gprs_proto_from_string(proto, &ctx->proto);
+		strncpy(ctx->apn, apn, OFONO_GPRS_MAX_APN_LENGTH);
+		ctx->apn[OFONO_GPRS_MAX_APN_LENGTH] = '\0';
+
+		req = g_try_new0(struct ofono_emulator_gprs_context_req, 1);
+		if (!req)
+			goto error;
+
+		req->proto = proto;
+		req->apn = apn;
+		req->cb = generic_cb;
+		req->cb_data = e;
+
+		e->status = OFONO_EMULATOR_STATUS_SET_CGDCONT;
+
+		notify_status_watches(e, req);
+
+		g_free(req);
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
 static void ppp_connect(const char *interface, const char *local,
 			const char *remote,
 			const char *dns1, const char *dns2,
@@ -353,6 +726,13 @@ int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 						e);
 
 	g_at_server_register(e->server, "D", dial_cb, e, NULL);
+	g_at_server_register(e->server, "+CFUN", cfun_cb, e, NULL);
+	g_at_server_register(e->server, "+CPIN", cpin_cb, e, NULL);
+	g_at_server_register(e->server, "+CREG", creg_cb, e, NULL);
+	g_at_server_register(e->server, "+CGREG", cgreg_cb, e, NULL);
+	g_at_server_register(e->server, "+COPS", cops_cb, e, NULL);
+	g_at_server_register(e->server, "+CGATT", cgatt_cb, e, NULL);
+	g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL);
 
 	return 0;
 }
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 14/21] gprs: Refactor to share remove_context method
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (12 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 13/21] emulator: Register mandatory AT command handlers =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 15/21] gprs: Add DUN +CGATT support in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4077 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Remove duplicated code in gprs_deactivate_for_remove and
gprs_remove_context. So they could share the same remove_context method.
---
 src/gprs.c |   59 +++++++++++++++++++++++++++++------------------------------
 1 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 830e143..05e1c70 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -1652,26 +1652,14 @@ static DBusMessage *gprs_add_context(DBusConnection *conn,
 	return NULL;
 }
 
-static void gprs_deactivate_for_remove(const struct ofono_error *error,
-						void *data)
+static void remove_context(struct pri_context *ctx)
 {
-	struct pri_context *ctx = data;
 	struct ofono_gprs *gprs = ctx->gprs;
 	DBusConnection *conn;
 	char *path;
 	const char *atompath;
 
-	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
-		DBG("Removing context failed with error: %s",
-				telephony_error_to_str(error));
-
-		__ofono_dbus_pending_reply(&gprs->pending,
-					__ofono_error_failed(gprs->pending));
-		return;
-	}
-
-	gprs_cid_release(gprs, ctx->context.cid);
-	ctx->context.cid = 0;
+	DBG("%s", ctx->path);
 
 	if (gprs->settings) {
 		g_key_file_remove_group(gprs->settings, ctx->key, NULL);
@@ -1684,9 +1672,6 @@ static void gprs_deactivate_for_remove(const struct ofono_error *error,
 	context_dbus_unregister(ctx);
 	gprs->contexts = g_slist_remove(gprs->contexts, ctx);
 
-	__ofono_dbus_pending_reply(&gprs->pending,
-				dbus_message_new_method_return(gprs->pending));
-
 	atompath = __ofono_atom_get_path(gprs->atom);
 	conn = ofono_dbus_get_connection();
 	g_dbus_emit_signal(conn, atompath, OFONO_CONNECTION_MANAGER_INTERFACE,
@@ -1695,13 +1680,38 @@ static void gprs_deactivate_for_remove(const struct ofono_error *error,
 	g_free(path);
 }
 
+
+static void gprs_deactivate_for_remove(const struct ofono_error *error,
+						void *data)
+{
+	struct pri_context *ctx = data;
+	struct ofono_gprs *gprs = ctx->gprs;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		DBG("Removing context failed with error: %s",
+				telephony_error_to_str(error));
+
+		__ofono_dbus_pending_reply(&gprs->pending,
+					__ofono_error_failed(gprs->pending));
+		return;
+	}
+
+	gprs_cid_release(gprs, ctx->context.cid);
+	ctx->context.cid = 0;
+
+	remove_context(ctx);
+
+	if (gprs->pending)
+		__ofono_dbus_pending_reply(&gprs->pending,
+				dbus_message_new_method_return(gprs->pending));
+}
+
 static DBusMessage *gprs_remove_context(DBusConnection *conn,
 					DBusMessage *msg, void *data)
 {
 	struct ofono_gprs *gprs = data;
 	struct pri_context *ctx;
 	const char *path;
-	const char *atompath;
 
 	if (gprs->pending)
 		return __ofono_error_busy(msg);
@@ -1730,22 +1740,11 @@ static DBusMessage *gprs_remove_context(DBusConnection *conn,
 		return NULL;
 	}
 
-	if (gprs->settings) {
-		g_key_file_remove_group(gprs->settings, ctx->key, NULL);
-		storage_sync(gprs->imsi, SETTINGS_STORE, gprs->settings);
-	}
-
 	DBG("Unregistering context: %s", ctx->path);
-	context_dbus_unregister(ctx);
-	gprs->contexts = g_slist_remove(gprs->contexts, ctx);
+	remove_context(ctx);
 
 	g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
 
-	atompath = __ofono_atom_get_path(gprs->atom);
-	g_dbus_emit_signal(conn, atompath, OFONO_CONNECTION_MANAGER_INTERFACE,
-				"ContextRemoved", DBUS_TYPE_OBJECT_PATH, &path,
-				DBUS_TYPE_INVALID);
-
 	return NULL;
 }
 
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 15/21] gprs: Add DUN +CGATT support in gprs atom
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (13 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 14/21] gprs: Refactor to share remove_context method =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:15 ` [PATCH 16/21] gprs: Add DUN +CGDCONT " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1835 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

DUN client may request to attach/deattach GPRS network. Use
gprs_netreg_update to set attach/deattach status.
---
 src/gprs.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 05e1c70..580188e 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -43,6 +43,8 @@
 #include "common.h"
 #include "storage.h"
 #include "idmap.h"
+#include "gatserver.h"
+
 
 #define GPRS_FLAG_ATTACHING 0x1
 #define GPRS_FLAG_RECHECK 0x2
@@ -2016,14 +2018,31 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
 	}
 }
 
+static void ofono_gprs_set_cgatt(struct ofono_gprs *gprs,
+				struct ofono_emulator_req *req)
+{
+	int *mode = req->data;
+
+	gprs->powered = *mode;
+
+	gprs_netreg_update(gprs);
+
+	req->cb(G_AT_SERVER_RESULT_OK, req->cb_data);
+}
+
 static void dun_status_watch(struct ofono_emulator *e,
 					enum ofono_emulator_status status,
 					void *data, void *user_data)
 {
+	struct ofono_gprs *gprs = user_data;
+
 	if (e == NULL)
 		return;
 
 	switch (status) {
+	case OFONO_EMULATOR_STATUS_SET_CGATT:
+		ofono_gprs_set_cgatt(gprs, data);
+		break;
 	default:
 		break;
 	}
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 16/21] gprs: Add DUN +CGDCONT support in gprs atom
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (14 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 15/21] gprs: Add DUN +CGATT support in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:15 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:16 ` [PATCH 17/21] gprs: Add DUN server GPRS connect support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2851 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

DUN client may request to define the APN of context. Find the existing
context and update the APN.
---
 src/gprs.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 580188e..0feb344 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -60,6 +60,13 @@
 static GSList *g_drivers = NULL;
 static GSList *g_context_drivers = NULL;
 
+struct gprs_dun_data {
+	ofono_emulator_gprs_connect_cb cb;
+	void *cb_data;
+	struct pri_context *context;
+	struct pri_context *dun;
+};
+
 struct ofono_gprs {
 	GSList *contexts;
 	ofono_bool_t attached;
@@ -87,6 +94,7 @@ struct ofono_gprs {
 	struct ofono_emulator *dun;
 	unsigned int dun_watch;
 	unsigned int dun_status_watch;
+	struct gprs_dun_data dun_data;
 };
 
 struct ofono_gprs_context {
@@ -2030,6 +2038,41 @@ static void ofono_gprs_set_cgatt(struct ofono_gprs *gprs,
 	req->cb(G_AT_SERVER_RESULT_OK, req->cb_data);
 }
 
+static void ofono_gprs_set_cgdcont(struct ofono_gprs *gprs,
+				struct ofono_emulator_gprs_context_req *req)
+{
+	struct gprs_dun_data *data = &gprs->dun_data;
+	struct pri_context *context = NULL;
+	enum ofono_gprs_proto proto;
+	GSList *l;
+
+	gprs_proto_from_string(req->proto, &proto);
+
+	for (l = gprs->contexts; l; l = l->next) {
+		struct pri_context *ctx = l->data;
+
+		if (ctx->type != OFONO_GPRS_CONTEXT_TYPE_INTERNET)
+			continue;
+
+		if (proto != ctx->context.proto)
+			continue;
+
+		context = ctx;
+		break;
+	}
+
+	if (context == NULL)
+		goto error;
+
+	strcpy(context->context.apn, req->apn);
+	data->context = context;
+	req->cb(G_AT_SERVER_RESULT_OK, req->cb_data);
+
+	return;
+error:
+	req->cb(G_AT_SERVER_RESULT_ERROR, req->cb_data);
+}
+
 static void dun_status_watch(struct ofono_emulator *e,
 					enum ofono_emulator_status status,
 					void *data, void *user_data)
@@ -2043,6 +2086,9 @@ static void dun_status_watch(struct ofono_emulator *e,
 	case OFONO_EMULATOR_STATUS_SET_CGATT:
 		ofono_gprs_set_cgatt(gprs, data);
 		break;
+	case OFONO_EMULATOR_STATUS_SET_CGDCONT:
+		ofono_gprs_set_cgdcont(gprs, data);
+		break;
 	default:
 		break;
 	}
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 17/21] gprs: Add DUN server GPRS connect support
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (15 preceding siblings ...)
  2011-01-12 17:15 ` [PATCH 16/21] gprs: Add DUN +CGDCONT " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:16 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:16 ` [PATCH 18/21] gprs: Add status watch functions =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 9112 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Implement dial up networking in GPRS atom.
---
 src/gprs.c |  229 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 227 insertions(+), 2 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 0feb344..e90f043 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -57,6 +57,10 @@
 #define MAX_CONTEXTS 256
 #define SUSPEND_TIMEOUT 8
 
+#define DUN_LOCAL "192.168.1.1"
+#define DUN_PEER "192.168.1.2"
+#define DUN_CONNECT_TIMEOUT 20
+
 static GSList *g_drivers = NULL;
 static GSList *g_context_drivers = NULL;
 
@@ -95,6 +99,9 @@ struct ofono_gprs {
 	unsigned int dun_watch;
 	unsigned int dun_status_watch;
 	struct gprs_dun_data dun_data;
+	int attach_source;
+	int context_source;
+	int timeout_source;
 };
 
 struct ofono_gprs_context {
@@ -136,6 +143,7 @@ struct pri_context {
 };
 
 static void gprs_netreg_update(struct ofono_gprs *gprs);
+static gboolean dun_connect_remove(gpointer user_data);
 static void gprs_deactivate_next(struct ofono_gprs *gprs);
 
 static const char *gprs_context_default_name(enum ofono_gprs_context_type type)
@@ -676,7 +684,9 @@ static void pri_activate_callback(const struct ofono_error *error,
 	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
 		DBG("Activating context failed with error: %s",
 				telephony_error_to_str(error));
-		__ofono_dbus_pending_reply(&ctx->pending,
+
+		if (ctx->pending)
+			__ofono_dbus_pending_reply(&ctx->pending,
 					__ofono_error_failed(ctx->pending));
 
 		gprs_cid_release(ctx->gprs, ctx->context.cid);
@@ -684,11 +694,15 @@ static void pri_activate_callback(const struct ofono_error *error,
 		ctx->context_driver->inuse = FALSE;
 		ctx->context_driver = NULL;
 
+		if (ctx->gprs->dun)
+			dun_connect_remove(ctx->gprs);
+
 		return;
 	}
 
 	ctx->active = TRUE;
-	__ofono_dbus_pending_reply(&ctx->pending,
+	if (ctx->pending)
+		__ofono_dbus_pending_reply(&ctx->pending,
 				dbus_message_new_method_return(ctx->pending));
 
 	/*
@@ -1967,6 +1981,27 @@ void ofono_gprs_set_cid_range(struct ofono_gprs *gprs,
 	gprs->cid_map = idmap_new_from_range(min, max);
 }
 
+static void ofono_gprs_remove_sources(struct ofono_gprs *gprs)
+{
+	if (gprs == NULL)
+		return;
+
+	if (gprs->timeout_source) {
+		g_source_remove(gprs->timeout_source);
+		gprs->timeout_source = 0;
+	}
+
+	if (gprs->attach_source) {
+		g_source_remove(gprs->attach_source);
+		gprs->attach_source = 0;
+	}
+
+	if (gprs->context_source) {
+		g_source_remove(gprs->context_source);
+		gprs->context_source = 0;
+	}
+}
+
 static void gprs_context_unregister(struct ofono_atom *atom)
 {
 	struct ofono_gprs_context *gc = __ofono_atom_get_data(atom);
@@ -1974,6 +2009,8 @@ static void gprs_context_unregister(struct ofono_atom *atom)
 	if (gc->gprs == NULL)
 		return;
 
+	ofono_gprs_remove_sources(gc->gprs);
+
 	gc->gprs->context_drivers = g_slist_remove(gc->gprs->context_drivers,
 							gc);
 	gc->gprs = NULL;
@@ -2026,6 +2063,183 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
 	}
 }
 
+static ofono_bool_t set_primary_context_powered(struct pri_context *ctx,
+						ofono_bool_t value)
+{
+	struct ofono_gprs_context *gc = ctx->context_driver;
+
+	if (gc == NULL || gc->driver->activate_primary == NULL ||
+			gc->driver->deactivate_primary == NULL ||
+			ctx->gprs->cid_map == NULL)
+		return FALSE;
+
+	if (ctx->pending)
+		return FALSE;
+
+	if (ctx->active == value)
+		return FALSE;
+
+	if (value && !ctx->gprs->attached)
+		return FALSE;
+
+	if (ctx->gprs->flags & GPRS_FLAG_ATTACHING)
+		return FALSE;
+
+	if (value) {
+		ctx->context.cid = gprs_cid_alloc(ctx->gprs);
+
+		if (ctx->context.cid == 0)
+			return FALSE;
+
+		if (ctx->context.cid !=
+				idmap_get_min(ctx->gprs->cid_map)) {
+			ofono_error("Multiple active contexts are"
+					" not yet supported");
+
+			gprs_cid_release(ctx->gprs, ctx->context.cid);
+			ctx->context.cid = 0;
+
+			return FALSE;
+		}
+	}
+
+	if (value)
+		gc->driver->activate_primary(gc, &ctx->context,
+					pri_activate_callback, ctx);
+	else
+		gc->driver->deactivate_primary(gc, ctx->context.cid,
+					pri_deactivate_callback, ctx);
+
+	return TRUE;
+}
+
+static void ofono_gprs_dun_disconnect(struct ofono_gprs *gprs,
+				struct ofono_emulator_req *req)
+{
+	struct pri_context *context = gprs->dun_data.context;
+
+	ofono_gprs_remove_sources(gprs);
+
+	if (context->active) {
+		struct ofono_gprs_context *gc = context->context_driver;
+
+		gc->driver->deactivate_primary(gc, context->context.cid,
+					gprs_deactivate_for_remove, context);
+	} else
+		remove_context(context);
+}
+
+static gboolean dun_connect_remove(gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	struct gprs_dun_data *data = &gprs->dun_data;
+	struct ofono_error error;
+
+	ofono_gprs_remove_sources(gprs);
+	remove_context(data->context);
+
+	error.type = OFONO_ERROR_TYPE_FAILURE;
+	data->cb(&error, NULL, NULL, NULL, NULL, data->cb_data);
+
+	data->cb = NULL;
+	data->cb_data = NULL;
+	data->context = NULL;
+	data->dun = NULL;
+
+	return FALSE;
+}
+
+static gboolean pri_context_update(gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	struct gprs_dun_data *data = &gprs->dun_data;
+	struct pri_context *context = data->context;
+	struct context_settings *settings = context->settings;
+	struct ofono_error error;
+
+	DBG("active %d\n", context->active);
+
+	if (context->active != TRUE)
+		return TRUE;
+
+	gprs->context_source = 0;
+	g_source_remove(gprs->timeout_source);
+
+	error.type = OFONO_ERROR_TYPE_NO_ERROR;
+
+	data->cb(&error, settings->interface, DUN_LOCAL, DUN_PEER,
+					(const char **)settings->dns,
+					data->cb_data);
+
+	return FALSE;
+}
+
+static gboolean gprs_attach_update(gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	struct gprs_dun_data *data = &gprs->dun_data;
+	struct pri_context *context = data->context;
+
+	DBG("attached %d driver attached %d\n", gprs->attached,
+						gprs->driver_attached);
+
+	if (gprs->attached != TRUE || gprs->driver_attached != TRUE)
+		return TRUE;
+
+	gprs->attach_source = 0;
+
+	if (context->active != TRUE) {
+		set_primary_context_powered(context, TRUE);
+
+		/* wait until the primary context is actived */
+		gprs->context_source = g_timeout_add_seconds(1,
+						pri_context_update, gprs);
+		return FALSE;
+	}
+
+	pri_context_update(gprs);
+
+	return FALSE;
+}
+
+static void ofono_gprs_dun_connect(struct ofono_gprs *gprs,
+				struct ofono_emulator_gprs_connect_req *req)
+{
+	const char *dial_str = req->dial_str;
+	struct gprs_dun_data *data = &gprs->dun_data;
+	struct ofono_error error;
+
+	DBG("%s", dial_str);
+
+	if (data->context == NULL)
+		goto error;
+
+	data->cb = req->cb;
+	data->cb_data = req->cb_data;
+
+	gprs->timeout_source = g_timeout_add_seconds(DUN_CONNECT_TIMEOUT,
+						dun_connect_remove, gprs);
+
+	/* check gprs attaching status */
+	if (!gprs->powered || !gprs->attached || !gprs->driver_attached) {
+		gprs->powered = TRUE;
+
+		gprs_netreg_update(gprs);
+
+		/* wait until GPRS is attached */
+		gprs->attach_source = g_timeout_add_seconds(1,
+						gprs_attach_update, gprs);
+		return;
+	}
+
+	gprs_attach_update(gprs);
+
+	return;
+error:
+	error.type = OFONO_ERROR_TYPE_FAILURE;
+	req->cb(&error, NULL, NULL, NULL, NULL, req->cb_data);
+}
+
 static void ofono_gprs_set_cgatt(struct ofono_gprs *gprs,
 				struct ofono_emulator_req *req)
 {
@@ -2083,12 +2297,21 @@ static void dun_status_watch(struct ofono_emulator *e,
 		return;
 
 	switch (status) {
+	case OFONO_EMULATOR_STATUS_DUN_CONNECT:
+		ofono_gprs_dun_connect(gprs, data);
+		break;
+	case OFONO_EMULATOR_STATUS_DUN_DISCONNECTED:
+		ofono_gprs_dun_disconnect(gprs, data);
+		break;
 	case OFONO_EMULATOR_STATUS_SET_CGATT:
 		ofono_gprs_set_cgatt(gprs, data);
 		break;
 	case OFONO_EMULATOR_STATUS_SET_CGDCONT:
 		ofono_gprs_set_cgdcont(gprs, data);
 		break;
+	case OFONO_EMULATOR_STATUS_DESTROY:
+		ofono_gprs_remove_sources(gprs);
+		break;
 	default:
 		break;
 	}
@@ -2287,6 +2510,8 @@ static void gprs_unregister(struct ofono_atom *atom)
 		gprs->dun = NULL;
 	}
 
+	ofono_gprs_remove_sources(gprs);
+
 	ofono_modem_remove_interface(modem,
 					OFONO_CONNECTION_MANAGER_INTERFACE);
 	g_dbus_unregister_interface(conn, path,
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 18/21] gprs: Add status watch functions
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (16 preceding siblings ...)
  2011-01-12 17:16 ` [PATCH 17/21] gprs: Add DUN server GPRS connect support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:16 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:16 ` [PATCH 19/21] gprs: Add gprs_get_status =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4643 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

So DUN server could watch GPRS status changes and notify client
unsolicited results like +CGREG.
---
 include/gprs.h |    9 +++++++++
 src/gprs.c     |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/include/gprs.h b/include/gprs.h
index ad7925c..7985115 100644
--- a/include/gprs.h
+++ b/include/gprs.h
@@ -36,6 +36,8 @@ typedef void (*ofono_gprs_status_cb_t)(const struct ofono_error *error,
 
 typedef void (*ofono_gprs_cb_t)(const struct ofono_error *error, void *data);
 
+typedef void (*ofono_gprs_status_notify_cb_t)(const int status, void *data);
+
 struct ofono_gprs_driver {
 	const char *name;
 	int (*probe)(struct ofono_gprs *gprs, unsigned int vendor,
@@ -77,6 +79,13 @@ void ofono_gprs_set_cid_range(struct ofono_gprs *gprs,
 void ofono_gprs_add_context(struct ofono_gprs *gprs,
 				struct ofono_gprs_context *gc);
 
+unsigned int __ofono_gprs_add_status_watch(struct ofono_gprs *gprs,
+				ofono_gprs_status_notify_cb_t cb,
+				void *data, ofono_destroy_func destroy);
+
+gboolean __ofono_gprs_remove_status_watch(struct ofono_gprs *gprs,
+						unsigned int id);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gprs.c b/src/gprs.c
index e90f043..895d95b 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -95,6 +95,7 @@ struct ofono_gprs {
 	const struct ofono_gprs_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ofono_watchlist *status_watches;
 	struct ofono_emulator *dun;
 	unsigned int dun_watch;
 	unsigned int dun_status_watch;
@@ -1925,6 +1926,51 @@ static GDBusSignalTable manager_signals[] = {
 	{ }
 };
 
+unsigned int __ofono_gprs_add_status_watch(struct ofono_gprs *gprs,
+				ofono_gprs_status_notify_cb_t notify,
+				void *data, ofono_destroy_func destroy)
+{
+	struct ofono_watchlist_item *item;
+
+	DBG("%p", gprs);
+
+	if (gprs == NULL)
+		return 0;
+
+	if (notify == NULL)
+		return 0;
+
+	item = g_new0(struct ofono_watchlist_item, 1);
+
+	item->notify = notify;
+	item->destroy = destroy;
+	item->notify_data = data;
+
+	return __ofono_watchlist_add_item(gprs->status_watches, item);
+}
+
+gboolean __ofono_gprs_remove_status_watch(struct ofono_gprs *gprs,
+						unsigned int id)
+{
+	DBG("%p", gprs);
+
+	return __ofono_watchlist_remove_item(gprs->status_watches, id);
+}
+
+static void notify_status_watches(struct ofono_gprs *gprs)
+{
+	struct ofono_watchlist_item *item;
+	GSList *l;
+	ofono_gprs_status_notify_cb_t notify;
+
+	for (l = gprs->status_watches->items; l; l = l->next) {
+		item = l->data;
+		notify = item->notify;
+
+		notify(gprs->status, item->notify_data);
+	}
+}
+
 void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
 {
 	DBG("%s", __ofono_atom_get_path(gprs->atom));
@@ -1932,6 +1978,8 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
 	gprs->driver_attached = FALSE;
 	gprs_attached_update(gprs);
 
+	notify_status_watches(gprs);
+
 	/*
 	 * TODO: The network forced a detach, we should wait for some time
 	 * and try to re-attach.  This might also be related to a suspend
@@ -1962,6 +2010,8 @@ void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status)
 	gprs->driver_attached = TRUE;
 	gprs_attached_update(gprs);
 
+	notify_status_watches(gprs);
+
 	return;
 
 detach:
@@ -2464,6 +2514,9 @@ static void gprs_unregister(struct ofono_atom *atom)
 	const char *path = __ofono_atom_get_path(atom);
 	GSList *l;
 
+	__ofono_watchlist_free(gprs->status_watches);
+	gprs->status_watches = NULL;
+
 	if (gprs->settings) {
 		storage_close(gprs->imsi, SETTINGS_STORE,
 				gprs->settings, TRUE);
@@ -2816,6 +2869,8 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
 	ofono_modem_add_interface(modem,
 				OFONO_CONNECTION_MANAGER_INTERFACE);
 
+	gprs->status_watches = __ofono_watchlist_new(g_free);
+
 	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
 
 	if (sim_atom) {
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 19/21] gprs: Add gprs_get_status
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (17 preceding siblings ...)
  2011-01-12 17:16 ` [PATCH 18/21] gprs: Add status watch functions =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:16 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:16 ` [PATCH 20/21] emulator: Watch GPRS status changes =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1658 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

DUN server want to get latest GPRS status.
---
 include/gprs.h |    2 ++
 src/gprs.c     |    9 +++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/include/gprs.h b/include/gprs.h
index 7985115..05cc086 100644
--- a/include/gprs.h
+++ b/include/gprs.h
@@ -86,6 +86,8 @@ unsigned int __ofono_gprs_add_status_watch(struct ofono_gprs *gprs,
 gboolean __ofono_gprs_remove_status_watch(struct ofono_gprs *gprs,
 						unsigned int id);
 
+int ofono_gprs_get_status(struct ofono_gprs *gprs);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/gprs.c b/src/gprs.c
index 895d95b..4ef33ef 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -2487,6 +2487,15 @@ void ofono_gprs_context_set_type(struct ofono_gprs_context *gc,
 	gc->type = type;
 }
 
+
+int ofono_gprs_get_status(struct ofono_gprs *gprs)
+{
+	if (gprs == NULL)
+		return -1;
+
+	return gprs->status;
+}
+
 int ofono_gprs_driver_register(const struct ofono_gprs_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 20/21] emulator: Watch GPRS status changes
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (18 preceding siblings ...)
  2011-01-12 17:16 ` [PATCH 19/21] gprs: Add gprs_get_status =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:16 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-12 17:16 ` [PATCH 21/21] emulator: Watch netreg " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 4711 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Watch GPRS status update to notify DUN client, such as +CGREG
unsolicited result.
---
 src/emulator.c |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 2a089a1..7701510 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -55,6 +55,7 @@ struct modem_settings {
 	int cgreg;
 	int cops;
 	int attached;
+	int gprs_status;
 };
 
 struct ofono_emulator {
@@ -68,6 +69,9 @@ struct ofono_emulator {
 	struct modem_settings settings;
 	enum ofono_emulator_status status;
 	struct ofono_watchlist *status_watches;
+	struct ofono_gprs *gprs;
+	unsigned int gprs_watch;
+	unsigned int gprs_status_watch;
 };
 
 static GSList *emulator_drivers = NULL;
@@ -305,12 +309,16 @@ static void cgreg_cb(GAtServerRequestType type, GAtResult *result,
 					gpointer user_data)
 {
 	struct ofono_emulator *e = user_data;
+	char buf[256];
 
 	switch (type) {
 	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
 		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
 		break;
 	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		snprintf(buf, sizeof(buf), "+CGREG: %d, %d", e->settings.cgreg,
+					e->settings.gprs_status);
+		ofono_emulator_send_info(e, buf, TRUE);
 		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
 		break;
 	case G_AT_SERVER_REQUEST_TYPE_SET:
@@ -710,6 +718,78 @@ error:
 	g_at_server_send_final(server, res);
 }
 
+static void emulator_gprs_update(struct ofono_emulator *e)
+{
+	GAtServer *server = e->server;
+	char buf[256];
+
+	switch (e->settings.cgreg) {
+	case 0:
+		break;
+	case 1:
+		snprintf(buf, sizeof(buf), "+CGREG: %d",
+						e->settings.gprs_status);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	case 2:
+		snprintf(buf, sizeof(buf), "+CGREG: %d",
+						e->settings.gprs_status);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	default:
+		break;
+	}
+}
+
+static void gprs_status_changed(int status, void *data)
+{
+	struct ofono_emulator *e = data;
+
+	DBG("%d", status);
+
+	e->settings.gprs_status = status;
+
+	emulator_gprs_update(e);
+}
+
+static void gprs_watch(struct ofono_atom *atom,
+				enum ofono_atom_watch_condition cond,
+				void *data)
+{
+	struct ofono_emulator *e = data;
+	struct ofono_gprs *gprs;
+
+	if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+		e->gprs_status_watch = 0;
+		e->gprs = NULL;
+		return;
+	}
+
+	gprs = __ofono_atom_get_data(atom);
+	e->gprs = gprs;
+	e->settings.gprs_status = ofono_gprs_get_status(gprs);
+	e->gprs_status_watch = __ofono_gprs_add_status_watch(e->gprs,
+					gprs_status_changed, e, NULL);
+
+	emulator_gprs_update(e);
+}
+
+static void add_gprs_watches(struct ofono_emulator *e)
+{
+	struct ofono_modem *modem = e->modem;
+	struct ofono_atom *gprs_atom;
+
+	e->gprs_watch = __ofono_modem_add_atom_watch(modem,
+					OFONO_ATOM_TYPE_GPRS,
+					gprs_watch, e, NULL);
+
+	gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+
+	if (gprs_atom && __ofono_atom_get_registered(gprs_atom))
+		gprs_watch(gprs_atom,
+				OFONO_ATOM_WATCH_CONDITION_REGISTERED, e);
+}
+
 int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 {
 	if (channel == NULL)
@@ -734,6 +814,8 @@ int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 	g_at_server_register(e->server, "+CGATT", cgatt_cb, e, NULL);
 	g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL);
 
+	add_gprs_watches(e);
+
 	return 0;
 }
 
@@ -761,6 +843,18 @@ static void emulator_remove(struct ofono_atom *atom)
 	if (e->server)
 		emulator_disable(e);
 
+	if (e->gprs_watch) {
+		if (e->gprs_status_watch) {
+			__ofono_gprs_remove_status_watch(e->gprs,
+						e->gprs_status_watch);
+			e->gprs_status_watch = 0;
+		}
+
+		__ofono_modem_remove_atom_watch(e->modem, e->gprs_watch);
+		e->gprs_watch = 0;
+		e->gprs = NULL;
+	}
+
 	e->status = OFONO_EMULATOR_STATUS_DESTROY;
 	notify_status_watches(e, NULL);
 
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* [PATCH 21/21] emulator: Watch netreg status changes
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (19 preceding siblings ...)
  2011-01-12 17:16 ` [PATCH 20/21] emulator: Watch GPRS status changes =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-12 17:16 ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-13  9:18 ` [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2011-01-25 19:07 ` Gustavo F. Padovan
  22 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-12 17:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 5246 bytes --]

From: Zhenhua Zhang <zhenhua.zhang@intel.com>

Watch netreg status update to notify DUN client, such as +CREG
unsolicited result.
---
 src/emulator.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 7701510..3444461 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -56,6 +56,9 @@ struct modem_settings {
 	int cops;
 	int attached;
 	int gprs_status;
+	int netreg_status;
+	int netreg_lac;
+	int netreg_ci;
 };
 
 struct ofono_emulator {
@@ -72,6 +75,9 @@ struct ofono_emulator {
 	struct ofono_gprs *gprs;
 	unsigned int gprs_watch;
 	unsigned int gprs_status_watch;
+	struct ofono_netreg *netreg;
+	unsigned int netreg_watch;
+	unsigned int netreg_status_watch;
 };
 
 static GSList *emulator_drivers = NULL;
@@ -265,12 +271,19 @@ static void creg_cb(GAtServerRequestType type, GAtResult *result,
 					gpointer user_data)
 {
 	struct ofono_emulator *e = user_data;
+	char buf[256];
 
 	switch (type) {
 	case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
 		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
 		break;
 	case G_AT_SERVER_REQUEST_TYPE_QUERY:
+		snprintf(buf, sizeof(buf), "+CREG: %d, %x, %x, %x",
+						e->settings.creg,
+						e->settings.netreg_status,
+						e->settings.netreg_lac,
+						e->settings.netreg_ci);
+		ofono_emulator_send_info(e, buf, TRUE);
 		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
 		break;
 	case G_AT_SERVER_REQUEST_TYPE_SET:
@@ -790,6 +803,86 @@ static void add_gprs_watches(struct ofono_emulator *e)
 				OFONO_ATOM_WATCH_CONDITION_REGISTERED, e);
 }
 
+static void emulator_netreg_update(struct ofono_emulator *e)
+{
+	GAtServer *server = e->server;
+	char buf[256];
+
+	switch (e->settings.creg) {
+	case 0:
+		break;
+	case 1:
+		snprintf(buf, sizeof(buf), "+CREG: %d",
+						e->settings.netreg_status);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	case 2:
+		snprintf(buf, sizeof(buf), "+CREG: %d, %x, %x",
+						e->settings.netreg_status,
+						e->settings.netreg_lac,
+						e->settings.netreg_ci);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	default:
+		break;
+	}
+}
+
+static void netreg_status_changed(int status, int lac, int ci, int tech,
+					const char *mcc, const char *mnc,
+					void *data)
+{
+	struct ofono_emulator *e = data;
+
+	DBG("%d %d %d", status, lac, ci);
+
+	e->settings.netreg_status = status;
+	e->settings.netreg_lac = lac;
+	e->settings.netreg_ci = ci;
+
+	emulator_netreg_update(e);
+}
+
+static void netreg_watch(struct ofono_atom *atom,
+				enum ofono_atom_watch_condition cond,
+				void *data)
+{
+	struct ofono_emulator *e = data;
+	struct ofono_netreg *netreg;
+
+	if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+		e->netreg_status_watch = 0;
+		e->netreg = NULL;
+		return;
+	}
+
+	netreg = __ofono_atom_get_data(atom);
+	e->netreg = netreg;
+	e->settings.netreg_status = ofono_netreg_get_status(netreg);
+	e->settings.netreg_lac = ofono_netreg_get_location(netreg);
+	e->settings.netreg_ci = ofono_netreg_get_cellid(netreg);
+	e->netreg_status_watch = __ofono_netreg_add_status_watch(e->netreg,
+					netreg_status_changed, e, NULL);
+
+	emulator_netreg_update(e);
+}
+
+static void add_netreg_watches(struct ofono_emulator *e)
+{
+	struct ofono_modem *modem = e->modem;
+	struct ofono_atom *netreg_atom;
+
+	e->netreg_watch = __ofono_modem_add_atom_watch(modem,
+					OFONO_ATOM_TYPE_NETREG,
+					netreg_watch, e, NULL);
+
+	netreg_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_NETREG);
+
+	if (netreg_atom && __ofono_atom_get_registered(netreg_atom))
+		netreg_watch(netreg_atom,
+				OFONO_ATOM_WATCH_CONDITION_REGISTERED, e);
+}
+
 int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 {
 	if (channel == NULL)
@@ -815,6 +908,7 @@ int ofono_emulator_enable(struct ofono_emulator *e, GIOChannel *channel)
 	g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL);
 
 	add_gprs_watches(e);
+	add_netreg_watches(e);
 
 	return 0;
 }
@@ -855,6 +949,18 @@ static void emulator_remove(struct ofono_atom *atom)
 		e->gprs = NULL;
 	}
 
+	if (e->netreg_watch) {
+		if (e->netreg_status_watch) {
+			__ofono_netreg_remove_status_watch(e->netreg,
+						e->netreg_status_watch);
+			e->netreg_status_watch = 0;
+		}
+
+		__ofono_modem_remove_atom_watch(e->modem, e->netreg_watch);
+		e->netreg_watch = 0;
+		e->netreg = NULL;
+	}
+
 	e->status = OFONO_EMULATOR_STATUS_DESTROY;
 	notify_status_watches(e, NULL);
 
-- 
1.7.1

---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (20 preceding siblings ...)
  2011-01-12 17:16 ` [PATCH 21/21] emulator: Watch netreg " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-13  9:18 ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2011-01-13 12:01   ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-25 19:07 ` Gustavo F. Padovan
  22 siblings, 1 reply; 29+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2011-01-13  9:18 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 959 bytes --]

On Wednesday 12 January 2011 19:15:43 ext Frédéric Dalleau, you wrote:
> This is rebased as of head of today

This seems quite useless work to me.

There are a number of AT commands that are required but really do not belong 
in oFono. Consider for example AT+CKPD/AT+CTSA/AT+CMEC input emulation and 
AT+CBC* battery notifications. Those things have nothing to do with Cellular 
other than the C in the command prefix.  Then we have commands that are related 
to cellular functionality but higher-level than oFono, like AT+CPB* for 
phonebook.

Now, I recognize this patch only attempts to provide BT DUN profile, not the 
whole 27.007 set. But doing that in userspace in oFono is probably the slowest 
and most inefficient approach to the problem. And MeeGo will have to solve the 
more general problem in any case, if MeeGo cellular devices are to be 
certified.

-- 
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki

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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-13  9:18 ` [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2011-01-13 12:01   ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-13 12:17     ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-13 12:01 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1399 bytes --]

On 01/13/2011 10:18 AM, Rémi Denis-Courmont wrote:

> This seems quite useless work to me.

This patch has been on the list for some time now. Why didn't you 
express your concern before that?

> There are a number of AT commands that are required but really do not belong
> in oFono...

For sure nobody wants oFono depend on everything in the world. But at 
some point, one component will need to do the final job of handling the 
AT command. Whether it is oFono or something else I personally don't 
bother. Having it inside oFono through the plugin mechanism will avoid 
some additional layer of IPC.

>  But doing that in userspace in oFono is probably the slowest
> and most inefficient approach to the problem.

Nowadays, relaying a gprs connection at 56k doesn't need to be done in a 
kernel module.
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-13 12:01   ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-13 12:17     ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2011-01-13 14:07       ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  0 siblings, 1 reply; 29+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2011-01-13 12:17 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 904 bytes --]

On Thursday 13 January 2011 14:01:16 ext Frédéric Dalleau, you wrote:
> On 01/13/2011 10:18 AM, Rémi Denis-Courmont wrote:
> > This seems quite useless work to me.
> 
> This patch has been on the list for some time now. Why didn't you
> express your concern before that?

I did point out limitations on some earlier occasion.

I also pointed out the problem to Aki and Marcel privately a long time ago.

> >  But doing that in userspace in oFono is probably the slowest
> > and most inefficient approach to the problem.
> 
> Nowadays, relaying a gprs connection at 56k doesn't need to be done in a
> kernel module.

HSPA category certification is achieved with PPP over USB and using the "final 
user" software. So we are talking about bandwidth in the 10 Mb/s order of 
magnitude on contemporary products.

-- 
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki

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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-13 12:17     ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2011-01-13 14:07       ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
  2011-01-13 14:20         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 29+ messages in thread
From: =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau @ 2011-01-13 14:07 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 956 bytes --]

On 01/13/2011 01:17 PM, Rémi Denis-Courmont wrote:

> HSPA category certification is achieved with PPP over USB and using the "final
> user" software. So we are talking about bandwidth in the 10 Mb/s order

This is another story. The patch uses the oFono ppp layer. This is the 
author's choice and I respect this choice.

Why do you think it cannot handle your requirements?
---------------------------------------------------------------------
Intel Corporation SAS (French simplified joint stock company)
Registered headquarters: "Les Montalets"- 2, rue de Paris, 
92196 Meudon Cedex, France
Registration Number:  302 456 199 R.C.S. NANTERRE
Capital: 4,572,000 Euros

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-13 14:07       ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-13 14:20         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 0 replies; 29+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2011-01-13 14:20 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 698 bytes --]

On Thursday 13 January 2011 16:07:06 ext Frédéric Dalleau, you wrote:
> On 01/13/2011 01:17 PM, Rémi Denis-Courmont wrote:
> > HSPA category certification is achieved with PPP over USB and using the
> > "final user" software. So we are talking about bandwidth in the 10 Mb/s
> > order
> 
> This is another story. The patch uses the oFono ppp layer. This is the
> author's choice and I respect this choice.
> 
> Why do you think it cannot handle your requirements?

I don't know if it can. I am only pointing out that we are not talking about 
orders of magnitude higher bandwidth than V90 which you invoked.

-- 
Rémi Denis-Courmont
Nokia Devices R&D, Maemo Software, Helsinki

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

* Re: [PATCH 02/21] bluetooth: Add Btio library for DUN
  2011-01-12 17:15 ` [PATCH 02/21] bluetooth: Add Btio library for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
@ 2011-01-13 23:31   ` Denis Kenzior
  0 siblings, 0 replies; 29+ messages in thread
From: Denis Kenzior @ 2011-01-13 23:31 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

Hi Frédéric,

On 01/12/2011 11:15 AM, Frédéric Dalleau wrote:
> From: Zhenhua Zhang <zhenhua.zhang@intel.com>
> 
> Btio library is the low level socket API for BT RFCOMM connection. We
> share the same library among BlueZ, Obex and oFono. So make sure you
> synchronize to other two projects when you make changes to btio.[ch].
> ---
>  Makefile.am  |    8 +-
>  btio/btio.c  | 1299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  btio/btio.h  |   97 +++++
>  configure.ac |    5 +
>  4 files changed, 1407 insertions(+), 2 deletions(-)
>  create mode 100644 btio/btio.c
>  create mode 100644 btio/btio.h
> 

This patch has been applied, thanks.

Regards,
-Denis

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

* Re: [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio
  2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
                   ` (21 preceding siblings ...)
  2011-01-13  9:18 ` [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2011-01-25 19:07 ` Gustavo F. Padovan
  22 siblings, 0 replies; 29+ messages in thread
From: Gustavo F. Padovan @ 2011-01-25 19:07 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2806 bytes --]

Hi all,

* Frédéric Dalleau <frederic.dalleau@intel.com> [2011-01-12 18:15:43 +0100]:

> This is rebased as of head of today
> 
> Zhenhua Zhang (21):
>   bluetooth: Add reference count for bluetooth utils
>   bluetooth: Add Btio library for DUN
>   bluetooth: Add bluetooth server support for DUN
>   emulator: Add emulator atom in oFono
>   dun_gw: Add DUN server plugin for oFono
>   gprs: Rename status_watch to netreg_status_watch
>   emulator: Add status watches for ofono emulator
>   emulator: Add emulator status watches in gprs atom
>   emulator: Add APIs to send GAtServer result
>   emulator: Implement dialing up for DUN
>   gprs: Make gprs_proto_to/from_string non-static
>   gprs: ignore the case of proto str when comparing
>   emulator: Register mandatory AT command handlers
>   gprs: Refactor to share remove_context method
>   gprs: Add DUN +CGATT support in gprs atom
>   gprs: Add DUN +CGDCONT support in gprs atom
>   gprs: Add DUN server GPRS connect support
>   gprs: Add status watch functions
>   gprs: Add gprs_get_status
>   emulator: Watch GPRS status changes
>   emulator: Watch netreg status changes
> 
>  Makefile.am            |   15 +-
>  btio/btio.c            | 1299 ++++++++++++++++++++++++++++++++++++++++++++++++
>  btio/btio.h            |   97 ++++
>  configure.ac           |    5 +
>  include/emulator.h     |   94 ++++
>  include/gprs-context.h |    4 +
>  include/gprs.h         |   11 +
>  plugins/bluetooth.c    |  441 ++++++++++++++++-
>  plugins/bluetooth.h    |   15 +
>  plugins/dun_gw.c       |  115 +++++
>  src/emulator.c         | 1072 +++++++++++++++++++++++++++++++++++++++
>  src/gprs.c             |  500 +++++++++++++++++--
>  src/modem.c            |    1 +
>  src/ofono.h            |   31 ++
>  14 files changed, 3636 insertions(+), 64 deletions(-)
>  create mode 100644 btio/btio.c
>  create mode 100644 btio/btio.h
>  create mode 100644 include/emulator.h
>  create mode 100644 plugins/dun_gw.c
>  create mode 100644 src/emulator.c

So I took this patches as a base to finish the DUN implementation on oFono.
The DUN Server is now working, it accepts a ATD*99 from the client and start
the PPP negotiation, then create the ppp interface to flow the internet
connection to the client. Code is here:

git://git.profusion.mobi/users/padovan/ofono.git dun

This not rebased upstream because I didn't touch the bluetooth patches yet,
mostly due the fact that Frédéric Danis is working on them.

The next step is to implement the packet forwarding to the ppp interface
inside ConnMan, you can follow the discussion and implementation in the
ConnMan mailing list.

http://www.mail-archive.com/connman(a)connman.net/msg03092.html

-- 
Gustavo F. Padovan
http://profusion.mobi

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

end of thread, other threads:[~2011-01-25 19:07 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-12 17:15 [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 01/21] bluetooth: Add reference count for bluetooth utils =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 02/21] bluetooth: Add Btio library for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-13 23:31   ` Denis Kenzior
2011-01-12 17:15 ` [PATCH 03/21] bluetooth: Add bluetooth server support " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 04/21] emulator: Add emulator atom in oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 05/21] dun_gw: Add DUN server plugin for oFono =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 06/21] gprs: Rename status_watch to netreg_status_watch =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 07/21] emulator: Add status watches for ofono emulator =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 08/21] emulator: Add emulator status watches in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 09/21] emulator: Add APIs to send GAtServer result =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 10/21] emulator: Implement dialing up for DUN =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 11/21] gprs: Make gprs_proto_to/from_string non-static =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 12/21] gprs: ignore the case of proto str when comparing =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 13/21] emulator: Register mandatory AT command handlers =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 14/21] gprs: Refactor to share remove_context method =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 15/21] gprs: Add DUN +CGATT support in gprs atom =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:15 ` [PATCH 16/21] gprs: Add DUN +CGDCONT " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:16 ` [PATCH 17/21] gprs: Add DUN server GPRS connect support =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:16 ` [PATCH 18/21] gprs: Add status watch functions =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:16 ` [PATCH 19/21] gprs: Add gprs_get_status =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:16 ` [PATCH 20/21] emulator: Watch GPRS status changes =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-12 17:16 ` [PATCH 21/21] emulator: Watch netreg " =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-13  9:18 ` [PATCH 00/21] Resubmit Zhenhua Zhang work on DUN server with btio =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2011-01-13 12:01   ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-13 12:17     ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2011-01-13 14:07       ` =?unknown-8bit?q?Fr=C3=A9d=C3=A9ric?= Dalleau
2011-01-13 14:20         ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2011-01-25 19:07 ` Gustavo F. Padovan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.