aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-10-15 10:30:00 +0200
committerAleksander Morgado <aleksander@aleksander.es>2019-10-15 10:30:00 +0200
commit395b22178c4f6dd24d552e82d2d46dfb24c65297 (patch)
treeb2bfd84ac1fc1f23bf3c2455000d29a7b28ed236
parent1a17996ccb3560c29e2a27c596ad0e9c7bbaaa61 (diff)
simtech: handle 'VOICE CALL' URCs
Just processing and parsing them for now, so that they don't interfere with other commands: $ 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 ' VOICE CALL: BEGIN''
-rw-r--r--plugins/simtech/mm-modem-helpers-simtech.c55
-rw-r--r--plugins/simtech/mm-modem-helpers-simtech.h9
-rw-r--r--plugins/simtech/mm-shared-simtech.c46
-rw-r--r--plugins/simtech/tests/test-modem-helpers-simtech.c54
4 files changed, 158 insertions, 6 deletions
diff --git a/plugins/simtech/mm-modem-helpers-simtech.c b/plugins/simtech/mm-modem-helpers-simtech.c
index e25bc118..5926c44f 100644
--- a/plugins/simtech/mm-modem-helpers-simtech.c
+++ b/plugins/simtech/mm-modem-helpers-simtech.c
@@ -93,3 +93,58 @@ mm_simtech_call_info_list_free (GList *call_info_list)
{
mm_3gpp_call_info_list_free (call_info_list);
}
+
+/*****************************************************************************/
+
+/*
+ * <CR><LF>VOICE CALL: BEGIN<CR><LF>
+ * <CR><LF>VOICE CALL: END: 000041<CR><LF>
+ */
+GRegex *
+mm_simtech_get_voice_call_urc_regex (void)
+{
+ return g_regex_new ("\\r\\nVOICE CALL:\\s*([A-Z]+)(?::\\s*(\\d+))?\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+}
+
+gboolean
+mm_simtech_parse_voice_call_urc (GMatchInfo *match_info,
+ gboolean *start_or_stop,
+ guint *duration,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ gchar *str;
+
+ str = mm_get_string_unquoted_from_match_info (match_info, 1);
+ if (!str) {
+ inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Couldn't read voice call URC action");
+ goto out;
+ }
+
+ if (g_strcmp0 (str, "BEGIN") == 0) {
+ *start_or_stop = TRUE;
+ *duration = 0;
+ goto out;
+ }
+
+ if (g_strcmp0 (str, "END") == 0) {
+ *start_or_stop = FALSE;
+ if (!mm_get_uint_from_match_info (match_info, 2, duration))
+ *duration = 0;
+ goto out;
+ }
+
+ inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Unknown voice call URC action: %s", str);
+
+out:
+ g_free (str);
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/plugins/simtech/mm-modem-helpers-simtech.h b/plugins/simtech/mm-modem-helpers-simtech.h
index 66e5c467..1a046f58 100644
--- a/plugins/simtech/mm-modem-helpers-simtech.h
+++ b/plugins/simtech/mm-modem-helpers-simtech.h
@@ -36,4 +36,13 @@ gboolean mm_simtech_parse_clcc_list (const gchar *str,
GError **error);
void mm_simtech_call_info_list_free (GList *call_info_list);
+/*****************************************************************************/
+/* VOICE CALL URC helpers */
+
+GRegex *mm_simtech_get_voice_call_urc_regex (void);
+gboolean mm_simtech_parse_voice_call_urc (GMatchInfo *match_info,
+ gboolean *start_or_stop,
+ guint *duration,
+ GError **error);
+
#endif /* MM_MODEM_HELPERS_SIMTECH_H */
diff --git a/plugins/simtech/mm-shared-simtech.c b/plugins/simtech/mm-shared-simtech.c
index 11be1a94..5a54ba44 100644
--- a/plugins/simtech/mm-shared-simtech.c
+++ b/plugins/simtech/mm-shared-simtech.c
@@ -52,11 +52,13 @@ typedef struct {
MMIfaceModemVoice *iface_modem_voice_parent;
FeatureSupport clcc_urc_support;
GRegex *clcc_urc_regex;
+ GRegex *voice_call_regex;
} Private;
static void
private_free (Private *ctx)
{
+ g_regex_unref (ctx->voice_call_regex);
g_regex_unref (ctx->clcc_urc_regex);
g_slice_free (Private, ctx);
}
@@ -77,6 +79,7 @@ get_private (MMSharedSimtech *self)
priv->cgps_support = FEATURE_SUPPORT_UNKNOWN;
priv->clcc_urc_support = FEATURE_SUPPORT_UNKNOWN;
priv->clcc_urc_regex = mm_simtech_get_clcc_urc_regex ();
+ priv->voice_call_regex = mm_simtech_get_voice_call_urc_regex ();
/* Setup parent class' MMIfaceModemLocation and MMIfaceModemVoice */
@@ -799,6 +802,34 @@ clcc_urc_received (MMPortSerialAt *port,
}
static void
+voice_call_urc_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMSharedSimtech *self)
+{
+ GError *error = NULL;
+ gboolean start_or_stop = FALSE; /* start = TRUE, stop = FALSE */
+ guint duration = 0;
+
+ if (!mm_simtech_parse_voice_call_urc (match_info, &start_or_stop, &duration, &error)) {
+ mm_warn ("couldn't parse VOICE CALL URC: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ if (start_or_stop) {
+ mm_dbg ("voice call started");
+ return;
+ }
+
+ if (duration) {
+ mm_dbg ("voice call finished (duration: %us)", duration);
+ return;
+ }
+
+ mm_dbg ("voice call finished");
+}
+
+static void
common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
gboolean enable)
{
@@ -808,10 +839,6 @@ common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
priv = get_private (MM_SHARED_SIMTECH (self));
- /* If +CLCC URCs not supported, we're done */
- if (priv->clcc_urc_support == FEATURE_NOT_SUPPORTED)
- return;
-
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
@@ -819,9 +846,16 @@ common_voice_setup_cleanup_unsolicited_events (MMSharedSimtech *self,
if (!ports[i])
continue;
+ if (priv->clcc_urc_support == FEATURE_SUPPORTED)
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ priv->clcc_urc_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)clcc_urc_received : NULL,
+ enable ? self : NULL,
+ NULL);
+
mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
- priv->clcc_urc_regex,
- enable ? (MMPortSerialAtUnsolicitedMsgFn)clcc_urc_received : NULL,
+ priv->voice_call_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)voice_call_urc_received : NULL,
enable ? self : NULL,
NULL);
}
diff --git a/plugins/simtech/tests/test-modem-helpers-simtech.c b/plugins/simtech/tests/test-modem-helpers-simtech.c
index a93d903a..3092e936 100644
--- a/plugins/simtech/tests/test-modem-helpers-simtech.c
+++ b/plugins/simtech/tests/test-modem-helpers-simtech.c
@@ -143,6 +143,56 @@ test_clcc_urc_complex (void)
/*****************************************************************************/
+static void
+common_test_voice_call_urc (const gchar *urc,
+ gboolean expected_start_or_stop,
+ guint expected_duration)
+{
+ GError *error = NULL;
+ gboolean start_or_stop = FALSE; /* start = TRUE, stop = FALSE */
+ guint duration = 0;
+ GRegex *voice_call_regex = NULL;
+ gboolean result;
+ GMatchInfo *match_info = NULL;
+
+ voice_call_regex = mm_simtech_get_voice_call_urc_regex ();
+
+ /* Same matching logic as done in MMSerialPortAt when processing URCs! */
+ result = g_regex_match_full (voice_call_regex, urc, -1, 0, 0, &match_info, &error);
+ g_assert_no_error (error);
+ g_assert (result);
+
+ result = mm_simtech_parse_voice_call_urc (match_info, &start_or_stop, &duration, &error);
+ g_assert_no_error (error);
+ g_assert (result);
+
+ g_assert_cmpuint (expected_start_or_stop, ==, start_or_stop);
+ g_assert_cmpuint (expected_duration, ==, duration);
+
+ g_match_info_free (match_info);
+ g_regex_unref (voice_call_regex);
+}
+
+static void
+test_voice_call_begin_urc (void)
+{
+ common_test_voice_call_urc ("\r\nVOICE CALL: BEGIN\r\n", TRUE, 0);
+}
+
+static void
+test_voice_call_end_urc (void)
+{
+ common_test_voice_call_urc ("\r\nVOICE CALL: END\r\n", FALSE, 0);
+}
+
+static void
+test_voice_call_end_duration_urc (void)
+{
+ common_test_voice_call_urc ("\r\nVOICE CALL: END: 000041\r\n", FALSE, 41);
+}
+
+/*****************************************************************************/
+
void
_mm_log (const char *loc,
const char *func,
@@ -173,5 +223,9 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/simtech/clcc/urc/multiple", test_clcc_urc_multiple);
g_test_add_func ("/MM/simtech/clcc/urc/complex", test_clcc_urc_complex);
+ g_test_add_func ("/MM/simtech/voicecall/urc/begin", test_voice_call_begin_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);
+
return g_test_run ();
}