[PATCH] gatserver: Don't free twice after user disconnect

2010-07-04 Thread Zhenhua Zhang
It's possible to free gatserver in user disconnect function. So we
should not free it again.
---
 gatchat/gatserver.c |3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
index 3fa26a0..c63f04b 100644
--- a/gatchat/gatserver.c
+++ b/gatchat/gatserver.c
@@ -1019,9 +1019,6 @@ static void io_disconnect(gpointer user_data)
 
if (server-user_disconnect)
server-user_disconnect(server-user_disconnect_data);
-
-   if (server-destroyed)
-   g_free(server);
 }
 
 static void server_wakeup_writer(GAtServer *server)
-- 
1.6.3.3

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 3/6] dun_gw: Add DUN emulator plugin

2010-07-04 Thread Zhenhua Zhang
It implements DUN server role and register itself as agent to BlueZ
interface.
---
 Makefile.am  |3 +
 plugins/dun_gw.c |  274 ++
 2 files changed, 277 insertions(+), 0 deletions(-)
 create mode 100644 plugins/dun_gw.c

diff --git a/Makefile.am b/Makefile.am
index 8ecb2d9..908e945 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -244,6 +244,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 += plugins/dun_gw.c
+
 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 000..95b176c
--- /dev/null
+++ b/plugins/dun_gw.c
@@ -0,0 +1,274 @@
+/*
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2010  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2010 Gustavo F. Padovan gust...@padovan.org
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include config.h
+#endif
+#include stdio.h
+#include string.h
+#include errno.h
+#include glib.h
+#include ofono.h
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include ofono/plugin.h
+#include ofono/log.h
+#include ofono/modem.h
+
+#include ofono/dbus.h
+
+#include gdbus.h
+#include bluetooth.h
+
+#ifndef DBUS_TYPE_UNIX_FD
+#define DBUS_TYPE_UNIX_FD -1
+#endif
+
+#defineBLUEZ_DUN_INTERFACE BLUEZ_SERVICE .SerialDUN
+#define DUN_AGENT_INTERFACEorg.bluez.DUNAgent
+
+static DBusConnection *connection;
+static GHashTable *adapter_hash;
+
+struct dun_data {
+   char *adapter;
+   char *path;
+   gboolean agent_registered;
+   struct ofono_emulator *e;
+};
+
+static struct ofono_emulator_driver dun_gw_driver;
+
+static int dun_gw_create_adapter(const char *path, const char *dev_addr,
+   const char *adapter, const char *alias)
+{
+   GSList *l;
+   struct dun_data *data;
+
+   /* Ignore if we already have this adapter */
+   l = g_hash_table_lookup(adapter_hash, (char *)adapter);
+   if (l != NULL)
+   return -EALREADY;
+
+   DBG(Adding adapter: %s, adapter);
+
+   data = g_try_new0(struct dun_data, 1);
+   if (!data)
+   return -ENOMEM;
+
+   data-adapter = g_strdup(adapter);
+   data-path = g_strdup(path);
+   data-agent_registered = FALSE;
+
+   g_hash_table_insert(adapter_hash, g_strdup(adapter), data);
+
+   return 0;
+}
+
+static gboolean remove_adapter(gpointer key, gpointer value, gpointer 
user_data)
+{
+   struct dun_data *data = value;
+
+   if (data) {
+   g_free(data-adapter);
+   g_free(data-path);
+   g_free(data);
+   data = NULL;
+   }
+
+   return TRUE;
+}
+
+static void dun_gw_remove_all_adapter()
+{
+   if (adapter_hash == NULL)
+   return;
+
+   DBG();
+
+   g_hash_table_foreach_remove(adapter_hash, remove_adapter, NULL);
+}
+
+static DBusMessage *dun_agent_new_connection(DBusConnection *conn,
+   DBusMessage *msg,
+   void *user_data)
+{
+   DBusMessage *reply;
+   int fd;
+
+   if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UNIX_FD, fd,
+   DBUS_TYPE_INVALID)) {
+   reply = g_dbus_create_error(msg, DUN_AGENT_INTERFACE, .Failed,
+   Invalid File Descriptor);
+   goto error;
+   }
+
+   return dbus_message_new_method_return(msg);
+
+error:
+   return reply;
+}
+
+static DBusMessage *dun_agent_release(DBusConnection *conn,
+   DBusMessage *msg, void *user_data)
+{
+   struct dun_data *data = user_data;
+   struct ofono_emulator *e = data-e;
+   const char *obj_path = ofono_emulator_get_path(e);
+
+   g_dbus_unregister_interface(connection, obj_path, DUN_AGENT_INTERFACE);
+   data-agent_registered = FALSE;
+
+   ofono_emulator_remove(e);
+
+   return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable agent_methods[] = {
+   { NewConnection, h, , dun_agent_new_connection,
+   

[PATCH 5/6] emulator: Add test case for ofono emulator

2010-07-04 Thread Zhenhua Zhang
Add gatchat/test-emulator to test DUN emulator.
1. Start ofonod and power on phonesim modem.
2. Run gatchat/test-emulator. It could find dun emulator and create pty
terminal. Use minicom to talk to the DUN emulator.
---
 Makefile.am |7 +-
 gatchat/test-emulator.c |  654 +++
 2 files changed, 660 insertions(+), 1 deletions(-)
 create mode 100644 gatchat/test-emulator.c

diff --git a/Makefile.am b/Makefile.am
index 908e945..b5e53a9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -405,7 +405,8 @@ unit_test_caif_SOURCES = unit/test-caif.c 
$(gatchat_sources) \
 unit_test_caif_LDADD = @GLIB_LIBS@
 unit_objects += $(unit_test_caif_OBJECTS)
 
-noinst_PROGRAMS += gatchat/gsmdial gatchat/test-server gatchat/test-qcdm
+noinst_PROGRAMS += gatchat/gsmdial gatchat/test-server gatchat/test-qcdm \
+   gatchat/test-emulator
 
 gatchat_gsmdial_SOURCES = gatchat/gsmdial.c $(gatchat_sources)
 gatchat_gsmdial_LDADD = @GLIB_LIBS@
@@ -416,6 +417,10 @@ gatchat_test_server_LDADD = @GLIB_LIBS@ -lutil
 gatchat_test_qcdm_SOURCES = gatchat/test-qcdm.c $(gatchat_sources)
 gatchat_test_qcdm_LDADD = @GLIB_LIBS@
 
+gatchat_test_emulator_SOURCES = gatchat/test-emulator.c $(gatchat_sources) \
+   $(gdbus_sources)
+gatchat_test_emulator_LDADD = @GLIB_LIBS@ -lutil -ldbus-1
+
 
 DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles
 
diff --git a/gatchat/test-emulator.c b/gatchat/test-emulator.c
new file mode 100644
index 000..562d9e2
--- /dev/null
+++ b/gatchat/test-emulator.c
@@ -0,0 +1,654 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-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 unistd.h
+#include stdio.h
+#include getopt.h
+#include stdlib.h
+#include string.h
+#include errno.h
+#include sys/socket.h
+#include sys/un.h
+#include netinet/in.h
+#include arpa/inet.h
+#include signal.h
+#include sys/signalfd.h
+
+#include gdbus.h
+#include glib.h
+#include utmp.h
+#include pty.h
+
+#include sys/types.h
+#include sys/stat.h
+
+#include gatserver.h
+
+#define OFONO_SERVICE org.ofono
+#define OFONO_MANAGER_INTERFACE org.ofono.Manager
+#define OFONO_MODEM_INTERFACE org.ofono.Modem
+#define OFONO_GPRS_INTERFACE org.ofono.DataConnectionManager
+#define OFONO_EMULATOR_INTERFACE org.ofono.Emulator
+
+#define DEFAULT_TCP_PORT 12346
+#define DEFAULT_SOCK_PATH ./server_sock
+
+struct sock_server{
+   int server_sock;
+};
+
+static GMainLoop *mainloop;
+static DBusConnection *connection;
+static GSList *modem_list;
+static char *modem_path;
+static unsigned int server_watch;
+const char *emulator = DUN;
+
+typedef void (*DBusNotifyFunction) (DBusMessage *message, void *user_data);
+
+static gboolean send_method_call_with_block(const char *dest, const char *path,
+   const char *interface, const char *method,
+   DBusNotifyFunction cb,
+   void *user_data, int type, ...)
+{
+   DBusMessage *msg, *reply;
+   DBusError err;
+   va_list args;
+
+   msg = dbus_message_new_method_call(dest, path, interface, method);
+   if (!msg) {
+   g_print(Unable to allocate new D-Bus %s message\n, method);
+   return FALSE;
+   }
+
+   va_start(args, type);
+
+   if (!dbus_message_append_args_valist(msg, type, args)) {
+   dbus_message_unref(msg);
+   va_end(args);
+   return FALSE;
+   }
+
+   va_end(args);
+
+   dbus_error_init(err);
+   reply = dbus_connection_send_with_reply_and_block(connection, msg, 100,
+   err);
+   if (!reply) {
+   dbus_message_unref(msg);
+   g_print(ofono replied with an error: %s, %s\n,
+   err.name, err.message);
+   dbus_error_free(err);
+   return FALSE;
+   }
+
+   cb(reply, user_data);
+
+   dbus_message_unref(msg);
+
+   return TRUE;
+}
+
+static gboolean server_cleanup()
+{
+   if (server_watch)
+   g_source_remove(server_watch);
+
+   g_free(modem_path);
+
+   if 

[PATCH 6/6] dun_gw: Probe emulator when we have new adapter

2010-07-04 Thread Zhenhua Zhang
Create emulator when we receive Bluetooth adapter property changes. In
order to do that, we iterate all active modems. If it has GPRS atom and
has not associated DUN emulator yet, create new emulator for it.
---
 include/emulator.h |4 
 plugins/dun_gw.c   |   29 +
 src/emulator.c |   28 
 src/modem.c|   15 +++
 src/ofono.h|6 ++
 5 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 9d96d67..2d23795 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -45,6 +45,10 @@ struct ofono_emulator_driver {
 };
 
 const char *ofono_emulator_get_path(struct ofono_emulator *e);
+
+struct ofono_emulator *ofono_emulator_find(struct ofono_modem *modem,
+   const char *type_str);
+
 void ofono_emulator_set_data(struct ofono_emulator *e, void *user_data);
 void *ofono_emulator_get_data(struct ofono_emulator *e);
 
diff --git a/plugins/dun_gw.c b/plugins/dun_gw.c
index 43a0b0a..8169228 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw.c
@@ -57,6 +57,33 @@ struct dun_data {
 
 static struct ofono_emulator_driver dun_gw_driver;
 
+static gboolean dun_gw_probe_emulator(struct ofono_modem *modem,
+   gpointer user_data)
+{
+   struct ofono_emulator *e;
+   ofono_bool_t powered;
+   struct ofono_atom *gprs_atom;
+
+   powered = ofono_modem_get_powered(modem);
+   if (!powered)
+   return TRUE;
+
+   /* Verify that modem has GPRS atom */
+   gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+   if (!gprs_atom || !__ofono_atom_get_registered(gprs_atom))
+   return TRUE;
+
+   /* Ignore if DUN already has associated adapter */
+   e = ofono_emulator_find(modem, dun);
+   if (e)
+   return TRUE;
+
+   ofono_emulator_create(modem, dun_gw_driver);
+
+/* Only create DUN emulator on one modem */
+   return FALSE;
+}
+
 static int dun_gw_create_adapter(const char *path, const char *dev_addr,
const char *adapter, const char *alias)
 {
@@ -80,6 +107,8 @@ static int dun_gw_create_adapter(const char *path, const 
char *dev_addr,
 
g_hash_table_insert(adapter_hash, g_strdup(adapter), data);
 
+   __ofono_modem_foreach(dun_gw_probe_emulator, NULL);
+
return 0;
 }
 
diff --git a/src/emulator.c b/src/emulator.c
index 1155769..c47152e 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -94,6 +94,14 @@ static const char *ofono_emulator_type_to_str(enum 
ofono_emulator_type type)
}
 }
 
+static enum ofono_emulator_type ofono_emulator_str_to_type(const char *type)
+{
+   if (!strcmp(type, dun))
+   return OFONO_EMULATOR_TYPE_DUN;
+
+   return OFONO_EMULATOR_TYPE_NONE;
+}
+
 const char *ofono_emulator_get_path(struct ofono_emulator *e)
 {
static char path[256];
@@ -105,6 +113,26 @@ const char *ofono_emulator_get_path(struct ofono_emulator 
*e)
return path;
 }
 
+struct ofono_emulator *ofono_emulator_find(struct ofono_modem *modem,
+   const char *type_str)
+{
+   GSList *l;
+   enum ofono_emulator_type type;
+
+   type = ofono_emulator_str_to_type(type_str);
+   if (type == OFONO_EMULATOR_TYPE_NONE)
+   return NULL;
+
+   for (l = emulator_list; l; l = l-next) {
+   struct ofono_emulator *e = l-data;
+
+   if (e-modem == modem  e-driver-type == type)
+   return e;
+   }
+
+   return NULL;
+}
+
 void ofono_emulator_set_data(struct ofono_emulator *e, void *user_data)
 {
if (!e)
diff --git a/src/modem.c b/src/modem.c
index 8137f97..697b068 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -1092,6 +1092,21 @@ void *ofono_devinfo_get_data(struct ofono_devinfo *info)
return info-driver_data;
 }
 
+void __ofono_modem_foreach(ofono_modem_foreach_cb func, gpointer user_data)
+{
+   GSList *l;
+   struct ofono_modem *modem;
+   gboolean ret;
+
+   for (l = g_modem_list; l; l = l-next) {
+   modem = l-data;
+
+   ret = (*func)(modem, user_data);
+   if (!ret)
+   break;
+   }
+}
+
 /* Clients only need to free *modems
  *
  * Note: this function will never return NULL. It will abort if it
diff --git a/src/ofono.h b/src/ofono.h
index ac2a5b0..b2f83c2 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -30,6 +30,12 @@ void __ofono_exit();
 int __ofono_manager_init();
 void __ofono_manager_cleanup();
 
+struct ofono_modem;
+
+typedef gboolean (*ofono_modem_foreach_cb)(struct ofono_modem *modem,
+   gpointer user_data);
+
+void __ofono_modem_foreach(ofono_modem_foreach_cb func, gpointer user_data);
 const char **__ofono_modem_get_list();
 void __ofono_modem_shutdown();

[PATCH 0/6] Add oFono DUN emulator

2010-07-04 Thread Zhenhua Zhang
Hi,

This series are the initial patches for ofono DUN emulator.

1. src/emulator.c handles emulator create, remove, enable, disable and etc..
2. plugins/dun_gw.c is the plugin similar to hfp.c. It's the interface with 
BlueZ serial DUN agent.
3. gatchat/test-emulator.c is the test case to test emulator without BlueZ 
interface.

Emulator driver is registered statically once ofonod starts up. It probes BlueZ 
adapter properties to create emulator on active modem that having GPRS 
interface.

Thanks,
Zhenhua

___
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono


[PATCH 1/6] emulator: Add ofono_emulator framework

2010-07-04 Thread Zhenhua Zhang
Each type of emulator can be register through emulator drivers
statically. When modem powers up, oFono probes emulator driver to create
emulator for each modem.
---
 Makefile.am|4 +-
 include/dbus.h |1 +
 include/emulator.h |   63 
 src/emulator.c |  271 
 src/modem.c|1 +
 src/ofono.h|6 +
 6 files changed, 344 insertions(+), 2 deletions(-)
 create mode 100644 include/emulator.h
 create mode 100644 src/emulator.c

diff --git a/Makefile.am b/Makefile.am
index 96116a5..8ecb2d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,7 @@ include_HEADERS = include/log.h include/plugin.h 
include/history.h \
include/cbs.h include/call-volume.h \
include/gprs.h include/gprs-context.h \
include/radio-settings.h include/stk.h \
-   include/nettime.h
+   include/nettime.h include/emulator.h
 
 nodist_include_HEADERS = include/version.h
 
@@ -272,7 +272,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/storage.c src/cbs.c src/watch.c src/call-volume.c \
src/gprs.c src/idmap.h src/idmap.c \
src/radio-settings.c src/stkutil.h src/stkutil.c \
-   src/nettime.c
+   src/nettime.c src/emulator.c
 
 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl
 
diff --git a/include/dbus.h b/include/dbus.h
index d988760..281be80 100644
--- a/include/dbus.h
+++ b/include/dbus.h
@@ -49,6 +49,7 @@ extern C {
 #define OFONO_VOICECALL_MANAGER_INTERFACE org.ofono.VoiceCallManager
 #define OFONO_DATA_CONNECTION_MANAGER_INTERFACE 
org.ofono.DataConnectionManager
 #define OFONO_DATA_CONTEXT_INTERFACE org.ofono.PrimaryDataContext
+#define OFONO_EMULATOR_INTERFACE org.ofono.Emulator
 
 /* Essentially a{sv} */
 #define OFONO_PROPERTIES_ARRAY_SIGNATURE DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \
diff --git a/include/emulator.h b/include/emulator.h
new file mode 100644
index 000..0c87b13
--- /dev/null
+++ b/include/emulator.h
@@ -0,0 +1,63 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-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;
+
+enum ofono_emulator_type {
+   OFONO_EMULATOR_TYPE_NONE,
+   OFONO_EMULATOR_TYPE_DUN,
+};
+
+struct ofono_emulator_driver {
+   const char *name;
+   enum ofono_emulator_type type;
+   int (*probe)(struct ofono_emulator *e);
+   void (*remove)(struct ofono_emulator *e);
+   int (*enable)(struct ofono_emulator *e, int fd);
+   int (*disable)(struct ofono_emulator *e);
+};
+
+const char *ofono_emulator_get_path(struct ofono_emulator *e);
+void ofono_emulator_set_data(struct ofono_emulator *e, void *user_data);
+void *ofono_emulator_get_data(struct ofono_emulator *e);
+
+struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
+   struct ofono_emulator_driver *driver);
+void ofono_emulator_remove(struct ofono_emulator *e);
+
+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 000..6b63398
--- /dev/null
+++ b/src/emulator.c
@@ -0,0 +1,271 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-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 

[PATCH 2/6] bluetooth: Add register service for bluetooth

2010-07-04 Thread Zhenhua Zhang
Add bluetooth_register_service() and bluetooth_unregister_service()
where bluetooth profiles plugins like DUN GW can register themselves per
adapter. It shares existing bluetooth framework to listen bluetooth
events (new adapters, bluetoothd shutdown, etc..)
---
 plugins/bluetooth.c |  125 ++-
 plugins/bluetooth.h |8 +++
 2 files changed, 112 insertions(+), 21 deletions(-)

diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 5a85eaa..3a3b5e6 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -38,8 +38,19 @@
 
 static DBusConnection *connection;
 static GHashTable *uuid_hash = NULL;
+static GHashTable *service_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
 
+static char *bluetooth_service_type_to_str(enum bluetooth_service_type type)
+{
+   switch (type) {
+   case DUN_GATEWAY:
+   return DUN;
+   default:
+   return ;
+   }
+}
+
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
 {
@@ -376,6 +387,9 @@ static void adapter_properties_cb(DBusPendingCall *call, 
gpointer user_data)
GSList *device_list = NULL;
GSList *l;
const char *addr;
+   GHashTableIter hash_iter;
+   gpointer key, value;
+   struct bluetooth_profile *profile;
 
reply = dbus_pending_call_steal_reply(call);
 
@@ -393,6 +407,12 @@ static void adapter_properties_cb(DBusPendingCall *call, 
gpointer user_data)
g_hash_table_insert(adapter_address_hash,
g_strdup(path), g_strdup(addr));
 
+   g_hash_table_iter_init(hash_iter, service_hash);
+   while (g_hash_table_iter_next(hash_iter, key, value)) {
+   profile = value;
+   profile-create(path, NULL, addr, NULL);
+   }
+
for (l = device_list; l; l = l-next) {
const char *device = l-data;
 
@@ -492,10 +512,13 @@ static void bluetooth_remove_all_modem(gpointer key, 
gpointer value,
 
 static void bluetooth_disconnect(DBusConnection *connection, void *user_data)
 {
-   if (!uuid_hash)
-   return;
+   if (uuid_hash)
+   g_hash_table_foreach(uuid_hash, bluetooth_remove_all_modem,
+   NULL);
 
-   g_hash_table_foreach(uuid_hash, bluetooth_remove_all_modem, NULL);
+   if (service_hash)
+   g_hash_table_foreach(service_hash, bluetooth_remove_all_modem,
+   NULL);
 }
 
 static guint bluetooth_watch;
@@ -503,12 +526,12 @@ 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;
+   if (adapter_address_hash)
+   return 0;
 
connection = ofono_dbus_get_connection();
 
@@ -536,19 +559,9 @@ int bluetooth_register_uuid(const char *uuid, struct 
bluetooth_profile *profile)
goto remove;
}
 
-   uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
-   g_free, NULL);
-
adapter_address_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
 
-done:
-   g_hash_table_insert(uuid_hash, g_strdup(uuid), profile);
-
-   bluetooth_send_with_reply(/, BLUEZ_MANAGER_INTERFACE, GetProperties,
-   manager_properties_cb, NULL, NULL, -1,
-   DBUS_TYPE_INVALID);
-
return 0;
 
 remove:
@@ -556,14 +569,13 @@ 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 void bluetooth_exit()
 {
-   g_hash_table_remove(uuid_hash, uuid);
-
-   if (g_hash_table_size(uuid_hash))
+   if (uuid_hash != NULL || service_hash != NULL)
return;
 
g_dbus_remove_watch(connection, bluetooth_watch);
@@ -571,9 +583,80 @@ 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);
+}
+
+
+int bluetooth_register_uuid(const char *uuid, struct bluetooth_profile 
*profile)
+{
+   int err;
+
+   err = bluetooth_init();
+   if (err)
+   return err;
+
+   if (!uuid_hash)
+   uuid_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+   g_free, NULL);
+
+   g_hash_table_insert(uuid_hash,