All of lore.kernel.org
 help / color / mirror / Atom feed
* [0/15] Implement DUN server in oFono
@ 2010-07-07 10:01 Zhenhua Zhang
  2010-07-07 10:01 ` [PATCH 01/15] dun_gw: Fix license header Zhenhua Zhang
  2010-07-07 10:08 ` [PATCH 0/15] Implement DUN server in oFono Zhang, Zhenhua
  0 siblings, 2 replies; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

This series are based on the previous 6 patches "Add oFono DUN emulator" sent on July 5th. It implements the main functionality of DUN server and interact with GPRS atom to create DUN context. You can use gatchat/test-emulator to create a pseudo terminal and then use gsmdial to create a DUN client connection.

Best regards,
Zhenhua

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

* [PATCH 01/15] dun_gw: Fix license header
  2010-07-07 10:01 [0/15] Implement DUN server in oFono Zhenhua Zhang
@ 2010-07-07 10:01 ` Zhenhua Zhang
  2010-07-07 10:01   ` [PATCH 02/15] watch: Simplify ofono_watchlist remove item Zhenhua Zhang
  2010-07-07 10:08 ` [PATCH 0/15] Implement DUN server in oFono Zhang, Zhenhua
  1 sibling, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Remove incorrect license. It should be merged with dun gw initial patch
later.
---
 plugins/dun_gw.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/plugins/dun_gw.c b/plugins/dun_gw.c
index 8169228..dae9939 100644
--- a/plugins/dun_gw.c
+++ b/plugins/dun_gw.c
@@ -2,7 +2,6 @@
  *  oFono - Open Source Telephony
  *
  *  Copyright (C) 2008-2010  Intel Corporation. All rights reserved.
- *  Copyright (C) 2010 Gustavo F. Padovan <gustavo@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
-- 
1.6.3.3


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

* [PATCH 02/15] watch: Simplify ofono_watchlist remove item
  2010-07-07 10:01 ` [PATCH 01/15] dun_gw: Fix license header Zhenhua Zhang
@ 2010-07-07 10:01   ` Zhenhua Zhang
  2010-07-07 10:01     ` [PATCH 03/15] emulator: Add status watches for ofono emulator Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Use g_slist function to remove items from ofono watchlist.
---
 src/watch.c |   69 ++++++++++++++++++++++++++++------------------------------
 1 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/src/watch.c b/src/watch.c
index f93b68c..cd3d908 100644
--- a/src/watch.c
+++ b/src/watch.c
@@ -46,58 +46,55 @@ unsigned int __ofono_watchlist_add_item(struct ofono_watchlist *watchlist,
 	return item->id;
 }
 
-gboolean __ofono_watchlist_remove_item(struct ofono_watchlist *watchlist,
-					unsigned int id)
+static gint watchlist_item_compare_by_id(gconstpointer a, gconstpointer b)
 {
-	struct ofono_watchlist_item *item;
-	GSList *p;
-	GSList *c;
-
-	p = NULL;
-	c = watchlist->items;
+	const struct ofono_watchlist_item *item = a;
+	unsigned int id = GPOINTER_TO_UINT(b);
 
-	while (c) {
-		item = c->data;
+	if (item->id < id)
+		return -1;
 
-		if (item->id != id) {
-			p = c;
-			c = c->next;
-			continue;
-		}
+	if (item->id > id)
+		return 1;
 
-		if (p)
-			p->next = c->next;
-		else
-			watchlist->items = c->next;
-
-		if (item->destroy)
-			item->destroy(item->notify_data);
+	return 0;
+}
 
-		if (watchlist->destroy)
-			watchlist->destroy(item);
-		g_slist_free_1(c);
+static void watchlist_remove_item(void *data, void *user_data)
+{
+	struct ofono_watchlist_item *item = data;
+	struct ofono_watchlist *watchlist = user_data;
 
-		return TRUE;
-	}
+	if (item->destroy)
+		item->destroy(item->notify_data);
 
-	return FALSE;
+	if (watchlist->destroy)
+		watchlist->destroy(item);
 }
 
