diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/simtech/mm-modem-helpers-simtech.c | 55 | ||||
-rw-r--r-- | plugins/simtech/mm-modem-helpers-simtech.h | 9 | ||||
-rw-r--r-- | plugins/simtech/mm-shared-simtech.c | 46 | ||||
-rw-r--r-- | plugins/simtech/tests/test-modem-helpers-simtech.c | 54 |
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 (); } |