shared-qmi: acquisition order preference TLV always same items
The acquisition order preference TLV must always have the same number of elements, just the order of the elements should be different. Also, always prefer the acquisition order preference TLV to the GSM+WCDMA specific one, which is the same logic the modem applies. Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/340
This commit is contained in:
+58
-50
@@ -1106,66 +1106,74 @@ mm_modem_capability_to_qmi_acquisition_order_preference (MMModemCapability caps)
|
||||
return array;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
radio_interface_array_contains (GArray *array,
|
||||
QmiNasRadioInterface act)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < array->len; i++) {
|
||||
QmiNasRadioInterface value;
|
||||
|
||||
value = g_array_index (array, QmiNasRadioInterface, i);
|
||||
if (value == act)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
radio_interface_array_add_missing (GArray *array,
|
||||
GArray *all)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < all->len; i++) {
|
||||
QmiNasRadioInterface value;
|
||||
|
||||
value = g_array_index (all, QmiNasRadioInterface, i);
|
||||
if (!radio_interface_array_contains (array, value))
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
}
|
||||
|
||||
GArray *
|
||||
mm_modem_mode_to_qmi_acquisition_order_preference (MMModemMode allowed,
|
||||
MMModemMode preferred,
|
||||
gboolean is_cdma,
|
||||
gboolean is_3gpp)
|
||||
mm_modem_mode_to_qmi_acquisition_order_preference (MMModemMode allowed,
|
||||
MMModemMode preferred,
|
||||
GArray *all)
|
||||
{
|
||||
GArray *array;
|
||||
QmiNasRadioInterface preferred_radio = QMI_NAS_RADIO_INTERFACE_UNKNOWN;
|
||||
QmiNasRadioInterface value;
|
||||
|
||||
array = g_array_new (FALSE, FALSE, sizeof (QmiNasRadioInterface));
|
||||
array = g_array_sized_new (FALSE, FALSE, sizeof (QmiNasRadioInterface), all->len);
|
||||
|
||||
if (allowed & MM_MODEM_MODE_5G) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_5GNR;
|
||||
if (preferred == MM_MODEM_MODE_5G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
#define PROCESS_ALLOWED_PREFERRED_MODE(MODE,RADIO) \
|
||||
if ((allowed & MODE) && (radio_interface_array_contains (all, RADIO))) { \
|
||||
if ((preferred == MODE) && (preferred_radio == QMI_NAS_RADIO_INTERFACE_UNKNOWN)) \
|
||||
preferred_radio = RADIO; \
|
||||
else { \
|
||||
value = RADIO; \
|
||||
g_array_append_val (array, value); \
|
||||
} \
|
||||
}
|
||||
|
||||
if (allowed & MM_MODEM_MODE_4G) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_LTE;
|
||||
if (preferred == MM_MODEM_MODE_4G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_5G, QMI_NAS_RADIO_INTERFACE_5GNR);
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_4G, QMI_NAS_RADIO_INTERFACE_LTE);
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_3G, QMI_NAS_RADIO_INTERFACE_UMTS);
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_3G, QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO);
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_2G, QMI_NAS_RADIO_INTERFACE_GSM);
|
||||
PROCESS_ALLOWED_PREFERRED_MODE (MM_MODEM_MODE_2G, QMI_NAS_RADIO_INTERFACE_CDMA_1X);
|
||||
|
||||
if (allowed & MM_MODEM_MODE_3G) {
|
||||
if (is_cdma) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO;
|
||||
if (preferred == MM_MODEM_MODE_3G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
if (is_3gpp) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_UMTS;
|
||||
if (preferred == MM_MODEM_MODE_3G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
}
|
||||
#undef PROCESS_ALLOWED_PREFERRED_MODE
|
||||
|
||||
if (allowed & MM_MODEM_MODE_2G) {
|
||||
if (is_cdma) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_CDMA_1X;
|
||||
if (preferred == MM_MODEM_MODE_2G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
if (is_3gpp) {
|
||||
value = QMI_NAS_RADIO_INTERFACE_GSM;
|
||||
if (preferred == MM_MODEM_MODE_2G)
|
||||
g_array_prepend_val (array, value);
|
||||
else
|
||||
g_array_append_val (array, value);
|
||||
}
|
||||
}
|
||||
if (preferred_radio != QMI_NAS_RADIO_INTERFACE_UNKNOWN)
|
||||
g_array_prepend_val (array, preferred_radio);
|
||||
|
||||
/* the acquisition order preference is a TLV that must ALWAYS contain the
|
||||
* same list of QmiNasRadioInterface values, just with a different order. */
|
||||
radio_interface_array_add_missing (array, all);
|
||||
g_assert_cmpuint (array->len, ==, all->len);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
@@ -66,11 +66,10 @@ QmiNasRatModePreference mm_modem_mode_to_qmi_rat_mode_preference (MMModemMode mo
|
||||
MMModemCapability mm_modem_capability_from_qmi_rat_mode_preference (QmiNasRatModePreference qmi);
|
||||
QmiNasRatModePreference mm_modem_capability_to_qmi_rat_mode_preference (MMModemCapability caps);
|
||||
|
||||
GArray *mm_modem_capability_to_qmi_acquisition_order_preference (MMModemCapability caps);
|
||||
GArray *mm_modem_mode_to_qmi_acquisition_order_preference (MMModemMode allowed,
|
||||
MMModemMode preferred,
|
||||
gboolean is_cdma,
|
||||
gboolean is_3gpp);
|
||||
GArray *mm_modem_capability_to_qmi_acquisition_order_preference (MMModemCapability caps);
|
||||
GArray *mm_modem_mode_to_qmi_acquisition_order_preference (MMModemMode allowed,
|
||||
MMModemMode preferred,
|
||||
GArray *all);
|
||||
|
||||
MMModemCapability mm_modem_capability_from_qmi_radio_technology_preference (QmiNasRadioTechnologyPreference qmi);
|
||||
QmiNasRadioTechnologyPreference mm_modem_capability_to_qmi_radio_technology_preference (MMModemCapability caps);
|
||||
|
||||
+37
-25
@@ -74,6 +74,8 @@ typedef struct {
|
||||
Feature feature_nas_tp;
|
||||
Feature feature_nas_ssp;
|
||||
Feature feature_nas_ssp_extended_lte_band_preference;
|
||||
Feature feature_nas_ssp_acquisition_order_preference;
|
||||
GArray *feature_nas_ssp_acquisition_order_preference_array;
|
||||
gboolean disable_4g_only_mode;
|
||||
GArray *supported_bands;
|
||||
|
||||
@@ -125,6 +127,8 @@ private_free (Private *priv)
|
||||
g_object_unref (priv->uim_client);
|
||||
if (priv->uim_refresh_start_timeout_id)
|
||||
g_source_remove (priv->uim_refresh_start_timeout_id);
|
||||
if (priv->feature_nas_ssp_acquisition_order_preference_array)
|
||||
g_array_unref (priv->feature_nas_ssp_acquisition_order_preference_array);
|
||||
g_strfreev (priv->loc_assistance_data_servers);
|
||||
g_slice_free (Private, priv);
|
||||
}
|
||||
@@ -144,6 +148,7 @@ get_private (MMSharedQmi *self)
|
||||
priv->feature_nas_tp = FEATURE_UNKNOWN;
|
||||
priv->feature_nas_ssp = FEATURE_UNKNOWN;
|
||||
priv->feature_nas_ssp_extended_lte_band_preference = FEATURE_UNKNOWN;
|
||||
priv->feature_nas_ssp_acquisition_order_preference = FEATURE_UNKNOWN;
|
||||
priv->config_active_i = -1;
|
||||
|
||||
/* Setup parent class' MMIfaceModemLocation */
|
||||
@@ -923,6 +928,7 @@ load_current_capabilities_get_system_selection_preference_ready (QmiClientNas *c
|
||||
|
||||
priv->feature_nas_ssp = FEATURE_UNSUPPORTED;
|
||||
priv->feature_nas_ssp_extended_lte_band_preference = FEATURE_UNSUPPORTED;
|
||||
priv->feature_nas_ssp_acquisition_order_preference = FEATURE_UNSUPPORTED;
|
||||
|
||||
output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error);
|
||||
if (!output) {
|
||||
@@ -938,6 +944,12 @@ load_current_capabilities_get_system_selection_preference_ready (QmiClientNas *c
|
||||
priv->feature_nas_ssp = FEATURE_SUPPORTED;
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_extended_lte_band_preference (output, NULL, NULL, NULL, NULL, NULL))
|
||||
priv->feature_nas_ssp_extended_lte_band_preference = FEATURE_SUPPORTED;
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_acquisition_order_preference (output, &acquisition_order_preference_array, NULL) &&
|
||||
acquisition_order_preference_array &&
|
||||
acquisition_order_preference_array->len) {
|
||||
priv->feature_nas_ssp_acquisition_order_preference = FEATURE_SUPPORTED;
|
||||
priv->feature_nas_ssp_acquisition_order_preference_array = g_array_ref (acquisition_order_preference_array);
|
||||
}
|
||||
|
||||
qmi_message_nas_get_system_selection_preference_output_get_mode_preference (
|
||||
output,
|
||||
@@ -1259,11 +1271,13 @@ static void
|
||||
set_current_modes_system_selection_preference (GTask *task)
|
||||
{
|
||||
MMIfaceModem *self;
|
||||
Private *priv;
|
||||
SetCurrentModesContext *ctx;
|
||||
QmiMessageNasSetSystemSelectionPreferenceInput *input;
|
||||
QmiNasRatModePreference pref;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
priv = get_private (MM_SHARED_QMI (self));
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
input = qmi_message_nas_set_system_selection_preference_input_new ();
|
||||
@@ -1272,16 +1286,17 @@ set_current_modes_system_selection_preference (GTask *task)
|
||||
/* Preferred modes */
|
||||
|
||||
if (ctx->preferred != MM_MODEM_MODE_NONE) {
|
||||
GArray *array;
|
||||
if (priv->feature_nas_ssp_acquisition_order_preference == FEATURE_SUPPORTED) {
|
||||
GArray *array;
|
||||
|
||||
/* Acquisition order array */
|
||||
array = mm_modem_mode_to_qmi_acquisition_order_preference (ctx->allowed,
|
||||
ctx->preferred,
|
||||
mm_iface_modem_is_cdma (self),
|
||||
mm_iface_modem_is_3gpp (self));
|
||||
g_assert (array);
|
||||
qmi_message_nas_set_system_selection_preference_input_set_acquisition_order_preference (input, array, NULL);
|
||||
g_array_unref (array);
|
||||
/* Acquisition order array */
|
||||
array = mm_modem_mode_to_qmi_acquisition_order_preference (ctx->allowed,
|
||||
ctx->preferred,
|
||||
priv->feature_nas_ssp_acquisition_order_preference_array);
|
||||
g_assert (array);
|
||||
qmi_message_nas_set_system_selection_preference_input_set_acquisition_order_preference (input, array, NULL);
|
||||
g_array_unref (array);
|
||||
}
|
||||
|
||||
/* Only set GSM/WCDMA acquisition order preference if both 2G and 3G given as allowed */
|
||||
if (mm_iface_modem_is_3gpp (self) && ((ctx->allowed & (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G))) {
|
||||
@@ -1508,24 +1523,11 @@ load_current_modes_system_selection_preference_ready (QmiClientNas *client,
|
||||
result->allowed = allowed;
|
||||
result->preferred = MM_MODEM_MODE_NONE;
|
||||
|
||||
/* For 2G+3G only rely on the GSM/WCDMA acquisition order preference TLV */
|
||||
if (mode_preference_mask == (QMI_NAS_RAT_MODE_PREFERENCE_GSM | QMI_NAS_RAT_MODE_PREFERENCE_UMTS)) {
|
||||
QmiNasGsmWcdmaAcquisitionOrderPreference gsm_or_wcdma;
|
||||
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_gsm_wcdma_acquisition_order_preference (
|
||||
output,
|
||||
&gsm_or_wcdma,
|
||||
NULL))
|
||||
result->preferred = mm_modem_mode_from_qmi_gsm_wcdma_acquisition_order_preference (gsm_or_wcdma, self);
|
||||
}
|
||||
/* Otherwise, rely on the acquisition order array TLV */
|
||||
else {
|
||||
/* If acquisition order preference is available, always use that first */
|
||||
if (priv->feature_nas_ssp_acquisition_order_preference == FEATURE_SUPPORTED) {
|
||||
GArray *array;
|
||||
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_acquisition_order_preference (
|
||||
output,
|
||||
&array,
|
||||
NULL) &&
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_acquisition_order_preference (output, &array, NULL) &&
|
||||
array->len > 0) {
|
||||
guint i;
|
||||
|
||||
@@ -1546,6 +1548,16 @@ load_current_modes_system_selection_preference_ready (QmiClientNas *client,
|
||||
}
|
||||
}
|
||||
}
|
||||
/* For 2G+3G only rely on the GSM/WCDMA acquisition order preference TLV */
|
||||
else if (mode_preference_mask == (QMI_NAS_RAT_MODE_PREFERENCE_GSM | QMI_NAS_RAT_MODE_PREFERENCE_UMTS)) {
|
||||
QmiNasGsmWcdmaAcquisitionOrderPreference gsm_or_wcdma;
|
||||
|
||||
if (qmi_message_nas_get_system_selection_preference_output_get_gsm_wcdma_acquisition_order_preference (
|
||||
output,
|
||||
&gsm_or_wcdma,
|
||||
NULL))
|
||||
result->preferred = mm_modem_mode_from_qmi_gsm_wcdma_acquisition_order_preference (gsm_or_wcdma, self);
|
||||
}
|
||||
|
||||
g_task_return_pointer (task, result, g_free);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user