diff options
Diffstat (limited to 'plugins/telit/mm-shared-telit.c')
-rw-r--r-- | plugins/telit/mm-shared-telit.c | 795 |
1 files changed, 0 insertions, 795 deletions
diff --git a/plugins/telit/mm-shared-telit.c b/plugins/telit/mm-shared-telit.c deleted file mode 100644 index 09c122bb..00000000 --- a/plugins/telit/mm-shared-telit.c +++ /dev/null @@ -1,795 +0,0 @@ -/* -*- 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) 2019 Daniele Palmas <dnlplm@gmail.com> - */ - -#include <config.h> - -#include <stdio.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#define _LIBMM_INSIDE_MM -#include <libmm-glib.h> - -#include "mm-log-object.h" -#include "mm-iface-modem.h" -#include "mm-iface-modem-location.h" -#include "mm-base-modem.h" -#include "mm-base-modem-at.h" -#include "mm-modem-helpers-telit.h" -#include "mm-shared-telit.h" - -/*****************************************************************************/ -/* Private data context */ - -#define TELIT_LM940_EXT_LTE_BND_SW_REVISION "24.01.516" - -#define PRIVATE_TAG "shared-telit-private-tag" -static GQuark private_quark; - -typedef struct { - MMIfaceModem *iface_modem_parent; - gboolean alternate_3g_bands; - gboolean ext_4g_bands; - GArray *supported_bands; - GArray *supported_modes; - gchar *software_package_version; -} Private; - -static void -private_free (Private *priv) -{ - if (priv->supported_bands) - g_array_unref (priv->supported_bands); - if (priv->supported_modes) - g_array_unref (priv->supported_modes); - g_free (priv->software_package_version); - g_slice_free (Private, priv); -} - -static gboolean -has_alternate_3g_bands (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_FN990 || - model == MM_TELIT_MODEL_LM940 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static gboolean -is_bnd_4g_format_hex (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_LE910C1 || - model == MM_TELIT_MODEL_LM940 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static gboolean -has_extended_4g_bands (const gchar *revision) -{ - MMTelitModel model; - - model = mm_telit_model_from_revision (revision); - if (model == MM_TELIT_MODEL_LM940) - return mm_telit_software_revision_cmp (revision, TELIT_LM940_EXT_LTE_BND_SW_REVISION) >= MM_TELIT_SW_REV_CMP_EQUAL; - - return (model == MM_TELIT_MODEL_FN980 || - model == MM_TELIT_MODEL_FN990 || - model == MM_TELIT_MODEL_LM960 || - model == MM_TELIT_MODEL_LN920); -} - -static Private * -get_private (MMSharedTelit *self) -{ - Private *priv; - - if (G_UNLIKELY (!private_quark)) - private_quark = g_quark_from_static_string (PRIVATE_TAG); - - priv = g_object_get_qdata (G_OBJECT (self), private_quark); - if (!priv) { - priv = g_slice_new0 (Private); - - if (MM_SHARED_TELIT_GET_INTERFACE (self)->peek_parent_modem_interface) - priv->iface_modem_parent = MM_SHARED_TELIT_GET_INTERFACE (self)->peek_parent_modem_interface (self); - - g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); - } - - return priv; -} - -void -mm_shared_telit_store_supported_modes (MMSharedTelit *self, - GArray *modes) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - priv->supported_modes = g_array_ref (modes); -} - -void -mm_shared_telit_store_revision (MMSharedTelit *self, - const gchar *revision) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - g_clear_pointer (&priv->software_package_version, g_free); - priv->software_package_version = g_strdup (revision); - priv->alternate_3g_bands = has_alternate_3g_bands (revision); - priv->ext_4g_bands = has_extended_4g_bands (revision); -} - -void -mm_shared_telit_get_bnd_parse_config (MMIfaceModem *self, MMTelitBNDParseConfig *config) -{ - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - config->modem_is_2g = mm_iface_modem_is_2g (self); - config->modem_is_3g = mm_iface_modem_is_3g (self); - config->modem_is_4g = mm_iface_modem_is_4g (self); - config->modem_alternate_3g_bands = priv->alternate_3g_bands; - config->modem_has_hex_format_4g_bands = is_bnd_4g_format_hex (priv->software_package_version); - config->modem_ext_4g_bands = priv->ext_4g_bands; -} - -/*****************************************************************************/ -/* Load current mode (Modem interface) */ - -gboolean -mm_shared_telit_load_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - MMModemMode *allowed, - MMModemMode *preferred, - GError **error) -{ - const gchar *response; - const gchar *str; - gint a; - - response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error); - if (!response) - return FALSE; - - str = mm_strip_tag (response, "+WS46: "); - - if (!sscanf (str, "%d", &a)) { - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse +WS46 response: '%s'", - response); - return FALSE; - } - - *preferred = MM_MODEM_MODE_NONE; - switch (a) { - case 12: - *allowed = MM_MODEM_MODE_2G; - return TRUE; - case 22: - *allowed = MM_MODEM_MODE_3G; - return TRUE; - case 25: - if (mm_iface_modem_is_3gpp_lte (self)) - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - else - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - case 28: - *allowed = MM_MODEM_MODE_4G; - return TRUE; - case 29: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); - return TRUE; - case 30: - *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G); - return TRUE; - case 31: - *allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); - return TRUE; - default: - break; - } - - g_set_error (error, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Couldn't parse unexpected +WS46 response: '%s'", - response); - return FALSE; -} - -void -mm_shared_telit_load_current_modes (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "+WS46?", - 3, - FALSE, - callback, - user_data); -} - -/*****************************************************************************/ -/* Load supported bands (Modem interface) */ - -GArray * -mm_shared_telit_modem_load_supported_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_supported_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - GArray *bands; - MMTelitBNDParseConfig config; - - mm_shared_telit_get_bnd_parse_config (MM_IFACE_MODEM (self), &config); - - bands = mm_telit_parse_bnd_test_response (response, &config, self, &error); - if (!bands) - g_task_return_error (task, error); - else { - /* Store supported bands to be able to build ANY when setting */ - priv->supported_bands = g_array_ref (bands); - if (priv->ext_4g_bands) - mm_obj_dbg (self, "telit modem using extended 4G band setup"); - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - } - - g_object_unref (task); -} - -static void -load_supported_bands_at (MMIfaceModem *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#BND=?", - 3, - TRUE, - (GAsyncReadyCallback) load_supported_bands_ready, - task); -} - -static void -parent_load_supported_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - bands = priv->iface_modem_parent->load_supported_bands_finish (MM_IFACE_MODEM (self), res, &error); - if (bands) { - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); - } else { - mm_obj_dbg (self, "parent load supported bands failure, falling back to AT commands"); - load_supported_bands_at (self, task); - g_clear_error (&error); - } -} - -void -mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->load_supported_bands && - priv->iface_modem_parent->load_supported_bands_finish) { - priv->iface_modem_parent->load_supported_bands (self, - (GAsyncReadyCallback) parent_load_supported_bands_ready, - task); - } else - load_supported_bands_at (self, task); -} - -/*****************************************************************************/ -/* Load current bands (Modem interface) */ - -GArray * -mm_shared_telit_modem_load_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - const gchar *response; - GError *error = NULL; - - response = mm_base_modem_at_command_finish (self, res, &error); - if (!response) - g_task_return_error (task, error); - else { - GArray *bands; - MMTelitBNDParseConfig config; - - mm_shared_telit_get_bnd_parse_config (MM_IFACE_MODEM (self), &config); - - bands = mm_telit_parse_bnd_query_response (response, &config, self, &error); - if (!bands) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - } - - g_object_unref (task); -} - -static void -load_current_bands_at (MMIfaceModem *self, - GTask *task) -{ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "#BND?", - 3, - FALSE, - (GAsyncReadyCallback) load_current_bands_ready, - task); -} - -static void -parent_load_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GArray *bands; - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - bands = priv->iface_modem_parent->load_current_bands_finish (MM_IFACE_MODEM (self), res, &error); - if (bands) { - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); - g_object_unref (task); - } else { - mm_obj_dbg (self, "parent load current bands failure, falling back to AT commands"); - load_current_bands_at (self, task); - g_clear_error (&error); - } -} - -void -mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->load_current_bands && - priv->iface_modem_parent->load_current_bands_finish) { - priv->iface_modem_parent->load_current_bands (self, - (GAsyncReadyCallback) parent_load_current_bands_ready, - task); - } else - load_current_bands_at (self, task); -} - -/*****************************************************************************/ -/* Set current bands (Modem interface) */ - -gboolean -mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -set_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static void -set_current_bands_at (MMIfaceModem *self, - GTask *task) -{ - GError *error = NULL; - gchar *cmd; - GArray *bands_array; - MMTelitBNDParseConfig config; - - bands_array = g_task_get_task_data (task); - g_assert (bands_array); - - if (bands_array->len == 1 && g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - if (!priv->supported_bands) { - g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Couldn't build ANY band settings: unknown supported bands"); - g_object_unref (task); - return; - } - bands_array = priv->supported_bands; - } - - mm_shared_telit_get_bnd_parse_config (self, &config); - cmd = mm_telit_build_bnd_request (bands_array, &config, &error); - if (!cmd) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 20, - FALSE, - (GAsyncReadyCallback)set_current_bands_ready, - task); - g_free (cmd); -} - -static void -parent_set_current_bands_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - if (priv->iface_modem_parent->set_current_bands_finish (MM_IFACE_MODEM (self), res, &error)) { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - } else { - g_clear_error (&error); - set_current_bands_at (self, task); - } -} - -void -mm_shared_telit_modem_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - priv = get_private (MM_SHARED_TELIT (self)); - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, g_array_ref (bands_array), (GDestroyNotify)g_array_unref); - - if (priv->iface_modem_parent && - priv->iface_modem_parent->set_current_bands && - priv->iface_modem_parent->set_current_bands_finish) { - priv->iface_modem_parent->set_current_bands (self, - bands_array, - (GAsyncReadyCallback) parent_set_current_bands_ready, - task); - } else - set_current_bands_at (self, task); -} - -/*****************************************************************************/ -/* Set current modes (Modem interface) */ - -gboolean -mm_shared_telit_set_current_modes_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -ws46_set_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - - mm_base_modem_at_command_finish (self, res, &error); - if (error) - /* Let the error be critical. */ - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_telit_set_current_modes (MMIfaceModem *self, - MMModemMode allowed, - MMModemMode preferred, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - gchar *command; - Private *priv; - gint ws46_mode = -1; - - priv = get_private (MM_SHARED_TELIT (self)); - task = g_task_new (self, NULL, callback, user_data); - - if (allowed == MM_MODEM_MODE_ANY && priv->supported_modes) { - guint i; - - allowed = MM_MODEM_MODE_NONE; - /* Process list of modes to gather supported ones */ - for (i = 0; i < priv->supported_modes->len; i++) { - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_2G) - allowed |= MM_MODEM_MODE_2G; - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_3G) - allowed |= MM_MODEM_MODE_3G; - if (g_array_index (priv->supported_modes, MMModemMode, i) & MM_MODEM_MODE_4G) - allowed |= MM_MODEM_MODE_4G; - } - } - - if (allowed == MM_MODEM_MODE_2G) - ws46_mode = 12; - else if (allowed == MM_MODEM_MODE_3G) - ws46_mode = 22; - else if (allowed == MM_MODEM_MODE_4G) - ws46_mode = 28; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) { - if (mm_iface_modem_is_3gpp_lte (self)) - ws46_mode = 29; - else - ws46_mode = 25; - } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G)) - ws46_mode = 30; - else if (allowed == (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) - ws46_mode = 31; - else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) - ws46_mode = 25; - - /* Telit modems do not support preferred mode selection */ - if ((ws46_mode < 0) || (preferred != MM_MODEM_MODE_NONE)) { - gchar *allowed_str; - gchar *preferred_str; - - allowed_str = mm_modem_mode_build_string_from_mask (allowed); - preferred_str = mm_modem_mode_build_string_from_mask (preferred); - g_task_return_new_error (task, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Requested mode (allowed: '%s', preferred: '%s') not " - "supported by the modem.", - allowed_str, - preferred_str); - g_free (allowed_str); - g_free (preferred_str); - - g_object_unref (task); - return; - } - - command = g_strdup_printf ("AT+WS46=%d", ws46_mode); - mm_base_modem_at_command ( - MM_BASE_MODEM (self), - command, - 10, - FALSE, - (GAsyncReadyCallback) ws46_set_ready, - task); - g_free (command); -} - -/*****************************************************************************/ -/* Revision loading */ - -gchar * -mm_shared_telit_modem_load_revision_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_pointer (G_TASK (res), error); -} - -static void -load_revision_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - GError *error; - GVariant *result; - - result = mm_base_modem_at_sequence_finish (self, res, NULL, &error); - if (!result) { - g_task_return_error (task, error); - g_object_unref (task); - } else { - gchar *revision = NULL; - - revision = g_variant_dup_string (result, NULL); - mm_shared_telit_store_revision (MM_SHARED_TELIT (self), revision); - g_task_return_pointer (task, revision, g_free); - g_object_unref (task); - } -} - -/* - * parse AT#SWPKGV command - * Execution command returns the software package version without #SWPKGV: command echo. - * The response is as follows: - * - * AT#SWPKGV - * <Telit Software Package Version>-<Production Parameters Version> - * <Modem FW Version> (Usually the same value returned by AT+GMR) - * <Production Parameters Version> - * <Application FW Version> - */ -static MMBaseModemAtResponseProcessorResult -software_package_version_ready (MMBaseModem *self, - gpointer none, - const gchar *command, - const gchar *response, - gboolean last_command, - const GError *error, - GVariant **result, - GError **result_error) -{ - gchar *version = NULL; - - if (error) { - *result = NULL; - - /* Ignore AT errors (ie, ERROR or CMx ERROR) */ - if (error->domain != MM_MOBILE_EQUIPMENT_ERROR || last_command) { - *result_error = g_error_copy (error); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_FAILURE; - } - - *result_error = NULL; - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - } - - version = mm_telit_parse_swpkgv_response (response); - if (!version) - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_CONTINUE; - - *result = g_variant_new_take_string (version); - return MM_BASE_MODEM_AT_RESPONSE_PROCESSOR_RESULT_SUCCESS; -} - -static const MMBaseModemAtCommand revisions[] = { - { "#SWPKGV", 3, TRUE, software_package_version_ready }, - { "+CGMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors }, - { "+GMR", 3, TRUE, mm_base_modem_response_processor_string_ignore_at_errors }, - { NULL } -}; - -void -mm_shared_telit_modem_load_revision (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - Private *priv; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_TELIT (self)); - - mm_obj_dbg (self, "loading revision..."); - if (priv->software_package_version) { - g_task_return_pointer (task, - g_strdup (priv->software_package_version), - g_free); - g_object_unref (task); - return; - } - - mm_base_modem_at_sequence ( - MM_BASE_MODEM (self), - revisions, - NULL, /* response_processor_context */ - NULL, /* response_processor_context_free */ - (GAsyncReadyCallback) load_revision_ready, - task); -} - -/*****************************************************************************/ - -static void -shared_telit_init (gpointer g_iface) -{ -} - -GType -mm_shared_telit_get_type (void) -{ - static GType shared_telit_type = 0; - - if (!G_UNLIKELY (shared_telit_type)) { - static const GTypeInfo info = { - sizeof (MMSharedTelit), /* class_size */ - shared_telit_init, /* base_init */ - NULL, /* base_finalize */ - }; - - shared_telit_type = g_type_register_static (G_TYPE_INTERFACE, "MMSharedTelit", &info, 0); - g_type_interface_add_prerequisite (shared_telit_type, MM_TYPE_IFACE_MODEM); - } - - return shared_telit_type; -} - |