diff options
-rw-r--r-- | src/mm-modem-helpers-qmi.c | 133 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.h | 11 | ||||
-rw-r--r-- | src/mm-shared-qmi.c | 58 |
3 files changed, 175 insertions, 27 deletions
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c index 5df344786..b43005afd 100644 --- a/src/mm-modem-helpers-qmi.c +++ b/src/mm-modem-helpers-qmi.c @@ -302,15 +302,51 @@ dms_add_qmi_lte_bands (GArray *mm_bands, } } +static void +dms_add_extended_qmi_lte_bands (GArray *mm_bands, + GArray *extended_qmi_bands) +{ + guint i; + + g_assert (mm_bands != NULL); + + if (!extended_qmi_bands) + return; + + for (i = 0; i < extended_qmi_bands->len; i++) { + guint16 val; + + val = g_array_index (extended_qmi_bands, guint16, i); + + /* MM_MODEM_BAND_EUTRAN_1 = 31, + * ... + * MM_MODEM_BAND_EUTRAN_71 = 101 + */ + if (val < 1 || val > 71) + mm_dbg ("Unexpected LTE band supported by module: EUTRAN %u", val); + else { + MMModemBand band; + + band = (MMModemBand)(val + MM_MODEM_BAND_EUTRAN_1 - 1); + g_array_append_val (mm_bands, band); + } + } +} + GArray * mm_modem_bands_from_qmi_band_capabilities (QmiDmsBandCapability qmi_bands, - QmiDmsLteBandCapability qmi_lte_bands) + QmiDmsLteBandCapability qmi_lte_bands, + GArray *extended_qmi_lte_bands) { GArray *mm_bands; mm_bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); dms_add_qmi_bands (mm_bands, qmi_bands); - dms_add_qmi_lte_bands (mm_bands, qmi_lte_bands); + + if (extended_qmi_lte_bands) + dms_add_extended_qmi_lte_bands (mm_bands, extended_qmi_lte_bands); + else + dms_add_qmi_lte_bands (mm_bands, qmi_lte_bands); return mm_bands; } @@ -463,15 +499,57 @@ nas_add_qmi_lte_bands (GArray *mm_bands, } } +static void +nas_add_extended_qmi_lte_bands (GArray *mm_bands, + const guint64 *extended_qmi_lte_bands, + guint extended_qmi_lte_bands_size) +{ + guint i; + + g_assert (mm_bands != NULL); + + for (i = 0; i < extended_qmi_lte_bands_size; i++) { + guint j; + + for (j = 0; j < 64; j++) { + guint val; + + if (!(extended_qmi_lte_bands[i] & (((guint64) 1) << j))) + continue; + + val = 1 + j + (i * 64); + + /* MM_MODEM_BAND_EUTRAN_1 = 31, + * ... + * MM_MODEM_BAND_EUTRAN_71 = 101 + */ + if (val < 1 || val > 71) + mm_dbg ("Unexpected LTE band supported by module: EUTRAN %u", val); + else { + MMModemBand band; + + band = (val + MM_MODEM_BAND_EUTRAN_1 - 1); + g_array_append_val (mm_bands, band); + } + } + } +} + GArray * mm_modem_bands_from_qmi_band_preference (QmiNasBandPreference qmi_bands, - QmiNasLteBandPreference qmi_lte_bands) + QmiNasLteBandPreference qmi_lte_bands, + const guint64 *extended_qmi_lte_bands, + guint extended_qmi_lte_bands_size) { GArray *mm_bands; mm_bands = g_array_new (FALSE, FALSE, sizeof (MMModemBand)); nas_add_qmi_bands (mm_bands, qmi_bands); - nas_add_qmi_lte_bands (mm_bands, qmi_lte_bands); + + if (extended_qmi_lte_bands && extended_qmi_lte_bands_size) + nas_add_extended_qmi_lte_bands (mm_bands, extended_qmi_lte_bands, extended_qmi_lte_bands_size); + else + nas_add_qmi_lte_bands (mm_bands, qmi_lte_bands); return mm_bands; } @@ -479,32 +557,53 @@ mm_modem_bands_from_qmi_band_preference (QmiNasBandPreference qmi_bands, void mm_modem_bands_to_qmi_band_preference (GArray *mm_bands, QmiNasBandPreference *qmi_bands, - QmiNasLteBandPreference *qmi_lte_bands) + QmiNasLteBandPreference *qmi_lte_bands, + guint64 *extended_qmi_lte_bands, + guint extended_qmi_lte_bands_size) { guint i; *qmi_bands = 0; *qmi_lte_bands = 0; + for (i = 0; i < extended_qmi_lte_bands_size; i++) + extended_qmi_lte_bands[i] = 0; for (i = 0; i < mm_bands->len; i++) { MMModemBand band; band = g_array_index (mm_bands, MMModemBand, i); - if (band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_44) { - /* Add LTE band preference */ - guint j; - - for (j = 0; j < G_N_ELEMENTS (nas_lte_bands_map); j++) { - if (nas_lte_bands_map[j].mm_band == band) { - *qmi_lte_bands |= nas_lte_bands_map[j].qmi_band; - break; + if (band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_71) { + if (extended_qmi_lte_bands && extended_qmi_lte_bands_size) { + /* Add extended LTE band preference */ + guint val; + guint j; + guint k; + + /* it's really (band - MM_MODEM_BAND_EUTRAN_1 +1 -1), because + * we want EUTRAN1 in index 0 */ + val = band - MM_MODEM_BAND_EUTRAN_1; + j = val / 64; + g_assert (j < extended_qmi_lte_bands_size); + k = val % 64; + + mm_dbg ("band %u ---> j %u, k %u", band, j, k); + extended_qmi_lte_bands[j] |= ((guint64)1 << k); + } else { + /* Add LTE band preference */ + guint j; + + for (j = 0; j < G_N_ELEMENTS (nas_lte_bands_map); j++) { + if (nas_lte_bands_map[j].mm_band == band) { + *qmi_lte_bands |= nas_lte_bands_map[j].qmi_band; + break; + } } - } - if (j == G_N_ELEMENTS (nas_lte_bands_map)) - mm_dbg ("Cannot add the following LTE band: '%s'", - mm_modem_band_get_string (band)); + if (j == G_N_ELEMENTS (nas_lte_bands_map)) + mm_dbg ("Cannot add the following LTE band: '%s'", + mm_modem_band_get_string (band)); + } } else { /* Add non-LTE band preference */ guint j; diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h index 1deea7c36..a51c4f66e 100644 --- a/src/mm-modem-helpers-qmi.h +++ b/src/mm-modem-helpers-qmi.h @@ -35,7 +35,8 @@ gboolean mm_pin_enabled_from_qmi_uim_pin_status (QmiDmsUimPinStatus status); QmiDmsUimFacility mm_3gpp_facility_to_qmi_uim_facility (MMModem3gppFacility mm); GArray *mm_modem_bands_from_qmi_band_capabilities (QmiDmsBandCapability qmi_bands, - QmiDmsLteBandCapability qmi_lte_bands); + QmiDmsLteBandCapability qmi_lte_bands, + GArray *extended_qmi_lte_bands); /*****************************************************************************/ /* QMI/NAS to MM translations */ @@ -77,10 +78,14 @@ QmiNasGsmWcdmaAcquisitionOrderPreference mm_modem_mode_to_qmi_gsm_wcdma_acquisit GArray *mm_modem_bands_from_qmi_rf_band_information_array (GArray *info_array); GArray *mm_modem_bands_from_qmi_band_preference (QmiNasBandPreference qmi_bands, - QmiNasLteBandPreference qmi_lte_bands); + QmiNasLteBandPreference qmi_lte_bands, + const guint64 *extended_qmi_lte_bands, + guint extended_qmi_lte_bands_size); void mm_modem_bands_to_qmi_band_preference (GArray *mm_bands, QmiNasBandPreference *qmi_bands, - QmiNasLteBandPreference *qmi_lte_bands); + QmiNasLteBandPreference *qmi_lte_bands, + guint64 *extended_qmi_lte_bands, + guint extended_qmi_lte_bands_size); MMModem3gppRegistrationState mm_modem_3gpp_registration_state_from_qmi_registration_state (QmiNasAttachState attach_state, QmiNasRegistrationState registration_state, diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c index aff43fd50..f3a1a47c3 100644 --- a/src/mm-shared-qmi.c +++ b/src/mm-shared-qmi.c @@ -53,6 +53,7 @@ typedef struct { GArray *supported_radio_interfaces; Feature feature_nas_technology_preference; Feature feature_nas_system_selection_preference; + Feature feature_extended_lte_band_preference; gboolean disable_4g_only_mode; GArray *supported_bands; @@ -1485,6 +1486,7 @@ dms_get_band_capabilities_ready (QmiClientDms *client, GArray *mm_bands = NULL; QmiDmsBandCapability qmi_bands = 0; QmiDmsLteBandCapability qmi_lte_bands = 0; + GArray *extended_qmi_lte_bands = NULL; self = g_task_get_source_object (task); priv = get_private (self); @@ -1503,8 +1505,12 @@ dms_get_band_capabilities_ready (QmiClientDms *client, output, &qmi_lte_bands, NULL); + qmi_message_dms_get_band_capabilities_output_get_extended_lte_band_capability ( + output, + &extended_qmi_lte_bands, + NULL); - mm_bands = mm_modem_bands_from_qmi_band_capabilities (qmi_bands, qmi_lte_bands); + mm_bands = mm_modem_bands_from_qmi_band_capabilities (qmi_bands, qmi_lte_bands, extended_qmi_lte_bands); if (mm_bands->len == 0) { g_clear_pointer (&mm_bands, g_array_unref); error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, @@ -1568,11 +1574,18 @@ load_bands_get_system_selection_preference_ready (QmiClientNas *client, GAsyncResult *res, GTask *task) { + MMSharedQmi *self; + Private *priv; QmiMessageNasGetSystemSelectionPreferenceOutput *output = NULL; GError *error = NULL; GArray *mm_bands = NULL; QmiNasBandPreference band_preference_mask = 0; QmiNasLteBandPreference lte_band_preference_mask = 0; + guint64 extended_lte_band_preference[4] = { 0 }; + guint extended_lte_band_preference_size = 0; + + self = g_task_get_source_object (task); + priv = get_private (self); output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error); if (!output || !qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) { @@ -1590,7 +1603,22 @@ load_bands_get_system_selection_preference_ready (QmiClientNas *client, <e_band_preference_mask, NULL); - mm_bands = mm_modem_bands_from_qmi_band_preference (band_preference_mask, lte_band_preference_mask); + if (qmi_message_nas_get_system_selection_preference_output_get_extended_lte_band_preference ( + output, + &extended_lte_band_preference[0], + &extended_lte_band_preference[1], + &extended_lte_band_preference[2], + &extended_lte_band_preference[3], + NULL)) + extended_lte_band_preference_size = G_N_ELEMENTS (extended_lte_band_preference); + + if (G_UNLIKELY (priv->feature_extended_lte_band_preference == FEATURE_UNKNOWN)) + priv->feature_extended_lte_band_preference = extended_lte_band_preference_size ? FEATURE_SUPPORTED : FEATURE_UNSUPPORTED; + + mm_bands = mm_modem_bands_from_qmi_band_preference (band_preference_mask, + lte_band_preference_mask, + extended_lte_band_preference_size ? extended_lte_band_preference : NULL, + extended_lte_band_preference_size); if (mm_bands->len == 0) { g_clear_pointer (&mm_bands, g_array_unref); @@ -1680,6 +1708,7 @@ mm_shared_qmi_set_current_bands (MMIfaceModem *self, QmiClient *client = NULL; QmiNasBandPreference qmi_bands = 0; QmiNasLteBandPreference qmi_lte_bands = 0; + guint64 extended_qmi_lte_bands[4] = { 0 }; if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self), QMI_SERVICE_NAS, &client, @@ -1697,14 +1726,29 @@ mm_shared_qmi_set_current_bands (MMIfaceModem *self, g_object_unref (task); return; } - mm_modem_bands_to_qmi_band_preference (priv->supported_bands, &qmi_bands, &qmi_lte_bands); - } else - mm_modem_bands_to_qmi_band_preference (bands_array, &qmi_bands, &qmi_lte_bands); + bands_array = priv->supported_bands; + } + + mm_modem_bands_to_qmi_band_preference (bands_array, + &qmi_bands, + &qmi_lte_bands, + priv->feature_extended_lte_band_preference == FEATURE_SUPPORTED ? extended_qmi_lte_bands : NULL, + G_N_ELEMENTS (extended_qmi_lte_bands)); input = qmi_message_nas_set_system_selection_preference_input_new (); qmi_message_nas_set_system_selection_preference_input_set_band_preference (input, qmi_bands, NULL); - if (mm_iface_modem_is_3gpp_lte (self)) - qmi_message_nas_set_system_selection_preference_input_set_lte_band_preference (input, qmi_lte_bands, NULL); + if (mm_iface_modem_is_3gpp_lte (self)) { + if (priv->feature_extended_lte_band_preference == FEATURE_SUPPORTED) + qmi_message_nas_set_system_selection_preference_input_set_extended_lte_band_preference ( + input, + extended_qmi_lte_bands[0], + extended_qmi_lte_bands[1], + extended_qmi_lte_bands[2], + extended_qmi_lte_bands[3], + NULL); + else + qmi_message_nas_set_system_selection_preference_input_set_lte_band_preference (input, qmi_lte_bands, NULL); + } qmi_message_nas_set_system_selection_preference_input_set_change_duration (input, QMI_NAS_CHANGE_DURATION_PERMANENT, NULL); qmi_client_nas_set_system_selection_preference ( |