/src/mm-broadband-modem-qmi.c
C | 7658 lines | 6171 code | 1080 blank | 407 comment | 636 complexity | 5f40a7f99878fcded4c8cbb7d20245ec MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details:
- *
- * Copyright (C) 2012 Google Inc.
- */
- #include <config.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <ctype.h>
- #include "mm-broadband-modem-qmi.h"
- #include "ModemManager.h"
- #include "mm-log.h"
- #include "mm-errors-types.h"
- #include "mm-modem-helpers.h"
- #include "mm-modem-helpers-qmi.h"
- #include "mm-iface-modem.h"
- #include "mm-iface-modem-3gpp.h"
- #include "mm-iface-modem-3gpp-ussd.h"
- #include "mm-iface-modem-cdma.h"
- #include "mm-iface-modem-messaging.h"
- #include "mm-iface-modem-location.h"
- #include "mm-iface-modem-firmware.h"
- #include "mm-sim-qmi.h"
- #include "mm-bearer-qmi.h"
- #include "mm-sms-qmi.h"
- static void iface_modem_init (MMIfaceModem *iface);
- static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
- static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface);
- static void iface_modem_cdma_init (MMIfaceModemCdma *iface);
- static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
- static void iface_modem_location_init (MMIfaceModemLocation *iface);
- static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
- static MMIfaceModemLocation *iface_modem_location_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)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_USSD, iface_modem_3gpp_ussd_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init))
- struct _MMBroadbandModemQmiPrivate {
- /* Cached device IDs, retrieved by the modem interface when loading device
- * IDs, and used afterwards in the 3GPP and CDMA interfaces. */
- gchar *imei;
- gchar *meid;
- gchar *esn;
- /* Cached supported frequency bands; in order to handle ANY */
- GArray *supported_bands;
- /* 3GPP and CDMA share unsolicited events setup/enable/disable/cleanup */
- gboolean unsolicited_events_enabled;
- gboolean unsolicited_events_setup;
- guint event_report_indication_id;
- #if defined WITH_NEWEST_QMI_COMMANDS
- guint signal_info_indication_id;
- #endif /* WITH_NEWEST_QMI_COMMANDS */
- /* 3GPP/CDMA registration helpers */
- gchar *current_operator_id;
- gchar *current_operator_description;
- gboolean unsolicited_registration_events_enabled;
- gboolean unsolicited_registration_events_setup;
- guint serving_system_indication_id;
- #if defined WITH_NEWEST_QMI_COMMANDS
- guint system_info_indication_id;
- #endif /* WITH_NEWEST_QMI_COMMANDS */
- /* Messaging helpers */
- gboolean messaging_unsolicited_events_enabled;
- gboolean messaging_unsolicited_events_setup;
- guint messaging_event_report_indication_id;
- /* Location helpers */
- MMModemLocationSource enabled_sources;
- guint location_event_report_indication_id;
- /* Firmware helpers */
- GList *firmware_list;
- MMFirmwareProperties *current_firmware;
- };
- /*****************************************************************************/
- static QmiClient *
- peek_qmi_client (MMBroadbandModemQmi *self,
- QmiService service,
- GError **error)
- {
- MMQmiPort *port;
- QmiClient *client;
- port = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self));
- if (!port) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Couldn't peek QMI port");
- return NULL;
- }
- client = mm_qmi_port_peek_client (port,
- service,
- MM_QMI_PORT_FLAG_DEFAULT);
- if (!client)
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Couldn't peek client for service '%s'",
- qmi_service_get_string (service));
- return client;
- }
- static gboolean
- ensure_qmi_client (MMBroadbandModemQmi *self,
- QmiService service,
- QmiClient **o_client,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GError *error = NULL;
- QmiClient *client;
- client = peek_qmi_client (self, service, &error);
- if (!client) {
- g_simple_async_report_take_gerror_in_idle (
- G_OBJECT (self),
- callback,
- user_data,
- error);
- return FALSE;
- }
- *o_client = client;
- return TRUE;
- }
- /*****************************************************************************/
- /* Create Bearer (Modem interface) */
- static MMBearer *
- modem_create_bearer_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- MMBearer *bearer;
- bearer = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
- mm_dbg ("New bearer created at DBus path '%s'", mm_bearer_get_path (bearer));
- return g_object_ref (bearer);
- }
- static void
- modem_create_bearer (MMIfaceModem *self,
- MMBearerProperties *properties,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- MMBearer *bearer;
- GSimpleAsyncResult *result;
- /* Set a new ref to the bearer object as result */
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_create_bearer);
- /* We just create a MMBearerQmi */
- mm_dbg ("Creating QMI bearer in QMI modem");
- bearer = mm_bearer_qmi_new (MM_BROADBAND_MODEM_QMI (self),
- properties);
- g_simple_async_result_set_op_res_gpointer (result, bearer, g_object_unref);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- }
- /*****************************************************************************/
- /* Current Capabilities loading (Modem interface) */
- typedef struct {
- MMBroadbandModemQmi *self;
- QmiClientNas *nas_client;
- QmiClientDms *dms_client;
- GSimpleAsyncResult *result;
- gboolean run_get_system_selection_preference;
- gboolean run_get_technology_preference;
- gboolean run_get_capabilities;
- MMModemCapability capabilities;
- } LoadCurrentCapabilitiesContext;
- static MMModemCapability
- modem_load_current_capabilities_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- MMModemCapability caps;
- gchar *caps_str;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return MM_MODEM_CAPABILITY_NONE;
- caps = ((MMModemCapability) GPOINTER_TO_UINT (
- g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res))));
- caps_str = mm_modem_capability_build_string_from_mask (caps);
- mm_dbg ("loaded current capabilities: %s", caps_str);
- g_free (caps_str);
- return caps;
- }
- static void
- load_current_capabilities_context_complete_and_free (LoadCurrentCapabilitiesContext *ctx)
- {
- g_simple_async_result_complete_in_idle (ctx->result);
- g_object_unref (ctx->result);
- g_object_unref (ctx->nas_client);
- g_object_unref (ctx->dms_client);
- g_object_unref (ctx->self);
- g_free (ctx);
- }
- static void load_current_capabilities_context_step (LoadCurrentCapabilitiesContext *ctx);
- static void
- load_current_capabilities_get_capabilities_ready (QmiClientDms *client,
- GAsyncResult *res,
- LoadCurrentCapabilitiesContext *ctx)
- {
- QmiMessageDmsGetCapabilitiesOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_capabilities_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (ctx->result, error);
- } else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get Capabilities: ");
- g_simple_async_result_take_error (ctx->result, error);
- } else {
- guint i;
- guint mask = MM_MODEM_CAPABILITY_NONE;
- GArray *radio_interface_list;
- qmi_message_dms_get_capabilities_output_get_info (
- output,
- NULL, /* info_max_tx_channel_rate */
- NULL, /* info_max_rx_channel_rate */
- NULL, /* info_data_service_capability */
- NULL, /* info_sim_capability */
- &radio_interface_list,
- NULL);
- for (i = 0; i < radio_interface_list->len; i++) {
- mask |= mm_modem_capability_from_qmi_radio_interface (g_array_index (radio_interface_list,
- QmiDmsRadioInterface,
- i));
- }
- /* Final capabilities are the intersection between the Technology
- * Preference (ie, allowed modes) or SSP and the device's capabilities.
- * If the Technology Preference was "auto" or unknown we just fall back
- * to the Get Capabilities response.
- */
- if (ctx->capabilities == MM_MODEM_CAPABILITY_NONE)
- ctx->capabilities = mask;
- else
- ctx->capabilities &= mask;
- }
- if (output)
- qmi_message_dms_get_capabilities_output_unref (output);
- g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (ctx->capabilities), NULL);
- load_current_capabilities_context_complete_and_free (ctx);
- }
- static void
- load_current_capabilities_get_technology_preference_ready (QmiClientNas *client,
- GAsyncResult *res,
- LoadCurrentCapabilitiesContext *ctx)
- {
- QmiMessageNasGetTechnologyPreferenceOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_nas_get_technology_preference_finish (client, res, &error);
- if (!output) {
- mm_dbg ("QMI operation failed: %s", error->message);
- g_error_free (error);
- } else if (!qmi_message_nas_get_technology_preference_output_get_result (output, &error)) {
- mm_dbg ("Couldn't get technology preference: %s", error->message);
- g_error_free (error);
- } else {
- QmiNasRadioTechnologyPreference preference_mask;
- qmi_message_nas_get_technology_preference_output_get_active (
- output,
- &preference_mask,
- NULL, /* duration */
- NULL);
- if (preference_mask != QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO) {
- gchar *str;
- str = qmi_nas_radio_technology_preference_build_string_from_mask (preference_mask);
- ctx->capabilities = mm_modem_capability_from_qmi_radio_technology_preference (preference_mask);
- mm_dbg ("%s modes reported in technology preference: '%s'",
- ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid",
- str);
- g_free (str);
- }
- }
- if (output)
- qmi_message_nas_get_technology_preference_output_unref (output);
- /* Mark as TP already run */
- ctx->run_get_technology_preference = FALSE;
- /* Get DMS Capabilities too */
- load_current_capabilities_context_step (ctx);
- }
- static void
- load_current_capabilities_get_system_selection_preference_ready (QmiClientNas *client,
- GAsyncResult *res,
- LoadCurrentCapabilitiesContext *ctx)
- {
- QmiMessageNasGetSystemSelectionPreferenceOutput *output = NULL;
- GError *error = NULL;
- QmiNasRatModePreference mode_preference_mask = 0;
- output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error);
- if (!output) {
- mm_dbg ("QMI operation failed: %s", error->message);
- g_error_free (error);
- } else if (!qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) {
- mm_dbg ("Couldn't get system selection preference: %s", error->message);
- g_error_free (error);
- } else if (!qmi_message_nas_get_system_selection_preference_output_get_mode_preference (
- output,
- &mode_preference_mask,
- NULL)) {
- QmiNasBandPreference band_preference_mask;
- mm_dbg ("Mode preference not reported in system selection preference");
- if (qmi_message_nas_get_system_selection_preference_output_get_band_preference (
- output,
- &band_preference_mask,
- NULL)) {
- gchar *str;
- str = qmi_nas_band_preference_build_string_from_mask (band_preference_mask);
- ctx->capabilities = mm_modem_capability_from_qmi_band_preference (band_preference_mask);
- mm_dbg ("%s bands reported in system selection preference: '%s'",
- ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid",
- str);
- g_free (str);
- /* Just the presence of the LTE band preference tells us it's LTE */
- if (qmi_message_nas_get_system_selection_preference_output_get_lte_band_preference (
- output,
- NULL,
- NULL)) {
- mm_dbg ("LTE band preference found");
- ctx->capabilities |= MM_MODEM_CAPABILITY_LTE;
- }
- } else
- mm_dbg ("Band preference not reported in system selection preference");
- } else {
- gchar *str;
- str = qmi_nas_rat_mode_preference_build_string_from_mask (mode_preference_mask);
- ctx->capabilities = mm_modem_capability_from_qmi_rat_mode_preference (mode_preference_mask);
- mm_dbg ("%s capabilities reported in system selection preference: '%s'",
- ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid",
- str);
- g_free (str);
- }
- if (output)
- qmi_message_nas_get_system_selection_preference_output_unref (output);
- /* Mark as SSP already run */
- ctx->run_get_system_selection_preference = FALSE;
- /* If we got some value, cache it and go on to DMS Get Capabilities */
- if (ctx->capabilities != MM_MODEM_CAPABILITY_NONE)
- ctx->run_get_technology_preference = FALSE;
- load_current_capabilities_context_step (ctx);
- }
- static void
- load_current_capabilities_context_step (LoadCurrentCapabilitiesContext *ctx)
- {
- if (ctx->run_get_system_selection_preference) {
- qmi_client_nas_get_system_selection_preference (
- ctx->nas_client,
- NULL, /* no input */
- 5,
- NULL, /* cancellable */
- (GAsyncReadyCallback)load_current_capabilities_get_system_selection_preference_ready,
- ctx);
- return;
- }
- if (ctx->run_get_technology_preference) {
- qmi_client_nas_get_technology_preference (
- ctx->nas_client,
- NULL, /* no input */
- 5,
- NULL, /* cancellable */
- (GAsyncReadyCallback)load_current_capabilities_get_technology_preference_ready,
- ctx);
- return;
- }
- if (ctx->run_get_capabilities) {
- qmi_client_dms_get_capabilities (
- ctx->dms_client,
- NULL, /* no input */
- 5,
- NULL, /* cancellable */
- (GAsyncReadyCallback)load_current_capabilities_get_capabilities_ready,
- ctx);
- return;
- }
- g_simple_async_result_set_error (
- ctx->result,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Loading current capabilities is not supported by this device");
- load_current_capabilities_context_complete_and_free (ctx);
- }
- static void
- modem_load_current_capabilities (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- LoadCurrentCapabilitiesContext *ctx;
- QmiClient *nas_client = NULL;
- QmiClient *dms_client = NULL;
- /* Best way to get current capabilities (ie, enabled radios) is
- * Get System Selection Preference's "mode preference" TLV, but that's
- * only supported by NAS >= 1.1, meaning older Gobi devices don't
- * implement it.
- *
- * On these devices, the DMS Get Capabilities call appears to report
- * currently enabled radios, but this does not take the user's
- * technology preference into account.
- *
- * So in the absence of System Selection Preference, we check the
- * Technology Preference first, and if that is "AUTO" we fall back to
- * Get Capabilities.
- */
- mm_dbg ("loading current capabilities...");
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_NAS, &nas_client,
- callback, user_data))
- return;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &dms_client,
- callback, user_data))
- return;
- ctx = g_new0 (LoadCurrentCapabilitiesContext, 1);
- ctx->self = g_object_ref (self);
- ctx->nas_client = g_object_ref (nas_client);
- ctx->dms_client = g_object_ref (dms_client);
- ctx->result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_current_capabilities);
- ctx->capabilities = MM_MODEM_CAPABILITY_NONE;
- /* System selection preference introduced in NAS 1.1 */
- ctx->run_get_system_selection_preference = qmi_client_check_version (nas_client, 1, 1);
- ctx->run_get_technology_preference = TRUE;
- ctx->run_get_capabilities = TRUE;
- load_current_capabilities_context_step (ctx);
- }
- /*****************************************************************************/
- /* Modem Capabilities loading (Modem interface) */
- static MMModemCapability
- modem_load_modem_capabilities_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- MMModemCapability caps;
- gchar *caps_str;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return MM_MODEM_CAPABILITY_NONE;
- caps = ((MMModemCapability) GPOINTER_TO_UINT (
- g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res))));
- caps_str = mm_modem_capability_build_string_from_mask (caps);
- mm_dbg ("loaded modem capabilities: %s", caps_str);
- g_free (caps_str);
- return caps;
- }
- static void
- dms_get_capabilities_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetCapabilitiesOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_capabilities_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get modem capabilities: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- guint i;
- guint mask = MM_MODEM_CAPABILITY_NONE;
- GArray *radio_interface_list;
- qmi_message_dms_get_capabilities_output_get_info (
- output,
- NULL, /* info_max_tx_channel_rate */
- NULL, /* info_max_rx_channel_rate */
- NULL, /* info_data_service_capability */
- NULL, /* info_sim_capability */
- &radio_interface_list,
- NULL);
- for (i = 0; i < radio_interface_list->len; i++) {
- mask |= mm_modem_capability_from_qmi_radio_interface (g_array_index (radio_interface_list,
- QmiDmsRadioInterface,
- i));
- }
- g_simple_async_result_set_op_res_gpointer (simple,
- GUINT_TO_POINTER (mask),
- NULL);
- }
- if (output)
- qmi_message_dms_get_capabilities_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_modem_capabilities (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_modem_capabilities);
- mm_dbg ("loading modem capabilities...");
- qmi_client_dms_get_capabilities (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_capabilities_ready,
- result);
- }
- /*****************************************************************************/
- /* Manufacturer loading (Modem interface) */
- static gchar *
- modem_load_manufacturer_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar *manufacturer;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- manufacturer = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded manufacturer: %s", manufacturer);
- return manufacturer;
- }
- static void
- dms_get_manufacturer_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetManufacturerOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_manufacturer_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_manufacturer_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get Manufacturer: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- const gchar *str;
- qmi_message_dms_get_manufacturer_output_get_manufacturer (output, &str, NULL);
- g_simple_async_result_set_op_res_gpointer (simple,
- g_strdup (str),
- (GDestroyNotify)g_free);
- }
- if (output)
- qmi_message_dms_get_manufacturer_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_manufacturer (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_manufacturer);
- mm_dbg ("loading manufacturer...");
- qmi_client_dms_get_manufacturer (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_manufacturer_ready,
- result);
- }
- /*****************************************************************************/
- /* Model loading (Modem interface) */
- static gchar *
- modem_load_model_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar *model;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- model = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded model: %s", model);
- return model;
- }
- static void
- dms_get_model_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetModelOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_model_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_model_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get Model: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- const gchar *str;
- qmi_message_dms_get_model_output_get_model (output, &str, NULL);
- g_simple_async_result_set_op_res_gpointer (simple,
- g_strdup (str),
- (GDestroyNotify)g_free);
- }
- if (output)
- qmi_message_dms_get_model_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_model (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_model);
- mm_dbg ("loading model...");
- qmi_client_dms_get_model (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_model_ready,
- result);
- }
- /*****************************************************************************/
- /* Revision loading (Modem interface) */
- static gchar *
- modem_load_revision_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar *revision;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- revision = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded revision: %s", revision);
- return revision;
- }
- static void
- dms_get_revision_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetRevisionOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_revision_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_revision_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get Revision: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- const gchar *str;
- qmi_message_dms_get_revision_output_get_revision (output, &str, NULL);
- g_simple_async_result_set_op_res_gpointer (simple,
- g_strdup (str),
- (GDestroyNotify)g_free);
- }
- if (output)
- qmi_message_dms_get_revision_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_revision (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_revision);
- mm_dbg ("loading revision...");
- qmi_client_dms_get_revision (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_revision_ready,
- result);
- }
- /*****************************************************************************/
- /* Equipment Identifier loading (Modem interface) */
- typedef struct {
- MMBroadbandModemQmi *self;
- QmiClient *client;
- GSimpleAsyncResult *result;
- } LoadEquipmentIdentifierContext;
- static void
- load_equipment_identifier_context_complete_and_free (LoadEquipmentIdentifierContext *ctx)
- {
- g_simple_async_result_complete (ctx->result);
- g_object_unref (ctx->result);
- g_object_unref (ctx->client);
- g_object_unref (ctx->self);
- g_free (ctx);
- }
- static gchar *
- modem_load_equipment_identifier_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar *equipment_identifier;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- equipment_identifier = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded equipment identifier: %s", equipment_identifier);
- return equipment_identifier;
- }
- static void
- dms_get_ids_ready (QmiClientDms *client,
- GAsyncResult *res,
- LoadEquipmentIdentifierContext *ctx)
- {
- QmiMessageDmsGetIdsOutput *output = NULL;
- GError *error = NULL;
- const gchar *str;
- output = qmi_client_dms_get_ids_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (ctx->result, error);
- load_equipment_identifier_context_complete_and_free (ctx);
- return;
- }
- if (!qmi_message_dms_get_ids_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get IDs: ");
- g_simple_async_result_take_error (ctx->result, error);
- qmi_message_dms_get_ids_output_unref (output);
- load_equipment_identifier_context_complete_and_free (ctx);
- return;
- }
- /* In order:
- * If we have a IMEI, use it...
- * Otherwise, if we have a ESN, use it...
- * Otherwise, if we have a MEID, use it...
- * Otherwise, 'unknown'
- */
- if (qmi_message_dms_get_ids_output_get_imei (output, &str, NULL) &&
- str[0] != '\0' && str[0] != '0') {
- g_free (ctx->self->priv->imei);
- ctx->self->priv->imei = g_strdup (str);
- }
- if (qmi_message_dms_get_ids_output_get_esn (output, &str, NULL) &&
- str[0] != '\0' && str[0] != '0') {
- g_free (ctx->self->priv->esn);
- ctx->self->priv->esn = g_strdup (str);
- }
- if (qmi_message_dms_get_ids_output_get_meid (output, &str, NULL) &&
- str[0] != '\0' && str[0] != '0') {
- g_free (ctx->self->priv->meid);
- ctx->self->priv->meid = g_strdup (str);
- }
- if (ctx->self->priv->imei)
- str = ctx->self->priv->imei;
- else if (ctx->self->priv->esn)
- str = ctx->self->priv->esn;
- else if (ctx->self->priv->meid)
- str = ctx->self->priv->meid;
- else
- str = "unknown";
- g_simple_async_result_set_op_res_gpointer (ctx->result,
- g_strdup (str),
- (GDestroyNotify)g_free);
- qmi_message_dms_get_ids_output_unref (output);
- load_equipment_identifier_context_complete_and_free (ctx);
- }
- static void
- modem_load_equipment_identifier (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- LoadEquipmentIdentifierContext *ctx;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- ctx = g_new (LoadEquipmentIdentifierContext, 1);
- ctx->self = g_object_ref (self);
- ctx->client = g_object_ref (client);
- ctx->result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_equipment_identifier);
- mm_dbg ("loading equipment identifier...");
- qmi_client_dms_get_ids (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_ids_ready,
- ctx);
- }
- /*****************************************************************************/
- /* Device identifier loading (Modem interface) */
- static gchar *
- modem_load_device_identifier_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar *device_identifier;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- device_identifier = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded device identifier: %s", device_identifier);
- return device_identifier;
- }
- static void
- modem_load_device_identifier (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- gchar *device_identifier;
- mm_dbg ("loading device identifier...");
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_device_identifier);
- /* Just use dummy ATI/ATI1 replies, all the other internal info should be
- * enough for uniqueness */
- device_identifier = mm_broadband_modem_create_device_identifier (MM_BROADBAND_MODEM (self), "", "");
- g_simple_async_result_set_op_res_gpointer (result,
- device_identifier,
- (GDestroyNotify)g_free);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- }
- /*****************************************************************************/
- /* Own Numbers loading (Modem interface) */
- static GStrv
- modem_load_own_numbers_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- gchar **own_numbers;
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- own_numbers = g_new0 (gchar *, 2);
- own_numbers[0] = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
- mm_dbg ("loaded own numbers: %s", own_numbers[0]);
- return own_numbers;
- }
- static void
- dms_get_msisdn_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetMsisdnOutput *output = NULL;
- GError *error = NULL;
- output = qmi_client_dms_get_msisdn_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_msisdn_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get MSISDN: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- const gchar *str = NULL;
- qmi_message_dms_get_msisdn_output_get_msisdn (output, &str, NULL);
- g_simple_async_result_set_op_res_gpointer (simple,
- g_strdup (str),
- (GDestroyNotify)g_free);
- }
- if (output)
- qmi_message_dms_get_msisdn_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_own_numbers (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_own_numbers);
- mm_dbg ("loading own numbers...");
- qmi_client_dms_get_msisdn (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_get_msisdn_ready,
- result);
- }
- /*****************************************************************************/
- /* Check if unlock required (Modem interface) */
- static MMModemLock
- modem_load_unlock_required_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return MM_MODEM_LOCK_UNKNOWN;
- return (MMModemLock) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
- }
- static void
- dms_uim_get_pin_status_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsUimGetPinStatusOutput *output;
- GError *error = NULL;
- output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
- /* When no SIM inserted, an internal error when checking PIN status
- * needs to be fatal so that we mark the modem unusable. */
- if (g_error_matches (error,
- QMI_PROTOCOL_ERROR,
- QMI_PROTOCOL_ERROR_INTERNAL)) {
- g_simple_async_result_set_error (simple,
- MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE,
- "Couldn't get PIN status: %s",
- error->message);
- g_error_free (error);
- } else {
- g_prefix_error (&error, "Couldn't get PIN status: ");
- g_simple_async_result_take_error (simple, error);
- }
- } else {
- MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
- QmiDmsUimPinStatus current_status;
- if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status (
- output,
- ¤t_status,
- NULL, /* verify_retries_left */
- NULL, /* unblock_retries_left */
- NULL))
- lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, TRUE);
- if (lock == MM_MODEM_LOCK_NONE &&
- qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
- output,
- ¤t_status,
- NULL, /* verify_retries_left */
- NULL, /* unblock_retries_left */
- NULL))
- lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, FALSE);
- g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (lock), NULL);
- }
- if (output)
- qmi_message_dms_uim_get_pin_status_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_unlock_required (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_unlock_required);
- /* CDMA-only modems don't need this */
- if (mm_iface_modem_is_cdma_only (self)) {
- mm_dbg ("Skipping unlock check in CDMA-only modem...");
- g_simple_async_result_set_op_res_gpointer (result,
- GUINT_TO_POINTER (MM_MODEM_LOCK_NONE),
- NULL);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- return;
- }
- mm_dbg ("loading unlock required...");
- qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)dms_uim_get_pin_status_ready,
- result);
- }
- /*****************************************************************************/
- /* Check if unlock retries (Modem interface) */
- static MMUnlockRetries *
- modem_load_unlock_retries_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
- {
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- return MM_UNLOCK_RETRIES (g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))));
- }
- static void
- retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsUimGetPinStatusOutput *output;
- GError *error = NULL;
- output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get unlock retries: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- MMUnlockRetries *retries;
- guint8 verify_retries_left;
- guint8 unblock_retries_left;
- retries = mm_unlock_retries_new ();
- if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status (
- output,
- NULL, /* current_status */
- &verify_retries_left,
- &unblock_retries_left,
- NULL)) {
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, verify_retries_left);
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, unblock_retries_left);
- }
- if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
- output,
- NULL, /* current_status */
- &verify_retries_left,
- &unblock_retries_left,
- NULL)) {
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, verify_retries_left);
- mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, unblock_retries_left);
- }
- g_simple_async_result_set_op_res_gpointer (simple, retries, g_object_unref);
- }
- if (output)
- qmi_message_dms_uim_get_pin_status_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
- }
- static void
- modem_load_unlock_retries (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
- {
- GSimpleAsyncResult *result;
- QmiClient *client = NULL;
- if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_unlock_retries);
- mm_dbg ("loading unlock retries...");
- qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client),
- NULL,
- 5,
- NULL,
- (GAsyncReadyCallback)retry_count_dms_uim_get_pin_status_ready,
- result);
- }
- /*****************************************************************************/
- /* Load supported bands (Modem interface) */
- static GArray *
- modem_load_supported_bands_finish (MMIfaceModem *_self,
- GAsyncResult *res,
- GError **error)
- {
- MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
- if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return NULL;
- if (self->priv->supported_bands)
- g_array_unref (self->priv->supported_bands);
- /* Cache the supported bands value */
- self->priv->supported_bands = g_array_ref (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
- return g_array_ref (self->priv->supported_bands);
- }
- static void
- dms_get_band_capabilities_ready (QmiClientDms *client,
- GAsyncResult *res,
- GSimpleAsyncResult *simple)
- {
- QmiMessageDmsGetBandCapabilitiesOutput *output;
- GError *error = NULL;
- output = qmi_client_dms_get_band_capabilities_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
- } else if (!qmi_message_dms_get_band_capabilities_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get band capabilities: ");
- g_simple_async_result_take_error (simple, error);
- } else {
- GArray *mm_bands;
- QmiDmsBandCapability qmi_bands = 0;
- QmiDmsLteBandCapability qmi_lte_bands = 0;
- qmi_message_dms_get_band_capabilities_output_get_band_capability (
- output,
- &qmi_bands,
- NULL);
- qmi_message_dms_get_band_capabilities_output_get_lte_band_capability (
- output,
- &qmi_lte_bands,
- NULL);
- mm_bands = mm_modem_bands_from_qmi_band_capabilities (qmi_bands, qmi_lte_bands);
- if (mm_bands->len == 0) {
- g_array_unref (mm_bands);
- g_simple_async_result_set_error (simple,
- MM_CORE_ERROR,
- MM_CORE_ERROR…
Large files files are truncated, but you can click here to view the full file