aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-03-15 17:46:49 +0100
committerAleksander Morgado <aleksander@aleksander.es>2021-03-15 17:46:49 +0100
commitfdfd4b270aa3bb31185feb833691f134c887f869 (patch)
tree4194c73eab79b87633e5b7459681c04bc433a65f /src
parentbb5bc9c8c560a24ef2951bdb9e1da18dedd7c5b0 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/mm-modem-helpers-qmi.c108
-rw-r--r--src/mm-modem-helpers-qmi.h9
-rw-r--r--src/mm-shared-qmi.c64
3 files changed, 100 insertions, 81 deletions
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c
index ef951bac..7d98084a 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -1106,67 +1106,75 @@ mm_modem_capability_to_qmi_acquisition_order_preference (MMModemCapability caps)
return array;
}
-GArray *
-mm_modem_mode_to_qmi_acquisition_order_preference (MMModemMode allowed,
- MMModemMode preferred,
- gboolean is_cdma,
- gboolean is_3gpp)
+static gboolean
+radio_interface_array_contains (GArray *array,
+ QmiNasRadioInterface act)
{
- GArray *array;
- QmiNasRadioInterface value;
+ guint i;
- array = g_array_new (FALSE, FALSE, sizeof (QmiNasRadioInterface));
+ for (i = 0; i < array->len; i++) {
+ QmiNasRadioInterface value;
- 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);
+ value = g_array_index (array, QmiNasRadioInterface, i);
+ if (value == act)
+ return TRUE;
}
+ return FALSE;
+}
- 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
+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);
}
+}
- 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);
- }
- }
+GArray *
+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;
- 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);
- }
+ array = g_array_sized_new (FALSE, FALSE, sizeof (QmiNasRadioInterface), all->len);
+
+#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); \
+ } \
}
+ 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);
+
+#undef PROCESS_ALLOWED_PREFERRED_MODE
+
+ 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;
}
diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h
index d64f94cb..831418a3 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -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);
diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c
index 84baa64c..f7e9eb0d 100644
--- a/src/mm-shared-qmi.c
+++ b/src/mm-shared-qmi.c
@@ -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;
-
- /* 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);
+ 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,
+ 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);