aboutsummaryrefslogtreecommitdiff
path: root/plugins/huawei/mm-call-huawei.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/huawei/mm-call-huawei.c')
-rw-r--r--plugins/huawei/mm-call-huawei.c196
1 files changed, 194 insertions, 2 deletions
diff --git a/plugins/huawei/mm-call-huawei.c b/plugins/huawei/mm-call-huawei.c
index 84738207..c20e091e 100644
--- a/plugins/huawei/mm-call-huawei.c
+++ b/plugins/huawei/mm-call-huawei.c
@@ -26,10 +26,178 @@
#include "mm-log.h"
#include "mm-base-modem-at.h"
+#include "mm-broadband-modem-huawei.h"
#include "mm-call-huawei.h"
G_DEFINE_TYPE (MMCallHuawei, mm_call_huawei, MM_TYPE_BASE_CALL)
+struct _MMCallHuaweiPrivate {
+ GRegex *conf_regex;
+ GRegex *conn_regex;
+ GRegex *cend_regex;
+ GRegex *ddtmf_regex;
+};
+
+/*****************************************************************************/
+/* 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 *
@@ -45,13 +213,37 @@ mm_call_huawei_new (MMBaseModem *modem)
static void
mm_call_huawei_init (MMCallHuawei *self)
{
+ /* Initialize private data */
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CALL_HUAWEI, MMCallHuaweiPrivate);
+}
+
+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);
MMBaseCallClass *base_call_class = MM_BASE_CALL_CLASS (klass);
- base_call_class->setup_unsolicited_events = NULL;
- base_call_class->cleanup_unsolicited_events = NULL;
+ g_type_class_add_private (object_class, sizeof (MMCallHuaweiPrivate));
+
+ object_class->finalize = finalize;
+
+ base_call_class->setup_unsolicited_events = setup_unsolicited_events;
+ base_call_class->cleanup_unsolicited_events = cleanup_unsolicited_events;
}