-void __ofono_watchlist_free(struct ofono_watchlist *watchlist)
+gboolean __ofono_watchlist_remove_item(struct ofono_watchlist *watchlist,
+					unsigned int id)
 {
 	struct ofono_watchlist_item *item;
 	GSList *l;
 
-	for (l = watchlist->items; l; l = l->next) {
-		item = l->data;
+	l = g_slist_find_custom(watchlist->items, GUINT_TO_POINTER(id),
+						watchlist_item_compare_by_id);
+	if (l == NULL)
+		return FALSE;
 
-		if (item->destroy)
-			item->destroy(item->notify_data);
+	item = l->data;
 
-		if (watchlist->destroy)
-			watchlist->destroy(item);
-	}
+	watchlist->items = g_slist_remove(watchlist->items, item);
 
+	watchlist_remove_item(item, watchlist);
+
+	return TRUE;
+}
+
+void __ofono_watchlist_free(struct ofono_watchlist *watchlist)
+{
+	g_slist_foreach(watchlist->items, watchlist_remove_item, watchlist);
 	g_slist_free(watchlist->items);
 	watchlist->items = NULL;
 	g_free(watchlist);
-- 
1.6.3.3


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

* [PATCH 03/15] emulator: Add status watches for ofono emulator
  2010-07-07 10:01   ` [PATCH 02/15] watch: Simplify ofono_watchlist remove item Zhenhua Zhang
@ 2010-07-07 10:01     ` Zhenhua Zhang
  2010-07-07 10:01       ` [PATCH 04/15] emulator: Add get properities for emulator Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

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     |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ofono.h        |   11 ++++++++++
 3 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index 2d23795..c76dbc7 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,
+};
+
 enum ofono_emulator_type {
 	OFONO_EMULATOR_TYPE_NONE,
 	OFONO_EMULATOR_TYPE_DUN,
diff --git a/src/emulator.c b/src/emulator.c
index c47152e..7551eb6 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -41,6 +41,8 @@ struct ofono_emulator {
 	void *user_data;
 	GAtServer *server;
 	ofono_bool_t powered;
+	enum ofono_emulator_status status;
+	struct ofono_watchlist *status_watches;
 };
 
 static GSList *emulator_list;
@@ -149,6 +151,20 @@ void *ofono_emulator_get_data(struct ofono_emulator *e)
 	return e->user_data;
 }
 
+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);
+	}
+}
+
 static void emulator_remove(struct ofono_atom *atom)
 {
 	struct ofono_emulator *e =  __ofono_atom_get_data(atom);
@@ -163,6 +179,7 @@ static void emulator_remove(struct ofono_atom *atom)
 	if (e->driver->remove)
 		e->driver->remove(e);
 
+	__ofono_watchlist_free(e->status_watches);
 	ofono_emulator_release_id(e->id);
 	g_free(e);
 	e = NULL;
@@ -173,6 +190,9 @@ void ofono_emulator_disable(struct ofono_emulator *e)
 	if (e->server == NULL)
 		return;
 
+	e->status = OFONO_EMULATOR_STATUS_DESTROY;
+	notify_status_watches(e, NULL);
+
 	g_at_server_shutdown(e->server);
 	g_at_server_unref(e->server);
 	e->server = NULL;
@@ -224,6 +244,9 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator *e, int fd)
 
 	e->powered = TRUE;
 
+	e->status = OFONO_EMULATOR_STATUS_CREATE;
+	notify_status_watches(e, NULL);
+
 	return TRUE;
 
 error:
@@ -253,6 +276,7 @@ static struct ofono_emulator *create_emulator(struct ofono_modem *modem,
 
 	e->modem = modem;
 	e->driver = driver;
+	e->status_watches = __ofono_watchlist_new(g_free);
 	e->id = ofono_emulator_next_id();
 
 	return e;
@@ -351,6 +375,37 @@ static gboolean ofono_emulator_dbus_register(struct ofono_modem *modem,
 	return TRUE;
 }
 
+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)
 {
diff --git a/src/ofono.h b/src/ofono.h
index b2f83c2..dc560df 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -285,3 +285,14 @@ void __ofono_nettime_info_received(struct ofono_modem *modem,
 
 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.6.3.3


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

* [PATCH 04/15] emulator: Add get properities for emulator
  2010-07-07 10:01     ` [PATCH 03/15] emulator: Add status watches for ofono emulator Zhenhua Zhang
@ 2010-07-07 10:01       ` Zhenhua Zhang
  2010-07-07 10:01         ` [PATCH 05/15] gprs: Rename status_watch to netreg_status_watch Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

oFono properties:
"Powered": Whether the emulator is powered on.
"Type": Type could be one of supported emulator type, default is DUN.
---
 src/emulator.c |   28 +++++++++++++++++++++++++++-
 1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 7551eb6..86a2eee 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -288,7 +288,33 @@ error:
 static DBusMessage *emulator_get_properties(DBusConnection *conn,
 						DBusMessage *msg, void *data)
 {
-	return dbus_message_new_method_return(msg);
+	struct ofono_emulator *e = data;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	const char *type_str;
+	int type;
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					OFONO_PROPERTIES_ARRAY_SIGNATURE,
+					&dict);
+
+	ofono_dbus_dict_append(&dict, "Powered", DBUS_TYPE_BOOLEAN,
+					&e->powered);
+
+	type = e->driver->type;
+	type_str = ofono_emulator_type_to_str(type);
+	ofono_dbus_dict_append(&dict, "Type", DBUS_TYPE_STRING, &type_str);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
 }
 
 static DBusMessage *emulator_enable(DBusConnection *conn,
-- 
1.6.3.3


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

* [PATCH 05/15] gprs: Rename status_watch to netreg_status_watch
  2010-07-07 10:01       ` [PATCH 04/15] emulator: Add get properities for emulator Zhenhua Zhang
@ 2010-07-07 10:01         ` Zhenhua Zhang
  2010-07-07 10:01           ` [PATCH 06/15] emulator: Add emulator status watches in gprs atom Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

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 cf4f626..829a22c 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -72,7 +72,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;
@@ -1524,10 +1524,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);
@@ -1611,15 +1611,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.6.3.3


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

* [PATCH 06/15] emulator: Add emulator status watches in gprs atom
  2010-07-07 10:01         ` [PATCH 05/15] gprs: Rename status_watch to netreg_status_watch Zhenhua Zhang
@ 2010-07-07 10:01           ` Zhenhua Zhang
  2010-07-07 10:01             ` [PATCH 07/15] emulator: Add emulator status watches in netreg Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

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 |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 829a22c..dd58c51 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -77,6 +77,10 @@ struct ofono_gprs {
 	char *imsi;
 	DBusMessage *pending;
 	struct ofono_gprs_context *context_driver;
+	struct ofono_watchlist *status_watches;
+	struct ofono_emulator *dun;
+	unsigned int dun_watch;
+	unsigned int dun_status_watch;
 	const struct ofono_gprs_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
@@ -1386,6 +1390,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);
@@ -1535,6 +1572,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_DATA_CONNECTION_MANAGER_INTERFACE);
 	g_dbus_unregister_interface(conn, path,
@@ -1778,6 +1827,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_DATA_CONNECTION_MANAGER_INTERFACE,
@@ -1792,6 +1842,8 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
 	ofono_modem_add_interface(modem,
 				OFONO_DATA_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) {
@@ -1811,6 +1863,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.6.3.3


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

* [PATCH 07/15] emulator: Add emulator status watches in netreg
  2010-07-07 10:01           ` [PATCH 06/15] emulator: Add emulator status watches in gprs atom Zhenhua Zhang
@ 2010-07-07 10:01             ` Zhenhua Zhang
  2010-07-07 10:01               ` [PATCH 08/15] emulator: Add APIs to send GAtServer result Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Add dun_watch to watch emulator status update for netreg atom.
---
 src/network.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/src/network.c b/src/network.c
index c6410a8..b9f0a08 100644
--- a/src/network.c
+++ b/src/network.c
@@ -80,6 +80,9 @@ struct ofono_netreg {
 	GKeyFile *settings;
 	char *imsi;
 	struct ofono_watchlist *status_watches;
+	struct ofono_emulator *dun;
+	unsigned int dun_watch;
+	unsigned int dun_status_watch;
 	const struct ofono_netreg_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
@@ -1613,6 +1616,37 @@ const char *ofono_netreg_get_mnc(struct ofono_netreg *netreg)
 	return netreg->current_operator->mnc;
 }
 
+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_netreg *netreg = data;
+	struct ofono_emulator *e = __ofono_atom_get_data(atom);
+
+	if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+		netreg->dun_status_watch = 0;
+		netreg->dun = NULL;
+		return;
+	}
+
+	netreg->dun = e;
+	netreg->dun_status_watch = __ofono_emulator_add_status_watch(e,
+						dun_status_watch, netreg, NULL);
+}
+
 int ofono_netreg_driver_register(const struct ofono_netreg_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1669,6 +1703,19 @@ static void netreg_unregister(struct ofono_atom *atom)
 		netreg->settings = NULL;
 	}
 
+	if (netreg->dun_watch) {
+		if (netreg->dun_status_watch) {
+			__ofono_emulator_remove_status_watch(netreg->dun,
+						netreg->dun_status_watch);
+			netreg->dun_status_watch = 0;
+			netreg->dun = NULL;
+		}
+
+		__ofono_modem_remove_atom_watch(modem, netreg->dun_watch);
+		netreg->dun_watch = 0;
+		netreg->dun = NULL;
+	}
+
 	g_dbus_unregister_interface(conn, path,
 					OFONO_NETWORK_REGISTRATION_INTERFACE);
 	ofono_modem_remove_interface(modem,
@@ -1773,6 +1820,7 @@ void ofono_netreg_register(struct ofono_netreg *netreg)
 	struct ofono_modem *modem = __ofono_atom_get_modem(netreg->atom);
 	const char *path = __ofono_atom_get_path(netreg->atom);
 	struct ofono_atom *sim_atom;
+	struct ofono_atom *dun_atom;
 
 	if (!g_dbus_register_interface(conn, path,
 					OFONO_NETWORK_REGISTRATION_INTERFACE,
@@ -1809,6 +1857,16 @@ void ofono_netreg_register(struct ofono_netreg *netreg)
 				sim_spn_read_cb, netreg);
 	}
 
+	netreg->dun_watch = __ofono_modem_add_atom_watch(modem,
+						OFONO_ATOM_TYPE_EMULATOR_DUN,
+						dun_watch, netreg, 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,
+						netreg);
+
 	__ofono_atom_register(netreg->atom, netreg_unregister);
 }
 
-- 
1.6.3.3


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

* [PATCH 08/15] emulator: Add APIs to send GAtServer result
  2010-07-07 10:01             ` [PATCH 07/15] emulator: Add emulator status watches in netreg Zhenhua Zhang
@ 2010-07-07 10:01               ` Zhenhua Zhang
  2010-07-07 10:01                 ` [PATCH 09/15] emulator: Implement dialing up for DUN Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Defines APIs to send final/intermediate/unsolicited result to DUN
client.
---
 include/emulator.h |    2 ++
 src/emulator.c     |   28 ++++++++++++++++++++++++++++
 src/ofono.h        |   10 ++++++++++
 3 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/include/emulator.h b/include/emulator.h
index c76dbc7..8b10f8c 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -50,6 +50,8 @@ struct ofono_emulator_driver {
 	int (*disable)(struct ofono_emulator *e);
 };
 
+enum _GAtServerResult;
+
 const char *ofono_emulator_get_path(struct ofono_emulator *e);
 
 struct ofono_emulator *ofono_emulator_find(struct ofono_modem *modem,
diff --git a/src/emulator.c b/src/emulator.c
index 86a2eee..aa203f1 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -401,6 +401,34 @@ static gboolean ofono_emulator_dbus_register(struct ofono_modem *modem,
 	return TRUE;
 }
 
+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);
+}
+
 unsigned int __ofono_emulator_add_status_watch(struct ofono_emulator *e,
 				ofono_emulator_status_notify_cb_t notify,
 				void *data, ofono_destroy_func destroy)
diff --git a/src/ofono.h b/src/ofono.h
index dc560df..2a63386 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -296,3 +296,13 @@ 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.6.3.3


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

* [PATCH 09/15] emulator: Implement dialing up for DUN
  2010-07-07 10:01               ` [PATCH 08/15] emulator: Add APIs to send GAtServer result Zhenhua Zhang
@ 2010-07-07 10:01                 ` Zhenhua Zhang
  2010-07-07 10:01                   ` [PATCH 10/15] emulator: Add emulator dial up support in GPRS Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/include/emulator.h b/include/emulator.h
index 8b10f8c..b8fb0d5 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -34,6 +34,10 @@ enum ofono_emulator_status {
 	OFONO_EMULATOR_STATUS_IDLE = 0,
 	OFONO_EMULATOR_STATUS_CREATE,
 	OFONO_EMULATOR_STATUS_DESTROY,
+	OFONO_EMULATOR_STATUS_GPRS_CONNECT,
+	OFONO_EMULATOR_STATUS_DUN_CONNECTING,
+	OFONO_EMULATOR_STATUS_DUN_CONNECTED,
+	OFONO_EMULATOR_STATUS_DUN_DISCONNECTED,
 };
 
 enum ofono_emulator_type {
@@ -52,6 +56,36 @@ struct ofono_emulator_driver {
 
 enum _GAtServerResult;
 
+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_dun_connect_req {
+	const char *iface;
+	const char *local;
+	const char *peer;
+	const char *dns1;
+	const char *dns2;
+	ofono_emulator_cb_t cb;
+	void *cb_data;
+};
+
 const char *ofono_emulator_get_path(struct ofono_emulator *e);
 
 struct ofono_emulator *ofono_emulator_find(struct ofono_modem *modem,
diff --git a/src/emulator.c b/src/emulator.c
index aa203f1..dda74a1 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -29,10 +29,22 @@
 #include <glib.h>
 #include <gdbus.h>
 
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
 #include "ofono.h"
 #include "gatserver.h"
+#include "gatppp.h"
 #include "common.h"
 
+struct context_info {
+	char *interface;
+	char *local;
+	char *peer;
+	char *dns1;
+	char *dns2;
+};
+
 struct ofono_emulator {
 	struct ofono_emulator_driver *driver;
 	struct ofono_modem *modem;
@@ -40,9 +52,11 @@ struct ofono_emulator {
 	unsigned int id;
 	void *user_data;
 	GAtServer *server;
+	GAtPPP *ppp;
 	ofono_bool_t powered;
 	enum ofono_emulator_status status;
 	struct ofono_watchlist *status_watches;
+	struct context_info *info;
 };
 
 static GSList *emulator_list;
@@ -165,6 +179,210 @@ static void notify_status_watches(struct ofono_emulator *e, void *data)
 	}
 }
 
+static void ppp_connect_cb(GAtServerResult res, void *user_data)
+{
+	struct ofono_emulator *e = user_data;
+
+	if (res == G_AT_SERVER_RESULT_OK) {
+		DBG("PPP actived!\n");
+		e->status = OFONO_EMULATOR_STATUS_DUN_CONNECTED;
+	} else {
+		DBG("Failed to active PPP connection!\n");
+		e->status = OFONO_EMULATOR_STATUS_IDLE;
+	}
+
+	notify_status_watches(e, NULL);
+}
+
+static void ppp_connect(const char *iface, const char *local, const char *peer,
+				const char *dns1, const char *dns2,
+				gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct ofono_emulator_dun_connect_req *req;
+
+	DBG("Network Device: %s\n", iface);
+	DBG("IP Address: %s\n", local);
+	DBG("Remote IP Address: %s\n", peer);
+	DBG("Primary DNS Server: %s\n", dns1);
+	DBG("Secondary DNS Server: %s\n", dns2);
+
+	req = g_try_new0(struct ofono_emulator_dun_connect_req, 1);
+	if (!req)
+		return;
+
+	req->iface = iface;
+	req->local = local;
+	req->peer = peer;
+	req->dns1 = dns1;
+	req->dns2 = dns2;
+	req->cb = ppp_connect_cb;
+	req->cb_data = e;
+
+	e->status = OFONO_EMULATOR_STATUS_DUN_CONNECTING;
+
+	notify_status_watches(e, req);
+
+	g_free(req);
+}
+
+static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
+{
+	struct ofono_emulator *e = user_data;
+	struct context_info *info = e->info;
+	struct ofono_emulator_req *req;
+
+	DBG("");
+
+	g_at_ppp_unref(e->ppp);
+	e->ppp = NULL;
+
+	g_at_server_resume(e->server);
+
+	g_free(info->interface);
+	g_free(info->local);
+	g_free(info->peer);
+	g_free(info->dns1);
+	g_free(info->dns2);
+	g_free(info);
+
+	req = ofono_emulator_req_new(generic_cb, e);
+	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_info *info = e->info;
+
+	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, info->local);
+	if (e->ppp == NULL) {
+		g_at_server_resume(server);
+		return FALSE;
+	}
+
+	g_at_ppp_set_server_info(e->ppp, info->peer, info->dns1, info->dns2);
+	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_info *info;
+
+	DBG("");
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		goto error;
+
+	if (!dns[0] || !dns[1])
+		goto error;
+
+	info = g_try_new0(struct context_info, 1);
+	if (!info)
+		goto error;
+
+	info->interface = g_strdup(interface);
+	info->local = g_strdup(local);
+	info->peer = g_strdup(peer);
+	info->dns1 = g_strdup(dns[0]);
+	info->dns2 = g_strdup(dns[1]);
+
+	e->info = info;
+
+	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_GPRS_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 (!dial_call(e, dial_str))
+		goto error;
+
+	return;
+
+error:
+	g_at_server_send_final(server, res);
+}
+
 static void emulator_remove(struct ofono_atom *atom)
 {
 	struct ofono_emulator *e =  __ofono_atom_get_data(atom);
@@ -190,6 +408,12 @@ void ofono_emulator_disable(struct ofono_emulator *e)
 	if (e->server == NULL)
 		return;
 
+	if (e->ppp) {
+		g_at_ppp_shutdown(e->ppp);
+		g_at_ppp_unref(e->ppp);
+		e->ppp = NULL;
+	}
+
 	e->status = OFONO_EMULATOR_STATUS_DESTROY;
 	notify_status_watches(e, NULL);
 
@@ -240,6 +464,8 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator *e, int fd)
 	g_at_server_set_debug(e->server, ofono_emulator_debug, "Server");
 	g_at_server_set_disconnect_function(e->server, emulator_disconnect, e);
 
+	g_at_server_register(e->server, "D", dial_cb, e, NULL);
+
 	g_io_channel_unref(channel);
 
 	e->powered = TRUE;
-- 
1.6.3.3


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

* [PATCH 10/15] emulator: Add emulator dial up support in GPRS
  2010-07-07 10:01                 ` [PATCH 09/15] emulator: Implement dialing up for DUN Zhenhua Zhang
@ 2010-07-07 10:01                   ` Zhenhua Zhang
  2010-07-07 10:01                     ` [PATCH 11/15] emulator: Register mandatory AT command handlers Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Implement dial up support in GPRS atom.
---
 src/gprs.c |  439 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 437 insertions(+), 2 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index dd58c51..cb83e23 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -39,6 +39,7 @@
 #include "common.h"
 #include "storage.h"
 #include "idmap.h"
+#include "gatserver.h"
 
 #define GPRS_FLAG_ATTACHING 0x1
 #define GPRS_FLAG_RECHECK 0x2
@@ -48,6 +49,10 @@
 #define MAX_CONTEXT_NAME_LENGTH 127
 #define MAX_CONTEXTS 256
 
+#define DUN_LOCAL "192.168.1.1"
+#define DUN_PEER "192.168.1.2"
+#define EMULATOR_GPRS_TIMEOUT 20
+
 static GSList *g_drivers = NULL;
 static GSList *g_context_drivers = NULL;
 
@@ -55,6 +60,7 @@ enum gprs_context_type {
 	GPRS_CONTEXT_TYPE_INTERNET = 0,
 	GPRS_CONTEXT_TYPE_MMS,
 	GPRS_CONTEXT_TYPE_WAP,
+	GPRS_CONTEXT_TYPE_DUN,
 	GPRS_CONTEXT_TYPE_INVALID,
 };
 
@@ -81,6 +87,9 @@ struct ofono_gprs {
 	struct ofono_emulator *dun;
 	unsigned int dun_watch;
 	unsigned int dun_status_watch;
+	int attach_source;
+	int context_source;
+	int timeout_source;
 	const struct ofono_gprs_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
@@ -115,6 +124,13 @@ struct pri_context {
 	struct ofono_gprs *gprs;
 };
 
+struct gprs_dun_data {
+	struct ofono_gprs *gprs;
+	ofono_emulator_gprs_connect_cb cb;
+	void *cb_data;
+	struct pri_context *context;
+};
+
 static void gprs_netreg_update(struct ofono_gprs *gprs);
 
 static const char *gprs_context_type_to_string(int type)
@@ -168,6 +184,21 @@ static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
 	return NULL;
 }
 
+static struct pri_context *gprs_context_by_type(struct ofono_gprs *gprs,
+						enum gprs_context_type type)
+{
+	GSList *l;
+
+	for (l = gprs->contexts; l; l = l->next) {
+		struct pri_context *ctx = l->data;
+
+		if (type == ctx->type)
+			return ctx;
+	}
+
+	return NULL;
+}
+
 static void context_settings_free(struct context_settings *settings)
 {
 	g_free(settings->interface);
@@ -401,6 +432,53 @@ static DBusMessage *pri_get_properties(DBusConnection *conn,
 	return reply;
 }
 
+static void dun_activate(const char *interface, const char *local,
+						const char *peer,
+						const char **dns,
+						void *data)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	struct pri_context *ctx = data;
+	const char *netmask = "255.255.255.255";
+	dbus_bool_t value;
+
+	DBG("%p %s", ctx, interface);
+
+	ctx->active = TRUE;
+
+	/* If we don't have the interface, don't bother emitting any settings,
+	 * as nobody can make use of them
+	 */
+	if (interface != NULL)
+		pri_update_context_settings(ctx, interface, TRUE,
+						local, netmask, peer, dns);
+
+	value = ctx->active;
+	ofono_dbus_signal_property_changed(conn, ctx->path,
+						OFONO_DATA_CONTEXT_INTERFACE,
+						"Active", DBUS_TYPE_BOOLEAN,
+						&value);
+}
+
+static void dun_deactivate(struct pri_context *ctx)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	dbus_bool_t value;
+
+	gprs_cid_release(ctx->gprs, ctx->context.cid);
+	ctx->context.cid = 0;
+
+	ctx->active = FALSE;
+
+	pri_reset_context_settings(ctx);
+
+	value = ctx->active;
+	ofono_dbus_signal_property_changed(conn, ctx->path,
+						OFONO_DATA_CONTEXT_INTERFACE,
+						"Active", DBUS_TYPE_BOOLEAN,
+						&value);
+}
+
 static void pri_activate_callback(const struct ofono_error *error,
 					const char *interface, ofono_bool_t static_ip,
 					const char *ip, const char *netmask,
@@ -417,7 +495,8 @@ 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(&gc->pending,
+		if (gc && gc->pending)
+			__ofono_dbus_pending_reply(&gc->pending,
 					__ofono_error_failed(gc->pending));
 
 		gprs_cid_release(ctx->gprs, ctx->context.cid);
@@ -427,7 +506,9 @@ static void pri_activate_callback(const struct ofono_error *error,
 	}
 
 	ctx->active = TRUE;
-	__ofono_dbus_pending_reply(&gc->pending,
+
+	if (gc && gc->pending)
+		__ofono_dbus_pending_reply(&gc->pending,
 				dbus_message_new_method_return(gc->pending));
 
 	/* If we don't have the interface, don't bother emitting any settings,
@@ -693,6 +774,12 @@ static DBusMessage *pri_set_property(DBusConnection *conn,
 
 		gc->pending = dbus_message_ref(msg);
 
+		if (ctx->type == GPRS_CONTEXT_TYPE_DUN) {
+			/* Not support yet */
+			ofono_error("Active DUN context are not yet supported");
+			return __ofono_error_failed(msg);
+		}
+
 		if (value)
 			gc->driver->activate_primary(gc, &ctx->context,
 						pri_activate_callback, ctx);
@@ -1095,6 +1182,82 @@ static DBusMessage *gprs_set_property(DBusConnection *conn,
 	return dbus_message_new_method_return(msg);
 }
 
+static struct pri_context *ofono_gprs_create_context(
+					struct ofono_gprs *gprs,
+					const char *name, const char *typestr)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	struct pri_context *context;
+	const char *path;
+	enum gprs_context_type type;
+	char **objpath_list;
+	unsigned int id;
+
+	if (strlen(name) == 0 || strlen(name) > MAX_CONTEXT_NAME_LENGTH)
+		return NULL;
+
+	type = gprs_context_string_to_type(typestr);
+
+	if (type == GPRS_CONTEXT_TYPE_INVALID)
+		return NULL;
+
+	if (gprs->last_context_id)
+		id = idmap_alloc_next(gprs->pid_map, gprs->last_context_id);
+	else
+		id = idmap_alloc(gprs->pid_map);
+
+	if (id > idmap_get_max(gprs->pid_map))
+		return NULL;
+
+	context = pri_context_create(gprs, name, type);
+	context->id = id;
+
+	if (!context) {
+		ofono_error("Unable to allocate context struct");
+		return NULL;
+	}
+
+	DBG("Registering new context");
+
+	if (!context_dbus_register(context)) {
+		ofono_error("Unable to register primary context");
+		return NULL;
+	}
+
+	gprs->last_context_id = id;
+
+	if (gprs->settings) {
+		g_key_file_set_string(gprs->settings, context->key,
+					"Name", context->name);
+		g_key_file_set_string(gprs->settings, context->key,
+					"AccessPointName",
+					context->context.apn);
+		g_key_file_set_string(gprs->settings, context->key,
+					"Username", context->context.username);
+		g_key_file_set_string(gprs->settings, context->key,
+					"Password", context->context.password);
+		g_key_file_set_string(gprs->settings, context->key, "Type",
+				gprs_context_type_to_string(context->type));
+		storage_sync(gprs->imsi, SETTINGS_STORE, gprs->settings);
+	}
+
+	gprs->contexts = g_slist_append(gprs->contexts, context);
+
+	objpath_list = gprs_contexts_path_list(gprs->contexts);
+
+	if (objpath_list) {
+		path = __ofono_atom_get_path(gprs->atom);
+		ofono_dbus_signal_array_property_changed(conn, path,
+					OFONO_DATA_CONNECTION_MANAGER_INTERFACE,
+					"PrimaryContexts",
+					DBUS_TYPE_OBJECT_PATH, &objpath_list);
+
+		g_strfreev(objpath_list);
+	}
+
+	return context;
+}
+
 static DBusMessage *gprs_create_context(DBusConnection *conn,
 					DBusMessage *msg, void *data)
 {
@@ -1390,14 +1553,284 @@ 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->gprs->context_driver;
+
+	if (gc == NULL || gc->driver->activate_primary == NULL ||
+			gc->driver->deactivate_primary == NULL ||
+			ctx->gprs->cid_map == NULL)
+		return FALSE;
+
+	if (gc->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_emulator_dun_disconnect(struct ofono_gprs *gprs,
+				struct ofono_emulator_req *req)
+{
+	struct pri_context *dun;
+
+	dun = gprs_context_by_type(gprs, GPRS_CONTEXT_TYPE_DUN);
+	if (!dun) {
+		req->cb(G_AT_SERVER_RESULT_NO_CARRIER, req->cb_data);
+		return;
+	}
+
+	dun_deactivate(dun);
+
+	context_dbus_unregister(dun);
+	gprs->contexts = g_slist_remove(gprs->contexts, dun);
+
+	req->cb(G_AT_SERVER_RESULT_NO_CARRIER, req->cb_data);
+}
+
+static void ofono_emulator_dun_connect(struct ofono_gprs *gprs,
+				struct ofono_emulator_dun_connect_req *req)
+{
+	struct pri_context *dun;
+	const char *dns[3];
+
+	dun = gprs_context_by_type(gprs, GPRS_CONTEXT_TYPE_DUN);
+	if (!dun) {
+		req->cb(G_AT_SERVER_RESULT_ERROR, req->cb_data);
+		return;
+	}
+
+	dns[0] = req->dns1;
+	dns[1] = req->dns2;
+	dns[2] = 0;
+
+	dun_activate(req->iface, req->local, req->peer, dns, dun);
+
+	req->cb(G_AT_SERVER_RESULT_OK, req->cb_data);
+}
+
+static void ofono_emulator_remove_sources(struct ofono_gprs *gprs)
+{
+	if (gprs == NULL)
+		return;
+
+	if (gprs->timeout_source)
+		g_source_remove(gprs->timeout_source);
+
+	if (gprs->attach_source)
+		g_source_remove(gprs->attach_source);
+
+	if (gprs->context_source)
+		g_source_remove(gprs->context_source);
+}
+
+static gboolean emulator_gprs_timeout(gpointer user_data)
+{
+	struct gprs_dun_data *data = user_data;
+	struct ofono_gprs *gprs = data->gprs;
+	struct pri_context *context = data->context;
+	struct ofono_error error;
+
+	ofono_emulator_remove_sources(gprs);
+
+	if (context->active == TRUE)
+		goto done;
+
+	error.type = OFONO_ERROR_TYPE_FAILURE;
+	data->cb(&error, NULL, NULL, NULL, NULL, data->cb_data);
+
+done:
+	g_free(data);
+
+	return FALSE;
+}
+
+static gboolean pri_context_update(gpointer user_data)
+{
+	struct gprs_dun_data *data = user_data;
+	struct ofono_gprs *gprs = data->gprs;
+	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);
+
+	g_free(data);
+
+	return FALSE;
+}
+
+static gboolean gprs_attach_update(gpointer user_data)
+{
+	struct gprs_dun_data *data = user_data;
+	struct ofono_gprs *gprs = data->gprs;
+	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, data);
+		return FALSE;
+	}
+
+	pri_context_update(data);
+
+	return FALSE;
+}
+
+static ofono_bool_t gprs_dun_connect(struct pri_context *dun,
+					ofono_emulator_gprs_connect_cb cb,
+					void *cb_data)
+{
+	struct ofono_gprs *gprs = dun->gprs;
+	struct pri_context *context;
+	struct gprs_dun_data *data = g_try_new0(struct gprs_dun_data, 1);
+
+	if (!data)
+		return FALSE;
+
+	/* Create context for real modem if not connected yet */
+	if (gprs->contexts)
+		context = gprs_context_by_type(gprs,
+						GPRS_CONTEXT_TYPE_INTERNET);
+	else
+		context = ofono_gprs_create_context(gprs,
+						"default", "internet");
+
+	if (!context)
+		return FALSE;
+
+	data->gprs = gprs;
+	data->cb = cb;
+	data->cb_data = cb_data;
+	data->context = context;
+
+	gprs->timeout_source = g_timeout_add_seconds(EMULATOR_GPRS_TIMEOUT,
+						emulator_gprs_timeout, data);
+
+	/* 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, data);
+		return TRUE;
+	}
+
+	gprs_attach_update(data);
+
+	return TRUE;
+}
+
+static void ofono_emulator_gprs_connect(struct ofono_gprs *gprs,
+				struct ofono_emulator_gprs_connect_req *req)
+{
+	const char *dial_str = req->dial_str;
+	struct pri_context *dun;
+	struct ofono_error error;
+
+	DBG("dial call %s", dial_str);
+
+	/* Create DUN context if not exists */
+	dun = gprs_context_by_type(gprs, GPRS_CONTEXT_TYPE_DUN);
+	if (!dun) {
+		dun = ofono_gprs_create_context(gprs, "dun", "dun");
+		if (!dun)
+			goto error;
+	}
+
+	if (!gprs_dun_connect(dun, req->cb, req->cb_data))
+		goto error;
+
+	return;
+error:
+	error.type = OFONO_ERROR_TYPE_FAILURE;
+	req->cb(&error, NULL, NULL, NULL, NULL, 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_GPRS_CONNECT:
+		ofono_emulator_gprs_connect(gprs, data);
+		break;
+	case OFONO_EMULATOR_STATUS_DUN_CONNECTING:
+		ofono_emulator_dun_connect(gprs, data);
+		break;
+	case OFONO_EMULATOR_STATUS_DUN_CONNECTED:
+		break;
+	case OFONO_EMULATOR_STATUS_DUN_DISCONNECTED:
+		ofono_emulator_dun_disconnect(gprs, data);
+		break;
+	case OFONO_EMULATOR_STATUS_DESTROY:
+		ofono_emulator_remove_sources(gprs);
+		break;
 	default:
 		break;
 	}
@@ -1584,6 +2017,8 @@ static void gprs_unregister(struct ofono_atom *atom)
 		gprs->dun = NULL;
 	}
 
