Skip to contentSkip to conversation

Emergency Calls

PATCH New Andras Domokos 1 participant 4 messages Dec 20, 2010

lore
Share & tools
lore
#0 lore raw

cover Emergency Calls

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(-)
#1 lore raw

RFC PATCH 1/3 modem: add Emergency property

---
 src/dbus.c  |    7 ++
 src/modem.c |  207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/ofono.h |    5 ++
 3 files changed, 216 insertions(+), 3 deletions(-)
src/dbus.c +7 -0
index c24615f..3be8d22 100644
@@ -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();
src/modem.c +204 -3

301 lines not on this page · raw message

src/ofono.h +5 -0
index 792134b..336d25b 100644
@@ -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);
Signature · 1 line
1.7.0.4
#2 lore raw

RFC PATCH 2/3 modem: move dial request_cb function

In reply to Andras Domokos
---
 src/voicecall.c |   70 +++++++++++++++++++++++++++---------------------------
 1 files changed, 35 insertions(+), 35 deletions(-)
src/voicecall.c +35 -35
index dbf3e9a..0120cd0 100644
@@ -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,
Signature · 1 line
1.7.0.4
#3 lore raw

RFC PATCH 3/3 voicecall: add emergency call handling

In reply to Andras Domokos
---
 src/voicecall.c |  122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 121 insertions(+), 1 deletions(-)
src/voicecall.c +121 -1
index 0120cd0..370f760 100644
@@ -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);
 }
Signature · 1 line
1.7.0.4