aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-07-02 12:38:03 +0200
committerAleksander Morgado <aleksander@aleksander.es>2019-07-11 23:21:00 +0200
commit12bad162e384e0d4a7217d40c5fcfc2189741b48 (patch)
tree8e507f82215d1a6a262d5a6c4c15fbb13c9f471c
parentee2f3fb904688f07593122ad1e798166735f253f (diff)
huawei: voice-related URCs are not in-call
The URCs report the specific call index they apply to, so they should be managed by the modem object and reported to the Voice interface.
-rw-r--r--plugins/huawei/mm-broadband-modem-huawei.c233
-rw-r--r--plugins/huawei/mm-call-huawei.c188
2 files changed, 212 insertions, 209 deletions
diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
index 8433895a..3d4d72f5 100644
--- a/plugins/huawei/mm-broadband-modem-huawei.c
+++ b/plugins/huawei/mm-broadband-modem-huawei.c
@@ -103,6 +103,13 @@ struct _MMBroadbandModemHuaweiPrivate {
GRegex *dsflowrpt_regex;
GRegex *ndisstat_regex;
+ /* Regex for voice management notifications */
+ GRegex *orig_regex;
+ GRegex *conf_regex;
+ GRegex *conn_regex;
+ GRegex *cend_regex;
+ GRegex *ddtmf_regex;
+
/* Regex to ignore */
GRegex *boot_regex;
GRegex *connect_regex;
@@ -123,7 +130,6 @@ struct _MMBroadbandModemHuaweiPrivate {
GRegex *ltersrp_regex;
GRegex *cschannelinfo_regex;
GRegex *eons_regex;
- GRegex *orig_regex;
FeatureSupport ndisdup_support;
FeatureSupport rfswitch_support;
@@ -2934,20 +2940,190 @@ modem_voice_check_support (MMIfaceModemVoice *self,
}
/*****************************************************************************/
+/* Common setup/cleanup voice unsolicited events */
+
+typedef enum {
+ HUAWEI_CALL_TYPE_VOICE = 0,
+ HUAWEI_CALL_TYPE_CS_DATA = 1,
+ HUAWEI_CALL_TYPE_PS_DATA = 2,
+ HUAWEI_CALL_TYPE_CDMA_SMS = 3,
+ HUAWEI_CALL_TYPE_OTA_STANDARD_OTASP = 7,
+ HUAWEI_CALL_TYPE_OTA_NON_STANDARD_OTASP = 8,
+ HUAWEI_CALL_TYPE_EMERGENCY = 9,
+} HuaweiCallType;
+
+static void
+orig_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemHuawei *self)
+{
+ MMCallInfo call_info = { 0 };
+ guint aux = 0;
+
+ if (!mm_get_uint_from_match_info (match_info, 2, &aux)) {
+ mm_warn ("couldn't parse call type from ^ORIG");
+ return;
+ }
+ if (aux != HUAWEI_CALL_TYPE_VOICE && aux != HUAWEI_CALL_TYPE_EMERGENCY) {
+ mm_dbg ("ignored ^ORIG for non-voice call");
+ return;
+ }
+
+ if (!mm_get_uint_from_match_info (match_info, 1, &aux)) {
+ mm_warn ("couldn't parse call index from ^ORIG");
+ return;
+ }
+ call_info.index = aux;
+ call_info.state = MM_CALL_STATE_DIALING;
+ call_info.direction = MM_CALL_DIRECTION_OUTGOING;
+
+ mm_dbg ("call %u state updated: dialing", call_info.index);
+
+ mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info);
+}
+
+static void
+conf_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemHuawei *self)
+{
+ MMCallInfo call_info = { 0 };
+ guint aux = 0;
+
+ if (!mm_get_uint_from_match_info (match_info, 1, &aux)) {
+ mm_warn ("couldn't parse call index from ^CONF");
+ return;
+ }
+ call_info.index = aux;
+ call_info.state = MM_CALL_STATE_RINGING_OUT;
+ call_info.direction = MM_CALL_DIRECTION_OUTGOING;
+
+ mm_dbg ("call %u state updated: ringing-out", call_info.index);
+
+ mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info);
+}
+
+static void
+conn_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemHuawei *self)
+{
+ MMCallInfo call_info = { 0 };
+ guint aux = 0;
+
+ if (!mm_get_uint_from_match_info (match_info, 1, &aux)) {
+ mm_warn ("couldn't parse call index from ^CONN");
+ return;
+ }
+ call_info.index = aux;
+ call_info.state = MM_CALL_STATE_ACTIVE;
+ call_info.direction = MM_CALL_DIRECTION_UNKNOWN;
+
+ mm_dbg ("call %u state updated: active", aux);
+
+ mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info);
+}
+
+static void
+cend_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemHuawei *self)
+{
+ MMCallInfo call_info = { 0 };
+ guint aux = 0;
+
+ /* only index is mandatory */
+ if (!mm_get_uint_from_match_info (match_info, 1, &aux)) {
+ mm_warn ("couldn't parse call index from ^CEND");
+ return;
+ }
+ call_info.index = aux;
+ call_info.state = MM_CALL_STATE_TERMINATED;
+ call_info.direction = MM_CALL_DIRECTION_UNKNOWN;
+
+ mm_dbg ("call %u state updated: terminated", call_info.index);
+ if (mm_get_uint_from_match_info (match_info, 2, &aux))
+ mm_dbg (" call duration: %u seconds", aux);
+ if (mm_get_uint_from_match_info (match_info, 3, &aux))
+ mm_dbg (" end status code: %u", aux);
+ if (mm_get_uint_from_match_info (match_info, 4, &aux))
+ mm_dbg (" call control cause: %u", aux);
+
+ mm_iface_modem_voice_report_call (MM_IFACE_MODEM_VOICE (self), &call_info);
+}
+
+static void
+ddtmf_received (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMBroadbandModemHuawei *self)
+{
+ gchar *dtmf;
+
+ dtmf = g_match_info_fetch (match_info, 1);
+ mm_dbg ("received DTMF: %s", dtmf);
+ /* call index unknown */
+ mm_iface_modem_voice_received_dtmf (MM_IFACE_MODEM_VOICE (self), 0, dtmf);
+ g_free (dtmf);
+}
+
+static void
+common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemHuawei *self,
+ gboolean enable)
+{
+ MMPortSerialAt *ports[2];
+ guint i;
+
+ ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
+ ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
+
+ for (i = 0; i < G_N_ELEMENTS (ports); i++) {
+ if (!ports[i])
+ continue;
+
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ self->priv->orig_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)orig_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ self->priv->conf_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)conf_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ self->priv->conn_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)conn_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ self->priv->cend_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)cend_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
+ self->priv->ddtmf_regex,
+ enable ? (MMPortSerialAtUnsolicitedMsgFn)ddtmf_received : NULL,
+ enable ? self : NULL,
+ NULL);
+ }
+}
+
+
+/*****************************************************************************/
/* Enabling unsolicited events (Voice interface) */
static gboolean
-modem_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self,
- GAsyncResult *res,
- GError **error)
+modem_voice_enable_unsolicited_events_finish (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
-own_voice_enable_unsolicited_events_ready (MMBaseModem *self,
+own_voice_enable_unsolicited_events_ready (MMBaseModem *self,
GAsyncResult *res,
- GTask *task)
+ GTask *task)
{
GError *error = NULL;
@@ -2967,8 +3143,8 @@ static const MMBaseModemAtCommand unsolicited_voice_enable_sequence[] = {
static void
parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self,
- GAsyncResult *res,
- GTask *task)
+ GAsyncResult *res,
+ GTask *task)
{
GError *error = NULL;
@@ -2991,9 +3167,9 @@ parent_voice_enable_unsolicited_events_ready (MMIfaceModemVoice *self,
}
static void
-modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
+modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GTask *task;
@@ -3010,17 +3186,17 @@ modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self,
/* Disabling unsolicited events (Voice interface) */
static gboolean
-modem_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self,
- GAsyncResult *res,
- GError **error)
+modem_voice_disable_unsolicited_events_finish (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
-own_voice_disable_unsolicited_events_ready (MMBaseModem *self,
+own_voice_disable_unsolicited_events_ready (MMBaseModem *self,
GAsyncResult *res,
- GTask *task)
+ GTask *task)
{
GError *error = NULL;
@@ -4039,10 +4215,6 @@ set_ignored_unsolicited_events_handlers (MMBroadbandModemHuawei *self)
port,
self->priv->eons_regex,
NULL, NULL, NULL);
- mm_port_serial_at_add_unsolicited_msg_handler (
- port,
- self->priv->orig_regex,
- NULL, NULL, NULL);
}
g_list_free_full (ports, g_object_unref);
@@ -4128,6 +4300,18 @@ mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self)
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->ndisstat_regex = g_regex_new ("\\r\\n(\\^NDISSTAT:.+)\\r+\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+
+ self->priv->orig_regex = g_regex_new ("\\r\\n\\^ORIG:\\s*(\\d+),\\s*(\\d+)\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ self->priv->conf_regex = g_regex_new ("\\r\\n\\^CONF:\\s*(\\d+)\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ self->priv->conn_regex = g_regex_new ("\\r\\n\\^CONN:\\s*(\\d+),\\s*(\\d+)\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ self->priv->cend_regex = g_regex_new ("\\r\\n\\^CEND:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*(\\d*))?\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+ self->priv->ddtmf_regex = g_regex_new ("\\r\\n\\^DDTMF:\\s*([0-9A-D\\*\\#])\\r\\n",
+ G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+
self->priv->boot_regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->connect_regex = g_regex_new ("\\r\\n\\^CONNECT .+\\r\\n",
@@ -4166,8 +4350,6 @@ mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self)
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->eons_regex = g_regex_new ("\\r\\n\\^EONS:.+\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- self->priv->orig_regex = g_regex_new ("\\r\\n\\^ORIG:.+\\r\\n",
- G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->ndisdup_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->rfswitch_support = FEATURE_SUPPORT_UNKNOWN;
@@ -4201,6 +4383,12 @@ finalize (GObject *object)
g_regex_unref (self->priv->mode_regex);
g_regex_unref (self->priv->dsflowrpt_regex);
g_regex_unref (self->priv->ndisstat_regex);
+ g_regex_unref (self->priv->orig_regex);
+ g_regex_unref (self->priv->conf_regex);
+ g_regex_unref (self->priv->conn_regex);
+ g_regex_unref (self->priv->cend_regex);
+ g_regex_unref (self->priv->ddtmf_regex);
+
g_regex_unref (self->priv->boot_regex);
g_regex_unref (self->priv->connect_regex);
g_regex_unref (self->priv->csnr_regex);
@@ -4220,7 +4408,6 @@ finalize (GObject *object)
g_regex_unref (self->priv->ltersrp_regex);
g_regex_unref (self->priv->cschannelinfo_regex);
g_regex_unref (self->priv->eons_regex);
- g_regex_unref (self->priv->orig_regex);
if (self->priv->syscfg_supported_modes)
g_array_unref (self->priv->syscfg_supported_modes);
diff --git a/plugins/huawei/mm-call-huawei.c b/plugins/huawei/mm-call-huawei.c
index 6c7a885d..c02c247a 100644
--- a/plugins/huawei/mm-call-huawei.c
+++ b/plugins/huawei/mm-call-huawei.c
@@ -41,12 +41,8 @@ enum {
static GParamSpec *properties[PROP_LAST];
struct _MMCallHuaweiPrivate {
- GRegex *conf_regex;
- GRegex *conn_regex;
- GRegex *cend_regex;
- GRegex *ddtmf_regex;
- guint audio_hz;
- guint audio_bits;
+ guint audio_hz;
+ guint audio_bits;
};
/*****************************************************************************/
@@ -165,166 +161,6 @@ setup_audio_channel (MMBaseCall *_self,
}
/*****************************************************************************/
-/* In-call unsolicited events */
-
-static void
-huawei_voice_ringback_tone (MMPortSerialAt *port,
- GMatchInfo *match_info,
- MMCallHuawei *self)
-{
- guint call_x = 0;
-
- if (!mm_get_uint_from_match_info (match_info, 1, &call_x))
- return;
-
- mm_dbg ("Ringback tone from call id '%u'", call_x);
-
- if (mm_gdbus_call_get_state (MM_GDBUS_CALL (self)) == MM_CALL_STATE_DIALING)
- mm_base_call_change_state (MM_BASE_CALL (self), MM_CALL_STATE_RINGING_OUT, MM_CALL_STATE_REASON_OUTGOING_STARTED);
-}
-
-static void
-huawei_voice_call_connection (MMPortSerialAt *port,
- GMatchInfo *match_info,
- MMCallHuawei *self)
-{
- guint call_x = 0;
- guint call_type = 0;
-
- if (!mm_get_uint_from_match_info (match_info, 1, &call_x))
- return;
-
- if (!mm_get_uint_from_match_info (match_info, 2, &call_type))
- return;
-
- mm_dbg ("Call id '%u' of type '%u' connected", call_x, call_type);
-
- if (mm_gdbus_call_get_state (MM_GDBUS_CALL (self)) == MM_CALL_STATE_RINGING_OUT)
- mm_base_call_change_state (MM_BASE_CALL (self), MM_CALL_STATE_ACTIVE, MM_CALL_STATE_REASON_ACCEPTED);
-}
-
-static void
-huawei_voice_call_end (MMPortSerialAt *port,
- GMatchInfo *match_info,
- MMCallHuawei *self)
-{
- guint call_x = 0;
- guint duration = 0;
- guint cc_cause = 0;
- guint end_status = 0;
-
- if (!mm_get_uint_from_match_info (match_info, 1, &call_x))
- return;
-
- if (!mm_get_uint_from_match_info (match_info, 2, &duration))
- return;
-
- if (!mm_get_uint_from_match_info (match_info, 3, &end_status))
- return;
-
- /* This is optional */
- mm_get_uint_from_match_info (match_info, 4, &cc_cause);
-
- mm_dbg ("Call id '%u' terminated with status '%u' and cause '%u'. Duration of call '%d'",
- call_x, end_status, cc_cause, duration);
-
- mm_base_call_change_state (MM_BASE_CALL (self), MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_TERMINATED);
-}
-
-static void
-huawei_voice_received_dtmf (MMPortSerialAt *port,
- GMatchInfo *match_info,
- MMCallHuawei *self)
-{
- gchar *key;
-
- key = g_match_info_fetch (match_info, 1);
-
- if (!key)
- return;
-
- mm_dbg ("Received DTMF '%s'", key);
- mm_base_call_received_dtmf (MM_BASE_CALL (self), key);
- g_free (key);
-}
-
-static gboolean
-common_setup_cleanup_unsolicited_events (MMCallHuawei *self,
- gboolean enable,
- GError **error)
-{
- MMBaseModem *modem = NULL;
- GList *ports, *l;
-
- if (G_UNLIKELY (!self->priv->conf_regex))
- self->priv->conf_regex = g_regex_new ("\\r\\n\\^CONF:\\s*(\\d+)\\r\\n",
- G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- if (G_UNLIKELY (!self->priv->conn_regex))
- self->priv->conn_regex = g_regex_new ("\\r\\n\\^CONN:\\s*(\\d+),(\\d+)\\r\\n",
- G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- if (G_UNLIKELY (!self->priv->cend_regex))
- self->priv->cend_regex = g_regex_new ("\\r\\n\\^CEND:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),?\\s*(\\d*)\\r\\n",
- G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
- if (G_UNLIKELY (!self->priv->ddtmf_regex))
- self->priv->ddtmf_regex = g_regex_new ("\\r\\n\\^DDTMF:\\s*([0-9A-D\\*\\#])\\r\\n",
- G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
-
- g_object_get (self,
- MM_BASE_CALL_MODEM, &modem,
- NULL);
-
- ports = mm_broadband_modem_huawei_get_at_port_list (MM_BROADBAND_MODEM_HUAWEI (modem));
-
- for (l = ports; l; l = g_list_next (l)) {
- MMPortSerialAt *port;
-
- port = MM_PORT_SERIAL_AT (l->data);
- mm_port_serial_at_add_unsolicited_msg_handler (
- port,
- self->priv->conf_regex,
- enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_voice_ringback_tone : NULL,
- enable ? self : NULL,
- NULL);
- mm_port_serial_at_add_unsolicited_msg_handler (
- port,
- self->priv->conn_regex,
- enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_voice_call_connection : NULL,
- enable ? self : NULL,
- NULL);
- mm_port_serial_at_add_unsolicited_msg_handler (
- port,
- self->priv->cend_regex,
- enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_voice_call_end : NULL,
- enable ? self : NULL,
- NULL);
- mm_port_serial_at_add_unsolicited_msg_handler (
- port,
- self->priv->ddtmf_regex,
- enable ? (MMPortSerialAtUnsolicitedMsgFn)huawei_voice_received_dtmf: NULL,
- enable ? self : NULL,
- NULL);
- }
-
- g_list_free_full (ports, g_object_unref);
- g_object_unref (modem);
- return TRUE;
-}
-
-static gboolean
-setup_unsolicited_events (MMBaseCall *self,
- GError **error)
-{
- return common_setup_cleanup_unsolicited_events (MM_CALL_HUAWEI (self), TRUE, error);
-}
-
-static gboolean
-cleanup_unsolicited_events (MMBaseCall *self,
- GError **error)
-{
- return common_setup_cleanup_unsolicited_events (MM_CALL_HUAWEI (self), FALSE, error);
-}
-
-/*****************************************************************************/
MMBaseCall *
mm_call_huawei_new (MMBaseModem *modem,
@@ -394,23 +230,6 @@ get_property (GObject *object,
}
static void
-finalize (GObject *object)
-{
- MMCallHuawei *self = MM_CALL_HUAWEI (object);
-
- if (self->priv->conf_regex)
- g_regex_unref (self->priv->conf_regex);
- if (self->priv->conn_regex)
- g_regex_unref (self->priv->conn_regex);
- if (self->priv->cend_regex)
- g_regex_unref (self->priv->cend_regex);
- if (self->priv->ddtmf_regex)
- g_regex_unref (self->priv->ddtmf_regex);
-
- G_OBJECT_CLASS (mm_call_huawei_parent_class)->finalize (object);
-}
-
-static void
mm_call_huawei_class_init (MMCallHuaweiClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -420,10 +239,7 @@ mm_call_huawei_class_init (MMCallHuaweiClass *klass)
object_class->get_property = get_property;
object_class->set_property = set_property;
- object_class->finalize = finalize;
- base_call_class->setup_unsolicited_events = setup_unsolicited_events;
- base_call_class->cleanup_unsolicited_events = cleanup_unsolicited_events;
base_call_class->setup_audio_channel = setup_audio_channel;
base_call_class->setup_audio_channel_finish = setup_audio_channel_finish;