+	ofono_emulator_remove_sources(gprs);
+
 	ofono_modem_remove_interface(modem,
 					OFONO_DATA_CONNECTION_MANAGER_INTERFACE);
 	g_dbus_unregister_interface(conn, path,
-- 
1.6.3.3


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

* [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-07 10:01                   ` [PATCH 10/15] emulator: Add emulator dial up support in GPRS Zhenhua Zhang
@ 2010-07-07 10:01                     ` Zhenhua Zhang
  2010-07-07 10:01                       ` [PATCH 12/15] emulator: Watch GPRS status changes Zhenhua Zhang
  2010-07-07 10:48                       ` [PATCH 11/15] emulator: Register mandatory AT command handlers =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 2 replies; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/include/emulator.h b/include/emulator.h
index b8fb0d5..487f347 100644
--- a/include/emulator.h
+++ b/include/emulator.h
@@ -38,6 +38,8 @@ enum ofono_emulator_status {
 	OFONO_EMULATOR_STATUS_DUN_CONNECTING,
 	OFONO_EMULATOR_STATUS_DUN_CONNECTED,
 	OFONO_EMULATOR_STATUS_DUN_DISCONNECTED,
+	OFONO_EMULATOR_STATUS_SET_CGATT,
+	OFONO_EMULATOR_STATUS_SET_CGDCONT,
 };
 
 enum ofono_emulator_type {
diff --git a/src/emulator.c b/src/emulator.c
index dda74a1..546a48b 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -57,6 +57,17 @@ struct ofono_emulator {
 	enum ofono_emulator_status status;
 	struct ofono_watchlist *status_watches;
 	struct context_info *info;
+
+	int modem_mode;
+	int modem_creg;
+	int modem_cgreg;
+	int modem_cops;
+	int modem_attached;
+	int modem_context;
+	int netreg_status;
+	int netreg_lac;
+	int netreg_ci;
+	int gprs_status;
 };
 
 static GSList *emulator_list;
@@ -179,6 +190,33 @@ 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 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 void ppp_connect_cb(GAtServerResult res, void *user_data)
 {
 	struct ofono_emulator *e = user_data;
@@ -383,6 +421,338 @@ error:
 	g_at_server_send_final(server, res);
 }
 
+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->modem_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->modem_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;
+	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->modem_creg, e->netreg_status,
+					e->netreg_lac, e->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:
+	{
+		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->modem_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;
+	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->modem_cgreg,
+					e->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:
+	{
+		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->modem_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->modem_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->modem_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->modem_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->modem_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_req *req;
+	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), "+CGDCONT: %d", e->modem_context);
+		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 cid;
+		const char *protocol;
+
+		g_at_result_iter_init(&iter, result);
+		g_at_result_iter_next(&iter, "+CGDCONT=");
+
+		if (g_at_result_iter_next_number(&iter, &cid) == FALSE)
+			goto error;
+
+		if (g_at_result_iter_next_string(&iter, &protocol) == FALSE)
+			goto error;
+
+		DBG("set CGDCONT %d %s", cid, protocol);
+
+		req = ofono_emulator_req_new(generic_cb, e);
+		if (!req)
+			goto error;
+
+		e->status = OFONO_EMULATOR_STATUS_SET_CGDCONT;
+
+		notify_status_watches(e, req);
+
+		e->modem_context = cid;
+
+		g_free(req);
+		break;
+	}
+	default:
+		goto error;
+	};
+
+	return;
+error:
+	ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR);
+}
+
 static void emulator_remove(struct ofono_atom *atom)
 {
 	struct ofono_emulator *e =  __ofono_atom_get_data(atom);
@@ -465,6 +835,13 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator *e, int fd)
 	g_at_server_set_disconnect_function(e->server, emulator_disconnect, 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);
 
 	g_io_channel_unref(channel);
 
