aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/mmcli-modem.c1
-rw-r--r--cli/mmcli-output.c1
-rw-r--r--cli/mmcli-output.h1
-rw-r--r--docs/reference/libmm-glib/libmm-glib-sections.txt5
-rw-r--r--introspection/org.freedesktop.ModemManager1.Modem.xml7
-rw-r--r--libmm-glib/mm-modem.c41
-rw-r--r--libmm-glib/mm-modem.h3
-rw-r--r--src/mm-iface-modem.c113
-rw-r--r--src/mm-iface-modem.h19
9 files changed, 191 insertions, 0 deletions
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index 9c964294..5d3c2713 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -351,6 +351,7 @@ print_modem_info (void)
mmcli_output_string (MMC_F_HARDWARE_MANUFACTURER, mm_modem_get_manufacturer (ctx->modem));
mmcli_output_string (MMC_F_HARDWARE_MODEL, mm_modem_get_model (ctx->modem));
mmcli_output_string (MMC_F_HARDWARE_REVISION, mm_modem_get_revision (ctx->modem));
+ mmcli_output_string (MMC_F_HARDWARE_CARRIER_CONFIGURATION, mm_modem_get_carrier_configuration (ctx->modem));
mmcli_output_string (MMC_F_HARDWARE_HW_REVISION, mm_modem_get_hardware_revision (ctx->modem));
mmcli_output_string_multiline (MMC_F_HARDWARE_SUPPORTED_CAPABILITIES, supported_capabilities_string);
mmcli_output_string_multiline (MMC_F_HARDWARE_CURRENT_CAPABILITIES, current_capabilities_string);
diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c
index 5822ff51..33819feb 100644
--- a/cli/mmcli-output.c
+++ b/cli/mmcli-output.c
@@ -97,6 +97,7 @@ static FieldInfo field_infos[] = {
[MMC_F_HARDWARE_MANUFACTURER] = { "modem.generic.manufacturer", "manufacturer", MMC_S_MODEM_HARDWARE, },
[MMC_F_HARDWARE_MODEL] = { "modem.generic.model", "model", MMC_S_MODEM_HARDWARE, },
[MMC_F_HARDWARE_REVISION] = { "modem.generic.revision", "revision", MMC_S_MODEM_HARDWARE, },
+ [MMC_F_HARDWARE_CARRIER_CONFIGURATION] = { "modem.generic.carrier-configuration", "carrier config", MMC_S_MODEM_HARDWARE, },
[MMC_F_HARDWARE_HW_REVISION] = { "modem.generic.hardware-revision", "h/w revision", MMC_S_MODEM_HARDWARE, },
[MMC_F_HARDWARE_SUPPORTED_CAPABILITIES] = { "modem.generic.supported-capabilities", "supported", MMC_S_MODEM_HARDWARE, },
[MMC_F_HARDWARE_CURRENT_CAPABILITIES] = { "modem.generic.current-capabilities", "current", MMC_S_MODEM_HARDWARE, },
diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h
index 4a9a9c46..75533b00 100644
--- a/cli/mmcli-output.h
+++ b/cli/mmcli-output.h
@@ -91,6 +91,7 @@ typedef enum {
MMC_F_HARDWARE_MANUFACTURER,
MMC_F_HARDWARE_MODEL,
MMC_F_HARDWARE_REVISION,
+ MMC_F_HARDWARE_CARRIER_CONFIGURATION,
MMC_F_HARDWARE_HW_REVISION,
MMC_F_HARDWARE_SUPPORTED_CAPABILITIES,
MMC_F_HARDWARE_CURRENT_CAPABILITIES,
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 41f3b0d6..40558684 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -137,6 +137,8 @@ mm_modem_get_model
mm_modem_dup_model
mm_modem_get_revision
mm_modem_dup_revision
+mm_modem_get_carrier_configuration
+mm_modem_dup_carrier_configuration
mm_modem_get_hardware_revision
mm_modem_dup_hardware_revision
mm_modem_get_drivers
@@ -2022,6 +2024,8 @@ mm_gdbus_modem_get_ports
mm_gdbus_modem_dup_ports
mm_gdbus_modem_get_revision
mm_gdbus_modem_dup_revision
+mm_gdbus_modem_get_carrier_configuration
+mm_gdbus_modem_dup_carrier_configuration
mm_gdbus_modem_get_hardware_revision
mm_gdbus_modem_dup_hardware_revision
mm_gdbus_modem_get_signal_quality
@@ -2093,6 +2097,7 @@ mm_gdbus_modem_set_plugin
mm_gdbus_modem_set_primary_port
mm_gdbus_modem_set_ports
mm_gdbus_modem_set_revision
+mm_gdbus_modem_set_carrier_configuration
mm_gdbus_modem_set_hardware_revision
mm_gdbus_modem_set_signal_quality
mm_gdbus_modem_set_sim
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.xml b/introspection/org.freedesktop.ModemManager1.Modem.xml
index 7ac7cdda..f647d2f0 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.xml
@@ -297,6 +297,13 @@
<property name="Revision" type="s" access="read" />
<!--
+ CarrierConfiguration:
+
+ The description of the carrier-specific configuration (MCFG) in use by the modem.
+ -->
+ <property name="CarrierConfiguration" type="s" access="read" />
+
+ <!--
HardwareRevision:
The revision identification of the hardware, as reported by the modem.
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c
index 80cb280b..d7d59542 100644
--- a/libmm-glib/mm-modem.c
+++ b/libmm-glib/mm-modem.c
@@ -503,6 +503,47 @@ mm_modem_dup_revision (MMModem *self)
/*****************************************************************************/
/**
+ * mm_modem_get_carrier_configuration:
+ * @self: A #MMModem.
+ *
+ * Gets the carrier-specific configuration (MCFG) in use, as reported by this #MMModem.
+ *
+ * <warning>The returned value is only valid until the property changes so
+ * it is only safe to use this function on the thread where
+ * @self was constructed. Use mm_modem_dup_carrier_configuration() if on another
+ * thread.</warning>
+ *
+ * Returns: (transfer none): The carrier configuration, or %NULL if none available. Do not free the returned value, it belongs to @self.
+ */
+const gchar *
+mm_modem_get_carrier_configuration (MMModem *self)
+{
+ g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (
+ mm_gdbus_modem_get_carrier_configuration (MM_GDBUS_MODEM (self)));
+}
+
+/**
+ * mm_modem_dup_carrier_configuration:
+ * @self: A #MMModem.
+ *
+ * Gets a copy of the carrier-specific configuration (MCFG) in use, as reported by this #MMModem.
+ *
+ * Returns: (transfer full): The carrier configuration, or %NULL if none available. The returned value should be freed with g_free().
+ */
+gchar *
+mm_modem_dup_carrier_configuration (MMModem *self)
+{
+ g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+ RETURN_NON_EMPTY_STRING (
+ mm_gdbus_modem_dup_carrier_configuration (MM_GDBUS_MODEM (self)));
+}
+
+/*****************************************************************************/
+
+/**
* mm_modem_get_hardware_revision:
* @self: A #MMModem.
*
diff --git a/libmm-glib/mm-modem.h b/libmm-glib/mm-modem.h
index 1b51b6c3..95719d6a 100644
--- a/libmm-glib/mm-modem.h
+++ b/libmm-glib/mm-modem.h
@@ -103,6 +103,9 @@ gchar *mm_modem_dup_model (MMModem *self);
const gchar *mm_modem_get_revision (MMModem *self);
gchar *mm_modem_dup_revision (MMModem *self);
+const gchar *mm_modem_get_carrier_configuration (MMModem *self);
+gchar *mm_modem_dup_carrier_configuration (MMModem *self);
+
const gchar *mm_modem_get_hardware_revision (MMModem *self);
gchar *mm_modem_dup_hardware_revision (MMModem *self);
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 1ffcb967..9befbddb 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -3942,6 +3942,7 @@ typedef enum {
INITIALIZATION_STEP_MANUFACTURER,
INITIALIZATION_STEP_MODEL,
INITIALIZATION_STEP_REVISION,
+ INITIALIZATION_STEP_CARRIER_CONFIG,
INITIALIZATION_STEP_HARDWARE_REVISION,
INITIALIZATION_STEP_EQUIPMENT_ID,
INITIALIZATION_STEP_DEVICE_ID,
@@ -3952,6 +3953,7 @@ typedef enum {
INITIALIZATION_STEP_SIM_HOT_SWAP,
INITIALIZATION_STEP_UNLOCK_REQUIRED,
INITIALIZATION_STEP_SIM,
+ INITIALIZATION_STEP_SETUP_CARRIER_CONFIG,
INITIALIZATION_STEP_OWN_NUMBERS,
INITIALIZATION_STEP_CURRENT_MODES,
INITIALIZATION_STEP_CURRENT_BANDS,
@@ -4334,6 +4336,51 @@ sim_reinit_ready (MMBaseSim *sim,
interface_initialization_step (task);
}
+static void
+setup_carrier_config_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ InitializationContext *ctx;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config_finish (self, res, &error)) {
+ mm_warn ("couldn't setup carrier config: '%s'", error->message);
+ g_error_free (error);
+ }
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
+static void
+load_carrier_config_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ InitializationContext *ctx;
+ GError *error = NULL;
+ gchar *carrier_configuration;
+
+ ctx = g_task_get_task_data (task);
+
+ carrier_configuration = MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config_finish (self, res, &error);
+ if (!carrier_configuration) {
+ mm_warn ("couldn't load carrier config: '%s'", error->message);
+ g_error_free (error);
+ } else {
+ mm_gdbus_modem_set_carrier_configuration (ctx->skeleton, carrier_configuration);
+ g_free (carrier_configuration);
+ }
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
void
mm_iface_modem_update_own_numbers (MMIfaceModem *self,
const GStrv own_numbers)
@@ -4700,6 +4747,21 @@ interface_initialization_step (GTask *task)
/* Fall down to next step */
ctx->step++;
+ case INITIALIZATION_STEP_CARRIER_CONFIG:
+ /* Current carrier config is meant to be loaded only once during the whole
+ * lifetime of the modem. Therefore, if we already have them loaded,
+ * don't try to load them again. */
+ if (mm_gdbus_modem_get_carrier_configuration (ctx->skeleton) == NULL &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config_finish) {
+ MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config (self,
+ (GAsyncReadyCallback)load_carrier_config_ready,
+ task);
+ return;
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
case INITIALIZATION_STEP_HARDWARE_REVISION:
/* HardwareRevision is meant to be loaded only once during the whole
* lifetime of the modem. Therefore, if we already have them loaded,
@@ -4899,6 +4961,49 @@ interface_initialization_step (GTask *task)
/* Fall down to next step */
ctx->step++;
+ case INITIALIZATION_STEP_SETUP_CARRIER_CONFIG:
+ /* Setup and perform automatic carrier config switching as soon as the
+ * SIM initialization has been performed, only applicable if there is
+ * actually a SIM found with a valid IMSI read */
+ if (!mm_iface_modem_is_cdma_only (self) &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config_finish) {
+ MMBaseSim *sim = NULL;
+ gchar *carrier_config_mapping = NULL;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_SIM, &sim,
+ MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING, &carrier_config_mapping,
+ NULL);
+
+ /* If we have a SIM object, and carrier config switching is supported,
+ * validate whether we're already using the best config or not. */
+ if (!sim)
+ mm_dbg ("not setting up carrier config: SIM not found");
+ else if (!carrier_config_mapping)
+ mm_dbg ("not setting up carrier config: mapping file not configured");
+ else {
+ const gchar *imsi;
+
+ imsi = mm_gdbus_sim_get_imsi (MM_GDBUS_SIM (sim));
+ if (imsi) {
+ MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config (self,
+ imsi,
+ carrier_config_mapping,
+ (GAsyncReadyCallback)setup_carrier_config_ready,
+ task);
+ g_object_unref (sim);
+ g_free (carrier_config_mapping);
+ return;
+ }
+ mm_warn ("couldn't setup carrier config: unknown IMSI");
+ }
+ g_clear_object (&sim);
+ g_free (carrier_config_mapping);
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
case INITIALIZATION_STEP_OWN_NUMBERS:
/* Own numbers is meant to be loaded only once during the whole
* lifetime of the modem. Therefore, if we already have them loaded,
@@ -5415,6 +5520,14 @@ iface_modem_init (gpointer g_iface)
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_interface_install_property
+ (g_iface,
+ g_param_spec_string (MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING,
+ "Carrier config mapping table",
+ "Path to the file including the carrier mapping for the module",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
initialized = TRUE;
}
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 5b1c891d..cb7a75ed 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -39,6 +39,7 @@
#define MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED "iface-modem-sim-hot-swap-supported"
#define MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED "iface-modem-sim-hot-swap-configured"
#define MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED "iface-modem-periodic-signal-check-disabled"
+#define MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING "iface-modem-carrier-config-mapping"
typedef struct _MMIfaceModem MMIfaceModem;
@@ -356,6 +357,24 @@ struct _MMIfaceModem {
gboolean (*setup_sim_hot_swap_finish) (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
+
+ /* Load carrier config */
+ void (* load_carrier_config) (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gchar * (* load_carrier_config_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
+
+ /* Setup carrier config based on IMSI */
+ void (* setup_carrier_config) (MMIfaceModem *self,
+ const gchar *imsi,
+ const gchar *carrier_config_mapping,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* setup_carrier_config_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_iface_modem_get_type (void);