diff options
-rw-r--r-- | src/mm-modem-helpers-qmi.c | 108 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.h | 9 | ||||
-rw-r--r-- | src/mm-shared-qmi.c | 64 |
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); |