-- 
1.6.3.3


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

* [PATCH 12/15] emulator: Watch GPRS status changes
  2010-07-07 10:01                     ` [PATCH 11/15] emulator: Register mandatory AT command handlers Zhenhua Zhang
@ 2010-07-07 10:01                       ` Zhenhua Zhang
  2010-07-07 10:01                         ` [PATCH 13/15] emulator: Watch netreg " Zhenhua Zhang
  2010-07-07 10:48                       ` [PATCH 11/15] emulator: Register mandatory AT command handlers =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  1 sibling, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Watch GPRS status changes to notify DUN client any unsolicited result,
like +CGREG status changes.
---
 include/gprs.h |   11 +++++++
 src/emulator.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gprs.c     |   64 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 163 insertions(+), 0 deletions(-)

diff --git a/include/gprs.h b/include/gprs.h
index a1cbcd9..ca23c45 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,
@@ -67,6 +69,15 @@ 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);
+
+int ofono_gprs_get_status(struct ofono_gprs *gprs);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/emulator.c b/src/emulator.c
index 546a48b..3bb32ae 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -68,6 +68,10 @@ struct ofono_emulator {
 	int netreg_lac;
 	int netreg_ci;
 	int gprs_status;
+
+	struct ofono_gprs *gprs;
+	unsigned int gprs_watch;
+	unsigned int gprs_status_watch;
 };
 
 static GSList *emulator_list;
