aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bascetta <marco.bascetta@sadel.it>2015-05-05 18:00:09 +0200
committerAleksander Morgado <aleksander@aleksander.es>2015-08-02 10:39:13 +0200
commit6d85146bba3edceeaf9f23e0e7a5281fda527d59 (patch)
treee09cc3e936ec9fc60cd4bac01da72e3118999ae8
parentc53bc10092563eb361b4980afb00080009067661 (diff)
core: handle incoming calls (RING/CRING, CLIP, NO CARRIER).
-rw-r--r--src/mm-broadband-modem.c59
-rw-r--r--src/mm-call-list.c59
-rw-r--r--src/mm-call-list.h3
-rw-r--r--src/mm-iface-modem-voice.c104
-rw-r--r--src/mm-iface-modem-voice.h8
-rw-r--r--src/mm-modem-helpers.c26
-rw-r--r--src/mm-modem-helpers.h8
7 files changed, 258 insertions, 9 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 720ef62c..a3e69c08 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -6285,7 +6285,7 @@ ring_received (MMPortSerialAt *port,
//Do not match anything from regex
(void)info;
- mm_iface_modem_voice_create_call(MM_IFACE_MODEM_VOICE(self));
+ mm_iface_modem_voice_create_incoming_call(MM_IFACE_MODEM_VOICE(self));
}
static void
@@ -6293,14 +6293,47 @@ cring_received (MMPortSerialAt *port,
GMatchInfo *info,
MMBroadbandModem *self)
{
- gchar *str;
-
/* The match info gives us in which storage the index applies */
- str = mm_get_string_unquoted_from_match_info (info, 1);
+ gchar *str = mm_get_string_unquoted_from_match_info (info, 1);
//TODO: In str you could have "VOICE" or "DATA". Now consider only "VOICE"
g_free (str);
- mm_iface_modem_voice_create_call(MM_IFACE_MODEM_VOICE(self));
+ mm_iface_modem_voice_create_incoming_call(MM_IFACE_MODEM_VOICE(self));
+}
+
+static void
+clip_received (MMPortSerialAt *port,
+ GMatchInfo *info,
+ MMBroadbandModem *self)
+{
+ /* The match info gives us in which storage the index applies */
+ gchar *str = mm_get_string_unquoted_from_match_info (info, 1);
+
+ if( !str ) {
+ guint validity = 0;
+ guint type = 0;
+
+ mm_get_uint_from_match_info (info, 2, &type);
+ mm_get_uint_from_match_info (info, 3, &validity);
+
+ mm_dbg ("[%s:%d] CLIP regex => number:'%s', type:'%d', validity:'%d'", __func__, __LINE__, str, type, validity);
+
+ mm_iface_modem_voice_update_incoming_call_number(MM_IFACE_MODEM_VOICE(self), str, type, validity);
+
+ g_free(str);
+ }
+}
+
+static void
+nocarrier_received (MMPortSerialAt *port,
+ GMatchInfo *info,
+ MMBroadbandModem *self)
+{
+ //Do not match anything from regex
+ (void)info;
+
+ mm_dbg ("[%s:%d]", __func__, __LINE__);
+ mm_iface_modem_voice_network_hangup(MM_IFACE_MODEM_VOICE(self));
}
static void
@@ -6344,8 +6377,10 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
{
GSimpleAsyncResult *result;
MMPortSerialAt *ports[2];
+ GRegex *nocarrier_regex;
GRegex *cring_regex;
GRegex *ring_regex;
+ GRegex *clip_regex;
GRegex *dtmf_regex;
guint i;
@@ -6354,8 +6389,10 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
user_data,
set_voice_unsolicited_events_handlers);
+ nocarrier_regex = mm_voice_nocarrier_regex_get ();
cring_regex = mm_voice_cring_regex_get ();
ring_regex = mm_voice_ring_regex_get ();
+ clip_regex = mm_voice_clip_regex_get ();
dtmf_regex = mm_voice_dtmf_regex_get ();
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
@@ -6383,6 +6420,18 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
NULL);
mm_port_serial_at_add_unsolicited_msg_handler (
ports[i],
+ clip_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn) clip_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (
+ ports[i],
+ nocarrier_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn) nocarrier_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (
+ ports[i],
dtmf_regex,
enable ? (MMPortSerialAtUnsolicitedMsgFn) dtmf_received : NULL,
enable ? self : NULL,
diff --git a/src/mm-call-list.c b/src/mm-call-list.c
index 76af785b..aa650058 100644
--- a/src/mm-call-list.c
+++ b/src/mm-call-list.c
@@ -84,6 +84,65 @@ mm_call_list_get_paths (MMCallList *self)
/*****************************************************************************/
+MMBaseCall* mm_call_list_get_new_incoming(MMCallList *self)
+{
+ MMBaseCall *call = NULL;
+ GList *l;
+ guint i;
+
+ for (i = 0, l = self->priv->list; l && !call; l = g_list_next (l)) {
+
+ MMCallState state;
+ MMCallStateReason reason;
+ MMCallDirection direct;
+
+ g_object_get (MM_BASE_CALL (l->data),
+ "state" , &state,
+ "state-reason", &reason,
+ "direction" , &direct,
+ NULL);
+
+ if( direct == MM_CALL_DIRECTION_INCOMING &&
+ state == MM_CALL_STATE_RINGING_IN &&
+ reason == MM_CALL_STATE_REASON_INCOMING_NEW ) {
+
+ call = MM_BASE_CALL (l->data);
+ break;
+ }
+ }
+
+ return call;
+}
+
+MMBaseCall* mm_call_list_get_first_non_terminated_call(MMCallList *self)
+{
+ MMBaseCall *call = NULL;
+ GList *l;
+ guint i;
+
+ for (i = 0, l = self->priv->list; l && !call; l = g_list_next (l)) {
+
+ MMCallState state;
+ MMCallStateReason reason;
+ MMCallDirection direct;
+
+ g_object_get (MM_BASE_CALL (l->data),
+ "state" , &state,
+ "state-reason", &reason,
+ "direction" , &direct,
+ NULL);
+
+ if( state != MM_CALL_STATE_TERMINATED ) {
+ call = MM_BASE_CALL (l->data);
+ break;
+ }
+ }
+
+ return call;
+}
+
+/*****************************************************************************/
+
typedef struct {
MMCallList *self;
GSimpleAsyncResult *result;
diff --git a/src/mm-call-list.h b/src/mm-call-list.h
index e3c2a65f..7d47e49c 100644
--- a/src/mm-call-list.h
+++ b/src/mm-call-list.h
@@ -72,4 +72,7 @@ gboolean mm_call_list_delete_call_finish (MMCallList *self,
GAsyncResult *res,
GError **error);
+MMBaseCall* mm_call_list_get_new_incoming (MMCallList *self);
+MMBaseCall* mm_call_list_get_first_non_terminated_call (MMCallList *self);
+
#endif /* MM_CALL_LIST_H */
diff --git a/src/mm-iface-modem-voice.c b/src/mm-iface-modem-voice.c
index 990ebee4..6b896dbd 100644
--- a/src/mm-iface-modem-voice.c
+++ b/src/mm-iface-modem-voice.c
@@ -46,6 +46,110 @@ mm_iface_modem_voice_create_call (MMIfaceModemVoice *self)
return MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->create_call (self);
}
+//BASCETTA:TODO: bisogna aggiungere la gestione degli errori.
+MMBaseCall *
+mm_iface_modem_voice_create_incoming_call (MMIfaceModemVoice *self)
+{
+ MMBaseCall *call = NULL;
+ MMCallList *list = NULL;
+
+ g_object_get (MM_BASE_MODEM (self),
+ MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
+ NULL);
+
+ if( list ) {
+
+ call = mm_call_list_get_new_incoming(list);
+ if( !call ) {
+
+ mm_dbg("[%s:%d] Incoming call does not exist; create it", __func__, __LINE__);
+
+ call = mm_base_call_new (MM_BASE_MODEM (self));
+ g_object_set (call,
+ "state", MM_CALL_STATE_RINGING_IN,
+ "state-reason", MM_CALL_STATE_REASON_INCOMING_NEW,
+ "direction", MM_CALL_DIRECTION_INCOMING,
+ NULL);
+
+ /* Only export once properly created */
+ mm_base_call_export (call);
+ mm_dbg ("[%s:%d] New call exported to DBUS", __func__, __LINE__);
+
+ mm_call_list_add_call(list, call);
+ mm_dbg ("[%s:%d] Call added to list", __func__, __LINE__);
+
+ } else {
+// mm_dbg("[%s:%d] Incoming call already exist. Do nothing", __func__, __LINE__);
+ }
+
+ g_object_unref (list);
+ }
+
+ return call;
+}
+
+gboolean mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoice *self, gchar *number, guint type, guint validity)
+{
+ gboolean updated = FALSE;
+ MMBaseCall *call = NULL;
+ MMCallList *list = NULL;
+
+ g_object_get (MM_BASE_MODEM (self),
+ MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
+ NULL);
+
+ if( list ) {
+
+ call = mm_call_list_get_new_incoming(list);
+ if( call ) {
+ g_object_set (call, "number", number, NULL);
+ mm_gdbus_call_set_number(MM_GDBUS_CALL (call), number);
+
+ //TODO: Maybe also this parameters should be used
+ (void)type;
+ (void)validity;
+
+ updated = TRUE;
+ } else {
+ mm_dbg("[%s:%d] Incoming call does not exist yet", __func__, __LINE__);
+ }
+ }
+
+ return updated;
+}
+
+gboolean mm_iface_modem_voice_network_hangup (MMIfaceModemVoice *self)
+{
+ gboolean updated = FALSE;
+ MMBaseCall *call = NULL;
+ MMCallList *list = NULL;
+
+ g_object_get (MM_BASE_MODEM (self),
+ MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
+ NULL);
+
+ if( list ) {
+
+ call = mm_call_list_get_first_non_terminated_call(list);
+ if( call ) {
+ //BASCETTA:TODO: Hang this call!
+ g_object_set (call,
+ "state", MM_CALL_STATE_TERMINATED,
+ "state-reason", MM_CALL_STATE_REASON_TERMINATED,
+ NULL);
+ mm_gdbus_call_set_state(MM_GDBUS_CALL (call), MM_CALL_STATE_TERMINATED);
+ mm_gdbus_call_set_state_reason(MM_GDBUS_CALL (call), MM_CALL_STATE_REASON_TERMINATED);
+ updated = TRUE;
+
+ //BASCETTA:TODO: I have to signal state change...
+
+ } else {
+ mm_dbg("[%s:%d] Incoming call does not exist yet", __func__, __LINE__);
+ }
+ }
+
+ return updated;
+}
/*****************************************************************************/
typedef struct {
diff --git a/src/mm-iface-modem-voice.h b/src/mm-iface-modem-voice.h
index 35415190..65e5a1e4 100644
--- a/src/mm-iface-modem-voice.h
+++ b/src/mm-iface-modem-voice.h
@@ -117,7 +117,13 @@ void mm_iface_modem_voice_bind_simple_status (MMIfaceModemVoice *self,
MMSimpleStatus *status);
/* CALL creation */
-MMBaseCall *mm_iface_modem_voice_create_call (MMIfaceModemVoice *self);
+MMBaseCall *mm_iface_modem_voice_create_call (MMIfaceModemVoice *self);
+MMBaseCall *mm_iface_modem_voice_create_incoming_call (MMIfaceModemVoice *self);
+gboolean mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoice *self,
+ gchar *number,
+ guint type,
+ guint validity);
+gboolean mm_iface_modem_voice_network_hangup (MMIfaceModemVoice *self);
/* Look for a new valid multipart reference */
guint8 mm_iface_modem_voice_get_local_multipart_reference (MMIfaceModemVoice *self,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 36eb0390..7ba00f9e 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -349,6 +349,32 @@ mm_voice_cring_regex_get (void)
}
GRegex *
+mm_voice_clip_regex_get (void)
+{
+ /* Example:
+ * <CR><LF>+CLIP: "+393351391306",145,,,,0<CR><LF>
+ * \_ Number \_ Type \_ Validity
+ */
+
+ return g_regex_new ("\\r\\n\\+CLIP:\\s*\"(\\S+)\",\\s*(\\d+),\\s*,\\s*,\\s*,\\s*(\\d+)\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE,
+ 0,
+ NULL);
+}
+
+GRegex *
+mm_voice_nocarrier_regex_get (void)
+{
+ /* Example:
+ * <CR><LF>NO CARRIER<CR><LF>
+ */
+ return g_regex_new ("\\r\\n\\NO CARRIER\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE,
+ 0,
+ NULL);
+}
+
+GRegex *
mm_voice_dtmf_regex_get (void)
{
/* Example:
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 1a3324a6..844368f8 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -85,9 +85,11 @@ GArray *mm_filter_supported_capabilities (MMModemCapability all,
/*****************************************************************************/
/* VOICE specific helpers and utilities */
/*****************************************************************************/
-GRegex *mm_voice_ring_regex_get (void);
-GRegex *mm_voice_cring_regex_get (void);
-GRegex *mm_voice_dtmf_regex_get (void);
+GRegex *mm_voice_ring_regex_get (void);
+GRegex *mm_voice_cring_regex_get(void);
+GRegex *mm_voice_clip_regex_get (void);
+GRegex *mm_voice_nocarrier_regex_get (void);
+GRegex *mm_voice_dtmf_regex_get (void);
/*****************************************************************************/
/* 3GPP specific helpers and utilities */