core: handle incoming calls (RING/CRING, CLIP, NO CARRIER).

This commit is contained in:
Marco Bascetta
2015-05-05 18:00:09 +02:00
committed by Aleksander Morgado
parent c53bc10092
commit 6d85146bba
7 changed files with 258 additions and 9 deletions

View File

@@ -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));
@@ -6381,6 +6418,18 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
enable ? (MMPortSerialAtUnsolicitedMsgFn) ring_received : NULL,
enable ? self : NULL,
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,

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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 {

View File

@@ -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,

View File

@@ -348,6 +348,32 @@ mm_voice_cring_regex_get (void)
NULL);
}
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)
{

View File

@@ -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 */