simtech: handle non-standard '+CRING' URCs
The SIM7600E ends up emitting these URCs with too many <CR>s, and the generic +CRING handler doesn't catch them, interfering with other actions, e.g.: $ sudo mmcli --call 1 --accept error: couldn't accept the call: 'GDBus.Error:org.freedesktop.ModemManager1.Error.Core.Failed: Couldn't accept the call: Unhandled response '+CRING: VOICE +CRING: VOICE''
This commit is contained in:
@@ -148,3 +148,16 @@ out:
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using TWO <CR> instead of one...
|
||||||
|
* <CR><CR><LF>+CRING: VOICE<CR><CR><LF>
|
||||||
|
*/
|
||||||
|
GRegex *
|
||||||
|
mm_simtech_get_cring_urc_regex (void)
|
||||||
|
{
|
||||||
|
return g_regex_new ("(?:\\r)+\\n\\+CRING:\\s*(\\S+)(?:\\r)+\\n",
|
||||||
|
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||||
|
}
|
||||||
|
@@ -45,4 +45,9 @@ gboolean mm_simtech_parse_voice_call_urc (GMatchInfo *match_info,
|
|||||||
guint *duration,
|
guint *duration,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Non-standard CRING URC helpers */
|
||||||
|
|
||||||
|
GRegex *mm_simtech_get_cring_urc_regex (void);
|
||||||
|
|
||||||
#endif /* MM_MODEM_HELPERS_SIMTECH_H */
|
#endif /* MM_MODEM_HELPERS_SIMTECH_H */
|
||||||
|
@@ -53,11 +53,13 @@ typedef struct {
|
|||||||
FeatureSupport clcc_urc_support;
|
FeatureSupport clcc_urc_support;
|
||||||
GRegex *clcc_urc_regex;
|
GRegex *clcc_urc_regex;
|
||||||
GRegex *voice_call_regex;
|
GRegex *voice_call_regex;
|
||||||
|
GRegex *cring_regex;
|
||||||
} Private;
|
} Private;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
private_free (Private *ctx)
|
private_free (Private *ctx)
|
||||||
{
|
{
|
||||||
|
g_regex_unref (ctx->cring_regex);
|
||||||
g_regex_unref (ctx->voice_call_regex);
|
g_regex_unref (ctx->voice_call_regex);
|
||||||
g_regex_unref (ctx->clcc_urc_regex);
|
g_regex_unref (ctx->clcc_urc_regex);
|
||||||
g_slice_free (Private, ctx);
|
g_slice_free (Private, ctx);
|
||||||
@@ -80,6 +82,7 @@ get_private (MMSharedSimtech *self)
|
|||||||
priv->clcc_urc_support = FEATURE_SUPPORT_UNKNOWN;
|
priv->clcc_urc_support = FEATURE_SUPPORT_UNKNOWN;
|
||||||
priv->clcc_urc_regex = mm_simtech_get_clcc_urc_regex ();
|
priv->clcc_urc_regex = mm_simtech_get_clcc_urc_regex ();
|
||||||
priv->voice_call_regex = mm_simtech_get_voice_call_urc_regex ();
|
priv->voice_call_regex = mm_simtech_get_voice_call_urc_regex ();
|
||||||
|
priv->cring_regex = mm_simtech_get_cring_urc_regex ();
|
||||||
|
|
||||||
/* Setup parent class' MMIfaceModemLocation and MMIfaceModemVoice */
|
/* Setup parent class' MMIfaceModemLocation and MMIfaceModemVoice */
|
||||||
|
|
||||||
@@ -829,6 +832,27 @@ voice_call_urc_received (MMPortSerialAt *port,
|
|||||||
mm_dbg ("voice call finished");
|
mm_dbg ("voice call finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cring_urc_received (MMPortSerialAt *port,
|
||||||
|
GMatchInfo *info,
|
||||||
|
MMSharedSimtech *self)
|
||||||
|
{
|
||||||
|
MMCallInfo call_info;
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
|
/* We could have "VOICE" or "DATA". Now consider only "VOICE" */
|
||||||
|
str = mm_get_string_unquoted_from_match_info (info, 1);
|
||||||
|
mm_dbg ("Ringing (%s)", str);
|
||||||
|
g_free (str);
|
||||||
|
|
||||||
|
call_info.index = 0;
|
||||||
|
call_info.direction = MM_CALL_DIRECTION_INCOMING;
|
||||||
|
call_info.state = MM_CALL_STATE_RINGING_IN;
|
||||||
|
call_info.number = NULL;
|
||||||
|
|
||||||
|
mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
|
common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
|
||||||
gboolean enable)
|
gboolean enable)
|
||||||
@@ -858,6 +882,12 @@ common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
|
|||||||
enable ? (MMPortSerialAtUnsolicitedMsgFn)voice_call_urc_received : NULL,
|
enable ? (MMPortSerialAtUnsolicitedMsgFn)voice_call_urc_received : NULL,
|
||||||
enable ? self : NULL,
|
enable ? self : NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
|
||||||
|
priv->cring_regex,
|
||||||
|
enable ? (MMPortSerialAtUnsolicitedMsgFn)cring_urc_received : NULL,
|
||||||
|
enable ? self : NULL,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -193,6 +193,47 @@ test_voice_call_end_duration_urc (void)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
common_test_cring_urc (const gchar *urc,
|
||||||
|
const gchar *expected_type)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GRegex *cring_regex = NULL;
|
||||||
|
GMatchInfo *match_info = NULL;
|
||||||
|
gchar *type;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
cring_regex = mm_simtech_get_cring_urc_regex ();
|
||||||
|
|
||||||
|
/* Same matching logic as done in MMSerialPortAt when processing URCs! */
|
||||||
|
result = g_regex_match_full (cring_regex, urc, -1, 0, 0, &match_info, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert (result);
|
||||||
|
|
||||||
|
type = g_match_info_fetch (match_info, 1);
|
||||||
|
g_assert (type);
|
||||||
|
|
||||||
|
g_assert_cmpstr (type, ==, expected_type);
|
||||||
|
|
||||||
|
g_match_info_free (match_info);
|
||||||
|
g_regex_unref (cring_regex);
|
||||||
|
g_free (type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cring_urc_two_crs (void)
|
||||||
|
{
|
||||||
|
common_test_cring_urc ("\r\r\n+CRING: VOICE\r\r\n", "VOICE");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cring_urc_one_cr (void)
|
||||||
|
{
|
||||||
|
common_test_cring_urc ("\r\n+CRING: VOICE\r\n", "VOICE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
_mm_log (const char *loc,
|
_mm_log (const char *loc,
|
||||||
const char *func,
|
const char *func,
|
||||||
@@ -227,5 +268,8 @@ int main (int argc, char **argv)
|
|||||||
g_test_add_func ("/MM/simtech/voicecall/urc/end", test_voice_call_end_urc);
|
g_test_add_func ("/MM/simtech/voicecall/urc/end", test_voice_call_end_urc);
|
||||||
g_test_add_func ("/MM/simtech/voicecall/urc/end-duration", test_voice_call_end_duration_urc);
|
g_test_add_func ("/MM/simtech/voicecall/urc/end-duration", test_voice_call_end_duration_urc);
|
||||||
|
|
||||||
|
g_test_add_func ("/MM/simtech/cring/urc/two-crs", test_cring_urc_two_crs);
|
||||||
|
g_test_add_func ("/MM/simtech/cring/urc/one-cr", test_cring_urc_one_cr);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user