diff options
-rw-r--r-- | plugins/huawei/mm-broadband-modem-huawei.c | 233 | ||||
-rw-r--r-- | plugins/huawei/mm-call-huawei.c | 188 |
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; |