huawei,call: handle in-call URCs in the call object itself
Instead of handling the URCs in the modem object and using the MMIfaceModem as a bridge to report the status read from the URC to a call obtained from the MMCallList... just handle the URCs in the call object itself.
This commit is contained in:

committed by
Dan Williams

parent
f71e120fb7
commit
fc0feee654
@@ -103,12 +103,6 @@ struct _MMBroadbandModemHuaweiPrivate {
|
||||
GRegex *dsflowrpt_regex;
|
||||
GRegex *ndisstat_regex;
|
||||
|
||||
/* Regex for voice call related notifications */
|
||||
GRegex *conf_regex;
|
||||
GRegex *conn_regex;
|
||||
GRegex *cend_regex;
|
||||
GRegex *ddtmf_regex;
|
||||
|
||||
/* Regex to ignore */
|
||||
GRegex *boot_regex;
|
||||
GRegex *connect_regex;
|
||||
@@ -151,8 +145,8 @@ struct _MMBroadbandModemHuaweiPrivate {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static GList *
|
||||
get_at_port_list (MMBroadbandModemHuawei *self)
|
||||
GList *
|
||||
mm_broadband_modem_huawei_get_at_port_list (MMBroadbandModemHuawei *self)
|
||||
{
|
||||
GList *out = NULL;
|
||||
MMPortSerialAt *port;
|
||||
@@ -1853,7 +1847,7 @@ set_3gpp_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
|
||||
{
|
||||
GList *ports, *l;
|
||||
|
||||
ports = get_at_port_list (self);
|
||||
ports = mm_broadband_modem_huawei_get_at_port_list (self);
|
||||
|
||||
/* Enable/disable unsolicited events in given port */
|
||||
for (l = ports; l; l = g_list_next (l)) {
|
||||
@@ -2517,7 +2511,7 @@ set_cdma_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
|
||||
{
|
||||
GList *ports, *l;
|
||||
|
||||
ports = get_at_port_list (self);
|
||||
ports = mm_broadband_modem_huawei_get_at_port_list (self);
|
||||
|
||||
/* Enable/disable unsolicited events in given port */
|
||||
for (l = ports; l; l = g_list_next (l)) {
|
||||
@@ -2862,200 +2856,6 @@ get_detailed_registration_state (MMIfaceModemCdma *self,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Setup/Cleanup unsolicited events (Voice interface) */
|
||||
|
||||
static void
|
||||
huawei_voice_ringback_tone (MMPortSerialAt *port,
|
||||
GMatchInfo *match_info,
|
||||
MMBroadbandModemHuawei *self)
|
||||
{
|
||||
guint call_x = 0;
|
||||
|
||||
if (!mm_get_uint_from_match_info (match_info, 1, &call_x))
|
||||
return;
|
||||
|
||||
mm_dbg ("[^CONF] Ringback tone from call id '%u'", call_x);
|
||||
|
||||
mm_iface_modem_voice_call_dialing_to_ringing (MM_IFACE_MODEM_VOICE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
huawei_voice_call_connection (MMPortSerialAt *port,
|
||||
GMatchInfo *match_info,
|
||||
MMBroadbandModemHuawei *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 ("[^CONN] Call id '%u' of type '%u' connected", call_x, call_type);
|
||||
|
||||
mm_iface_modem_voice_call_ringing_to_active (MM_IFACE_MODEM_VOICE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
huawei_voice_call_end (MMPortSerialAt *port,
|
||||
GMatchInfo *match_info,
|
||||
MMBroadbandModemHuawei *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 ("[^CEND] Call '%u' terminated with status '%u' and cause '%u'. Duration of call '%d'", call_x, end_status, cc_cause, duration);
|
||||
|
||||
mm_iface_modem_voice_network_hangup (MM_IFACE_MODEM_VOICE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
huawei_voice_received_dtmf (MMPortSerialAt *port,
|
||||
GMatchInfo *match_info,
|
||||
MMBroadbandModemHuawei *self)
|
||||
{
|
||||
gchar *key;
|
||||
|
||||
key = g_match_info_fetch (match_info, 1);
|
||||
|
||||
if (key) {
|
||||
mm_dbg ("[^DDTMF] Received DTMF '%s'", key);
|
||||
mm_iface_modem_voice_received_dtmf (MM_IFACE_MODEM_VOICE (self), key);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_voice_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
|
||||
gboolean enable)
|
||||
{
|
||||
GList *ports, *l;
|
||||
|
||||
ports = get_at_port_list (self);
|
||||
|
||||
/* Enable/disable unsolicited events in given port */
|
||||
for (l = ports; l; l = g_list_next (l)) {
|
||||
MMPortSerialAt *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);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
modem_voice_setup_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
parent_voice_setup_unsolicited_events_ready (MMIfaceModemVoice *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!iface_modem_voice_parent->setup_unsolicited_events_finish (self, res, &error))
|
||||
g_task_return_error (task, error);
|
||||
else {
|
||||
/* Our own setup now */
|
||||
set_voice_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), TRUE);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_setup_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
/* Chain up parent's setup */
|
||||
iface_modem_voice_parent->setup_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)parent_voice_setup_unsolicited_events_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
parent_voice_cleanup_unsolicited_events_ready (MMIfaceModemVoice *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!iface_modem_voice_parent->cleanup_unsolicited_events_finish (self, res, &error))
|
||||
g_task_return_error (task, error);
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
/* Our own cleanup first */
|
||||
set_voice_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE);
|
||||
|
||||
/* And now chain up parent's cleanup */
|
||||
iface_modem_voice_parent->cleanup_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)parent_voice_cleanup_unsolicited_events_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Enabling unsolicited events (Voice interface) */
|
||||
|
||||
@@ -3275,7 +3075,7 @@ enable_disable_unsolicited_rfswitch_event_handler (MMBroadbandModemHuawei *self,
|
||||
{
|
||||
GList *ports, *l;
|
||||
|
||||
ports = get_at_port_list (self);
|
||||
ports = mm_broadband_modem_huawei_get_at_port_list (self);
|
||||
|
||||
mm_dbg ("%s ^RFSWITCH unsolicited event handler",
|
||||
enable ? "Enable" : "Disable");
|
||||
@@ -4053,7 +3853,7 @@ set_ignored_unsolicited_events_handlers (MMBroadbandModemHuawei *self)
|
||||
{
|
||||
GList *ports, *l;
|
||||
|
||||
ports = get_at_port_list (self);
|
||||
ports = mm_broadband_modem_huawei_get_at_port_list (self);
|
||||
|
||||
/* Enable/disable unsolicited events in given port */
|
||||
for (l = ports; l; l = g_list_next (l)) {
|
||||
@@ -4162,7 +3962,6 @@ setup_ports (MMBroadbandModem *self)
|
||||
/* Now reset the unsolicited messages we'll handle when enabled */
|
||||
set_3gpp_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE);
|
||||
set_cdma_unsolicited_events_handlers (MM_BROADBAND_MODEM_HUAWEI (self), FALSE);
|
||||
set_voice_unsolicited_events_handlers(MM_BROADBAND_MODEM_HUAWEI (self), FALSE);
|
||||
|
||||
/* NMEA GPS monitoring */
|
||||
gps_data_port = mm_base_modem_peek_port_gps (MM_BASE_MODEM (self));
|
||||
@@ -4259,28 +4058,8 @@ 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);
|
||||
|
||||
/* Voice related regex
|
||||
* <CR><LF>^ORIG: <call_x>,<call_type><CR><LF> (ignored)
|
||||
* <CR><LF>^CONF: <call_x><CR><LF>
|
||||
* <CR><LF>^CONN: <call_x>,<call_type><CR><LF>
|
||||
* <CR><LF>^CEND: <call_x>,<duration>,<end_status>[,<cc_cause>]<CR><LF>
|
||||
*/
|
||||
self->priv->orig_regex = g_regex_new ("\\r\\n\\^ORIG:.+\\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+),(\\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);
|
||||
|
||||
/* Voice: receive DTMF regex
|
||||
* <CR><LF>^DDTMF: <key><CR><LF>
|
||||
* Key should be 0-9, A-D, *, #
|
||||
*/
|
||||
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->ndisdup_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
self->priv->rfswitch_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
@@ -4330,13 +4109,9 @@ finalize (GObject *object)
|
||||
g_regex_unref (self->priv->posend_regex);
|
||||
g_regex_unref (self->priv->ecclist_regex);
|
||||
g_regex_unref (self->priv->ltersrp_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->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);
|
||||
@@ -4451,10 +4226,6 @@ iface_modem_voice_init (MMIfaceModemVoice *iface)
|
||||
{
|
||||
iface_modem_voice_parent = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->setup_unsolicited_events = modem_voice_setup_unsolicited_events;
|
||||
iface->setup_unsolicited_events_finish = modem_voice_setup_cleanup_unsolicited_events_finish;
|
||||
iface->cleanup_unsolicited_events = modem_voice_cleanup_unsolicited_events;
|
||||
iface->cleanup_unsolicited_events_finish = modem_voice_setup_cleanup_unsolicited_events_finish;
|
||||
iface->enable_unsolicited_events = modem_voice_enable_unsolicited_events;
|
||||
iface->enable_unsolicited_events_finish = modem_voice_enable_unsolicited_events_finish;
|
||||
iface->disable_unsolicited_events = modem_voice_disable_unsolicited_events;
|
||||
|
@@ -50,5 +50,6 @@ MMBroadbandModemHuawei *mm_broadband_modem_huawei_new (const gchar *device,
|
||||
|
||||
MMPortSerialAt *mm_broadband_modem_huawei_peek_port_at_for_data (MMBroadbandModemHuawei *self,
|
||||
MMPort *port);
|
||||
GList *mm_broadband_modem_huawei_get_at_port_list (MMBroadbandModemHuawei *self);
|
||||
|
||||
#endif /* MM_BROADBAND_MODEM_HUAWEI_H */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -30,9 +30,11 @@
|
||||
|
||||
typedef struct _MMCallHuawei MMCallHuawei;
|
||||
typedef struct _MMCallHuaweiClass MMCallHuaweiClass;
|
||||
typedef struct _MMCallHuaweiPrivate MMCallHuaweiPrivate;
|
||||
|
||||
struct _MMCallHuawei {
|
||||
MMBaseCall parent;
|
||||
MMCallHuaweiPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MMCallHuaweiClass {
|
||||
|
@@ -109,99 +109,6 @@ mm_call_list_get_first_ringing_in_call (MMCallList *self)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMBaseCall *
|
||||
mm_call_list_get_first_ringing_out_call (MMCallList *self)
|
||||
{
|
||||
MMBaseCall *call = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = self->priv->list; l; l = g_list_next (l)) {
|
||||
MMCallState state;
|
||||
|
||||
g_object_get (MM_BASE_CALL (l->data),
|
||||
"state", &state,
|
||||
NULL);
|
||||
|
||||
if (state == MM_CALL_STATE_RINGING_IN ||
|
||||
state == MM_CALL_STATE_RINGING_OUT) {
|
||||
call = MM_BASE_CALL (l->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
MMBaseCall *
|
||||
mm_call_list_get_first_outgoing_dialing_call (MMCallList *self)
|
||||
{
|
||||
MMBaseCall *call = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = self->priv->list; l; l = g_list_next (l)) {
|
||||
MMCallState state;
|
||||
MMCallDirection direction;
|
||||
|
||||
g_object_get (MM_BASE_CALL (l->data),
|
||||
"state", &state,
|
||||
"direction", &direction,
|
||||
NULL);
|
||||
|
||||
if (direction == MM_CALL_DIRECTION_OUTGOING &&
|
||||
state == MM_CALL_STATE_DIALING) {
|
||||
call = MM_BASE_CALL (l->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
MMBaseCall *
|
||||
mm_call_list_get_first_non_terminated_call (MMCallList *self)
|
||||
{
|
||||
MMBaseCall *call = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = self->priv->list; l; l = g_list_next (l)) {
|
||||
MMCallState state;
|
||||
|
||||
g_object_get (MM_BASE_CALL (l->data),
|
||||
"state", &state,
|
||||
NULL);
|
||||
|
||||
if (state != MM_CALL_STATE_TERMINATED) {
|
||||
call = MM_BASE_CALL (l->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_call_list_send_dtmf_to_active_calls (MMCallList *self,
|
||||
const gchar *dtmf)
|
||||
{
|
||||
gboolean signaled = FALSE;
|
||||
GList *l;
|
||||
|
||||
for (l = self->priv->list; l; l = g_list_next (l)) {
|
||||
MMCallState state;
|
||||
|
||||
g_object_get (MM_BASE_CALL (l->data),
|
||||
"state", &state,
|
||||
NULL);
|
||||
|
||||
if (state == MM_CALL_STATE_ACTIVE) {
|
||||
signaled = TRUE;
|
||||
mm_base_call_received_dtmf (MM_BASE_CALL (l->data), dtmf);
|
||||
}
|
||||
}
|
||||
|
||||
return signaled;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint
|
||||
|
@@ -69,10 +69,5 @@ gboolean mm_call_list_delete_call (MMCallList *self,
|
||||
GError **error);
|
||||
|
||||
MMBaseCall *mm_call_list_get_first_ringing_in_call (MMCallList *self);
|
||||
MMBaseCall *mm_call_list_get_first_ringing_out_call (MMCallList *self);
|
||||
MMBaseCall *mm_call_list_get_first_outgoing_dialing_call (MMCallList *self);
|
||||
MMBaseCall *mm_call_list_get_first_non_terminated_call (MMCallList *self);
|
||||
gboolean mm_call_list_send_dtmf_to_active_calls (MMCallList *self,
|
||||
const gchar *dtmf);
|
||||
|
||||
#endif /* MM_CALL_LIST_H */
|
||||
|
@@ -123,99 +123,6 @@ mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoice *self,
|
||||
return updated;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_voice_call_dialing_to_ringing (MMIfaceModemVoice *self)
|
||||
{
|
||||
gboolean updated = FALSE;
|
||||
MMBaseCall *call = NULL;
|
||||
MMCallList *list = NULL;
|
||||
|
||||
g_object_get (MM_BASE_MODEM (self),
|
||||
MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
|
||||
NULL);
|
||||
|
||||
if (list) {
|
||||
call = mm_call_list_get_first_outgoing_dialing_call (list);
|
||||
|
||||
if (call) {
|
||||
mm_base_call_change_state (call, MM_CALL_STATE_RINGING_OUT, MM_CALL_STATE_REASON_OUTGOING_STARTED);
|
||||
updated = TRUE;
|
||||
} else {
|
||||
mm_dbg ("Outgoing dialing call does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_voice_call_ringing_to_active (MMIfaceModemVoice *self)
|
||||
{
|
||||
gboolean updated = FALSE;
|
||||
MMBaseCall *call = NULL;
|
||||
MMCallList *list = NULL;
|
||||
|
||||
g_object_get (MM_BASE_MODEM (self),
|
||||
MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
|
||||
NULL);
|
||||
|
||||
if (list) {
|
||||
call = mm_call_list_get_first_ringing_out_call (list);
|
||||
|
||||
if (call) {
|
||||
mm_base_call_change_state (call, MM_CALL_STATE_ACTIVE, MM_CALL_STATE_REASON_ACCEPTED);
|
||||
updated = TRUE;
|
||||
} else {
|
||||
mm_dbg ("Ringing call does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_voice_network_hangup (MMIfaceModemVoice *self)
|
||||
{
|
||||
gboolean updated = FALSE;
|
||||
MMBaseCall *call = NULL;
|
||||
MMCallList *list = NULL;
|
||||
|
||||
g_object_get (MM_BASE_MODEM (self),
|
||||
MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
|
||||
NULL);
|
||||
|
||||
if (list) {
|
||||
call = mm_call_list_get_first_non_terminated_call (list);
|
||||
|
||||
if (call) {
|
||||
mm_base_call_change_state (call, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_TERMINATED);
|
||||
updated = TRUE;
|
||||
} else {
|
||||
mm_dbg ("No call to hangup");
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_voice_received_dtmf (MMIfaceModemVoice *self,
|
||||
gchar *dtmf)
|
||||
{
|
||||
gboolean updated = FALSE;
|
||||
MMCallList *list = NULL;
|
||||
|
||||
g_object_get (MM_BASE_MODEM (self),
|
||||
MM_IFACE_MODEM_VOICE_CALL_LIST, &list,
|
||||
NULL);
|
||||
|
||||
if (list) {
|
||||
updated = mm_call_list_send_dtmf_to_active_calls (list, dtmf);
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
|
@@ -123,11 +123,6 @@ gboolean mm_iface_modem_voice_update_incoming_call_number (MMIfaceModemVoi
|
||||
gchar *number,
|
||||
guint type,
|
||||
guint validity);
|
||||
gboolean mm_iface_modem_voice_call_dialing_to_ringing (MMIfaceModemVoice *self);
|
||||
gboolean mm_iface_modem_voice_call_ringing_to_active (MMIfaceModemVoice *self);
|
||||
gboolean mm_iface_modem_voice_network_hangup (MMIfaceModemVoice *self);
|
||||
gboolean mm_iface_modem_voice_received_dtmf (MMIfaceModemVoice *self,
|
||||
gchar *dtmf);
|
||||
|
||||
/* Look for a new valid multipart reference */
|
||||
guint8 mm_iface_modem_voice_get_local_multipart_reference (MMIfaceModemVoice *self,
|
||||
|
Reference in New Issue
Block a user