modem-qmi: implement voice unsolicited events and process all_call_status indication
This commit is contained in:
committed by
Aleksander Morgado
parent
a0ef2f403f
commit
ea645522fa
@@ -148,6 +148,11 @@ struct _MMBroadbandModemQmiPrivate {
|
||||
gboolean ussd_unsolicited_events_setup;
|
||||
GTask *pending_ussd_action;
|
||||
|
||||
/* Voice helpers */
|
||||
guint all_call_status_indication_id;
|
||||
gboolean all_call_status_unsolicited_events_enabled;
|
||||
gboolean all_call_status_unsolicited_events_setup;
|
||||
|
||||
/* Firmware helpers */
|
||||
gboolean firmware_list_preloaded;
|
||||
GList *firmware_list;
|
||||
@@ -8457,9 +8462,9 @@ common_3gpp_ussd_enable_disable_unsolicited_events_finish (MMIfaceModem3gppUssd
|
||||
}
|
||||
|
||||
static void
|
||||
voice_indication_register_ready (QmiClientVoice *client,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
ussd_indication_register_ready (QmiClientVoice *client,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
g_autoptr(QmiMessageVoiceIndicationRegisterOutput) output = NULL;
|
||||
GError *error = NULL;
|
||||
@@ -8508,7 +8513,7 @@ common_3gpp_ussd_enable_disable_unsolicited_events (MMBroadbandModemQmi *self,
|
||||
input,
|
||||
10,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) voice_indication_register_ready,
|
||||
(GAsyncReadyCallback) ussd_indication_register_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
@@ -8760,6 +8765,256 @@ modem_voice_check_support (MMIfaceModemVoice *self,
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* All Call Status indications */
|
||||
|
||||
static void
|
||||
all_call_status_indication_cb (QmiClientVoice *client,
|
||||
QmiIndicationVoiceAllCallStatusOutput *output,
|
||||
MMBroadbandModemQmi *self)
|
||||
{
|
||||
GArray *qmi_remote_party_number_list = NULL;
|
||||
GArray *qmi_call_information_list = NULL;
|
||||
GList *call_info_list = NULL;
|
||||
guint i;
|
||||
guint j;
|
||||
|
||||
qmi_indication_voice_all_call_status_output_get_remote_party_number (output, &qmi_remote_party_number_list, NULL);
|
||||
qmi_indication_voice_all_call_status_output_get_call_information (output, &qmi_call_information_list, NULL);
|
||||
|
||||
if (!qmi_remote_party_number_list || !qmi_call_information_list) {
|
||||
mm_obj_dbg (self, "Ignoring All Call Status indication. Remote party number or call information not available");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < qmi_call_information_list->len; i++) {
|
||||
QmiIndicationVoiceAllCallStatusOutputCallInformationCall qmi_call_information;
|
||||
|
||||
qmi_call_information = g_array_index (qmi_call_information_list,
|
||||
QmiIndicationVoiceAllCallStatusOutputCallInformationCall,
|
||||
i);
|
||||
for (j = 0; j < qmi_remote_party_number_list->len; j++) {
|
||||
QmiIndicationVoiceAllCallStatusOutputRemotePartyNumberCall qmi_remote_party_number;
|
||||
|
||||
qmi_remote_party_number = g_array_index (qmi_remote_party_number_list,
|
||||
QmiIndicationVoiceAllCallStatusOutputRemotePartyNumberCall,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mm_iface_modem_voice_report_all_calls (MM_IFACE_MODEM_VOICE (self), call_info_list);
|
||||
mm_3gpp_call_info_list_free (call_info_list);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Setup/cleanup unsolicited events */
|
||||
|
||||
static gboolean
|
||||
common_voice_setup_cleanup_unsolicited_events_finish (MMIfaceModemVoice *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
common_voice_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self,
|
||||
gboolean setup,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
QmiClient *client = NULL;
|
||||
|
||||
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);
|
||||
|
||||
if (setup == self->priv->all_call_status_unsolicited_events_setup) {
|
||||
mm_obj_dbg (self, "All Call Status unsolicited events already %s; skipping",
|
||||
setup ? "setup" : "cleanup");
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
self->priv->all_call_status_unsolicited_events_setup = setup;
|
||||
|
||||
if (setup) {
|
||||
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);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_setup_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), TRUE, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_cleanup_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
common_voice_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), FALSE, callback, user_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Enable/disable unsolicited events */
|
||||
|
||||
static gboolean
|
||||
common_voice_enable_disable_unsolicited_events_finish (MMIfaceModemVoice *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
call_indication_register_ready (QmiClientVoice *client,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
g_autoptr(QmiMessageVoiceIndicationRegisterOutput) output = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
output = qmi_client_voice_indication_register_finish (client, res, &error);
|
||||
if (!output) {
|
||||
g_prefix_error (&error, "QMI operation failed: ");
|
||||
g_task_return_error (task, error);
|
||||
} else if (!qmi_message_voice_indication_register_output_get_result (output, &error)) {
|
||||
g_prefix_error (&error, "Couldn't register voice call indications: ");
|
||||
g_task_return_error (task, error);
|
||||
} else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
common_voice_enable_disable_unsolicited_events (MMBroadbandModemQmi *self,
|
||||
gboolean enable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(QmiMessageVoiceIndicationRegisterInput) input = NULL;
|
||||
GTask *task;
|
||||
QmiClient *client;
|
||||
|
||||
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);
|
||||
|
||||
if (enable == self->priv->all_call_status_unsolicited_events_enabled) {
|
||||
mm_obj_dbg (self, "All Call Status unsolicited events already %s; skipping",
|
||||
enable ? "enabled" : "disabled");
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
self->priv->all_call_status_unsolicited_events_enabled = enable;
|
||||
|
||||
input = qmi_message_voice_indication_register_input_new ();
|
||||
qmi_message_voice_indication_register_input_set_call_notification_events (input, enable, NULL);
|
||||
qmi_client_voice_indication_register (QMI_CLIENT_VOICE (client),
|
||||
input,
|
||||
10,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) call_indication_register_ready,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_enable_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
common_voice_enable_disable_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), TRUE, callback, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
common_voice_enable_disable_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), FALSE, callback, user_data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Create CALL (Voice interface) */
|
||||
|
||||
@@ -11316,6 +11571,14 @@ iface_modem_voice_init (MMIfaceModemVoice *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;
|
||||
iface->setup_unsolicited_events_finish = common_voice_setup_cleanup_unsolicited_events_finish;
|
||||
iface->enable_unsolicited_events = modem_voice_enable_unsolicited_events;
|
||||
iface->enable_unsolicited_events_finish = common_voice_enable_disable_unsolicited_events_finish;
|
||||
iface->disable_unsolicited_events = modem_voice_disable_unsolicited_events;
|
||||
iface->disable_unsolicited_events_finish = common_voice_enable_disable_unsolicited_events_finish;
|
||||
iface->cleanup_unsolicited_events = modem_voice_cleanup_unsolicited_events;
|
||||
iface->cleanup_unsolicited_events_finish = common_voice_setup_cleanup_unsolicited_events_finish;
|
||||
iface->create_call = modem_voice_create_call;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user