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.
This commit is contained in:

committed by
Aleksander Morgado

parent
fcd393a6c2
commit
a25b45f795
@@ -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);
|
||||
|
@@ -637,6 +637,94 @@ out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* ^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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
@@ -83,6 +83,15 @@ gboolean mm_cinterion_parse_cnmi_test (const gchar *response,
|
||||
GArray **supported_bfr,
|
||||
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 */
|
||||
|
||||
@@ -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 */
|
||||
|
@@ -1743,6 +1743,187 @@ test_sgauth_response (void)
|
||||
g_assert (!result);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* 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 ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user