@@ -767,6 +771,18 @@ static void emulator_remove(struct ofono_atom *atom)
 	if (e->driver->remove)
 		e->driver->remove(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;
+	}
+
 	__ofono_watchlist_free(e->status_watches);
 	ofono_emulator_release_id(e->id);
 	g_free(e);
@@ -794,6 +810,76 @@ void ofono_emulator_disable(struct ofono_emulator *e)
 	e->powered = FALSE;
 }
 
+static void emulator_gprs_update(struct ofono_emulator *e)
+{
+	GAtServer *server = e->server;
+	char buf[256];
+
+	switch (e->modem_cgreg) {
+	case 0:
+		break;
+	case 1:
+		snprintf(buf, sizeof(buf), "+CGREG: %d", e->gprs_status);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	case 2:
+		snprintf(buf, sizeof(buf), "+CGREG: %d", e->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->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->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);
+}
+
 static int set_powered(struct ofono_emulator *e, ofono_bool_t powered, int fd)
 {
 	int val;
@@ -843,6 +929,8 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator *e, int fd)
 	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);
+
 	g_io_channel_unref(channel);
 
 	e->powered = TRUE;
diff --git a/src/gprs.c b/src/gprs.c
index cb83e23..3ed056a 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -142,6 +142,8 @@ static const char *gprs_context_type_to_string(int type)
 		return "mms";
 	case GPRS_CONTEXT_TYPE_WAP:
 		return "wap";
