aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-12-18 14:52:44 +0100
committerAleksander Morgado <aleksander@aleksander.es>2019-04-02 12:11:25 +0200
commit94cf7f0ceb8c00a413d279a1fbdb491c01240d81 (patch)
tree5b5111e0c2c0f7d4e1fcb3b66e9219f7a2e285fc
parentb8daedd3c015e150955d2063b9e79589640693e5 (diff)
iface-modem: new carrier config support
During initialization phase we will allow querying the modem for the details of which carrier-specific configuration is being used, and will expose a description string in the API. In addition to showing the current configuration, we will also allow automatically switching the configuration based on the SIM card detected in the device. In order to allow this, plugins/modems will need to provide the expected mapping between carrier config description and MCCMNC. This mapping cannot be generic, because different manufacturers may use different description strings.
-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);