aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Taedcke <christian.taedcke@lemonbeat.com>2022-05-18 15:45:57 +0200
committerAleksander Morgado <aleksander@aleksander.es>2022-09-28 10:26:08 +0000
commita25b45f795a9d9ccbfee1638fe67f1e6d0b6d64c (patch)
treea917cf91aa2bbbd7065be63ad4c7dc41389f2299
parentfcd393a6c2a6faeb09cd7ae3ee60addef7ac3e2c (diff)
cinterion: add support for mode setting using SXRAT
The previously used COPS command to set to LTE-only mode did not work for an ELS81 modem. Now ^SXRAT is used to switch modes instead of COPS, if SXRAT is supported by the modem.
-rw-r--r--plugins/cinterion/mm-broadband-modem-cinterion.c265
-rw-r--r--plugins/cinterion/mm-modem-helpers-cinterion.c151
-rw-r--r--plugins/cinterion/mm-modem-helpers-cinterion.h16
-rw-r--r--plugins/cinterion/tests/test-modem-helpers-cinterion.c184
4 files changed, 601 insertions, 15 deletions
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c
index 3be8da8b..90791355 100644
--- a/plugins/cinterion/mm-broadband-modem-cinterion.c
+++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -88,6 +88,10 @@ struct _MMBroadbandModemCinterionPrivate {
GArray *cnmi_supported_ds;
GArray *cnmi_supported_bfr;
+ /* Cached supported rats for SXRAT */
+ GArray *sxrat_supported_rat;
+ GArray *sxrat_supported_pref1;
+
/* ignore regex */
GRegex *sysstart_regex;
/* +CIEV indications as configured via AT^SIND */
@@ -100,6 +104,10 @@ struct _MMBroadbandModemCinterionPrivate {
FeatureSupport sind_psinfo_support;
FeatureSupport smoni_support;
FeatureSupport sind_simstatus_support;
+ FeatureSupport sxrat_support;
+
+ /* Mode combination to apply if "any" requested */
+ MMModemMode any_allowed;
/* Flags for model-based behaviors */
MMCinterionModemFamily modem_family;
@@ -1797,15 +1805,186 @@ parent_load_supported_modes_ready (MMIfaceModem *self,
}
static void
-load_supported_modes (MMIfaceModem *self,
+sxrat_load_supported_modes_ready (MMBroadbandModemCinterion *self,
+ GTask *task)
+{
+ GArray *combinations;
+ MMModemModeCombination mode;
+
+ g_assert (self->priv->sxrat_supported_rat);
+ g_assert (self->priv->sxrat_supported_pref1);
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
+
+ if (value_supported (self->priv->sxrat_supported_rat, 0)) {
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 1)) {
+ /* 2G+3G with none preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ self->priv->any_allowed = mode.allowed;
+
+ if (value_supported (self->priv->sxrat_supported_pref1, 0)) {
+ /* 2G preferred */
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_pref1, 2)) {
+ /* 3G preferred */
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ }
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 2)) {
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 3)) {
+ /* 4G only */
+ mode.allowed = MM_MODEM_MODE_4G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 4)) {
+ /* 3G+4G with none preferred */
+ mode.allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ self->priv->any_allowed = mode.allowed;
+
+ if (value_supported (self->priv->sxrat_supported_pref1, 2)) {
+ /* 3G preferred */
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_pref1, 3)) {
+ /* 4G preferred */
+ mode.preferred = MM_MODEM_MODE_4G;
+ g_array_append_val (combinations, mode);
+ }
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 5)) {
+ /* 2G+4G with none preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ self->priv->any_allowed = mode.allowed;
+
+ if (value_supported (self->priv->sxrat_supported_pref1, 0)) {
+ /* 2G preferred */
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_pref1, 3)) {
+ /* 4G preferred */
+ mode.preferred = MM_MODEM_MODE_4G;
+ g_array_append_val (combinations, mode);
+ }
+ }
+ if (value_supported (self->priv->sxrat_supported_rat, 6)) {
+ /* 2G+3G+4G with none preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ self->priv->any_allowed = mode.allowed;
+
+ if (value_supported (self->priv->sxrat_supported_pref1, 0)) {
+ /* 2G preferred */
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_pref1, 2)) {
+ /* 3G preferred */
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ }
+ if (value_supported (self->priv->sxrat_supported_pref1, 3)) {
+ /* 4G preferred */
+ mode.preferred = MM_MODEM_MODE_4G;
+ g_array_append_val (combinations, mode);
+ }
+ }
+
+ g_task_return_pointer (task, combinations, (GDestroyNotify) g_array_unref);
+ g_object_unref (task);
+}
+
+static void
+sxrat_test_ready (MMBaseModem *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+ g_autoptr(GError) error = NULL;
+ const gchar *response;
+
+ response = mm_base_modem_at_command_finish (_self, res, &error);
+ if (!error) {
+ mm_cinterion_parse_sxrat_test (response,
+ &self->priv->sxrat_supported_rat,
+ &self->priv->sxrat_supported_pref1,
+ NULL,
+ &error);
+ if (!error) {
+ self->priv->sxrat_support = FEATURE_SUPPORTED;
+ sxrat_load_supported_modes_ready (self, task);
+ return;
+ }
+ mm_obj_warn (self, "error reading SXRAT response: %s", error->message);
+ }
+
+ self->priv->sxrat_support = FEATURE_NOT_SUPPORTED;
+
+ /* Run parent's loading in case SXRAT is not supported */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ task);
+}
+
+static void
+load_supported_modes (MMIfaceModem *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ /* First check SXRAT support, if not already done */
+ if (self->priv->sxrat_support == FEATURE_SUPPORT_UNKNOWN) {
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "^SXRAT=?",
+ 3,
+ TRUE,
+ (GAsyncReadyCallback)sxrat_test_ready,
+ task);
+ return;
+ }
+
+ if (self->priv->sxrat_support == FEATURE_SUPPORTED) {
+ sxrat_load_supported_modes_ready (self, task);
+ return;
+ }
+
/* Run parent's loading */
iface_modem_parent->load_supported_modes (
MM_IFACE_MODEM (self),
(GAsyncReadyCallback)parent_load_supported_modes_ready,
- g_task_new (self, NULL, callback, user_data));
+ task);
}
/*****************************************************************************/
@@ -1849,20 +2028,15 @@ allowed_access_technology_update_ready (MMBroadbandModemCinterion *self,
}
static void
-set_current_modes (MMIfaceModem *_self,
- MMModemMode allowed,
- MMModemMode preferred,
- GAsyncReadyCallback callback,
- gpointer user_data)
+cops_set_current_modes (MMBroadbandModemCinterion *self,
+ MMModemMode allowed,
+ MMModemMode preferred,
+ GTask *task)
{
- MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
- gchar *command;
- GTask *task;
+ gchar *command;
g_assert (preferred == MM_MODEM_MODE_NONE);
- task = g_task_new (self, NULL, callback, user_data);
-
/* We will try to simulate the possible allowed modes here. The
* Cinterion devices do not seem to allow setting preferred access
* technology in devices, but they allow restricting to a given
@@ -1874,11 +2048,11 @@ set_current_modes (MMIfaceModem *_self,
* which is based on the quality of the connection.
*/
- if (mm_iface_modem_is_4g (_self) && allowed == MM_MODEM_MODE_4G)
+ if (mm_iface_modem_is_4g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_4G)
command = g_strdup ("+COPS=,,,7");
- else if (mm_iface_modem_is_3g (_self) && allowed == MM_MODEM_MODE_3G)
+ else if (mm_iface_modem_is_3g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_3G)
command = g_strdup ("+COPS=,,,2");
- else if (mm_iface_modem_is_2g (_self) && allowed == MM_MODEM_MODE_2G)
+ else if (mm_iface_modem_is_2g (MM_IFACE_MODEM (self)) && allowed == MM_MODEM_MODE_2G)
command = g_strdup ("+COPS=,,,0");
else {
/* For any other combination (e.g. ANY or no AcT given, defaults to Auto. For this case, we cannot provide
@@ -1902,6 +2076,60 @@ set_current_modes (MMIfaceModem *_self,
g_free (command);
}
+static void
+sxrat_set_current_modes (MMBroadbandModemCinterion *self,
+ MMModemMode allowed,
+ MMModemMode preferred,
+ GTask *task)
+{
+ gchar *command;
+ GError *error = NULL;
+
+ g_assert (self->priv->any_allowed != MM_MODEM_MODE_NONE);
+
+ /* Handle ANY */
+ if (allowed == MM_MODEM_MODE_ANY)
+ allowed = self->priv->any_allowed;
+
+ command = mm_cinterion_build_sxrat_set_command (allowed, preferred, &error);
+
+ if (!command) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ mm_base_modem_at_command (
+ MM_BASE_MODEM (self),
+ command,
+ 30,
+ FALSE,
+ (GAsyncReadyCallback)allowed_access_technology_update_ready,
+ task);
+
+ g_free (command);
+}
+
+static void
+set_current_modes (MMIfaceModem *_self,
+ MMModemMode allowed,
+ MMModemMode preferred,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (self->priv->sxrat_support == FEATURE_SUPPORTED)
+ sxrat_set_current_modes (self, allowed, preferred, task);
+ else if (self->priv->sxrat_support == FEATURE_NOT_SUPPORTED)
+ cops_set_current_modes (self, allowed, preferred, task);
+ else
+ g_assert_not_reached ();
+}
+
/*****************************************************************************/
/* Supported bands (Modem interface) */
@@ -2917,6 +3145,7 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
self->priv->swwan_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->sind_simstatus_support = FEATURE_SUPPORT_UNKNOWN;
+ self->priv->sxrat_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*([a-z]+),(\\d+)\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
@@ -2924,6 +3153,8 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
self->priv->scks_regex = g_regex_new ("\\^SCKS:\\s*([0-3])\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
+
+ self->priv->any_allowed = MM_MODEM_MODE_NONE;
}
static void
@@ -2943,6 +3174,10 @@ finalize (GObject *object)
g_array_unref (self->priv->cnmi_supported_ds);
if (self->priv->cnmi_supported_bfr)
g_array_unref (self->priv->cnmi_supported_bfr);
+ if (self->priv->sxrat_supported_rat)
+ g_array_unref (self->priv->sxrat_supported_rat);
+ if (self->priv->sxrat_supported_pref1)
+ g_array_unref (self->priv->sxrat_supported_pref1);
g_regex_unref (self->priv->ciev_regex);
g_regex_unref (self->priv->sysstart_regex);
diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.c b/plugins/cinterion/mm-modem-helpers-cinterion.c
index 9219bff4..f22a998c 100644
--- a/plugins/cinterion/mm-modem-helpers-cinterion.c
+++ b/plugins/cinterion/mm-modem-helpers-cinterion.c
@@ -638,6 +638,94 @@ out:
}
/*****************************************************************************/
+/* ^SXRAT test parser
+ *
+ * Example (ELS61-E2):
+ * AT^SXRAT=?
+ * ^SXRAT: (0-6),(0,2,3),(0,2,3)
+ */
+
+gboolean
+mm_cinterion_parse_sxrat_test (const gchar *response,
+ GArray **supported_rat,
+ GArray **supported_pref1,
+ GArray **supported_pref2,
+ GError **error)
+{
+ g_autoptr(GRegex) r = NULL;
+ g_autoptr(GMatchInfo) match_info = NULL;
+ GError *inner_error = NULL;
+ GArray *tmp_supported_rat = NULL;
+ GArray *tmp_supported_pref1 = NULL;
+ GArray *tmp_supported_pref2 = NULL;
+
+ if (!response) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response");
+ return FALSE;
+ }
+
+ r = g_regex_new ("\\^SXRAT:\\s*\\(([^\\)]*)\\),\\(([^\\)]*)\\)(,\\(([^\\)]*)\\))?(?:\\r\\n)?",
+ G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
+ 0, NULL);
+
+ g_assert (r != NULL);
+
+ g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
+
+ if (!inner_error && g_match_info_matches (match_info)) {
+ if (supported_rat) {
+ g_autofree gchar *str = NULL;
+
+ str = mm_get_string_unquoted_from_match_info (match_info, 1);
+ tmp_supported_rat = mm_parse_uint_list (str, &inner_error);
+
+ if (inner_error)
+ goto out;
+ }
+ if (supported_pref1) {
+ g_autofree gchar *str = NULL;
+
+ str = mm_get_string_unquoted_from_match_info (match_info, 2);
+ tmp_supported_pref1 = mm_parse_uint_list (str, &inner_error);
+
+ if (inner_error)
+ goto out;
+ }
+ if (supported_pref2) {
+ g_autofree gchar *str = NULL;
+
+ /* this match is optional */
+ str = mm_get_string_unquoted_from_match_info (match_info, 4);
+ if (str) {
+ tmp_supported_pref2 = mm_parse_uint_list (str, &inner_error);
+
+ if (inner_error)
+ goto out;
+ }
+ }
+ }
+
+out:
+
+ if (inner_error) {
+ g_clear_pointer (&tmp_supported_rat, g_array_unref);
+ g_clear_pointer (&tmp_supported_pref1, g_array_unref);
+ g_clear_pointer (&tmp_supported_pref2, g_array_unref);
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ if (supported_rat)
+ *supported_rat = tmp_supported_rat;
+ if (supported_pref1)
+ *supported_pref1 = tmp_supported_pref1;
+ if (supported_pref2)
+ *supported_pref2 = tmp_supported_pref2;
+
+ return TRUE;
+}
+
+/*****************************************************************************/
/* Build Cinterion-specific band value */
gboolean
@@ -1651,3 +1739,66 @@ mm_cinterion_build_auth_string (gpointer log_object,
quoted_passwd,
quoted_user);
}
+
+/*****************************************************************************/
+/* ^SXRAT set command builder */
+
+/* Index of the array is the centerion-specific sxrat value */
+static const MMModemMode sxrat_combinations[] = {
+ [0] = ( MM_MODEM_MODE_2G ),
+ [1] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G ),
+ [2] = ( MM_MODEM_MODE_3G ),
+ [3] = ( MM_MODEM_MODE_4G ),
+ [4] = ( MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ),
+ [5] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_4G ),
+ [6] = ( MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G ),
+};
+
+static gboolean
+append_sxrat_rat_value (GString *str,
+ MMModemMode mode,
+ GError **error)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (sxrat_combinations); i++) {
+ if (sxrat_combinations[i] == mode) {
+ g_string_append_printf (str, "%u", i);
+ return TRUE;
+ }
+ }
+
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "No AcT value matches requested mode");
+ return FALSE;
+}
+
+gchar *
+mm_cinterion_build_sxrat_set_command (MMModemMode allowed,
+ MMModemMode preferred,
+ GError **error)
+{
+ GString *command;
+
+ command = g_string_new ("^SXRAT=");
+ if (!append_sxrat_rat_value (command, allowed, error)) {
+ g_string_free (command, TRUE);
+ return NULL;
+ }
+
+ if (preferred != MM_MODEM_MODE_NONE) {
+ if (mm_count_bits_set (preferred) != 1) {
+ *error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "AcT preferred value should be a single AcT");
+ g_string_free (command, TRUE);
+ return NULL;
+ }
+ g_string_append (command, ",");
+ if (!append_sxrat_rat_value (command, preferred, error)) {
+ g_string_free (command, TRUE);
+ return NULL;
+ }
+ }
+
+ return g_string_free (command, FALSE);
+}
diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.h b/plugins/cinterion/mm-modem-helpers-cinterion.h
index 7bbd789a..3155d0c1 100644
--- a/plugins/cinterion/mm-modem-helpers-cinterion.h
+++ b/plugins/cinterion/mm-modem-helpers-cinterion.h
@@ -84,6 +84,15 @@ gboolean mm_cinterion_parse_cnmi_test (const gchar *response,
GError **error);
/*****************************************************************************/
+/* ^SXRAT test parser */
+
+gboolean mm_cinterion_parse_sxrat_test (const gchar *response,
+ GArray **supported_rat,
+ GArray **supported_pref1,
+ GArray **supported_pref2,
+ GError **error);
+
+/*****************************************************************************/
/* Build Cinterion-specific band value */
gboolean mm_cinterion_build_band (GArray *bands,
@@ -192,4 +201,11 @@ gchar *mm_cinterion_build_auth_string (gpointer log_object,
MMBearerProperties *config,
guint cid);
+/*****************************************************************************/
+/* ^SXRAT set command helper */
+
+gchar *mm_cinterion_build_sxrat_set_command (MMModemMode allowed,
+ MMModemMode preferred,
+ GError **error);
+
#endif /* MM_MODEM_HELPERS_CINTERION_H */
diff --git a/plugins/cinterion/tests/test-modem-helpers-cinterion.c b/plugins/cinterion/tests/test-modem-helpers-cinterion.c
index 8332700b..d4816199 100644
--- a/plugins/cinterion/tests/test-modem-helpers-cinterion.c
+++ b/plugins/cinterion/tests/test-modem-helpers-cinterion.c
@@ -1744,6 +1744,187 @@ test_sgauth_response (void)
}
/*****************************************************************************/
+/* Test ^SXRAT responses */
+
+static void
+common_test_sxrat (const gchar *response,
+ const GArray *expected_rat,
+ const GArray *expected_pref1,
+ const GArray *expected_pref2)
+{
+ GArray *supported_rat = NULL;
+ GArray *supported_pref1 = NULL;
+ GArray *supported_pref2 = NULL;
+ GError *error = NULL;
+ gboolean res;
+
+ g_assert (expected_rat != NULL);
+ g_assert (expected_pref1 != NULL);
+
+ res = mm_cinterion_parse_sxrat_test (response,
+ &supported_rat,
+ &supported_pref1,
+ &supported_pref2,
+ &error);
+ g_assert_no_error (error);
+ g_assert (res == TRUE);
+ g_assert (supported_rat != NULL);
+ g_assert (supported_pref1 != NULL);
+ if (expected_pref2)
+ g_assert (supported_pref2 != NULL);
+ else
+ g_assert (supported_pref2 == NULL);
+
+ compare_arrays (supported_rat, expected_rat);
+ compare_arrays (supported_pref1, expected_pref1);
+ if (expected_pref2)
+ compare_arrays (supported_pref2, expected_pref2);
+
+ g_array_unref (supported_rat);
+ g_array_unref (supported_pref1);
+ if (supported_pref2)
+ g_array_unref (supported_pref2);
+}
+
+static void
+test_sxrat_response_els61 (void)
+{
+ GArray *expected_rat;
+ GArray *expected_pref1;
+ GArray *expected_pref2;
+ guint val;
+ const gchar *response =
+ "^SXRAT: (0-6),(0,2,3),(0,2,3)\r\n"
+ "\r\n";
+
+ expected_rat = g_array_sized_new (FALSE, FALSE, sizeof (guint), 7);
+ val = 0, g_array_append_val (expected_rat, val);
+ val = 1, g_array_append_val (expected_rat, val);
+ val = 2, g_array_append_val (expected_rat, val);
+ val = 3, g_array_append_val (expected_rat, val);
+ val = 4, g_array_append_val (expected_rat, val);
+ val = 5, g_array_append_val (expected_rat, val);
+ val = 6, g_array_append_val (expected_rat, val);
+
+ expected_pref1 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
+ val = 0, g_array_append_val (expected_pref1, val);
+ val = 2, g_array_append_val (expected_pref1, val);
+ val = 3, g_array_append_val (expected_pref1, val);
+
+ expected_pref2 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
+ val = 0, g_array_append_val (expected_pref2, val);
+ val = 2, g_array_append_val (expected_pref2, val);
+ val = 3, g_array_append_val (expected_pref2, val);
+
+ common_test_sxrat (response,
+ expected_rat,
+ expected_pref1,
+ expected_pref2);
+
+ g_array_unref (expected_rat);
+ g_array_unref (expected_pref1);
+ g_array_unref (expected_pref2);
+}
+
+static void
+test_sxrat_response_other (void)
+{
+ GArray *expected_rat;
+ GArray *expected_pref1;
+ GArray *expected_pref2 = NULL;
+ guint val;
+ const gchar *response =
+ "^SXRAT: (0-2),(0,2)\r\n"
+ "\r\n";
+
+ expected_rat = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
+ val = 0, g_array_append_val (expected_rat, val);
+ val = 1, g_array_append_val (expected_rat, val);
+ val = 2, g_array_append_val (expected_rat, val);
+
+ expected_pref1 = g_array_sized_new (FALSE, FALSE, sizeof (guint), 3);
+ val = 0, g_array_append_val (expected_pref1, val);
+ val = 2, g_array_append_val (expected_pref1, val);
+
+ common_test_sxrat (response,
+ expected_rat,
+ expected_pref1,
+ expected_pref2);
+
+ g_array_unref (expected_rat);
+ g_array_unref (expected_pref1);
+}
+
+typedef struct {
+ const gchar *str;
+ MMModemMode allowed;
+ MMModemMode preferred;
+ gboolean success;
+} SxratBuildTest;
+
+static const SxratBuildTest sxrat_build_tests[] = {
+ {
+ .str = "^SXRAT=0",
+ .allowed = MM_MODEM_MODE_2G,
+ .preferred = MM_MODEM_MODE_NONE,
+ .success = TRUE,
+ },
+ {
+ .str = "^SXRAT=3",
+ .allowed = MM_MODEM_MODE_4G,
+ .preferred = MM_MODEM_MODE_NONE,
+ .success = TRUE,
+ },
+ {
+ .str = "^SXRAT=1,2",
+ .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G,
+ .preferred = MM_MODEM_MODE_3G,
+ .success = TRUE,
+ },
+ {
+ .str = "^SXRAT=6,3",
+ .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G,
+ .preferred = MM_MODEM_MODE_4G,
+ .success = TRUE,
+ },
+ {
+ .str = NULL,
+ .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G,
+ .preferred = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G,
+ .success = FALSE,
+ },
+ {
+ .str = NULL,
+ .allowed = MM_MODEM_MODE_5G,
+ .preferred = MM_MODEM_MODE_NONE,
+ .success = FALSE,
+ },
+
+};
+
+static void
+test_sxrat (void)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (sxrat_build_tests); i++) {
+ GError *error = NULL;
+ gchar* result;
+
+ result = mm_cinterion_build_sxrat_set_command (sxrat_build_tests[i].allowed,
+ sxrat_build_tests[i].preferred,
+ &error);
+ if (sxrat_build_tests[i].success) {
+ g_assert_no_error (error);
+ g_assert (result);
+ g_assert_cmpstr (result, ==, sxrat_build_tests[i].str);
+ } else {
+ g_assert (error);
+ g_assert (!result);
+ }
+ }
+}
+/*****************************************************************************/
int main (int argc, char **argv)
{
@@ -1778,6 +1959,9 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/cinterion/smoni/query_response_to_signal", test_smoni_response_to_signal);
g_test_add_func ("/MM/cinterion/scfg/provcfg", test_provcfg_response);
g_test_add_func ("/MM/cinterion/sgauth", test_sgauth_response);
+ g_test_add_func ("/MM/cinterion/sxrat", test_sxrat);
+ g_test_add_func ("/MM/cinterion/sxrat/response/els61", test_sxrat_response_els61);
+ g_test_add_func ("/MM/cinterion/sxrat/response/other", test_sxrat_response_other);
return g_test_run ();
}