+	case GPRS_CONTEXT_TYPE_DUN:
+		return "dun";
 	}
 
 	return NULL;
@@ -155,6 +157,8 @@ static enum gprs_context_type gprs_context_string_to_type(const char *str)
 		return GPRS_CONTEXT_TYPE_WAP;
 	else if (g_str_equal(str, "mms"))
 		return GPRS_CONTEXT_TYPE_MMS;
+	else if (g_str_equal(str, "dun"))
+		return GPRS_CONTEXT_TYPE_DUN;
 
 	return GPRS_CONTEXT_TYPE_INVALID;
 }
@@ -1467,6 +1471,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)
 {
 	if (gprs->driver_attached == FALSE)
@@ -1476,6 +1525,8 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
 
 	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
 	 */
@@ -1489,6 +1540,8 @@ void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status)
 
 	gprs->status = status;
 	gprs_attached_update(gprs);
+
+	notify_status_watches(gprs);
 }
 
 void ofono_gprs_set_cid_range(struct ofono_gprs *gprs,
@@ -1944,6 +1997,14 @@ struct ofono_modem *ofono_gprs_context_get_modem(struct ofono_gprs_context *gc)
 	return __ofono_atom_get_modem(gc->atom);
 }
 
+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);
@@ -1971,6 +2032,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);
-- 
1.6.3.3


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

* [PATCH 13/15] emulator: Watch netreg status changes
  2010-07-07 10:01                       ` [PATCH 12/15] emulator: Watch GPRS status changes Zhenhua Zhang
@ 2010-07-07 10:01                         ` Zhenhua Zhang
  2010-07-07 10:01                           ` [PATCH 14/15] gprs: Add DUN +CGATT support in gprs atom Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

Watch netreg status changes to notify DUN client any unsolicited result,
like +CREG status changes.
---
 src/emulator.c |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/src/emulator.c b/src/emulator.c
index 3bb32ae..8cc83bb 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -72,6 +72,10 @@ 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_list;
@@ -783,6 +787,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;
+	}
+
 	__ofono_watchlist_free(e->status_watches);
 	ofono_emulator_release_id(e->id);
 	g_free(e);
@@ -810,6 +826,83 @@ void ofono_emulator_disable(struct ofono_emulator *e)
 	e->powered = FALSE;
 }
 
+static void emulator_netreg_update(struct ofono_emulator *e)
+{
+	GAtServer *server = e->server;
+	char buf[256];
+
+	switch (e->modem_creg) {
+	case 0:
+		break;
+	case 1:
+		snprintf(buf, sizeof(buf), "+CREG: %d", e->netreg_status);
+		g_at_server_send_unsolicited(server, buf);
+		break;
+	case 2:
+		snprintf(buf, sizeof(buf), "+CREG: %d, %x, %x",
+				e->netreg_status, e->netreg_lac, e->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->netreg_status = status;
+	e->netreg_lac = lac;
+	e->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->netreg_status = ofono_netreg_get_status(netreg);
+	e->netreg_lac = ofono_netreg_get_location(netreg);
+	e->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);
+}
+
 static void emulator_gprs_update(struct ofono_emulator *e)
 {
 	GAtServer *server = e->server;
@@ -930,6 +1023,7 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator *e, int fd)
 	g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL);
 
 	add_gprs_watches(e);
+	add_netreg_watches(e);
 
 	g_io_channel_unref(channel);
 
-- 
1.6.3.3


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

* [PATCH 14/15] gprs: Add DUN +CGATT support in gprs atom
  2010-07-07 10:01                         ` [PATCH 13/15] emulator: Watch netreg " Zhenhua Zhang
@ 2010-07-07 10:01                           ` Zhenhua Zhang
  2010-07-07 10:01                             ` [PATCH 15/15] gprs: Add DUN +CGDCONT " Zhenhua Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

DUN client may request us to attach/deattach GPRS network. In such case,
use gprs_netreg_update to update gprs status.
---
 src/gprs.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 3ed056a..1f9e396 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -1860,6 +1860,18 @@ error:
 	req->cb(&error, NULL, NULL, NULL, NULL, req->cb_data);
 }
 
