core: handle incoming calls (RING/CRING, CLIP, NO CARRIER).
This commit is contained in:

committed by
Aleksander Morgado

parent
c53bc10092
commit
6d85146bba
@@ -6285,7 +6285,7 @@ ring_received (MMPortSerialAt *port,
|
|||||||
//Do not match anything from regex
|
//Do not match anything from regex
|
||||||
(void)info;
|
(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
|
static void
|
||||||
@@ -6293,14 +6293,47 @@ cring_received (MMPortSerialAt *port,
|
|||||||
GMatchInfo *info,
|
GMatchInfo *info,
|
||||||
MMBroadbandModem *self)
|
MMBroadbandModem *self)
|
||||||
{
|
{
|
||||||
gchar *str;
|
|
||||||
|
|
||||||
/* The match info gives us in which storage the index applies */
|
/* 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"
|
//TODO: In str you could have "VOICE" or "DATA". Now consider only "VOICE"
|
||||||
g_free (str);
|
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
|
static void
|
||||||
@@ -6344,8 +6377,10 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
|
|||||||
{
|
{
|
||||||
GSimpleAsyncResult *result;
|
GSimpleAsyncResult *result;
|
||||||
MMPortSerialAt *ports[2];
|
MMPortSerialAt *ports[2];
|
||||||
|
GRegex *nocarrier_regex;
|
||||||
GRegex *cring_regex;
|
GRegex *cring_regex;
|
||||||
GRegex *ring_regex;
|
GRegex *ring_regex;
|
||||||
|
GRegex *clip_regex;
|
||||||
GRegex *dtmf_regex;
|
GRegex *dtmf_regex;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
@@ -6354,8 +6389,10 @@ set_voice_unsolicited_events_handlers (MMIfaceModemVoice *self,
|
|||||||
user_data,
|
user_data,
|
||||||
set_voice_unsolicited_events_handlers);
|
set_voice_unsolicited_events_handlers);
|
||||||
|
|
||||||
|
nocarrier_regex = mm_voice_nocarrier_regex_get ();
|
||||||
cring_regex = mm_voice_cring_regex_get ();
|
cring_regex = mm_voice_cring_regex_get ();
|
||||||
ring_regex = mm_voice_ring_regex_get ();
|
ring_regex = mm_voice_ring_regex_get ();
|
||||||
|
clip_regex = mm_voice_clip_regex_get ();
|
||||||
dtmf_regex = mm_voice_dtmf_regex_get ();
|
dtmf_regex = mm_voice_dtmf_regex_get ();
|
||||||
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
|
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
|
||||||
ports[1] = mm_base_modem_peek_port_secondary (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 ? (MMPortSerialAtUnsolicitedMsgFn) ring_received : NULL,
|
||||||
enable ? self : NULL,
|
enable ? self : NULL,
|
||||||
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 (
|
mm_port_serial_at_add_unsolicited_msg_handler (
|
||||||
ports[i],
|
ports[i],
|
||||||
dtmf_regex,
|
dtmf_regex,
|
||||||
|
@@ -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 {
|
typedef struct {
|
||||||
MMCallList *self;
|
MMCallList *self;
|
||||||
GSimpleAsyncResult *result;
|
GSimpleAsyncResult *result;
|
||||||
|
@@ -72,4 +72,7 @@ gboolean mm_call_list_delete_call_finish (MMCallList *self,
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error);
|
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 */
|
#endif /* MM_CALL_LIST_H */
|
||||||
|
@@ -46,6 +46,110 @@ mm_iface_modem_voice_create_call (MMIfaceModemVoice *self)
|
|||||||
return MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->create_call (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 {
|
typedef struct {
|
||||||
|
@@ -118,6 +118,12 @@ void mm_iface_modem_voice_bind_simple_status (MMIfaceModemVoice *self,
|
|||||||
|
|
||||||
/* CALL creation */
|
/* 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 */
|
/* Look for a new valid multipart reference */
|
||||||
guint8 mm_iface_modem_voice_get_local_multipart_reference (MMIfaceModemVoice *self,
|
guint8 mm_iface_modem_voice_get_local_multipart_reference (MMIfaceModemVoice *self,
|
||||||
|
@@ -348,6 +348,32 @@ mm_voice_cring_regex_get (void)
|
|||||||
NULL);
|
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 *
|
GRegex *
|
||||||
mm_voice_dtmf_regex_get (void)
|
mm_voice_dtmf_regex_get (void)
|
||||||
{
|
{
|
||||||
|
@@ -87,6 +87,8 @@ GArray *mm_filter_supported_capabilities (MMModemCapability all,
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
GRegex *mm_voice_ring_regex_get (void);
|
GRegex *mm_voice_ring_regex_get (void);
|
||||||
GRegex *mm_voice_cring_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);
|
GRegex *mm_voice_dtmf_regex_get (void);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
Reference in New Issue
Block a user