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.
This commit is contained in:
Aleksander Morgado
2019-07-11 23:21:00 +02:00
parent ee2f3fb904
commit 12bad162e3
2 changed files with 212 additions and 209 deletions
+210 -23
View File
@@ -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;
@@ -2933,21 +2939,191 @@ modem_voice_check_support (MMIfaceModemVoice *self,
task);
}
/*****************************************************************************/
/* 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);
+2 -186
View File
@@ -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;
};
/*****************************************************************************/
@@ -164,166 +160,6 @@ setup_audio_channel (MMBaseCall *_self,
task);
}
/*****************************************************************************/
/* 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 *
@@ -393,23 +229,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)
{
@@ -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;