+static void ofono_emulator_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)
@@ -1881,6 +1893,9 @@ static void dun_status_watch(struct ofono_emulator *e,
 	case OFONO_EMULATOR_STATUS_DUN_DISCONNECTED:
 		ofono_emulator_dun_disconnect(gprs, data);
 		break;
+	case OFONO_EMULATOR_STATUS_SET_CGATT:
+		ofono_emulator_set_cgatt(gprs, data);
+		break;
 	case OFONO_EMULATOR_STATUS_DESTROY:
 		ofono_emulator_remove_sources(gprs);
 		break;
-- 
1.6.3.3


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

* [PATCH 15/15] gprs: Add DUN +CGDCONT support in gprs atom
  2010-07-07 10:01                           ` [PATCH 14/15] gprs: Add DUN +CGATT support in gprs atom Zhenhua Zhang
@ 2010-07-07 10:01                             ` Zhenhua Zhang
  0 siblings, 0 replies; 24+ messages in thread
From: Zhenhua Zhang @ 2010-07-07 10:01 UTC (permalink / raw)
  To: ofono

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

DUN client could request to create new context in gprs atom.
---
 src/gprs.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 1f9e396..05a7a05 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -1872,6 +1872,23 @@ static void ofono_emulator_set_cgatt(struct ofono_gprs *gprs,
 	req->cb(G_AT_SERVER_RESULT_OK, req->cb_data);
 }
 
+static void ofono_emulator_set_cgdcont(struct ofono_gprs *gprs,
+				struct ofono_emulator_req *req)
+{
+	struct pri_context *context;
+
+	context = gprs_context_by_type(gprs, GPRS_CONTEXT_TYPE_DUN);
+	if (!context) {
+		context = ofono_gprs_create_context(gprs, "dun", "dun");
+		if (!context) {
+			req->cb(G_AT_SERVER_RESULT_ERROR, req->cb_data);
+			return;
+		}
+	}
+
+	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)
@@ -1896,6 +1913,9 @@ static void dun_status_watch(struct ofono_emulator *e,
 	case OFONO_EMULATOR_STATUS_SET_CGATT:
 		ofono_emulator_set_cgatt(gprs, data);
 		break;
+	case OFONO_EMULATOR_STATUS_SET_CGDCONT:
+		ofono_emulator_set_cgdcont(gprs, data);
+		break;
 	case OFONO_EMULATOR_STATUS_DESTROY:
 		ofono_emulator_remove_sources(gprs);
 		break;
-- 
1.6.3.3


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

* [PATCH 0/15] Implement DUN server in oFono
  2010-07-07 10:01 [0/15] Implement DUN server in oFono Zhenhua Zhang
  2010-07-07 10:01 ` [PATCH 01/15] dun_gw: Fix license header Zhenhua Zhang
@ 2010-07-07 10:08 ` Zhang, Zhenhua
  1 sibling, 0 replies; 24+ messages in thread
From: Zhang, Zhenhua @ 2010-07-07 10:08 UTC (permalink / raw)
  To: ofono

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

Hi,

[Fix misleading title and content in previous 0/15 mail. Sorry for that.]

This series are based on the previous 6 patches "Add oFono DUN emulator" sent on July 5th. It implements the main functionality of DUN server and interact with GPRS atom to create DUN context. You can use gatchat/test-emulator to create a pseudo terminal and then use gsmdial to create a DUN client connection. 

Regards,
Zhenhua


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

* Re: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-07 10:01                     ` [PATCH 11/15] emulator: Register mandatory AT command handlers Zhenhua Zhang
  2010-07-07 10:01                       ` [PATCH 12/15] emulator: Watch GPRS status changes Zhenhua Zhang
@ 2010-07-07 10:48                       ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-07-07 11:12                         ` Marcel Holtmann
  1 sibling, 1 reply; 24+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-07-07 10:48 UTC (permalink / raw)
  To: ofono

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


On Wed,  7 Jul 2010 18:01:48 +0800, Zhenhua Zhang <zhenhua.zhang@intel.com>
wrote:
> +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->modem_mode);
> +		ofono_emulator_send_info(e, buf, TRUE);
> +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
> +		break;

Does not make much sense. If mode is 0, the device has functionality
minimum, meaning usually power off or close to that. oFono does not run in
such stage, so it won't be there to answer CFUN: 0.

> +	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->modem_mode = mode;
> +		g_timeout_add_seconds(1, send_ok, e);
> +		break;
> +	}

I might be missing something, but it does not look like AT+CFUN=0 will
power off the system, which is more or less what it is expected to do.

> +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->modem_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->modem_cops = mode;
> +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);

You won't get away with this. You're supposed to register/unregister/etc
from the network here.
Similarly, AT+CGATT is wrong, GPRS should be attached/detached. Yes, that
means you may have to tear down someone else's GPRS context, which may seem
evil.

Last, AT+CPIN should at the very least return PIN READY when appropriate,
if I read the spec right.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


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

* Re: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-07 10:48                       ` [PATCH 11/15] emulator: Register mandatory AT command handlers =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-07-07 11:12                         ` Marcel Holtmann
  2010-07-08  2:31                           ` Zhang, Zhenhua
  0 siblings, 1 reply; 24+ messages in thread
From: Marcel Holtmann @ 2010-07-07 11:12 UTC (permalink / raw)
  To: ofono

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

Hi Remi,

> > +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->modem_mode);
> > +		ofono_emulator_send_info(e, buf, TRUE);
> > +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
> > +		break;
> 
> Does not make much sense. If mode is 0, the device has functionality
> minimum, meaning usually power off or close to that. oFono does not run in
> such stage, so it won't be there to answer CFUN: 0.

this is actually more fake than real. We are not mapping all commands
1:1 to the real modem. It is mainly to just make some dialers and things
like Windows happy ;)

> > +	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->modem_mode = mode;
> > +		g_timeout_add_seconds(1, send_ok, e);
> > +		break;
> > +	}
> 
> I might be missing something, but it does not look like AT+CFUN=0 will
> power off the system, which is more or less what it is expected to do.

Look again, it won't. It is an arbitrary delay for testing. If we would
follow the Bluetooth DUN specification literally, then only the magic
AT*99# syntax would be needed, but there are other commands that are
expected to work. So in most cases we just fake them.

> +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->modem_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->modem_cops = mode;
> > +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
> 
> You won't get away with this. You're supposed to register/unregister/etc
> from the network here.
> Similarly, AT+CGATT is wrong, GPRS should be attached/detached. Yes, that
> means you may have to tear down someone else's GPRS context, which may seem
> evil.

Same here actually. We will fake COPS and CGATT for the client. Compared
to the CFUN code this needs a bit more work since we should return an
error when the real modem is not ready yet or GPRS is not attached.

That said, there has to be done some work for CFUN as well if our modem
is offline. However my take here is to just disable DUN service when the
modems goes offline.

> Last, AT+CPIN should at the very least return PIN READY when appropriate,
> if I read the spec right.

We will fake this again and always return READY here. If the physical
modem is not ready (sim_post state), then we will not provide DUN server
support.

Regards

Marcel



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

* RE: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-07 11:12                         ` Marcel Holtmann
@ 2010-07-08  2:31                           ` Zhang, Zhenhua
  2010-07-08  6:46                             ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 24+ messages in thread
From: Zhang, Zhenhua @ 2010-07-08  2:31 UTC (permalink / raw)
  To: ofono

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

Hi Remi,

Marcel Holtmann wrote:
> Hi Remi,
> 
>>> +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->modem_mode);
>>> +		ofono_emulator_send_info(e, buf, TRUE);
>>> +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
>>> +		break;
>> 
>> Does not make much sense. If mode is 0, the device has functionality
>> minimum, meaning usually power off or close to that. oFono does not
>> run in such stage, so it won't be there to answer CFUN: 0.
> 
> this is actually more fake than real. We are not mapping all commands
> 1:1 to the real modem. It is mainly to just make some dialers
> and things
> like Windows happy ;)

Marcel is right. Here I fake most AT commands like +CFUN to make DUN client happy. We don't need to power on/off real modem at all. See gatchat/test-server.c for similar implementation.

>>> +	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->modem_mode = mode;
>>> +		g_timeout_add_seconds(1, send_ok, e);
>>> +		break;
>>> +	}
>> 
>> I might be missing something, but it does not look like AT+CFUN=0
>> will power off the system, which is more or less what it is expected
>> to do. 
> 
> Look again, it won't. It is an arbitrary delay for testing. If we
> would follow the Bluetooth DUN specification literally, then only the
> magic AT*99# syntax would be needed, but there are other commands
> that are expected to work. So in most cases we just fake them.
> 
>> +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->modem_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->modem_cops = mode;
>>> +		ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK);
>> 
>> You won't get away with this. You're supposed to
>> register/unregister/etc from the network here. Similarly, AT+CGATT
>> is wrong, GPRS should be attached/detached. Yes, that means you may
>> have to tear down someone else's GPRS context, which may seem evil.
> 
> Same here actually. We will fake COPS and CGATT for the
> client. Compared
> to the CFUN code this needs a bit more work since we should return an
> error when the real modem is not ready yet or GPRS is not attached.

For +COPS, we could fake one to the client. Do not register/unregister from the real network and stop sending +CREG/+CGREG unsolicited result to client.

For +CGATT, my current implementation (Patch 14/15) is still rough. GPRS atom will get notification from dun status watch and try to set GPRS attached if we have +CGATT=1. 

But if we have +CGATT=0, it seems we need to do more works (not done yet). Do not detach GPRS on real modem. Meanwhile, remove all dun created contexts.

Feel free to let me know your opinions.

> That said, there has to be done some work for CFUN as well if our
> modem is offline. However my take here is to just disable DUN
> service when the
> modems goes offline.
> 
>> Last, AT+CPIN should at the very least return PIN READY when
>> appropriate, if I read the spec right.
> 
> We will fake this again and always return READY here. If the physical
> modem is not ready (sim_post state), then we will not provide
> DUN server
> support.

Yes. DUN server is probed after driver completes post_sim state. It's probed like ofono_history and ofono_nettime. So if the modem is going offline, DUN server atom will be destroyed. 

