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_ds;
|
||||||
GArray *cnmi_supported_bfr;
|
GArray *cnmi_supported_bfr;
|
||||||
|
|
||||||
|
/* Cached supported rats for SXRAT */
|
||||||
|
GArray *sxrat_supported_rat;
|
||||||
|
GArray *sxrat_supported_pref1;
|
||||||
|
|
||||||
/* ignore regex */
|
/* ignore regex */
|
||||||
GRegex *sysstart_regex;
|
GRegex *sysstart_regex;
|
||||||
/* +CIEV indications as configured via AT^SIND */
|
/* +CIEV indications as configured via AT^SIND */
|
||||||
@@ -100,6 +104,10 @@ struct _MMBroadbandModemCinterionPrivate {
|
|||||||
FeatureSupport sind_psinfo_support;
|
FeatureSupport sind_psinfo_support;
|
||||||
FeatureSupport smoni_support;
|
FeatureSupport smoni_support;
|
||||||
FeatureSupport sind_simstatus_support;
|
FeatureSupport sind_simstatus_support;
|
||||||
|
FeatureSupport sxrat_support;
|
||||||
|
|
||||||
|
/* Mode combination to apply if "any" requested */
|
||||||
|
MMModemMode any_allowed;
|
||||||
|
|
||||||
/* Flags for model-based behaviors */
|
/* Flags for model-based behaviors */
|
||||||
MMCinterionModemFamily modem_family;
|
MMCinterionModemFamily modem_family;
|
||||||
@@ -1797,15 +1805,186 @@ parent_load_supported_modes_ready (MMIfaceModem *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
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 */
|
/* Run parent's loading */
|
||||||
iface_modem_parent->load_supported_modes (
|
iface_modem_parent->load_supported_modes (
|
||||||
MM_IFACE_MODEM (self),
|
MM_IFACE_MODEM (self),
|
||||||
(GAsyncReadyCallback)parent_load_supported_modes_ready,
|
(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
|
static void
|
||||||
set_current_modes (MMIfaceModem *_self,
|
cops_set_current_modes (MMBroadbandModemCinterion *self,
|
||||||
MMModemMode allowed,
|
MMModemMode allowed,
|
||||||
MMModemMode preferred,
|
MMModemMode preferred,
|
||||||
GAsyncReadyCallback callback,
|
GTask *task)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
|
gchar *command;
|
||||||
gchar *command;
|
|
||||||
GTask *task;
|
|
||||||
|
|
||||||
g_assert (preferred == MM_MODEM_MODE_NONE);
|
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
|
/* We will try to simulate the possible allowed modes here. The
|
||||||
* Cinterion devices do not seem to allow setting preferred access
|
* Cinterion devices do not seem to allow setting preferred access
|
||||||
* technology in devices, but they allow restricting to a given
|
* 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.
|
* 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");
|
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");
|
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");
|
command = g_strdup ("+COPS=,,,0");
|
||||||
else {
|
else {
|
||||||
/* For any other combination (e.g. ANY or no AcT given, defaults to Auto. For this case, we cannot provide
|
/* 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);
|
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) */
|
/* Supported bands (Modem interface) */
|
||||||
|
|
||||||
@@ -2917,6 +3145,7 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
|
|||||||
self->priv->swwan_support = FEATURE_SUPPORT_UNKNOWN;
|
self->priv->swwan_support = FEATURE_SUPPORT_UNKNOWN;
|
||||||
self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN;
|
self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN;
|
||||||
self->priv->sind_simstatus_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",
|
self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*([a-z]+),(\\d+)\\r\\n",
|
||||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
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);
|
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||||
self->priv->scks_regex = g_regex_new ("\\^SCKS:\\s*([0-3])\\r\\n",
|
self->priv->scks_regex = g_regex_new ("\\^SCKS:\\s*([0-3])\\r\\n",
|
||||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||||
|
|
||||||
|
self->priv->any_allowed = MM_MODEM_MODE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2943,6 +3174,10 @@ finalize (GObject *object)
|
|||||||
g_array_unref (self->priv->cnmi_supported_ds);
|
g_array_unref (self->priv->cnmi_supported_ds);
|
||||||
if (self->priv->cnmi_supported_bfr)
|
if (self->priv->cnmi_supported_bfr)
|
||||||
g_array_unref (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->ciev_regex);
|
||||||
g_regex_unref (self->priv->sysstart_regex);
|
g_regex_unref (self->priv->sysstart_regex);
|
||||||
|
@@ -637,6 +637,94 @@ out:
|
|||||||
return TRUE;
|
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 */
|
/* Build Cinterion-specific band value */
|
||||||
|
|
||||||
@@ -1651,3 +1739,66 @@ mm_cinterion_build_auth_string (gpointer log_object,
|
|||||||
quoted_passwd,
|
quoted_passwd,
|
||||||
quoted_user);
|
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,
|
GArray **supported_bfr,
|
||||||
GError **error);
|
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 */
|
/* Build Cinterion-specific band value */
|
||||||
|
|
||||||
@@ -192,4 +201,11 @@ gchar *mm_cinterion_build_auth_string (gpointer log_object,
|
|||||||
MMBearerProperties *config,
|
MMBearerProperties *config,
|
||||||
guint cid);
|
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 */
|
#endif /* MM_MODEM_HELPERS_CINTERION_H */
|
||||||
|
@@ -1743,6 +1743,187 @@ test_sgauth_response (void)
|
|||||||
g_assert (!result);
|
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)
|
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/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/scfg/provcfg", test_provcfg_response);
|
||||||
g_test_add_func ("/MM/cinterion/sgauth", test_sgauth_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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user