aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-broadband-modem-qmi.c233
-rw-r--r--src/mm-broadband-modem.c57
-rw-r--r--src/mm-iface-modem-voice.c56
-rw-r--r--src/mm-iface-modem-voice.h15
4 files changed, 356 insertions, 5 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 9d508216..9a4c932f 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -65,6 +65,7 @@ static void shared_qmi_init (MMSharedQmi *iface);
static MMIfaceModemLocation *iface_modem_location_parent;
static MMIfaceModemMessaging *iface_modem_messaging_parent;
+static MMIfaceModemVoice *iface_modem_voice_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmi, mm_broadband_modem_qmi, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
@@ -8772,9 +8773,14 @@ modem_voice_check_support (MMIfaceModemVoice *self,
mm_obj_dbg (self, "Voice capabilities not supported");
g_task_return_boolean (task, FALSE);
} else {
- /* In case of QMI, we don't need polling as call list will be dynamically updated by All Call Status indication */
+ /*
+ * In case of QMI, we don't need polling as call list
+ * will be dynamically updated by All Call Status indication.
+ * If an AT URC is received, reload the call list through QMI.
+ */
g_object_set (self,
MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED, TRUE,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED, TRUE,
NULL);
mm_obj_dbg (self, "Voice capabilities supported");
g_task_return_boolean (task, TRUE);
@@ -8927,6 +8933,38 @@ supplementary_service_indication_cb (QmiClientVoice
/*****************************************************************************/
/* Setup/cleanup unsolicited events */
+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)) {
+ mm_obj_warn (self, "setting up parent voice unsolicited events failed: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (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)) {
+ mm_obj_warn (self, "cleaning up parent voice unsolicited events failed: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
static gboolean
common_voice_setup_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self,
GAsyncResult *res,
@@ -8952,7 +8990,7 @@ common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self,
task = g_task_new (self, NULL, callback, user_data);
if (setup == self->priv->all_call_status_unsolicited_events_setup) {
- mm_obj_dbg (self, "All Call Status unsolicited events already %s; skipping",
+ mm_obj_dbg (self, "voice unsolicited events already %s; skipping",
setup ? "setup" : "cleanup");
g_task_return_boolean (task, TRUE);
g_object_unref (task);
@@ -8961,16 +8999,37 @@ common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self,
self->priv->all_call_status_unsolicited_events_setup = setup;
if (setup) {
+ /* Connect QMI indications signals for calls */
g_assert (self->priv->all_call_status_indication_id == 0);
self->priv->all_call_status_indication_id =
g_signal_connect (client,
"all-call-status",
G_CALLBACK (all_call_status_indication_cb),
self);
+
+ /* Setup AT URCs as fall back for calls */
+ if (iface_modem_voice_parent->setup_unsolicited_events) {
+ iface_modem_voice_parent->setup_unsolicited_events (
+ MM_IFACE_MODEM_VOICE (self),
+ (GAsyncReadyCallback) parent_voice_setup_unsolicited_events_ready,
+ task);
+ return;
+ }
+
} else {
+ /* Disconnect QMI indications signals for calls */
g_assert (self->priv->all_call_status_indication_id != 0);
g_signal_handler_disconnect (client, self->priv->all_call_status_indication_id);
self->priv->all_call_status_indication_id = 0;
+
+ /* Cleanup AT URCs as fall back for calls */
+ if (iface_modem_voice_parent->cleanup_unsolicited_events) {
+ iface_modem_voice_parent->cleanup_unsolicited_events (
+ MM_IFACE_MODEM_VOICE (self),
+ (GAsyncReadyCallback) parent_voice_cleanup_unsolicited_events_ready,
+ task);
+ return;
+ }
}
g_task_return_boolean (task, TRUE);
@@ -9147,6 +9206,172 @@ modem_voice_cleanup_in_call_unsolicited_events (MMIfaceModemVoice *self,
}
/*****************************************************************************/
+/* Load full list of calls (Voice interface) */
+
+static gboolean
+modem_voice_load_call_list_finish (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GList **out_call_info_list,
+ GError **error)
+{
+ GList *call_info_list;
+ GError *inner_error = NULL;
+
+ call_info_list = g_task_propagate_pointer (G_TASK (res), &inner_error);
+ if (inner_error) {
+ g_assert (!call_info_list);
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ *out_call_info_list = call_info_list;
+ return TRUE;
+}
+
+static void
+process_get_all_call_info (QmiClientVoice *client,
+ QmiMessageVoiceGetAllCallInfoOutput *output,
+ GTask *task)
+{
+ GArray *qmi_remote_party_number_list = NULL;
+ GArray *qmi_call_information_list = NULL;
+ GList *call_info_list = NULL;
+ guint i;
+ guint j;
+
+ qmi_message_voice_get_all_call_info_output_get_remote_party_number (output, &qmi_remote_party_number_list, NULL);
+ qmi_message_voice_get_all_call_info_output_get_call_information (output, &qmi_call_information_list, NULL);
+
+ if (!qmi_remote_party_number_list || !qmi_call_information_list) {
+ mm_obj_dbg (client, "Ignoring Get All Call Status message. Remote party number or call information not available");
+ return;
+ }
+
+ for (i = 0; i < qmi_call_information_list->len; i++) {
+ QmiMessageVoiceGetAllCallInfoOutputCallInformationCall qmi_call_information;
+
+ qmi_call_information = g_array_index (qmi_call_information_list,
+ QmiMessageVoiceGetAllCallInfoOutputCallInformationCall,
+ i);
+ for (j = 0; j < qmi_remote_party_number_list->len; j++) {
+ QmiMessageVoiceGetAllCallInfoOutputRemotePartyNumberCall qmi_remote_party_number;
+
+ qmi_remote_party_number = g_array_index (qmi_remote_party_number_list,
+ QmiMessageVoiceGetAllCallInfoOutputRemotePartyNumberCall,
+ j);
+ if (qmi_call_information.id == qmi_remote_party_number.id) {
+ MMCallInfo *call_info;
+
+ call_info = g_slice_new0 (MMCallInfo);
+ call_info->index = qmi_call_information.id;
+ call_info->number = g_strdup (qmi_remote_party_number.type);
+
+ switch (qmi_call_information.state) {
+ case QMI_VOICE_CALL_STATE_UNKNOWN:
+ call_info->state = MM_CALL_STATE_UNKNOWN;
+ break;
+ case QMI_VOICE_CALL_STATE_ORIGINATION:
+ case QMI_VOICE_CALL_STATE_CC_IN_PROGRESS:
+ call_info->state = MM_CALL_STATE_DIALING;
+ break;
+ case QMI_VOICE_CALL_STATE_ALERTING:
+ call_info->state = MM_CALL_STATE_RINGING_OUT;
+ break;
+ case QMI_VOICE_CALL_STATE_SETUP:
+ case QMI_VOICE_CALL_STATE_INCOMING:
+ call_info->state = MM_CALL_STATE_RINGING_IN;
+ break;
+ case QMI_VOICE_CALL_STATE_CONVERSATION:
+ call_info->state = MM_CALL_STATE_ACTIVE;
+ break;
+ case QMI_VOICE_CALL_STATE_HOLD:
+ call_info->state = MM_CALL_STATE_HELD;
+ break;
+ case QMI_VOICE_CALL_STATE_WAITING:
+ call_info->state = MM_CALL_STATE_WAITING;
+ break;
+ case QMI_VOICE_CALL_STATE_DISCONNECTING:
+ case QMI_VOICE_CALL_STATE_END:
+ call_info->state = MM_CALL_STATE_TERMINATED;
+ break;
+ default:
+ call_info->state = MM_CALL_STATE_UNKNOWN;
+ break;
+ }
+
+ switch (qmi_call_information.direction) {
+ case QMI_VOICE_CALL_DIRECTION_UNKNOWN:
+ call_info->direction = MM_CALL_DIRECTION_UNKNOWN;
+ break;
+ case QMI_VOICE_CALL_DIRECTION_MO:
+ call_info->direction = MM_CALL_DIRECTION_OUTGOING;
+ break;
+ case QMI_VOICE_CALL_DIRECTION_MT:
+ call_info->direction = MM_CALL_DIRECTION_INCOMING;
+ break;
+ default:
+ call_info->direction = MM_CALL_DIRECTION_UNKNOWN;
+ break;
+ }
+
+ call_info_list = g_list_append (call_info_list, call_info);
+ }
+ }
+ }
+
+ g_task_return_pointer (task, call_info_list, (GDestroyNotify)mm_3gpp_call_info_list_free);
+}
+
+static void
+modem_voice_load_call_list_ready (QmiClientVoice *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autoptr(QmiMessageVoiceGetAllCallInfoOutput) output = NULL;
+ GError *error = NULL;
+
+ /* Parse QMI message */
+ output = qmi_client_voice_get_all_call_info_finish (client, res, &error);
+
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_task_return_error (task, error);
+ } else if (!qmi_message_voice_get_all_call_info_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't process Get All Call Info action: ");
+ g_task_return_error (task, error);
+ } else {
+ process_get_all_call_info (client, output, task);
+ }
+
+ /* We're done, call list already returned */
+ g_object_unref (task);
+}
+
+static void
+modem_voice_load_call_list (MMIfaceModemVoice *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ QmiClient *client = NULL;
+ GTask *task;
+
+ if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_VOICE, &client,
+ callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ /* Update call list through QMI instead of AT+CLCC */
+ qmi_client_voice_get_all_call_info (QMI_CLIENT_VOICE (client),
+ NULL, /* no input data */
+ 10,
+ NULL,
+ (GAsyncReadyCallback) modem_voice_load_call_list_ready,
+ task);
+}
+
+/*****************************************************************************/
/* Create CALL (Voice interface) */
static MMBaseCall *
@@ -12098,6 +12323,8 @@ iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface)
static void
iface_modem_voice_init (MMIfaceModemVoice *iface)
{
+ iface_modem_voice_parent = g_type_interface_peek_parent (iface);
+
iface->check_support = modem_voice_check_support;
iface->check_support_finish = modem_voice_check_support_finish;
iface->setup_unsolicited_events = modem_voice_setup_unsolicited_events;
@@ -12115,6 +12342,8 @@ iface_modem_voice_init (MMIfaceModemVoice *iface)
iface->cleanup_in_call_unsolicited_events_finish = common_voice_setup_cleanup_in_call_unsolicited_events_finish;
iface->create_call = modem_voice_create_call;
+ iface->load_call_list = modem_voice_load_call_list;
+ iface->load_call_list_finish = modem_voice_load_call_list_finish;
iface->hold_and_accept = modem_voice_hold_and_accept;
iface->hold_and_accept_finish = modem_voice_hold_and_accept_finish;
iface->hangup_and_accept = modem_voice_hangup_and_accept;
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index ab166cc9..dad19948 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -129,6 +129,7 @@ enum {
PROP_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED,
PROP_MODEM_PERIODIC_ACCESS_TECH_CHECK_DISABLED,
PROP_MODEM_PERIODIC_CALL_LIST_CHECK_DISABLED,
+ PROP_MODEM_INDICATION_CALL_LIST_RELOAD_ENABLED,
PROP_MODEM_CARRIER_CONFIG_MAPPING,
PROP_MODEM_FIRMWARE_IGNORE_CARRIER,
PROP_FLOW_CONTROL,
@@ -246,6 +247,7 @@ struct _MMBroadbandModemPrivate {
GObject *modem_voice_dbus_skeleton;
MMCallList *modem_voice_call_list;
gboolean periodic_call_list_check_disabled;
+ gboolean indication_call_list_reload_enabled;
gboolean clcc_supported;
/*<--- Modem Time interface --->*/
@@ -7852,6 +7854,17 @@ ccwa_received (MMPortSerialAt *port,
MMBroadbandModem *self)
{
MMCallInfo call_info;
+ gboolean indication_call_list_reload_enabled = FALSE;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED, &indication_call_list_reload_enabled,
+ NULL);
+
+ if (indication_call_list_reload_enabled) {
+ mm_obj_dbg (self, "call waiting, refreshing call list");
+ mm_iface_modem_voice_reload_all_calls (MM_IFACE_MODEM_VOICE (self), NULL, NULL);
+ return;
+ }
call_info.index = 0;
call_info.direction = MM_CALL_DIRECTION_INCOMING;
@@ -7870,6 +7883,17 @@ ring_received (MMPortSerialAt *port,
MMBroadbandModem *self)
{
MMCallInfo call_info;
+ gboolean indication_call_list_reload_enabled = FALSE;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED, &indication_call_list_reload_enabled,
+ NULL);
+
+ if (indication_call_list_reload_enabled) {
+ mm_obj_dbg (self, "ringing, refreshing call list");
+ mm_iface_modem_voice_reload_all_calls (MM_IFACE_MODEM_VOICE (self), NULL, NULL);
+ return;
+ }
call_info.index = 0;
call_info.direction = MM_CALL_DIRECTION_INCOMING;
@@ -7887,6 +7911,17 @@ cring_received (MMPortSerialAt *port,
{
MMCallInfo call_info;
gchar *str;
+ gboolean indication_call_list_reload_enabled = FALSE;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED, &indication_call_list_reload_enabled,
+ NULL);
+
+ if (indication_call_list_reload_enabled) {
+ mm_obj_dbg (self, "ringing, refreshing call list");
+ mm_iface_modem_voice_reload_all_calls (MM_IFACE_MODEM_VOICE (self), NULL, NULL);
+ return;
+ }
/* We could have "VOICE" or "DATA". Now consider only "VOICE" */
str = mm_get_string_unquoted_from_match_info (info, 1);
@@ -7907,6 +7942,17 @@ clip_received (MMPortSerialAt *port,
MMBroadbandModem *self)
{
MMCallInfo call_info;
+ gboolean indication_call_list_reload_enabled = FALSE;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED, &indication_call_list_reload_enabled,
+ NULL);
+
+ if (indication_call_list_reload_enabled) {
+ mm_obj_dbg (self, "ringing, refreshing call list");
+ mm_iface_modem_voice_reload_all_calls (MM_IFACE_MODEM_VOICE (self), NULL, NULL);
+ return;
+ }
call_info.index = 0;
call_info.direction = MM_CALL_DIRECTION_INCOMING;
@@ -12942,6 +12988,9 @@ set_property (GObject *object,
case PROP_MODEM_PERIODIC_CALL_LIST_CHECK_DISABLED:
self->priv->periodic_call_list_check_disabled = g_value_get_boolean (value);
break;
+ case PROP_MODEM_INDICATION_CALL_LIST_RELOAD_ENABLED:
+ self->priv->indication_call_list_reload_enabled = g_value_get_boolean (value);
+ break;
case PROP_MODEM_CARRIER_CONFIG_MAPPING:
self->priv->carrier_config_mapping = g_value_dup_string (value);
break;
@@ -13086,6 +13135,9 @@ get_property (GObject *object,
case PROP_MODEM_PERIODIC_CALL_LIST_CHECK_DISABLED:
g_value_set_boolean (value, self->priv->periodic_call_list_check_disabled);
break;
+ case PROP_MODEM_INDICATION_CALL_LIST_RELOAD_ENABLED:
+ g_value_set_boolean (value, self->priv->indication_call_list_reload_enabled);
+ break;
case PROP_MODEM_CARRIER_CONFIG_MAPPING:
g_value_set_string (value, self->priv->carrier_config_mapping);
break;
@@ -13131,6 +13183,7 @@ mm_broadband_modem_init (MMBroadbandModem *self)
self->priv->periodic_signal_check_disabled = FALSE;
self->priv->periodic_access_tech_check_disabled = FALSE;
self->priv->periodic_call_list_check_disabled = FALSE;
+ self->priv->indication_call_list_reload_enabled = FALSE;
self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_NONE;
self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_NONE;
self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_NONE;
@@ -13721,6 +13774,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED);
g_object_class_override_property (object_class,
+ PROP_MODEM_INDICATION_CALL_LIST_RELOAD_ENABLED,
+ MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED);
+
+ g_object_class_override_property (object_class,
PROP_MODEM_CARRIER_CONFIG_MAPPING,
MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING);
diff --git a/src/mm-iface-modem-voice.c b/src/mm-iface-modem-voice.c
index 03aaeb0a..3b918259 100644
--- a/src/mm-iface-modem-voice.c
+++ b/src/mm-iface-modem-voice.c
@@ -2503,6 +2503,54 @@ setup_call_list_polling (MMCallList *call_list,
}
/*****************************************************************************/
+/* Call list reload */
+
+gboolean
+mm_iface_modem_voice_reload_all_calls_finish (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+reload_all_calls_ready (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GList *call_info_list = NULL;
+ GError *error = NULL;
+
+ g_assert (MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->load_call_list_finish);
+ if (!MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->load_call_list_finish (self, res, &call_info_list, &error)) {
+ mm_obj_warn (self, "couldn't reload call list: %s", error->message);
+
+ g_task_return_error (task, error);
+ } else {
+ /* Always report the list even if NULL (it would mean no ongoing calls) */
+ mm_iface_modem_voice_report_all_calls (self, call_info_list);
+ mm_3gpp_call_info_list_free (call_info_list);
+
+ g_task_return_boolean (task, TRUE);
+ }
+
+ g_object_unref (task);
+}
+
+void
+mm_iface_modem_voice_reload_all_calls (MMIfaceModemVoice *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ MM_IFACE_MODEM_VOICE_GET_INTERFACE (self)->load_call_list (self,
+ reload_all_calls_ready,
+ task);
+}
+
+/*****************************************************************************/
static void
update_call_list (MmGdbusModemVoice *skeleton,
@@ -3134,6 +3182,14 @@ iface_modem_voice_init (gpointer g_iface)
FALSE,
G_PARAM_READWRITE));
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_boolean (MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED,
+ "Reload call list on call update",
+ "Ignore call updates and forcefully reload all calls.",
+ FALSE,
+ G_PARAM_READWRITE));
+
initialized = TRUE;
}
diff --git a/src/mm-iface-modem-voice.h b/src/mm-iface-modem-voice.h
index fe2ae243..f3164d64 100644
--- a/src/mm-iface-modem-voice.h
+++ b/src/mm-iface-modem-voice.h
@@ -30,9 +30,10 @@
#define MM_IS_IFACE_MODEM_VOICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_IFACE_MODEM_VOICE))
#define MM_IFACE_MODEM_VOICE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_IFACE_MODEM_VOICE, MMIfaceModemVoice))
-#define MM_IFACE_MODEM_VOICE_DBUS_SKELETON "iface-modem-voice-dbus-skeleton"
-#define MM_IFACE_MODEM_VOICE_CALL_LIST "iface-modem-voice-call-list"
-#define MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED "iface-modem-voice-periodic-call-list-check-disabled"
+#define MM_IFACE_MODEM_VOICE_DBUS_SKELETON "iface-modem-voice-dbus-skeleton"
+#define MM_IFACE_MODEM_VOICE_CALL_LIST "iface-modem-voice-call-list"
+#define MM_IFACE_MODEM_VOICE_PERIODIC_CALL_LIST_CHECK_DISABLED "iface-modem-voice-periodic-call-list-check-disabled"
+#define MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED "iface-modem-voice-indication-call-list-reload-enabled"
typedef struct _MMIfaceModemVoice MMIfaceModemVoice;
@@ -239,6 +240,14 @@ void mm_iface_modem_voice_report_call (MMIfaceModemVoice *self,
void mm_iface_modem_voice_report_all_calls (MMIfaceModemVoice *self,
GList *call_info_list);
+/* Full reload of call list (async) */
+void mm_iface_modem_voice_reload_all_calls (MMIfaceModemVoice *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_iface_modem_voice_reload_all_calls_finish (MMIfaceModemVoice *self,
+ GAsyncResult *res,
+ GError **error);
+
/* Report an incoming DTMF received */
void mm_iface_modem_voice_received_dtmf (MMIfaceModemVoice *self,
guint index,