> Regards
> 
> Marcel
> 
> 
> _______________________________________________
> ofono mailing list
> ofono(a)ofono.org
> http://lists.ofono.org/listinfo/ofono

Regards,
Zhenhua


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

* RE: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-08  2:31                           ` Zhang, Zhenhua
@ 2010-07-08  6:46                             ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-07-08 13:26                               ` Marcel Holtmann
  0 siblings, 1 reply; 24+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-07-08  6:46 UTC (permalink / raw)
  To: ofono

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


On Thu, 8 Jul 2010 10:31:03 +0800, "Zhang, Zhenhua"
<zhenhua.zhang@intel.com> wrote:
> Marcel is right. Here I fake most AT commands like +CFUN to make DUN
> client happy. We don't need to power on/off real modem at all. See
> gatchat/test-server.c for similar implementation.

That depends much what you're trying to achieve. If you only care about
Dial-Up Networking, that might work. But if you care about passing various
some kinds of certification testing, AT commands _must_ work _correctly_.

So I doubt oFono will get away with this in the medium term.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


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

* RE: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-08  6:46                             ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-07-08 13:26                               ` Marcel Holtmann
  2010-07-08 14:23                                 ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  0 siblings, 1 reply; 24+ messages in thread
From: Marcel Holtmann @ 2010-07-08 13:26 UTC (permalink / raw)
  To: ofono

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

Hi Remi,

> > Marcel is right. Here I fake most AT commands like +CFUN to make DUN
> > client happy. We don't need to power on/off real modem at all. See
> > gatchat/test-server.c for similar implementation.
> 
> That depends much what you're trying to achieve. If you only care about
> Dial-Up Networking, that might work. But if you care about passing various
> some kinds of certification testing, AT commands _must_ work _correctly_.
> 
> So I doubt oFono will get away with this in the medium term.

we are clearly and on purpose splitting Bluetooth Dialup support from
generic Serial Port Profile support.

For the serial port for certification testing you will NOT be able to
use dialup channel. Also I doubt that you wanna do the certification
testing over Bluetooth. I assume that will most likely be done via USB
with the device in some special R&D mode.

Regards

Marcel



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

* RE: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-08 13:26                               ` Marcel Holtmann
@ 2010-07-08 14:23                                 ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
  2010-07-08 14:30                                   ` Denis Kenzior
  0 siblings, 1 reply; 24+ messages in thread
From: =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont @ 2010-07-08 14:23 UTC (permalink / raw)
  To: ofono

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


On Thu, 08 Jul 2010 10:26:04 -0300, Marcel Holtmann <marcel@holtmann.org>
wrote:
>> > Marcel is right. Here I fake most AT commands like +CFUN to make DUN
>> > client happy. We don't need to power on/off real modem at all. See
>> > gatchat/test-server.c for similar implementation.
>>
>> That depends much what you're trying to achieve. If you only care about
>> Dial-Up Networking, that might work. But if you care about passing
> various
>> some kinds of certification testing, AT commands _must_ work
> _correctly_.
>>
>> So I doubt oFono will get away with this in the medium term.
> 
> we are clearly and on purpose splitting Bluetooth Dialup support from
> generic Serial Port Profile support.
> 
> For the serial port for certification testing you will NOT be able to
> use dialup channel.

I think it's quite the opposite. In my understanding, some tests do require
DUN. Obviously you loose the ability to send AT commands while PPP is
active.

> Also I doubt that you wanna do the certification testing over Bluetooth.

Sure, but that's hardly relevant. I assume oFono will need to support both
BlueTooth and USB, not just BlueTooth. I don't see any reason why it would
have two different AT server implementations. (As a side note, N900 does
use the exact same AT commands server for USB CDC ACM and BT DUN.)

> I assume that will most likely be done via USB

Yes.

> with the device in some special R&D mode.

No. Except for possibly being inside a Faraday cage, there's nothing
special.

-- 
Rémi Denis-Courmont
http://www.remlab.net
http://fi.linkedin.com/in/remidenis


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

* Re: [PATCH 11/15] emulator: Register mandatory AT command handlers
  2010-07-08 14:23                                 ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
@ 2010-07-08 14:30                                   ` Denis Kenzior
  0 siblings, 0 replies; 24+ messages in thread
From: Denis Kenzior @ 2010-07-08 14:30 UTC (permalink / raw)
  To: ofono

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

Hi Remi,

On 07/08/2010 09:23 AM, Rémi Denis-Courmont wrote:
> 
> On Thu, 08 Jul 2010 10:26:04 -0300, Marcel Holtmann <marcel@holtmann.org>
> wrote:
>>>> Marcel is right. Here I fake most AT commands like +CFUN to make DUN
>>>> client happy. We don't need to power on/off real modem at all. See
>>>> gatchat/test-server.c for similar implementation.
>>>
>>> That depends much what you're trying to achieve. If you only care about
>>> Dial-Up Networking, that might work. But if you care about passing
>> various
>>> some kinds of certification testing, AT commands _must_ work
>> _correctly_.
>>>
>>> So I doubt oFono will get away with this in the medium term.
>>
>> we are clearly and on purpose splitting Bluetooth Dialup support from
>> generic Serial Port Profile support.
>>
>> For the serial port for certification testing you will NOT be able to
>> use dialup channel.
> 
> I think it's quite the opposite. In my understanding, some tests do require
> DUN. Obviously you loose the ability to send AT commands while PPP is
> active.
> 

Our first goal here is to make the mandatory DUN aspects work.  This
means covering the mandatory AT commands specified by the Bluetooth DUN
profile, PPP server aspects and ConnMan integration.  If we have to fake
some commands to keep the clients happy, so be it.

Once we have this, we can start talking about more advanced features
you're talking about here.  Since you seem to have some experience in
this area, we'd certainly appreciate you getting involved and helping out.

Regards,
-Denis

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

end of thread, other threads:[~2010-07-08 14:30 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-07 10:01 [0/15] Implement DUN server in oFono Zhenhua Zhang
2010-07-07 10:01 ` [PATCH 01/15] dun_gw: Fix license header Zhenhua Zhang
2010-07-07 10:01   ` [PATCH 02/15] watch: Simplify ofono_watchlist remove item Zhenhua Zhang
2010-07-07 10:01     ` [PATCH 03/15] emulator: Add status watches for ofono emulator Zhenhua Zhang
2010-07-07 10:01       ` [PATCH 04/15] emulator: Add get properities for emulator Zhenhua Zhang
2010-07-07 10:01         ` [PATCH 05/15] gprs: Rename status_watch to netreg_status_watch Zhenhua Zhang
2010-07-07 10:01           ` [PATCH 06/15] emulator: Add emulator status watches in gprs atom Zhenhua Zhang
2010-07-07 10:01             ` [PATCH 07/15] emulator: Add emulator status watches in netreg Zhenhua Zhang
2010-07-07 10:01               ` [PATCH 08/15] emulator: Add APIs to send GAtServer result Zhenhua Zhang
2010-07-07 10:01                 ` [PATCH 09/15] emulator: Implement dialing up for DUN Zhenhua Zhang
2010-07-07 10:01                   ` [PATCH 10/15] emulator: Add emulator dial up support in GPRS Zhenhua Zhang
2010-07-07 10:01                     ` [PATCH 11/15] emulator: Register mandatory AT command handlers Zhenhua Zhang
2010-07-07 10:01                       ` [PATCH 12/15] emulator: Watch GPRS status changes Zhenhua Zhang
2010-07-07 10:01                         ` [PATCH 13/15] emulator: Watch netreg " Zhenhua Zhang
2010-07-07 10:01                           ` [PATCH 14/15] gprs: Add DUN +CGATT support in gprs atom Zhenhua Zhang
2010-07-07 10:01                             ` [PATCH 15/15] gprs: Add DUN +CGDCONT " Zhenhua Zhang
2010-07-07 10:48                       ` [PATCH 11/15] emulator: Register mandatory AT command handlers =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-07-07 11:12                         ` Marcel Holtmann
2010-07-08  2:31                           ` Zhang, Zhenhua
2010-07-08  6:46                             ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-07-08 13:26                               ` Marcel Holtmann
2010-07-08 14:23                                 ` =?unknown-8bit?q?R=C3=A9mi?= Denis-Courmont
2010-07-08 14:30                                   ` Denis Kenzior
2010-07-07 10:08 ` [PATCH 0/15] Implement DUN server in oFono Zhang, Zhenhua

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.