diff options
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 269dca6d..3a91a285 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -44,6 +44,7 @@ #include "mm-iface-modem-firmware.h" #include "mm-iface-modem-sar.h" #include "mm-iface-modem-signal.h" +#include "mm-iface-modem-time.h" #include "mm-iface-modem-oma.h" #include "mm-shared-qmi.h" #include "mm-sim-qmi.h" @@ -67,12 +68,14 @@ static void iface_modem_oma_init (MMIfaceModemOmaInterface static void iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface); static void iface_modem_sar_init (MMIfaceModemSarInterface *iface); static void iface_modem_signal_init (MMIfaceModemSignalInterface *iface); +static void iface_modem_time_init (MMIfaceModemTimeInterface *iface); static void shared_qmi_init (MMSharedQmi *iface); static MMIfaceModemCellBroadcastInterface *iface_modem_cell_broadcast_parent; static MMIfaceModemLocationInterface *iface_modem_location_parent; static MMIfaceModemMessagingInterface *iface_modem_messaging_parent; static MMIfaceModemVoiceInterface *iface_modem_voice_parent; +static MMIfaceModemTimeInterface *iface_modem_time_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) @@ -86,6 +89,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmi, mm_broadband_modem_qmi, MM_TYPE_BRO G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SAR, iface_modem_sar_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_OMA, iface_modem_oma_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QMI, shared_qmi_init)) @@ -190,6 +194,9 @@ struct _MMBroadbandModemQmiPrivate { /* Packet service state helpers when using NAS System Info and DSD * (not applicable when using NAS Serving System) */ gboolean dsd_supported; + + /* NAS doesn't support Get Network Time; chain up to parent */ + gboolean nas_time_use_parent; }; /*****************************************************************************/ @@ -9367,6 +9374,326 @@ enable_location_gathering (MMIfaceModemLocation *self, } /*****************************************************************************/ +/* Load network time (Time interface) */ + +static gchar * +modem_time_load_network_time_finish (MMIfaceModemTime *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +get_time_ready (QmiClientNas *client, + GAsyncResult *res, + GTask *task) +{ + g_autoptr(QmiMessageNasGetNetworkTimeOutput) output = NULL; + GError *error = NULL; + guint16 year = 0; + guint8 month = 0; + guint8 day = 0; + guint8 hour = 0; + guint8 minute = 0; + guint8 second = 0; + gint8 tz_offset = 0; + + output = qmi_client_nas_get_network_time_finish (client, res, &error); + if (!output) { + g_prefix_error (&error, "QMI operation failed: "); + g_task_return_error (task, error); + } else if (!qmi_message_nas_get_network_time_output_get_result (output, &error)) { + g_prefix_error (&error, "Couldn't get network time: "); + g_task_return_error (task, error); + } else if (!qmi_message_nas_get_network_time_output_get_3gpp_time (output, + &year, + &month, + &day, + &hour, + &minute, + &second, + NULL, + &tz_offset, + NULL, + NULL, + &error)) { + g_prefix_error (&error, "Couldn't get 3GPP network time info: "); + g_task_return_error (task, error); + } else { + gchar *iso8601p; + + /* Return ISO-8601 format date/time string */ + iso8601p = mm_new_iso8601_time (year, month, day, hour, + minute, second, + TRUE, (tz_offset * 15), + &error); + if (iso8601p) + g_task_return_pointer (task, iso8601p, g_free); + else + g_task_return_error (task, error); + } + + g_object_unref (task); +} + +static void +parent_load_network_time_ready (MMIfaceModemTime *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + gchar *iso8601p; + + iso8601p = iface_modem_time_parent->load_network_time_finish (self, res, &error); + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, iso8601p, g_free); + + g_object_unref (task); +} + +static void +modem_time_load_network_time (MMIfaceModemTime *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); + QmiClient *client; + GTask *task; + GError *error = NULL; + + task = g_task_new (self, NULL, callback, user_data); + + if (self->priv->nas_time_use_parent) { + iface_modem_time_parent->load_network_time ( + MM_IFACE_MODEM_TIME (self), + (GAsyncReadyCallback) parent_load_network_time_ready, + task); + return; + } + + client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), + QMI_SERVICE_NAS, + MM_PORT_QMI_FLAG_DEFAULT, + &error); + if (!client) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + qmi_client_nas_get_network_time (QMI_CLIENT_NAS (client), + NULL, + 10, + NULL, + (GAsyncReadyCallback)get_time_ready, + task); +} + +/*****************************************************************************/ +/* Load network timezone (Time interface) */ + +static MMNetworkTimezone * +modem_time_load_network_timezone_finish (MMIfaceModemTime *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +get_timezone_ready (QmiClientNas *client, + GAsyncResult *res, + GTask *task) +{ + g_autoptr(QmiMessageNasGetNetworkTimeOutput) output = NULL; + GError *error = NULL; + gint8 tz_offset = 0; + + output = qmi_client_nas_get_network_time_finish (client, res, &error); + if (!output) { + g_prefix_error (&error, "QMI operation failed: "); + g_task_return_error (task, error); + } else if (!qmi_message_nas_get_network_time_output_get_result (output, &error)) { + g_prefix_error (&error, "Couldn't get network time: "); + g_task_return_error (task, error); + } else if (!qmi_message_nas_get_network_time_output_get_3gpp_time (output, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &tz_offset, + NULL, + NULL, + &error)) { + g_prefix_error (&error, "Couldn't get 3GPP network time info: "); + g_task_return_error (task, error); + } else { + MMNetworkTimezone *tz; + + tz = mm_network_timezone_new (); + mm_network_timezone_set_offset (tz, tz_offset * 15); + g_task_return_pointer (task, tz, g_object_unref); + } + + g_object_unref (task); +} + +static void +parent_load_network_timezone_ready (MMIfaceModemTime *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + MMNetworkTimezone *tz; + + tz = iface_modem_time_parent->load_network_timezone_finish (self, res, &error); + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, tz, g_object_unref); + + g_object_unref (task); +} + +static void +modem_time_load_network_timezone (MMIfaceModemTime *_self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); + QmiClient *client; + GTask *task; + GError *error = NULL; + + task = g_task_new (self, NULL, callback, user_data); + + if (self->priv->nas_time_use_parent) { + iface_modem_time_parent->load_network_timezone ( + MM_IFACE_MODEM_TIME (self), + (GAsyncReadyCallback) parent_load_network_timezone_ready, + task); + return; + } + + client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), + QMI_SERVICE_NAS, + MM_PORT_QMI_FLAG_DEFAULT, + &error); + if (!client) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + qmi_client_nas_get_network_time (QMI_CLIENT_NAS (client), + NULL, + 10, + NULL, + (GAsyncReadyCallback)get_timezone_ready, + task); +} + +/*****************************************************************************/ +/* Check support (Time interface) */ + +static gboolean +modem_time_check_support_finish (MMIfaceModemTime *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +parent_time_check_support_ready (MMIfaceModemTime *_self, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); + GError *error = NULL; + gboolean supported; + + self->priv->nas_time_use_parent = TRUE; + + supported = iface_modem_time_parent->check_support_finish (_self, res, &error); + if (error) + g_task_return_error (task, error); + else + g_task_return_boolean (task, supported); + + g_object_unref (task); +} + +static void +check_time_support_ready (QmiClientNas *client, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self; + g_autoptr(QmiMessageNasGetNetworkTimeOutput) output = NULL; + + self = g_task_get_source_object (task); + + output = qmi_client_nas_get_network_time_finish (client, res, NULL); + if (!output || !qmi_message_nas_get_network_time_output_get_result (output, NULL)) { + /* Try parent implementation */ + if (iface_modem_time_parent->check_support && + iface_modem_time_parent->load_network_time && + iface_modem_time_parent->load_network_time_finish && + iface_modem_time_parent->load_network_timezone && + iface_modem_time_parent->load_network_timezone_finish) { + iface_modem_time_parent->check_support ( + MM_IFACE_MODEM_TIME (self), + (GAsyncReadyCallback) parent_time_check_support_ready, + task); + return; + } + + /* Otherwise unsupported */ + g_task_return_boolean (task, FALSE); + } else { + g_task_return_boolean (task, TRUE); + } + + g_object_unref (task); +} + +static void +modem_time_check_support (MMIfaceModemTime *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + QmiClient *client; + GTask *task; + GError *error = NULL; + + task = g_task_new (self, NULL, callback, user_data); + + client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), + QMI_SERVICE_NAS, + MM_PORT_QMI_FLAG_DEFAULT, + &error); + if (!client) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + qmi_client_nas_get_network_time (QMI_CLIENT_NAS (client), + NULL, + 10, + NULL, + (GAsyncReadyCallback)check_time_support_ready, + task); +} + +/*****************************************************************************/ /* Check support (OMA interface) */ static gboolean @@ -15058,6 +15385,19 @@ iface_modem_sar_init (MMIfaceModemSarInterface *iface) } static void +iface_modem_time_init (MMIfaceModemTimeInterface *iface) +{ + iface_modem_time_parent = g_type_interface_peek_parent (iface); + + iface->check_support = modem_time_check_support; + iface->check_support_finish = modem_time_check_support_finish; + iface->load_network_time = modem_time_load_network_time; + iface->load_network_time_finish = modem_time_load_network_time_finish; + iface->load_network_timezone = modem_time_load_network_timezone; + iface->load_network_timezone_finish = modem_time_load_network_timezone_finish; +} + +static void iface_modem_signal_init (MMIfaceModemSignalInterface *iface) { iface->check_support = signal_check_support; |