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'
This commit is contained in:
Aleksander Morgado
2018-10-05 13:17:28 +02:00
parent c906da415c
commit c7d5902c15
3 changed files with 172 additions and 26 deletions

View File

@@ -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,51 @@ 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;
memset (extended_qmi_lte_bands, 0, extended_qmi_lte_bands_size * sizeof (guint64));
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;
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;
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;
/* 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;
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;

View File

@@ -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,

View File

@@ -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,
&lte_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 (