diff options
Diffstat (limited to 'plugins/cinterion/mm-broadband-modem-cinterion.c')
-rw-r--r-- | plugins/cinterion/mm-broadband-modem-cinterion.c | 171 |
1 files changed, 137 insertions, 34 deletions
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c index 6e526ad3..f931dc58 100644 --- a/plugins/cinterion/mm-broadband-modem-cinterion.c +++ b/plugins/cinterion/mm-broadband-modem-cinterion.c @@ -79,7 +79,7 @@ struct _MMBroadbandModemCinterionPrivate { gchar *sleep_mode_cmd; /* Cached supported bands in Cinterion format */ - guint supported_bands; + guint supported_bands[MM_CINTERION_RB_BLOCK_N]; /* Cached supported modes for SMS setup */ GArray *cnmi_supported_mode; @@ -95,6 +95,13 @@ struct _MMBroadbandModemCinterionPrivate { FeatureSupport swwan_support; FeatureSupport sind_psinfo_support; FeatureSupport smoni_support; + + /* Flags for model-based behaviors */ + MMCinterionModemFamily modem_family; + MMCinterionRadioBandFormat rb_format; + + /* Command sequence */ + MMBaseModemAtCommandAlloc *cmds; }; /*****************************************************************************/ @@ -1150,27 +1157,61 @@ scfg_test_ready (MMBaseModem *_self, response = mm_base_modem_at_command_finish (_self, res, &error); if (!response || !mm_cinterion_parse_scfg_test (response, + self->priv->modem_family, mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), &bands, + &self->priv->rb_format, &error)) g_task_return_error (task, error); else { - mm_cinterion_build_band (bands, 0, FALSE, &self->priv->supported_bands, NULL); - g_assert (self->priv->supported_bands != 0); - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); + if (!mm_cinterion_build_band (bands, + NULL, + FALSE, + self->priv->rb_format, + self->priv->modem_family, + self->priv->supported_bands, + &error)) + g_task_return_error (task, error); + else + g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); } g_object_unref (task); } static void -load_supported_bands (MMIfaceModem *self, +load_supported_bands (MMIfaceModem *_self, GAsyncReadyCallback callback, gpointer user_data) { - GTask *task; + MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); + GTask *task; + MMPort *primary; + MMKernelDevice *port; + const gchar *family = NULL; + + /* Lookup for the tag specifying which modem family the current device belongs */ + primary = MM_PORT (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self))); + port = mm_port_peek_kernel_device (primary); + family = mm_kernel_device_get_global_property (port, "ID_MM_CINTERION_MODEM_FAMILY"); + + /* if the property is not set, default family */ + self->priv->modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT; + + /* set used family also in the string for mm_obj_dbg */ + if (!family) + family = "default"; + + if (g_ascii_strcasecmp (family, "imt") == 0) + self->priv->modem_family = MM_CINTERION_MODEM_FAMILY_IMT; + else if (g_ascii_strcasecmp (family, "default") != 0) { + mm_obj_dbg (self, "cinterion modem family '%s' unknown", family); + family = "default"; + } - task = g_task_new (self, NULL, callback, user_data); - mm_base_modem_at_command (MM_BASE_MODEM (self), + mm_obj_dbg (self, "Using cinterion %s modem family", family); + + task = g_task_new (_self, NULL, callback, user_data); + mm_base_modem_at_command (MM_BASE_MODEM (_self), "AT^SCFG=?", 3, FALSE, @@ -1190,19 +1231,22 @@ load_current_bands_finish (MMIfaceModem *self, } static void -get_band_ready (MMBaseModem *self, +get_band_ready (MMBaseModem *_self, GAsyncResult *res, GTask *task) { + MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self); const gchar *response; GError *error = NULL; GArray *bands = NULL; - response = mm_base_modem_at_command_finish (self, res, &error); + response = mm_base_modem_at_command_finish (_self, res, &error); if (!response || !mm_cinterion_parse_scfg_response (response, + self->priv->modem_family, mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)), &bands, + self->priv->rb_format, &error)) g_task_return_error (task, error); else @@ -1220,7 +1264,7 @@ load_current_bands (MMIfaceModem *self, task = g_task_new (self, NULL, callback, user_data); mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SCFG=\"Radio/Band\"", + "AT^SCFG?", 3, FALSE, (GAsyncReadyCallback)get_band_ready, @@ -1253,43 +1297,100 @@ scfg_set_ready (MMBaseModem *self, } static void +scfg_set_ready_sequence (MMBaseModem *_self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + gpointer ctx = NULL; + guint i; + MMBroadbandModemCinterion *self; + + self = g_task_get_source_object (task); + for (i = 0; self->priv->cmds[i].command; i++) + mm_base_modem_at_command_alloc_clear (&self->priv->cmds[i]); + g_free(self->priv->cmds); + self->priv->cmds = NULL; + + mm_base_modem_at_sequence_finish (_self, res, &ctx, &error); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void set_bands_3g (GTask *task, GArray *bands_array) { MMBroadbandModemCinterion *self; GError *error = NULL; - guint band = 0; - gchar *cmd; + guint band[MM_CINTERION_RB_BLOCK_N] = { 0 }; self = g_task_get_source_object (task); if (!mm_cinterion_build_band (bands_array, self->priv->supported_bands, FALSE, /* 2G and 3G */ - &band, + self->priv->rb_format, + self->priv->modem_family, + band, &error)) { g_task_return_error (task, error); g_object_unref (task); return; } - /* Following the setup: - * AT^SCFG="Radion/Band",<rba> - * We will set the preferred band equal to the allowed band, so that we force - * the modem to connect at that specific frequency only. Note that we will be - * passing a number here! - * - * The optional <rbe> field is set to 1, so that changes take effect - * immediately. - */ - cmd = g_strdup_printf ("^SCFG=\"Radio/Band\",%u,1", band); - mm_base_modem_at_command (MM_BASE_MODEM (self), - cmd, - 15, - FALSE, - (GAsyncReadyCallback)scfg_set_ready, - task); - g_free (cmd); + if (self->priv->rb_format == MM_CINTERION_RADIO_BAND_FORMAT_SINGLE) { + g_autofree gchar *cmd = NULL; + + /* Following the setup: + * AT^SCFG="Radion/Band",<rba> + * We will set the preferred band equal to the allowed band, so that we force + * the modem to connect at that specific frequency only. Note that we will be + * passing a number here! + * + * The optional <rbe> field is set to 1, so that changes take effect + * immediately. + */ + cmd = g_strdup_printf ("^SCFG=\"Radio/Band\",%u,1", band[MM_CINTERION_RB_BLOCK_LEGACY]); + mm_base_modem_at_command (MM_BASE_MODEM (self), + cmd, + 15, + FALSE, + (GAsyncReadyCallback)scfg_set_ready, + task); + } else { /* self->priv->rb_format == MM_CINTERION_RADIO_BAND_FORMAT_MULTIPLE */ + if (self->priv->modem_family == MM_CINTERION_MODEM_FAMILY_IMT) { + g_autofree gchar *bandstr2G = NULL; + g_autofree gchar *bandstr3G = NULL; + g_autofree gchar *bandstr4G = NULL; + + bandstr2G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_GSM]); + bandstr3G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_UMTS]); + bandstr4G = g_strdup_printf ("0x%08X", band[MM_CINTERION_RB_BLOCK_LTE_LOW]); + bandstr2G = mm_broadband_modem_take_and_convert_to_current_charset (MM_BROADBAND_MODEM (self), bandstr2G); + bandstr3G = mm_broadband_modem_take_and_convert_to_current_charset (MM_BROADBAND_MODEM (self), bandstr3G); + bandstr4G = mm_broadband_modem_take_and_convert_to_current_charset (MM_BROADBAND_MODEM (self), bandstr4G); + self->priv->cmds = g_new0 (MMBaseModemAtCommandAlloc, 3 + 1); + self->priv->cmds[0].command = g_strdup_printf ("^SCFG=\"Radio/Band/2G\",\"%s\"", bandstr2G); + self->priv->cmds[1].command = g_strdup_printf ("^SCFG=\"Radio/Band/3G\",\"%s\"", bandstr3G); + self->priv->cmds[2].command = g_strdup_printf ("^SCFG=\"Radio/Band/4G\",\"%s\"", bandstr4G); + self->priv->cmds[0].timeout = self->priv->cmds[1].timeout = self->priv->cmds[2].timeout = 60; + } else { + self->priv->cmds = g_new0 (MMBaseModemAtCommandAlloc, 3 + 1); + self->priv->cmds[0].command = g_strdup_printf ("^SCFG=\"Radio/Band/2G\",\"%08x\",1", band[MM_CINTERION_RB_BLOCK_GSM]); + self->priv->cmds[1].command = g_strdup_printf ("^SCFG=\"Radio/Band/3G\",\"%08x\",1", band[MM_CINTERION_RB_BLOCK_UMTS]); + self->priv->cmds[2].command = g_strdup_printf ("^SCFG=\"Radio/Band/4G\",\"%08x\",\"%08x\",1", band[MM_CINTERION_RB_BLOCK_LTE_LOW], band[MM_CINTERION_RB_BLOCK_LTE_HIGH]); + self->priv->cmds[0].timeout = self->priv->cmds[1].timeout = self->priv->cmds[2].timeout = 15; + } + + mm_base_modem_at_sequence (MM_BASE_MODEM (self), + (const MMBaseModemAtCommand *)self->priv->cmds, + NULL, + NULL, + (GAsyncReadyCallback)scfg_set_ready_sequence, + task); + } + } static void @@ -1298,7 +1399,7 @@ set_bands_2g (GTask *task, { MMBroadbandModemCinterion *self; GError *error = NULL; - guint band = 0; + guint band[MM_CINTERION_RB_BLOCK_N] = { 0 }; gchar *cmd; gchar *bandstr; @@ -1307,7 +1408,9 @@ set_bands_2g (GTask *task, if (!mm_cinterion_build_band (bands_array, self->priv->supported_bands, TRUE, /* 2G only */ - &band, + MM_CINTERION_RADIO_BAND_FORMAT_SINGLE, + 0, + band, &error)) { g_task_return_error (task, error); g_object_unref (task); @@ -1315,7 +1418,7 @@ set_bands_2g (GTask *task, } /* Build string with the value, in the proper charset */ - bandstr = g_strdup_printf ("%u", band); + bandstr = g_strdup_printf ("%u", band[MM_CINTERION_RB_BLOCK_LEGACY]); bandstr = mm_broadband_modem_take_and_convert_to_current_charset (MM_BROADBAND_MODEM (self), bandstr); if (!bandstr) { g_task_return_new_error (task, |