summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-10-05 13:17:28 +0200
committerAleksander Morgado <aleksander@aleksander.es>2018-10-09 11:46:23 +0200
commitf7bab78581e02f65c25ff6a827222bcb6524c7e9 (patch)
tree824c764dc466db3eb656069845092ec83e83112f
parent1ac79ccdfd82af5277c6baac7760d3a9588a0bd4 (diff)
downloadModemManager-aleksander/extended-band-list.tar.gz
shared-qmi: implement support for the 'extended' LTE band listaleksander/extended-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'
-rw-r--r--src/mm-modem-helpers-qmi.c133
-rw-r--r--src/mm-modem-helpers-qmi.h11
-rw-r--r--src/mm-shared-qmi.c58
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,
&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 (