Open Source Telephony
 help / color / mirror / Atom feed
* [PATCH 0/4] Emergency Calls
@ 2010-12-20 13:21 Andras Domokos
  2010-12-20 13:21 ` [RFC PATCH 1/3] modem: add Emergency property Andras Domokos
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andras Domokos @ 2010-12-20 13:21 UTC (permalink / raw)
  To: ofono

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

Steps in handling emergency calls:
- subscribe to modem online notifications
- emergency call detected (phone number is an emergency number)
- increment emergency mode 
  - advertise "Emergency" property change on D-Bus (first call)
  - set modem online (minimal setup) if mode was offline
    - adevertise "Online" property change on D-Bus
- if modem is not online postpone making the call, otherwise make
  the emergency call
- when modem online notification comes and there is postponed emergency call
  request, make the emergency call
- when an emergency call ends decrement emergency mode
  - set modem to pre emergency call state (last call)
    - advertise "Online" property change on D-Bus (if any)
  - advertise "Emergency" property change on D-Bus (last call)

Andras Domokos (3):
  modem: add Emergency property
  modem: move dial request_cb function
  voicecall: add emergency call handling

 src/dbus.c      |    7 ++
 src/modem.c     |  207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/ofono.h     |    5 ++
 src/voicecall.c |  186 ++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 369 insertions(+), 36 deletions(-)


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

* [RFC PATCH 1/3] modem: add Emergency property
  2010-12-20 13:21 [PATCH 0/4] Emergency Calls Andras Domokos
@ 2010-12-20 13:21 ` Andras Domokos
  2010-12-20 13:22 ` [RFC PATCH 2/3] modem: move dial request_cb function Andras Domokos
  2010-12-20 13:22 ` [RFC PATCH 3/3] voicecall: add emergency call handling Andras Domokos
  2 siblings, 0 replies; 4+ messages in thread
From: Andras Domokos @ 2010-12-20 13:21 UTC (permalink / raw)
  To: ofono

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

---
 src/dbus.c  |    7 ++
 src/modem.c |  207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/ofono.h |    5 ++
 3 files changed, 216 insertions(+), 3 deletions(-)

diff --git a/src/dbus.c b/src/dbus.c
index c24615f..3be8d22 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -345,6 +345,13 @@ DBusMessage *__ofono_error_access_denied(DBusMessage *msg)
 					"Operation not permitted");
 }
 
+DBusMessage *__ofono_error_emergency_active(DBusMessage *msg)
+{
+	return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
+					".EmergencyActive",
+					"Emergency state active");
+}
+
 void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
