summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Van Assche <me@dylanvanassche.be>2021-08-15 16:53:18 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-09-08 10:02:51 +0200
commit15d66197b369384c72675b71ce83758289a87dc4 (patch)
treea69cb18ffa7dc7dacd9fb5370512b73b1cba0f95
parent92ad38432c2a14d1ac310b58fde7d9336a45aff9 (diff)
downloadModemManager-15d66197b369384c72675b71ce83758289a87dc4.tar.gz
mm-broadband-modem-qmi: add AT URCs fall back for calls
Enable AT URCs for calls on top of QMI Voice indications for AT+QMI devices only. Some AT+QMI devices send unreliable QMI indications when the host is resuming. In such cases, AT URCs can be used as a fall back to make calls reliable. While AT+QMI devices relied before on AT commands to load call list information and handle AT URCs for async updates, this is now handled through QMI by forcefully reloading the call list instead of processing the AT URCs. This approach is disabled by default through the MM_IFACE_MODEM_VOICE_INDICATION_CALL_LIST_RELOAD_ENABLED property. This property is set to true in case of QMI modems.
-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 9d5082161..9a4c932fb 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 ab166cc9c..dad19948b 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 03aaeb0a4..3b918259e 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 fe2ae2432..f3164d64d 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,