From f7bab78581e02f65c25ff6a827222bcb6524c7e9 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Fri, 5 Oct 2018 13:17:28 +0200 Subject: shared-qmi: implement support for the 'extended' LTE band list This will allow us to configure via mmcli devices that support LTE bands that would not fit in the standard TLVs (e.g. band 66 below) or bands which aren't really reported in the standard TLVs (e.g. bands 46 and 48 below). $ sudo qmicli -d /dev/cdc-wdm0 -p --dms-get-band-capabilities [/dev/cdc-wdm0] Device band capabilities retrieved: Bands: 'wcdma-2100, wcdma-pcs-1900, wcdma-1700-us, wcdma-850-us, wcdma-800, wcdma-900, wcdma-1700-japan, wcdma-850-japan' LTE bands: '1, 2, 3, 4, 5, 7, 8, 12, 13, 14, 17, 18, 19, 20, 25, 38, 39, 40, 41, 42, 43' LTE bands (extended): '1, 2, 3, 4, 5, 7, 8, 12, 13, 14, 17, 18, 19, 20, 25, 26, 28, 29, 30, 32, 38, 39, 40, 41, 42, 43, 46, 48, 66' --- src/mm-modem-helpers-qmi.c | 133 +++++++++++++++++++++++++++++++++++++++------ src/mm-modem-helpers-qmi.h | 11 +++- 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 ( -- cgit v1.2.1