diff --git a/src/modem.c b/src/modem.c
index 2f9387c..1ad72bd 100644
--- a/src/modem.c
+++ b/src/modem.c
@@ -61,6 +61,8 @@ enum modem_state {
 struct ofono_modem {
 	char			*path;
 	enum modem_state	modem_state;
+	enum modem_state	modem_state_pre_emergency;
+	ofono_bool_t		modem_state_pending;
 	GSList			*atoms;
 	struct ofono_watchlist	*atom_watches;
 	GSList			*interface_list;
@@ -73,6 +75,7 @@ struct ofono_modem {
 	guint			timeout;
 	ofono_bool_t		online;
 	struct ofono_watchlist	*online_watches;
+	unsigned int		emergency;
 	GHashTable		*properties;
 	struct ofono_sim	*sim;
 	unsigned int		sim_watch;
@@ -401,6 +404,11 @@ static void modem_change_state(struct ofono_modem *modem,
 
 	modem->modem_state = new_state;
 
+	if (modem->emergency > 0)
+		modem->modem_state_pre_emergency = new_state;
+
+	modem->modem_state_pending = FALSE;
+
 	if (old_state > new_state)
 		flush_atoms(modem, new_state);
 
@@ -440,11 +448,25 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *user)
 
 	switch (new_state) {
 	case OFONO_SIM_STATE_NOT_PRESENT:
+		if (modem->emergency != 0) {
+			modem->modem_state_pre_emergency = MODEM_STATE_PRE_SIM;
+			break;
+		}
+
 		modem_change_state(modem, MODEM_STATE_PRE_SIM);
 		break;
 	case OFONO_SIM_STATE_INSERTED:
 		break;
 	case OFONO_SIM_STATE_READY:
+		if (modem->emergency != 0) {
+			modem->modem_state_pre_emergency = MODEM_STATE_OFFLINE;
+
+			if (modem->driver->set_online == NULL)
+				modem->modem_state_pre_emergency = MODEM_STATE_ONLINE;
+
+			break;
+		}
+
 		modem_change_state(modem, MODEM_STATE_OFFLINE);
 
 		/*
@@ -482,6 +504,73 @@ void __ofono_modem_remove_online_watch(struct ofono_modem *modem,
 	__ofono_watchlist_remove_item(modem->online_watches, id);
 }
 
+static void modem_change_online(struct ofono_modem *modem,
+				enum modem_state new_state)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	enum modem_state old_state = modem->modem_state;
+	ofono_bool_t new_online = new_state == MODEM_STATE_ONLINE;
+
+	DBG("old state: %d, new state: %d", old_state, new_state);
+
+	modem->modem_state = new_state;
+	modem->modem_state_pending = FALSE;
+	modem->online = new_online;
+
+	ofono_dbus_signal_property_changed(conn, modem->path,
+					OFONO_MODEM_INTERFACE, "Online",
+					DBUS_TYPE_BOOLEAN, &modem->online);
+
+	notify_online_watches(modem);
+}
+
+static void emergency_online_cb(const struct ofono_error *error, void *data)
+{
+	struct ofono_modem *modem = data;
+
+	DBG("modem: %p", modem);
+
+	if (error->type == OFONO_ERROR_TYPE_NO_ERROR &&
+			modem->modem_state != MODEM_STATE_ONLINE) {
+		modem_change_online(modem, MODEM_STATE_ONLINE);
+	} else {
+		modem->modem_state_pending = FALSE;
+		notify_online_watches(modem);
+	}
+}
+
+static void emergency_offline_cb(const struct ofono_error *error, void *data)
+{
+	struct ofono_modem *modem = data;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = ofono_modem_get_path(modem);
+	gboolean state = FALSE;
+
+	DBG("modem: %p", modem);
+
+	if (error->type == OFONO_ERROR_TYPE_NO_ERROR &&
+			modem->modem_state == MODEM_STATE_ONLINE) {
+		modem_change_online(modem, modem->modem_state_pre_emergency);
+	} else {
+		modem->modem_state_pending = FALSE;
+		notify_online_watches(modem);
+	}
+
+	modem->emergency--;
+	if (modem->emergency != 0) {
+		modem->modem_state_pending = TRUE;
+		modem->driver->set_online(modem, TRUE,
+						emergency_online_cb, modem);
+		return;
+	}
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_MODEM_INTERFACE,
+					"Emergency",
+					DBUS_TYPE_BOOLEAN,
+					&state);
+}
+
 static void online_cb(const struct ofono_error *error, void *data)
 {
 	struct ofono_modem *modem = data;
@@ -495,9 +584,18 @@ static void online_cb(const struct ofono_error *error, void *data)
 
 	__ofono_dbus_pending_reply(&modem->pending, reply);
 
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR &&
+			modem->emergency != 0) {
+		modem->modem_state_pending = FALSE;
+		notify_online_watches(modem);
+		return;
+	}
+
 	if (error->type == OFONO_ERROR_TYPE_NO_ERROR &&
 			modem->modem_state == MODEM_STATE_OFFLINE)
 		modem_change_state(modem, MODEM_STATE_ONLINE);
+	else
+		modem->modem_state_pending = FALSE;
 }
 
 static void offline_cb(const struct ofono_error *error, void *data)
@@ -512,9 +610,99 @@ static void offline_cb(const struct ofono_error *error, void *data)
 
 	__ofono_dbus_pending_reply(&modem->pending, reply);
 
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR &&
+			modem->emergency != 0) {
+		modem->modem_state_pending = FALSE;
+		notify_online_watches(modem);
+		return;
+	}
+
 	if (error->type == OFONO_ERROR_TYPE_NO_ERROR &&
-				modem->modem_state == MODEM_STATE_ONLINE)
+				modem->modem_state == MODEM_STATE_ONLINE) {
 		modem_change_state(modem, MODEM_STATE_OFFLINE);
+
+		if (modem->emergency != 0) {
+			modem->modem_state_pending = TRUE;
+			modem->driver->set_online(modem, TRUE,
+						emergency_online_cb, modem);
+		}
+	} else {
+		modem->modem_state_pending = FALSE;
+	}
+}
+
+ofono_bool_t ofono_modem_get_emergency(struct ofono_modem *modem)
+{
+	if (modem == NULL)
+		return FALSE;
+
+	return modem->emergency != 0;
+}
+
+void ofono_modem_inc_emergency(struct ofono_modem *modem)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = ofono_modem_get_path(modem);
+	gboolean state = TRUE;
+
+	DBG("modem: %p", modem);
+
+	modem->emergency++;
+	if (modem->emergency > 1)
+		return;
+
+	ofono_dbus_signal_property_changed(conn, path,
+						OFONO_MODEM_INTERFACE,
+						"Emergency",
+						DBUS_TYPE_BOOLEAN,
+						&state);
+
+	if (modem->modem_state_pending == TRUE)
+		return;
+
+	if (modem->modem_state == MODEM_STATE_ONLINE) {
+		modem->modem_state_pre_emergency = MODEM_STATE_ONLINE;
+		return;
+	}
+
+	modem->modem_state_pre_emergency = modem->modem_state;
+	modem->modem_state_pending = TRUE;
+	modem->driver->set_online(modem, TRUE, emergency_online_cb, modem);
+}
+
+void ofono_modem_dec_emergency(struct ofono_modem *modem)
+{
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = ofono_modem_get_path(modem);
+	gboolean state = FALSE;
+
+	DBG("modem: %p", modem);
+
+	if (modem->emergency == 0) {
+		ofono_error("Emergency reference counter already 0 on path %s",
+				modem->path);
+		return;
+	}
+
+	if (modem->emergency > 1) {
+		modem->emergency--;
+		return;
+	}
+
+	if (modem->modem_state_pre_emergency != MODEM_STATE_ONLINE) {
+		modem->modem_state_pending = TRUE;
+		modem->driver->set_online(modem, FALSE,
+						emergency_offline_cb, modem);
+		return;
+	}
+
+	modem->emergency--;
+
+	ofono_dbus_signal_property_changed(conn, path,
+						OFONO_MODEM_INTERFACE,
+						"Emergency",
+						DBUS_TYPE_BOOLEAN,
+						&state);
 }
 
 static DBusMessage *set_property_online(struct ofono_modem *modem,
@@ -529,7 +717,10 @@ static DBusMessage *set_property_online(struct ofono_modem *modem,
 
 	dbus_message_iter_get_basic(var, &online);
 
-	if (modem->pending != NULL)
+	if (modem->emergency > 0)
+		return __ofono_error_emergency_active(msg);
+
+	if (modem->modem_state_pending == TRUE)
 		return __ofono_error_busy(msg);
 
 	if (driver->set_online == NULL)
@@ -542,6 +733,7 @@ static DBusMessage *set_property_online(struct ofono_modem *modem,
 		return dbus_message_new_method_return(msg);
 
 	modem->pending = dbus_message_ref(msg);
+	modem->modem_state_pending = TRUE;
 
 	driver->set_online(modem, online,
 				online ? online_cb : offline_cb, modem);
@@ -551,7 +743,7 @@ static DBusMessage *set_property_online(struct ofono_modem *modem,
 
 ofono_bool_t ofono_modem_get_online(struct ofono_modem *modem)
 {
-	if (modem == NULL)
+	if (modem == NULL || modem->modem_state_pending == TRUE)
 		return FALSE;
 
 	return modem->online;
@@ -565,6 +757,7 @@ void __ofono_modem_append_properties(struct ofono_modem *modem,
 	int i;
 	GSList *l;
 	struct ofono_atom *devinfo_atom;
+	ofono_bool_t val;
 
 	ofono_dbus_dict_append(dict, "Online", DBUS_TYPE_BOOLEAN,
 				&modem->online);
@@ -572,6 +765,10 @@ void __ofono_modem_append_properties(struct ofono_modem *modem,
 	ofono_dbus_dict_append(dict, "Powered", DBUS_TYPE_BOOLEAN,
 				&modem->powered);
 
+	val = ofono_modem_get_emergency(modem);
+	ofono_dbus_dict_append(dict, "Emergency",
+				DBUS_TYPE_BOOLEAN, &val);
+
 	devinfo_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_DEVINFO);
 
 	/* We cheat a little here and don't check the registered status */
@@ -650,6 +847,9 @@ static int set_powered(struct ofono_modem *modem, ofono_bool_t powered)
 	if (modem->powered_pending == powered)
 		return -EALREADY;
 
+	if (modem->emergency > 0)
+		return -EPERM;
+
 	/* Remove the atoms even if the driver is no longer available */
 	if (powered == FALSE)
 		modem_change_state(modem, MODEM_STATE_POWER_OFF);
@@ -1575,6 +1775,7 @@ static void modem_unregister(struct ofono_modem *modem)
 	if (modem->pending) {
 		dbus_message_unref(modem->pending);
 		modem->pending = NULL;
+		modem->modem_state_pending = FALSE;
 	}
 
 	if (modem->interface_update) {
diff --git a/src/ofono.h b/src/ofono.h
index 792134b..336d25b 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -58,6 +58,7 @@ DBusMessage *__ofono_error_not_attached(DBusMessage *msg);
 DBusMessage *__ofono_error_attach_in_progress(DBusMessage *msg);
 DBusMessage *__ofono_error_canceled(DBusMessage *msg);
 DBusMessage *__ofono_error_access_denied(DBusMessage *msg);
+DBusMessage *__ofono_error_emergency_active(DBusMessage *msg);
 
 void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply);
 
@@ -186,6 +187,10 @@ unsigned int __ofono_modem_add_online_watch(struct ofono_modem *modem,
 void __ofono_modem_remove_online_watch(struct ofono_modem *modem,
 					unsigned int id);
 
+ofono_bool_t ofono_modem_get_emergency(struct ofono_modem *modem);
+void ofono_modem_inc_emergency(struct ofono_modem *modem);
+void ofono_modem_dec_emergency(struct ofono_modem *modem);
+
 #include <ofono/call-barring.h>
 
 gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb);
-- 
1.7.0.4


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

* [RFC PATCH 2/3] modem: move dial request_cb function
  2010-12-20 13:21 [PATCH 0/4] Emergency Calls Andras Domokos
  2010-12-20 13:21 ` [RFC PATCH 1/3] modem: add Emergency property Andras Domokos
@ 2010-12-20 13:22 ` Andras Domokos
  2010-12-20 13:22 ` [RFC PATCH 3/3] voicecall: add emergency call handling Andras Domokos
  2 siblings, 0 replies; 4+ messages in thread
From: Andras Domokos @ 2010-12-20 13:22 UTC (permalink / raw)
  To: ofono

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

---
 src/voicecall.c |   70 +++++++++++++++++++++++++++---------------------------
 1 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index dbf3e9a..0120cd0 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -2209,6 +2209,41 @@ static void sim_watch(struct ofono_atom *atom,
 	sim_state_watch(ofono_sim_get_state(sim), vc);
 }
 
+static void dial_request_cb(const struct ofono_error *error, void *data)
+{
+	struct ofono_voicecall *vc = data;
+	gboolean need_to_emit;
+	struct voicecall *v;
+
+	v = dial_handle_result(vc, error,
+				phone_number_to_string(&vc->dial_req->ph),
+				&need_to_emit);
+
+	if (v == NULL) {
+		dial_request_finish(vc);
+		return;
+	}
+
+	v->message = vc->dial_req->message;
+	v->icon_id = vc->dial_req->icon_id;
+
+	vc->dial_req->message = NULL;
+	vc->dial_req->call = v;
+
+	/*
+	 * TS 102 223 Section 6.4.13: The terminal shall not store
+	 * in the UICC the call set-up details (called party number
+	 * and associated parameters)
+	 */
+	v->untracked = TRUE;
+
+	if (v->call->status == CALL_STATUS_ACTIVE)
+		dial_request_finish(vc);
+
+	if (need_to_emit)
+		voicecalls_emit_call_added(vc, v);
+}
+
 void ofono_voicecall_register(struct ofono_voicecall *vc)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
@@ -2301,41 +2336,6 @@ ofono_bool_t __ofono_voicecall_is_busy(struct ofono_voicecall *vc,
 	return TRUE;
 }
 
-static void dial_request_cb(const struct ofono_error *error, void *data)
-{
-	struct ofono_voicecall *vc = data;
-	gboolean need_to_emit;
-	struct voicecall *v;
-
-	v = dial_handle_result(vc, error,
-				phone_number_to_string(&vc->dial_req->ph),
-				&need_to_emit);
-
-	if (v == NULL) {
-		dial_request_finish(vc);
-		return;
-	}
-
-	v->message = vc->dial_req->message;
-	v->icon_id = vc->dial_req->icon_id;
-
-	vc->dial_req->message = NULL;
-	vc->dial_req->call = v;
-
-	/*
-	 * TS 102 223 Section 6.4.13: The terminal shall not store
-	 * in the UICC the call set-up details (called party number
-	 * and associated parameters)
-	 */
-	v->untracked = TRUE;
-
-	if (v->call->status == CALL_STATUS_ACTIVE)
-		dial_request_finish(vc);
-
-	if (need_to_emit)
-		voicecalls_emit_call_added(vc, v);
-}
-
 static void dial_request(struct ofono_voicecall *vc)
 {
 	vc->driver->dial(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
-- 
1.7.0.4


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

* [RFC PATCH 3/3] voicecall: add emergency call handling
  2010-12-20 13:21 [PATCH 0/4] Emergency Calls Andras Domokos
  2010-12-20 13:21 ` [RFC PATCH 1/3] modem: add Emergency property Andras Domokos
  2010-12-20 13:22 ` [RFC PATCH 2/3] modem: move dial request_cb function Andras Domokos
@ 2010-12-20 13:22 ` Andras Domokos
  2 siblings, 0 replies; 4+ messages in thread
From: Andras Domokos @ 2010-12-20 13:22 UTC (permalink / raw)
  To: ofono

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

---
 src/voicecall.c |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/src/voicecall.c b/src/voicecall.c
index 0120cd0..370f760 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -52,6 +52,7 @@ struct ofono_voicecall {
 	struct ofono_sim *sim;
 	unsigned int sim_watch;
 	unsigned int sim_state_watch;
+	unsigned int modem_online_watch;
 	const struct ofono_voicecall_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
@@ -134,6 +135,22 @@ static void add_to_en_list(GSList **l, const char **list)
 		*l = g_slist_prepend(*l, g_strdup(list[i++]));
 }
 
+static gint number_compare(gconstpointer a, gconstpointer b)
+{
+	const char *s1 = a, *s2 = b;
+	return strcmp(s1, s2);
+}
+
+static ofono_bool_t emergency_number(struct ofono_voicecall *vc,
+					const char *number)
+{
+	if (number == NULL)
+		return FALSE;
+
+	return g_slist_find_custom(vc->en_list,
+				number, number_compare) ? TRUE : FALSE;
+}
+
 static const char *disconnect_reason_to_string(enum ofono_disconnect_reason r)
 {
 	switch (r) {
@@ -1134,6 +1151,7 @@ handled:
 static void manager_dial_callback(const struct ofono_error *error, void *data)
 {
 	struct ofono_voicecall *vc = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
 	DBusMessage *reply;
 	const char *number;
 	gboolean need_to_emit;
@@ -1152,8 +1170,12 @@ static void manager_dial_callback(const struct ofono_error *error, void *data)
 
 		dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
 						DBUS_TYPE_INVALID);
-	} else
+	} else {
+		if (emergency_number(vc, number))
+			ofono_modem_dec_emergency(modem);
+
 		reply = __ofono_error_failed(vc->pending);
+	}
 
 	__ofono_dbus_pending_reply(&vc->pending, reply);
 
@@ -1165,6 +1187,7 @@ static DBusMessage *manager_dial(DBusConnection *conn,
 					DBusMessage *msg, void *data)
 {
 	struct ofono_voicecall *vc = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
 	const char *number;
 	struct ofono_phone_number ph;
 	const char *clirstr;
@@ -1204,6 +1227,16 @@ static DBusMessage *manager_dial(DBusConnection *conn,
 
 	string_to_phone_number(number, &ph);
 
+	if (emergency_number(vc, number)) {
+		int online;
+
+		ofono_modem_inc_emergency(modem);
+
+		online = ofono_modem_get_online(modem);
+		if (online != TRUE)
+			return NULL;
+	}
+
 	vc->driver->dial(vc, &ph, clir, OFONO_CUG_OPTION_DEFAULT,
 				manager_dial_callback, vc);
 
@@ -1757,6 +1790,7 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
 				const struct ofono_error *error)
 {
 	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
+	const char *number;
 	GSList *l;
 	struct voicecall *call;
 	time_t ts;
@@ -1776,6 +1810,7 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
 	}
 
 	call = l->data;
+	number = phone_number_to_string(&call->call->phone_number);
 
 	ts = time(NULL);
 	prev_status = call->call->status;
@@ -1814,6 +1849,9 @@ void ofono_voicecall_disconnected(struct ofono_voicecall *vc, int id,
 
 	voicecalls_emit_call_removed(vc, call);
 
+	if (emergency_number(vc, number))
+		ofono_modem_dec_emergency(modem);
+
 	voicecall_dbus_unregister(vc, call);
 
 	vc->call_list = g_slist_remove(vc->call_list, call);
@@ -2074,6 +2112,7 @@ static void voicecall_unregister(struct ofono_atom *atom)
 static void voicecall_remove(struct ofono_atom *atom)
 {
 	struct ofono_voicecall *vc = __ofono_atom_get_data(atom);
+	struct ofono_modem *modem = __ofono_atom_get_modem(atom);
 
 	DBG("atom: %p", atom);
 
@@ -2115,6 +2154,12 @@ static void voicecall_remove(struct ofono_atom *atom)
 		g_queue_free(vc->toneq);
 	}
 
+	if (vc->modem_online_watch) {
+		__ofono_modem_remove_online_watch(modem,
+						vc->modem_online_watch);
+		vc->modem_online_watch = 0;
+	}
+
 	g_free(vc);
 }
 
@@ -2212,6 +2257,7 @@ static void sim_watch(struct ofono_atom *atom,
 static void dial_request_cb(const struct ofono_error *error, void *data)
 {
 	struct ofono_voicecall *vc = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
 	gboolean need_to_emit;
 	struct voicecall *v;
 
@@ -2221,6 +2267,10 @@ static void dial_request_cb(const struct ofono_error *error, void *data)
 
 	if (v == NULL) {
 		dial_request_finish(vc);
+
+		if (emergency_number(vc,
+				phone_number_to_string(&vc->dial_req->ph)))
+			ofono_modem_dec_emergency(modem);
 		return;
 	}
 
@@ -2244,6 +2294,61 @@ static void dial_request_cb(const struct ofono_error *error, void *data)
 		voicecalls_emit_call_added(vc, v);
 }
 
+static void modem_online_watch(ofono_bool_t online, void *data)
+{
+	struct ofono_voicecall *vc = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
+	static ofono_bool_t modem_online = FALSE;
+	static ofono_bool_t modem_online_prev;
+	const char *number;
+	struct ofono_phone_number ph;
+	const char *clirstr;
+	enum ofono_clir_option clir;
+
+	modem_online_prev = modem_online;
+	modem_online = online;
+
+	if (ofono_modem_get_emergency(modem) != TRUE)
+		return;
+
+	if (vc->dial_req)
+		vc->driver->dial(vc, &vc->dial_req->ph,
+					OFONO_CLIR_OPTION_DEFAULT,
+					OFONO_CUG_OPTION_DEFAULT,
+					dial_request_cb, vc);
+
+	if (vc->pending == NULL)
+		return;
+
+	if (strcmp(dbus_message_get_member(vc->pending), "Dial"))
+		return;
+
+	if (dbus_message_get_args(vc->pending, NULL, DBUS_TYPE_STRING, &number,
+					DBUS_TYPE_STRING, &clirstr,
+					DBUS_TYPE_INVALID) == FALSE)
+		return;
+
+	if (emergency_number(vc, number) == FALSE)
+		return;
+
+	if (online == FALSE) {
+		if (online == modem_online_prev) {
+			DBusMessage *reply = __ofono_error_failed(vc->pending);
+
+			__ofono_dbus_pending_reply(&vc->pending, reply);
+			ofono_modem_dec_emergency(modem);
+		}
+
+		return;
+	}
+
+	clir_string_to_clir(clirstr, &clir);
+	string_to_phone_number(number, &ph);
+
+	vc->driver->dial(vc, &ph, clir, OFONO_CUG_OPTION_DEFAULT,
+				manager_dial_callback, vc);
+}
+
 void ofono_voicecall_register(struct ofono_voicecall *vc)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
@@ -2262,6 +2367,9 @@ void ofono_voicecall_register(struct ofono_voicecall *vc)
 	}
 
 	ofono_modem_add_interface(modem, OFONO_VOICECALL_MANAGER_INTERFACE);
+	vc->modem_online_watch = __ofono_modem_add_online_watch(modem,
+							modem_online_watch,
+							vc, NULL);
 
 	/*
 	 * Start out with the 22.101 mandated numbers, if we have a SIM and
@@ -2338,6 +2446,18 @@ ofono_bool_t __ofono_voicecall_is_busy(struct ofono_voicecall *vc,
 
 static void dial_request(struct ofono_voicecall *vc)
 {
+	struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
+
+	if (emergency_number(vc, phone_number_to_string(&vc->dial_req->ph))) {
+		int online;
+
+		ofono_modem_inc_emergency(modem);
+
+		online = ofono_modem_get_online(modem);
+		if (online != TRUE)
+			return;
+	}
+
 	vc->driver->dial(vc, &vc->dial_req->ph, OFONO_CLIR_OPTION_DEFAULT,
 				OFONO_CUG_OPTION_DEFAULT, dial_request_cb, vc);
 }
-- 
1.7.0.4


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

end of thread, other threads:[~2010-12-20 13:22 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-20 13:21 [PATCH 0/4] Emergency Calls Andras Domokos
2010-12-20 13:21 ` [RFC PATCH 1/3] modem: add Emergency property Andras Domokos
2010-12-20 13:22 ` [RFC PATCH 2/3] modem: move dial request_cb function Andras Domokos
2010-12-20 13:22 ` [RFC PATCH 3/3] voicecall: add emergency call handling Andras Domokos

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox