diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2019-09-09 15:01:56 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2019-09-17 10:52:42 +0200 |
commit | be4fa661c12a45b4b6c278c3906e7c126ddae3e8 (patch) | |
tree | 4e25caf386e634874ef571db053701898a35695a | |
parent | 40521e315fc8cc94837c1508dca94efeed939f82 (diff) |
plugins,telit: refactor #BND command support
And added support for several new things, including:
* Setting "any" band now attempts to set all supported bands.
* Added new 2G band value '5' (egsm+dcs+pcs+g850).
* Setup support for two different 3G band combinations, a default one
plus an alternate one applicable to the LM940/960 models only. The
alternate combination is selected via udev tags.
During the refactor, the following Telit-specific helpers were also
removed and exchanged with more generic counterparts.
* mm_telit_bands_contains() -> mm_common_bands_garray_lookup()
* mm_telit_get_band_flags_from_string() -> mm_parse_uint_list()
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 14 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 5 | ||||
-rw-r--r-- | plugins/Makefile.am | 6 | ||||
-rw-r--r-- | plugins/telit/77-mm-telit-port-types.rules | 6 | ||||
-rw-r--r-- | plugins/telit/mm-broadband-modem-mbim-telit.c | 4 | ||||
-rw-r--r-- | plugins/telit/mm-broadband-modem-telit.c | 4 | ||||
-rw-r--r-- | plugins/telit/mm-modem-helpers-telit.c | 820 | ||||
-rw-r--r-- | plugins/telit/mm-modem-helpers-telit.h | 98 | ||||
-rw-r--r-- | plugins/telit/mm-shared-telit.c | 301 | ||||
-rw-r--r-- | plugins/telit/mm-shared-telit.h | 10 | ||||
-rw-r--r-- | plugins/telit/tests/test-mm-modem-helpers-telit.c | 675 |
11 files changed, 1061 insertions, 882 deletions
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c index a3cd16ab..8673421d 100644 --- a/libmm-glib/mm-common-helpers.c +++ b/libmm-glib/mm-common-helpers.c @@ -722,6 +722,20 @@ mm_common_bands_garray_cmp (GArray *a, GArray *b) return !different; } +gboolean +mm_common_bands_garray_lookup (GArray *array, + MMModemBand value) +{ + guint i; + + for (i = 0; i < array->len; i++) { + if (value == g_array_index (array, MMModemBand, i)) + return TRUE; + } + + return FALSE; +} + void mm_common_bands_garray_sort (GArray *array) { diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h index 71ef978a..5af58422 100644 --- a/libmm-glib/mm-common-helpers.h +++ b/libmm-glib/mm-common-helpers.h @@ -103,8 +103,9 @@ GVariant *mm_common_bands_garray_to_variant (GArray *array); GVariant *mm_common_build_bands_any (void); GVariant *mm_common_build_bands_unknown (void); -gboolean mm_common_bands_garray_cmp (GArray *a, GArray *b); -void mm_common_bands_garray_sort (GArray *array); +gboolean mm_common_bands_garray_cmp (GArray *a, GArray *b); +void mm_common_bands_garray_sort (GArray *array); +gboolean mm_common_bands_garray_lookup (GArray *array, MMModemBand value); gboolean mm_common_band_is_gsm (MMModemBand band); gboolean mm_common_band_is_utran (MMModemBand band); diff --git a/plugins/Makefile.am b/plugins/Makefile.am index d3242e0a..dd66d2f1 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -901,8 +901,12 @@ noinst_PROGRAMS += test-modem-helpers-telit test_modem_helpers_telit_SOURCES = \ telit/tests/test-mm-modem-helpers-telit.c \ $(NULL) -test_modem_helpers_telit_CPPFLAGS = $(PLUGIN_TELIT_COMPILER_FLAGS) +test_modem_helpers_telit_CPPFLAGS = \ + $(PLUGIN_TELIT_COMPILER_FLAGS) \ + $(TEST_COMMON_COMPILER_FLAGS) \ + $(NULL) test_modem_helpers_telit_LDADD = \ + $(TEST_COMMON_LIBADD_FLAGS) \ $(builddir)/libhelpers-telit.la \ $(top_builddir)/src/libhelpers.la \ $(top_builddir)/libmm-glib/libmm-glib.la \ diff --git a/plugins/telit/77-mm-telit-port-types.rules b/plugins/telit/77-mm-telit-port-types.rules index 4d48aa44..6ec5a7e7 100644 --- a/plugins/telit/77-mm-telit-port-types.rules +++ b/plugins/telit/77-mm-telit-port-types.rules @@ -45,4 +45,10 @@ ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="00", ENV{ ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1101", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" +# LM940/960 use alternate settings for 3G band management +ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="0x1040", ENV{ID_MM_TELIT_BND_ALTERNATE}="1" +ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="0x1041", ENV{ID_MM_TELIT_BND_ALTERNATE}="1" +ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="0x1042", ENV{ID_MM_TELIT_BND_ALTERNATE}="1" +ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="0x1043", ENV{ID_MM_TELIT_BND_ALTERNATE}="1" + LABEL="mm_telit_port_types_end" diff --git a/plugins/telit/mm-broadband-modem-mbim-telit.c b/plugins/telit/mm-broadband-modem-mbim-telit.c index d4a80951..43bce7fa 100644 --- a/plugins/telit/mm-broadband-modem-mbim-telit.c +++ b/plugins/telit/mm-broadband-modem-mbim-telit.c @@ -159,9 +159,9 @@ iface_modem_init (MMIfaceModem *iface) iface->set_current_bands = mm_shared_telit_modem_set_current_bands; iface->set_current_bands_finish = mm_shared_telit_modem_set_current_bands_finish; iface->load_current_bands = mm_shared_telit_modem_load_current_bands; - iface->load_current_bands_finish = mm_shared_telit_modem_load_bands_finish; + iface->load_current_bands_finish = mm_shared_telit_modem_load_current_bands_finish; iface->load_supported_bands = mm_shared_telit_modem_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_telit_modem_load_bands_finish; + iface->load_supported_bands_finish = mm_shared_telit_modem_load_supported_bands_finish; iface->load_supported_modes = load_supported_modes; iface->load_supported_modes_finish = load_supported_modes_finish; iface->load_current_modes = mm_shared_telit_load_current_modes; diff --git a/plugins/telit/mm-broadband-modem-telit.c b/plugins/telit/mm-broadband-modem-telit.c index 29f4b136..d6b1ea2d 100644 --- a/plugins/telit/mm-broadband-modem-telit.c +++ b/plugins/telit/mm-broadband-modem-telit.c @@ -1031,9 +1031,9 @@ iface_modem_init (MMIfaceModem *iface) iface->set_current_bands = mm_shared_telit_modem_set_current_bands; iface->set_current_bands_finish = mm_shared_telit_modem_set_current_bands_finish; iface->load_current_bands = mm_shared_telit_modem_load_current_bands; - iface->load_current_bands_finish = mm_shared_telit_modem_load_bands_finish; + iface->load_current_bands_finish = mm_shared_telit_modem_load_current_bands_finish; iface->load_supported_bands = mm_shared_telit_modem_load_supported_bands; - iface->load_supported_bands_finish = mm_shared_telit_modem_load_bands_finish; + iface->load_supported_bands_finish = mm_shared_telit_modem_load_supported_bands_finish; iface->load_unlock_retries_finish = modem_load_unlock_retries_finish; iface->load_unlock_retries = modem_load_unlock_retries; iface->reset = modem_reset; diff --git a/plugins/telit/mm-modem-helpers-telit.c b/plugins/telit/mm-modem-helpers-telit.c index c162964d..e4bacc5b 100644 --- a/plugins/telit/mm-modem-helpers-telit.c +++ b/plugins/telit/mm-modem-helpers-telit.c @@ -10,8 +10,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2015 Telit. - * + * Copyright (C) 2015-2019 Telit. + * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> */ #include <stdlib.h> @@ -27,114 +27,298 @@ #include "mm-modem-helpers.h" #include "mm-modem-helpers-telit.h" +/*****************************************************************************/ +/* AT#BND 2G values */ + +#define MM_MODEM_BAND_TELIT_2G_FIRST MM_MODEM_BAND_EGSM +#define MM_MODEM_BAND_TELIT_2G_LAST MM_MODEM_BAND_G850 + +#define B2G_FLAG(band) (1 << (band - MM_MODEM_BAND_TELIT_2G_FIRST)) + +/* Index of the array is the telit 2G band value [0-5] + * The bitmask value here is built from the 2G MMModemBand values right away. */ +static const guint32 telit_2g_to_mm_band_mask[] = { + [0] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS), + [1] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_PCS), + [2] = B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_G850), + [3] = B2G_FLAG (MM_MODEM_BAND_PCS) + B2G_FLAG (MM_MODEM_BAND_G850), + [4] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_PCS), + [5] = B2G_FLAG (MM_MODEM_BAND_EGSM) + B2G_FLAG (MM_MODEM_BAND_DCS) + B2G_FLAG (MM_MODEM_BAND_PCS) + B2G_FLAG (MM_MODEM_BAND_G850), +}; + +/*****************************************************************************/ +/* AT#BND 3G values */ + +/* NOTE: UTRAN_1 to UTRAN_9 enum values are NOT IN ORDER! + * E.g. numerically UTRAN_7 is after UTRAN_9... + * + * This array allows us to iterate them in a way which is a bit + * more friendly. + */ +static const guint band_utran_index[] = { + [MM_MODEM_BAND_UTRAN_1] = 1, + [MM_MODEM_BAND_UTRAN_2] = 2, + [MM_MODEM_BAND_UTRAN_3] = 3, + [MM_MODEM_BAND_UTRAN_4] = 4, + [MM_MODEM_BAND_UTRAN_5] = 5, + [MM_MODEM_BAND_UTRAN_6] = 6, + [MM_MODEM_BAND_UTRAN_7] = 7, + [MM_MODEM_BAND_UTRAN_8] = 8, + [MM_MODEM_BAND_UTRAN_9] = 9, + [MM_MODEM_BAND_UTRAN_10] = 10, + [MM_MODEM_BAND_UTRAN_11] = 11, + [MM_MODEM_BAND_UTRAN_12] = 12, + [MM_MODEM_BAND_UTRAN_13] = 13, + [MM_MODEM_BAND_UTRAN_14] = 14, + [MM_MODEM_BAND_UTRAN_19] = 19, + [MM_MODEM_BAND_UTRAN_20] = 20, + [MM_MODEM_BAND_UTRAN_21] = 21, + [MM_MODEM_BAND_UTRAN_22] = 22, + [MM_MODEM_BAND_UTRAN_25] = 25, + [MM_MODEM_BAND_UTRAN_26] = 26, + [MM_MODEM_BAND_UTRAN_32] = 32, +}; + +#define MM_MODEM_BAND_TELIT_3G_FIRST MM_MODEM_BAND_UTRAN_1 +#define MM_MODEM_BAND_TELIT_3G_LAST MM_MODEM_BAND_UTRAN_19 + +#define B3G_NUM(band) band_utran_index[band] +#define B3G_FLAG(band) ((B3G_NUM (band) > 0) ? (1 << (B3G_NUM (band) - B3G_NUM (MM_MODEM_BAND_TELIT_3G_FIRST))) : 0) + +/* Index of the arrays is the telit 3G band value. + * The bitmask value here is built from the 3G MMModemBand values right away. + * + * We have 2 different sets of bands that are different for values >=12, because + * the LM940/960 models support a different set of 3G bands. + */ + +#define TELIT_3G_TO_MM_BAND_MASK_DEFAULT_N_ELEMENTS 27 +static guint32 telit_3g_to_mm_band_mask_default[TELIT_3G_TO_MM_BAND_MASK_DEFAULT_N_ELEMENTS]; + +#define TELIT_3G_TO_MM_BAND_MASK_ALTERNATE_N_ELEMENTS 20 +static guint32 telit_3g_to_mm_band_mask_alternate[TELIT_3G_TO_MM_BAND_MASK_ALTERNATE_N_ELEMENTS]; + +static void +initialize_telit_3g_to_mm_band_masks (void) +{ + static gboolean initialized = FALSE; + + /* We need to initialize the arrays in runtime because gcc < 8 doesn't like initializing + * with operations that are using the band_utran_index constant array elements */ + + if (initialized) + return; + + telit_3g_to_mm_band_mask_default[0] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1); + telit_3g_to_mm_band_mask_default[1] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2); + telit_3g_to_mm_band_mask_default[2] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[3] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[4] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[5] = B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[6] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[7] = B3G_FLAG (MM_MODEM_BAND_UTRAN_4); + telit_3g_to_mm_band_mask_default[8] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[9] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[10] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[11] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[12] = B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[13] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3); + telit_3g_to_mm_band_mask_default[14] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[15] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[16] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[17] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[18] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[19] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[20] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[21] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6); + telit_3g_to_mm_band_mask_default[22] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_default[23] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3); + telit_3g_to_mm_band_mask_default[24] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_default[25] = B3G_FLAG (MM_MODEM_BAND_UTRAN_19); + telit_3g_to_mm_band_mask_default[26] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_19); + + /* Initialize alternate 3G band set */ + telit_3g_to_mm_band_mask_alternate[0] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1); + telit_3g_to_mm_band_mask_alternate[1] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2); + telit_3g_to_mm_band_mask_alternate[2] = B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[3] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[4] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[5] = B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[6] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[7] = B3G_FLAG (MM_MODEM_BAND_UTRAN_4); + telit_3g_to_mm_band_mask_alternate[8] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[9] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[10] = B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[11] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[12] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[13] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3); + telit_3g_to_mm_band_mask_alternate[14] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[15] = B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5); + telit_3g_to_mm_band_mask_alternate[16] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_3) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[17] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8); + telit_3g_to_mm_band_mask_alternate[18] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + B3G_FLAG (MM_MODEM_BAND_UTRAN_9) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_19); + telit_3g_to_mm_band_mask_alternate[19] = B3G_FLAG (MM_MODEM_BAND_UTRAN_1) + B3G_FLAG (MM_MODEM_BAND_UTRAN_2) + B3G_FLAG (MM_MODEM_BAND_UTRAN_4) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_5) + B3G_FLAG (MM_MODEM_BAND_UTRAN_6) + B3G_FLAG (MM_MODEM_BAND_UTRAN_8) + + B3G_FLAG (MM_MODEM_BAND_UTRAN_9) + B3G_FLAG (MM_MODEM_BAND_UTRAN_19); +} + +/*****************************************************************************/ +/* AT#BND 4G values + * + * The Telit-specific value for 4G bands is a bitmask of the band values, given + * in hexadecimal or decimal format. + */ + +#define MM_MODEM_BAND_TELIT_4G_FIRST MM_MODEM_BAND_EUTRAN_1 +#define MM_MODEM_BAND_TELIT_4G_LAST MM_MODEM_BAND_EUTRAN_44 + +#define B4G_FLAG(band) (((guint64) 1) << (band - MM_MODEM_BAND_TELIT_4G_FIRST)) /*****************************************************************************/ /* Set current bands helpers */ -void -mm_telit_get_band_flag (GArray *bands_array, - gint *flag2g, - gint *flag3g, - gint *flag4g) +gchar * +mm_telit_build_bnd_request (GArray *bands_array, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error) { - guint mask2g = 0; - guint mask3g = 0; - guint mask4g = 0; - guint found4g = FALSE; - guint i; + guint32 mask2g = 0; + guint32 mask3g = 0; + guint64 mask4g = 0; + guint i; + gint flag2g = -1; + gint flag3g = -1; + gint flag4g = -1; + gchar *cmd; + const guint32 *telit_3g_to_mm_band_mask; + guint telit_3g_to_mm_band_mask_n_elements; + + initialize_telit_3g_to_mm_band_masks (); + + /* Select correct 3G band mask */ + if (modem_alternate_3g_bands) { + telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_alternate; + telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_alternate); + } else { + telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_default; + telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_default); + } for (i = 0; i < bands_array->len; i++) { - MMModemBand band = g_array_index (bands_array, MMModemBand, i); - - if (flag2g != NULL) { - switch (band) { - case MM_MODEM_BAND_EGSM: - case MM_MODEM_BAND_DCS: - case MM_MODEM_BAND_PCS: - case MM_MODEM_BAND_G850: - mask2g += 1 << band; - break; - default: - break; + MMModemBand band; + + band = g_array_index (bands_array, MMModemBand, i); + + /* Convert 2G bands into a bitmask, to match against telit_2g_to_mm_band_mask. */ + if (flag2g && mm_common_band_is_gsm (band) && + (band >= MM_MODEM_BAND_TELIT_2G_FIRST) && (band <= MM_MODEM_BAND_TELIT_2G_LAST)) + mask2g += B2G_FLAG (band); + + /* Convert 3G bands into a bitmask, to match against telit_3g_to_mm_band_mask. */ + if (flag3g && mm_common_band_is_utran (band) && + (B3G_NUM (band) >= B3G_NUM (MM_MODEM_BAND_TELIT_3G_FIRST)) && (B3G_NUM (band) <= B3G_NUM (MM_MODEM_BAND_TELIT_3G_LAST))) + mask3g += B3G_FLAG (band); + + /* Convert 4G bands into a bitmask. We use a 64bit explicit bitmask so that + * all values fit correctly. */ + if (flag4g && mm_common_band_is_eutran (band) && + (band >= MM_MODEM_BAND_TELIT_4G_FIRST && band <= MM_MODEM_BAND_TELIT_4G_LAST)) + mask4g += B4G_FLAG (band); + } + + /* Get 2G-specific telit value */ + if (mask2g) { + for (i = 0; i < G_N_ELEMENTS (telit_2g_to_mm_band_mask); i++) { + if (mask2g == telit_2g_to_mm_band_mask[i]) { + flag2g = i; + break; } } + if (flag2g == -1) { + gchar *bands_str; - if (flag3g != NULL) { - switch (band) { - case MM_MODEM_BAND_UTRAN_1: - case MM_MODEM_BAND_UTRAN_2: - case MM_MODEM_BAND_UTRAN_3: - case MM_MODEM_BAND_UTRAN_4: - case MM_MODEM_BAND_UTRAN_5: - case MM_MODEM_BAND_UTRAN_6: - case MM_MODEM_BAND_UTRAN_7: - case MM_MODEM_BAND_UTRAN_8: - case MM_MODEM_BAND_UTRAN_9: - mask3g += 1 << band; - break; - default: - break; + bands_str = mm_common_build_bands_string ((const MMModemBand *)(bands_array->data), bands_array->len); + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't find matching 2G bands Telit value for band combination: '%s'", bands_str); + g_free (bands_str); + return NULL; + } + } + + /* Get 3G-specific telit value */ + if (mask3g) { + for (i = 0; i < telit_3g_to_mm_band_mask_n_elements; i++) { + if (mask3g == telit_3g_to_mm_band_mask[i]) { + flag3g = i; + break; } } + if (flag3g == -1) { + gchar *bands_str; - if (flag4g != NULL && - band >= MM_MODEM_BAND_EUTRAN_1 && band <= MM_MODEM_BAND_EUTRAN_44) { - mask4g += 1 << (band - MM_MODEM_BAND_EUTRAN_1); - found4g = TRUE; + bands_str = mm_common_build_bands_string ((const MMModemBand *)(bands_array->data), bands_array->len); + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't find matching 3G bands Telit value for band combination: '%s'", bands_str); + g_free (bands_str); + return NULL; } } - /* Get 2G flag */ - if (flag2g != NULL) { - if (mask2g == ((1 << MM_MODEM_BAND_EGSM) + (1 << MM_MODEM_BAND_DCS))) - *flag2g = 0; - else if (mask2g == ((1 << MM_MODEM_BAND_EGSM) + (1 << MM_MODEM_BAND_PCS))) - *flag2g = 1; - else if (mask2g == ((1 << MM_MODEM_BAND_G850) + (1 << MM_MODEM_BAND_DCS))) - *flag2g = 2; - else if (mask2g == ((1 << MM_MODEM_BAND_G850) + (1 << MM_MODEM_BAND_PCS))) - *flag2g = 3; - else - *flag2g = -1; - } + /* Get 4G-specific telit band bitmask */ + flag4g = (mask4g != 0) ? mask4g : -1; - /* Get 3G flag */ - if (flag3g != NULL) { - if (mask3g == (1 << MM_MODEM_BAND_UTRAN_1)) - *flag3g = 0; - else if (mask3g == (1 << MM_MODEM_BAND_UTRAN_2)) - *flag3g = 1; - else if (mask3g == (1 << MM_MODEM_BAND_UTRAN_5)) - *flag3g = 2; - else if (mask3g == ((1 << MM_MODEM_BAND_UTRAN_1) + - (1 << MM_MODEM_BAND_UTRAN_2) + - (1 << MM_MODEM_BAND_UTRAN_5))) - *flag3g = 3; - else if (mask3g == ((1 << MM_MODEM_BAND_UTRAN_2) + - (1 << MM_MODEM_BAND_UTRAN_5))) - *flag3g = 4; - else if (mask3g == (1 << MM_MODEM_BAND_UTRAN_8)) - *flag3g = 5; - else if (mask3g == ((1 << MM_MODEM_BAND_UTRAN_1) + - (1 << MM_MODEM_BAND_UTRAN_8))) - *flag3g = 6; - else if (mask3g == (1 << MM_MODEM_BAND_UTRAN_4)) - *flag3g = 7; - else - *flag3g = -1; + /* If the modem supports a given access tech, we must always give band settings + * for the specific tech */ + if (modem_is_2g && flag2g == -1) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, + "None or invalid 2G bands combination in the provided list"); + return NULL; } - - /* 4G flag correspond to the mask */ - if (flag4g != NULL) { - if (found4g) - *flag4g = mask4g; - else - *flag4g = -1; + if (modem_is_3g && flag3g == -1) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, + "None or invalid 3G bands combination in the provided list"); + return NULL; + } + if (modem_is_4g && flag4g == -1) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND, + "None or invalid 4G bands combination in the provided list"); + return NULL; } -} -#define SUPP_BAND_RESPONSE_REGEX "#BND:\\s*\\((?P<Bands2G>[0-9\\-,]*)\\)(,\\s*\\((?P<Bands3G>[0-9\\-,]*)\\))?(,\\s*\\((?P<Bands4G>[0-9\\-,]*)\\))?" -#define CURR_BAND_RESPONSE_REGEX "#BND:\\s*(?P<Bands2G>\\d+)(,\\s*(?P<Bands3G>\\d+))?(,\\s*(?P<Bands4G>\\d+))?" + if (modem_is_2g && !modem_is_3g && !modem_is_4g) + cmd = g_strdup_printf ("#BND=%d", flag2g); + else if (!modem_is_2g && modem_is_3g && !modem_is_4g) + cmd = g_strdup_printf ("#BND=0,%d", flag3g); + else if (!modem_is_2g && !modem_is_3g && modem_is_4g) + cmd = g_strdup_printf ("#BND=0,0,%d", flag4g); + else if (modem_is_2g && modem_is_3g && !modem_is_4g) + cmd = g_strdup_printf ("#BND=%d,%d", flag2g, flag3g); + else if (!modem_is_2g && modem_is_3g && modem_is_4g) + cmd = g_strdup_printf ("#BND=0,%d,%d", flag3g, flag4g); + else if (modem_is_2g && !modem_is_3g && modem_is_4g) + cmd = g_strdup_printf ("#BND=%d,0,%d", flag2g, flag4g); + else if (modem_is_2g && modem_is_3g && modem_is_4g) + cmd = g_strdup_printf ("#BND=%d,%d,%d", flag2g, flag3g, flag4g); + else + g_assert_not_reached (); + + return cmd; +} /*****************************************************************************/ /* #BND response parser @@ -187,333 +371,255 @@ mm_telit_get_band_flag (GArray *bands_array, * 4 = 3G band flag 4 is U1900 + U850 * */ -gboolean -mm_telit_parse_bnd_response (const gchar *response, - gboolean modem_is_2g, - gboolean modem_is_3g, - gboolean modem_is_4g, - MMTelitLoadBandsType band_type, - GArray **supported_bands, - GError **error) -{ - GArray *bands = NULL; - GMatchInfo *match_info = NULL; - GRegex *r = NULL; - gboolean ret = FALSE; - - switch (band_type) { - case LOAD_SUPPORTED_BANDS: - /* Parse #BND=? response */ - r = g_regex_new (SUPP_BAND_RESPONSE_REGEX, G_REGEX_RAW, 0, NULL); - break; - case LOAD_CURRENT_BANDS: - /* Parse #BND? response */ - r = g_regex_new (CURR_BAND_RESPONSE_REGEX, G_REGEX_RAW, 0, NULL); - default: - break; - } - - if (!g_regex_match (r, response, 0, &match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not parse response '%s'", response); - goto end; - } - - if (!g_match_info_matches (match_info)) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find matches in response '%s'", response); - goto end; - } - - bands = g_array_new (TRUE, TRUE, sizeof (MMModemBand)); - - if (modem_is_2g && !mm_telit_get_2g_mm_bands (match_info, &bands, error)) - goto end; - - if (modem_is_3g && !mm_telit_get_3g_mm_bands (match_info, &bands, error)) - goto end; - - if (modem_is_4g && !mm_telit_get_4g_mm_bands (match_info, &bands, error)) - goto end; - - *supported_bands = bands; - ret = TRUE; - -end: - if (!ret && bands != NULL) - g_array_free (bands, TRUE); - - g_match_info_free (match_info); - g_regex_unref (r); - - return ret; -} - -gboolean -mm_telit_get_2g_mm_bands (GMatchInfo *match_info, - GArray **bands, - GError **error) +static gboolean +telit_get_2g_mm_bands (GMatchInfo *match_info, + GArray **bands, + GError **error) { - GArray *flags = NULL; - gchar *match_str = NULL; - guint i; - gboolean ret = TRUE; - - TelitToMMBandMap map [5] = { - { BND_FLAG_GSM900_DCS1800, {MM_MODEM_BAND_EGSM, MM_MODEM_BAND_DCS, MM_MODEM_BAND_UNKNOWN} }, /* 0 */ - { BND_FLAG_GSM900_PCS1900, {MM_MODEM_BAND_EGSM, MM_MODEM_BAND_PCS, MM_MODEM_BAND_UNKNOWN} }, /* 1 */ - { BND_FLAG_GSM850_DCS1800, {MM_MODEM_BAND_DCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_UNKNOWN} }, /* 2 */ - { BND_FLAG_GSM850_PCS1900, {MM_MODEM_BAND_PCS, MM_MODEM_BAND_G850, MM_MODEM_BAND_UNKNOWN} }, /* 3 */ - { BND_FLAG_UNKNOWN, {}}, - }; + GError *inner_error = NULL; + GArray *values = NULL; + gchar *match_str = NULL; + guint i; match_str = g_match_info_fetch_named (match_info, "Bands2G"); - - if (match_str == NULL || match_str[0] == '\0') { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 2G band flags from response"); - ret = FALSE; - goto end; + if (!match_str || match_str[0] == '\0') { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not find 2G band values from response"); + goto out; } - flags = g_array_new (FALSE, FALSE, sizeof (guint)); + values = mm_parse_uint_list (match_str, &inner_error); + if (!values) + goto out; - if (!mm_telit_get_band_flags_from_string (match_str, &flags, error)) { - ret = FALSE; - goto end; - } + for (i = 0; i < values->len; i++) { + guint value; - for (i = 0; i < flags->len; i++) { - guint flag; + value = g_array_index (values, guint, i); + if (value < G_N_ELEMENTS (telit_2g_to_mm_band_mask)) { + guint j; - flag = g_array_index (flags, guint, i); - if (!mm_telit_update_band_array (flag, map, bands, error)) { - ret = FALSE; - goto end; - } + for (j = MM_MODEM_BAND_TELIT_2G_FIRST; j <= MM_MODEM_BAND_TELIT_2G_LAST; j++) { + if ((telit_2g_to_mm_band_mask[value] & B2G_FLAG (j)) && !mm_common_bands_garray_lookup (*bands, j)) + *bands = g_array_append_val (*bands, j); + } + } else + mm_dbg ("unhandled telit 2G band value configuration: %u", value); } -end: +out: g_free (match_str); + g_clear_pointer (&values, g_array_unref); - if (flags != NULL) - g_array_free (flags, TRUE); - - return ret; + if (inner_error) { + g_propagate_error (error, inner_error); + return FALSE; + } + return TRUE; } -gboolean -mm_telit_get_3g_mm_bands (GMatchInfo *match_info, - GArray **bands, - GError **error) +static gboolean +telit_get_3g_mm_bands (GMatchInfo *match_info, + GArray **bands, + gboolean modem_alternate_3g_bands, + GError **error) { - GArray *flags = NULL; - gchar *match_str = NULL; - guint i; - gboolean ret = TRUE; - - TelitToMMBandMap map [] = { - { BND_FLAG_0, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_1, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_2, { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_3, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_4, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_5, { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_6, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_7, { MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UNKNOWN} }, - { BND_FLAG_8, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_9, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_10, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_12, { MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN}}, - { BND_FLAG_13, { MM_MODEM_BAND_UTRAN_3, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_14, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_15, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_3, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_16, { MM_MODEM_BAND_UTRAN_8, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_17, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_18, { MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN}}, - { BND_FLAG_19, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN }}, - { BND_FLAG_20, { MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN}}, - { BND_FLAG_21, { MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_6, MM_MODEM_BAND_UNKNOWN}}, - { BND_FLAG_UNKNOWN, {}}, - }; + GError *inner_error = NULL; + GArray *values = NULL; + gchar *match_str = NULL; + guint i; + const guint32 *telit_3g_to_mm_band_mask; + guint telit_3g_to_mm_band_mask_n_elements; + + initialize_telit_3g_to_mm_band_masks (); + + /* Select correct 3G band mask */ + if (modem_alternate_3g_bands) { + telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_alternate; + telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_alternate); + } else { + telit_3g_to_mm_band_mask = telit_3g_to_mm_band_mask_default; + telit_3g_to_mm_band_mask_n_elements = G_N_ELEMENTS (telit_3g_to_mm_band_mask_default); + } match_str = g_match_info_fetch_named (match_info, "Bands3G"); - - if (match_str == NULL || match_str[0] == '\0') { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not find 3G band flags from response"); - ret = FALSE; - goto end; + if (!match_str || match_str[0] == '\0') { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not find 3G band values from response"); + goto out; } - flags = g_array_new (FALSE, FALSE, sizeof (guint)); + values = mm_parse_uint_list (match_str, &inner_error); + if (!values) + goto out; - if (!mm_telit_get_band_flags_from_string (match_str, &flags, error)) { - ret = FALSE; - goto end; - } + for (i = 0; i < values->len; i++) { + guint value; - for (i = 0; i < flags->len; i++) { - guint flag; + value = g_array_index (values, guint, i); - flag = g_array_index (flags, guint, i); - if (!mm_telit_update_band_array (flag, map, bands, error)) { - ret = FALSE; - goto end; - } + if (value < telit_3g_to_mm_band_mask_n_elements) { + guint j; + + for (j = 0; j < G_N_ELEMENTS (band_utran_index); j++) { + /* ignore non-3G bands */ + if (band_utran_index[j] == 0) + continue; + + if ((telit_3g_to_mm_band_mask[value] & B3G_FLAG (j)) && !mm_common_bands_garray_lookup (*bands, j)) + *bands = g_array_append_val (*bands, j); + } + } else + mm_dbg ("unhandled telit 3G band value configuration: %u", value); } -end: +out: g_free (match_str); + g_clear_pointer (&values, g_array_unref); - if (flags != NULL) - g_array_free (flags, TRUE); - - return ret; + if (inner_error) { + g_propagate_error (error, inner_error); + return FALSE; + } + return TRUE; } -gboolean -mm_telit_get_4g_mm_bands (GMatchInfo *match_info, - GArray **bands, - GError **error) +static gboolean +telit_get_4g_mm_bands (GMatchInfo *match_info, + GArray **bands, + GError **error) { - MMModemBand band; - gboolean ret = TRUE; - gchar *match_str = NULL; - guint i; - guint value; - gchar **tokens; + GError *inner_error = NULL; + MMModemBand band; + gchar *match_str = NULL; + guint64 value; + gchar **tokens = NULL; match_str = g_match_info_fetch_named (match_info, "Bands4G"); - - if (match_str == NULL || match_str[0] == '\0') { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + if (!match_str || match_str[0] == '\0') { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Could not find 4G band flags from response"); - ret = FALSE; - goto end; + goto out; } - if (strstr (match_str, "-")) { - tokens = g_strsplit (match_str, "-", -1); - if (tokens == NULL) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not get 4G band ranges from string '%s'", - match_str); - ret = FALSE; - goto end; - } - sscanf (tokens[1], "%d", &value); - g_strfreev (tokens); - } else { - sscanf (match_str, "%d", &value); + /* splitting will never return NULL as string is not empty */ + tokens = g_strsplit (match_str, "-", -1); + + /* If this is a range, get upper threshold, which contains the total supported mask */ + if (!mm_get_u64_from_str (tokens[1] ? tokens[1] : tokens[0], &value)) { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not parse 4G band mask from string: '%s'", match_str); + goto out; } - for (i = 0; value > 0; i++) { - if (value % 2 != 0) { - band = MM_MODEM_BAND_EUTRAN_1 + i; + for (band = MM_MODEM_BAND_TELIT_4G_FIRST; band <= MM_MODEM_BAND_TELIT_4G_LAST; band++) { + if ((value & B4G_FLAG (band)) && !mm_common_bands_garray_lookup (*bands, band)) g_array_append_val (*bands, band); - } - value = value >> 1; } -end: +out: + g_strfreev (tokens); g_free (match_str); - return ret; -} - -gboolean -mm_telit_bands_contains (GArray *mm_bands, const MMModemBand mm_band) -{ - guint i; - - for (i = 0; i < mm_bands->len; i++) { - if (mm_band == g_array_index (mm_bands, MMModemBand, i)) - return TRUE; + if (inner_error) { + g_propagate_error (error, inner_error); + return FALSE; } - - return FALSE; + return TRUE; } -gboolean -mm_telit_update_band_array (const gint bands_flag, - const TelitToMMBandMap *map, - GArray **bands, - GError **error) +typedef enum { + LOAD_BANDS_TYPE_SUPPORTED, + LOAD_BANDS_TYPE_CURRENT, +} LoadBandsType; + +static GArray * +common_parse_bnd_response (const gchar *response, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + LoadBandsType load_type, + GError **error) { - guint i; - guint j; - - for (i = 0; map[i].flag != BND_FLAG_UNKNOWN; i++) { - if (bands_flag == map[i].flag) { - for (j = 0; map[i].mm_bands[j] != MM_MODEM_BAND_UNKNOWN; j++) { - if (!mm_telit_bands_contains (*bands, map[i].mm_bands[j])) { - g_array_append_val (*bands, map[i].mm_bands[j]); - } - } - - return TRUE; - } - } - - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "No MM band found for Telit #BND flag '%d'", - bands_flag); - - return FALSE; -} + GError *inner_error = NULL; + GArray *bands = NULL; + GMatchInfo *match_info = NULL; + GRegex *r; + static const gchar *load_bands_regex[] = { + [LOAD_BANDS_TYPE_SUPPORTED] = "#BND:\\s*\\((?P<Bands2G>[0-9\\-,]*)\\)(,\\s*\\((?P<Bands3G>[0-9\\-,]*)\\))?(,\\s*\\((?P<Bands4G>[0-9\\-,]*)\\))?", + [LOAD_BANDS_TYPE_CURRENT] = "#BND:\\s*(?P<Bands2G>\\d+)(,\\s*(?P<Bands3G>\\d+))?(,\\s*(?P<Bands4G>\\d+))?", + }; -gboolean -mm_telit_get_band_flags_from_string (const gchar *flag_str, - GArray **band_flags, - GError **error) -{ - gchar **range; - gchar **tokens; - guint flag; - guint i; + r = g_regex_new (load_bands_regex[load_type], G_REGEX_RAW, 0, NULL); + g_assert (r); - if (flag_str == NULL || flag_str[0] == '\0') { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "String is empty, no band flags to parse"); - return FALSE; + if (!g_regex_match (r, response, 0, &match_info)) { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not parse response '%s'", response); + goto out; } - tokens = g_strsplit (flag_str, ",", -1); - if (!tokens) { - g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, - "Could not get the list of flags"); - return FALSE; + if (!g_match_info_matches (match_info)) { + g_set_error (&inner_error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not find matches in response '%s'", response); + goto out; } - for (i = 0; tokens[i]; i++) { - /* check whether tokens[i] defines a - * single band value or a range of bands */ - if (!strstr (tokens[i], "-")) { - sscanf (tokens[i], "%d", &flag); - g_array_append_val (*band_flags, flag); - } else { - gint range_start; - gint range_end; + bands = g_array_new (TRUE, TRUE, sizeof (MMModemBand)); - range = g_strsplit (tokens[i], "-", 2); + if (modem_is_2g && !telit_get_2g_mm_bands (match_info, &bands, &inner_error)) + goto out; - sscanf (range[0], "%d", &range_start); - sscanf (range[1], "%d", &range_end); + if (modem_is_3g && !telit_get_3g_mm_bands (match_info, &bands, modem_alternate_3g_bands, &inner_error)) + goto out; - for (flag = range_start; flag <= range_end; flag++) { - g_array_append_val (*band_flags, flag); - } + if (modem_is_4g && !telit_get_4g_mm_bands (match_info, &bands, &inner_error)) + goto out; - g_strfreev (range); - } +out: + g_match_info_free (match_info); + g_regex_unref (r); + + if (inner_error) { + g_propagate_error (error, inner_error); + g_clear_pointer (&bands, g_array_unref); + return NULL; } - g_strfreev (tokens); + return bands; +} - return TRUE; +GArray * +mm_telit_parse_bnd_query_response (const gchar *response, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error) +{ + return common_parse_bnd_response (response, + modem_is_2g, modem_is_3g, modem_is_4g, + modem_alternate_3g_bands, + LOAD_BANDS_TYPE_CURRENT, + error); +} + +GArray * +mm_telit_parse_bnd_test_response (const gchar *response, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error) +{ + return common_parse_bnd_response (response, + modem_is_2g, modem_is_3g, modem_is_4g, + modem_alternate_3g_bands, + LOAD_BANDS_TYPE_SUPPORTED, + error); } /*****************************************************************************/ diff --git a/plugins/telit/mm-modem-helpers-telit.h b/plugins/telit/mm-modem-helpers-telit.h index 0b82c42d..491e8fa6 100644 --- a/plugins/telit/mm-modem-helpers-telit.h +++ b/plugins/telit/mm-modem-helpers-telit.h @@ -10,8 +10,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2015 Telit. - * + * Copyright (C) 2015-2019 Telit. + * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> */ #ifndef MM_MODEM_HELPERS_TELIT_H #define MM_MODEM_HELPERS_TELIT_H @@ -19,81 +19,25 @@ #include <glib.h> #include "ModemManager.h" -#define MAX_BANDS_LIST_LEN 20 - -#define BND_FLAG_UNKNOWN -1 - -/* AT#BND 2G flags */ -typedef enum { - BND_FLAG_GSM900_DCS1800, - BND_FLAG_GSM900_PCS1900, - BND_FLAG_GSM850_DCS1800, - BND_FLAG_GSM850_PCS1900, -} BndFlag2G; - -/* AT#BND 3G flags */ -typedef enum { - BND_FLAG_0, /* B1 (2100 MHz) */ - BND_FLAG_1, /* B2 (1900 MHz) */ - BND_FLAG_2, /* B5 (850 MHz) */ - BND_FLAG_3, /* B1 (2100 MHz) + B2 (1900 MHz) + B5 (850 MHz) */ - BND_FLAG_4, /* B2 (1900 MHz) + B5 (850 MHz) */ - BND_FLAG_5, /* B8 (900 MHz) */ - BND_FLAG_6, /* B1 (2100 MHz) + B8 (900 MHz) */ - BND_FLAG_7, /* B4 (1700 MHz) */ - BND_FLAG_8, /* B1 (2100 MHz) + B5 (850 MHz) */ - BND_FLAG_9, /* B1 (2100 MHz) + B8 (900 MHz) + B5 (850 MHz) */ - BND_FLAG_10, /* B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) */ - BND_FLAG_12, /* B6 (800 MHz) */ - BND_FLAG_13, /* B3 (1800 MHz) */ - BND_FLAG_14, /* B1 (2100 MHz) + B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) + B6 (800MHz) */ - BND_FLAG_15, /* B1 (2100 MHz) + B8 (900 MHz) + B3 (1800 MHz) */ - BND_FLAG_16, /* B8 (900 MHz) + B5 (850 MHz) */ - BND_FLAG_17, /* B2 (1900 MHz) + B4 (1700 MHz) + B5 (850 MHz) + B6 (800 MHz) */ - BND_FLAG_18, /* B1 (2100 MHz) + B2 (1900 MHz) + B5 (850 MHz) + B6 (800 MHz) */ - BND_FLAG_19, /* B2 (1900 MHz) + B6 (800 MHz) */ - BND_FLAG_20, /* B5 (850 MHz) + B6 (800 MHz) */ - BND_FLAG_21, /* B2 (1900 MHz) + B5 (850 MHz) + B6 (800 MHz) */ -} BndFlag3G; - -typedef struct { - gint flag; - MMModemBand mm_bands[MAX_BANDS_LIST_LEN]; -} TelitToMMBandMap; - -typedef enum { - LOAD_SUPPORTED_BANDS, - LOAD_CURRENT_BANDS -} MMTelitLoadBandsType; - -/* #BND response parser */ -gboolean -mm_telit_parse_bnd_response (const gchar *response, - gboolean modem_is_2g, - gboolean modem_is_3g, - gboolean modem_is_4g, - MMTelitLoadBandsType band_type, - GArray **supported_bands, - GError **error); - - -gboolean mm_telit_bands_contains (GArray *mm_bands, const MMModemBand mm_band); - -gboolean mm_telit_update_band_array (const gint bands_flag, - const TelitToMMBandMap *map, - GArray **bands, - GError **error); - -gboolean mm_telit_get_band_flags_from_string (const gchar *flag_str, GArray **band_flags, GError **error); -gboolean mm_telit_get_2g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error); -gboolean mm_telit_get_3g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error); -gboolean mm_telit_get_4g_mm_bands(GMatchInfo *match_info, GArray **bands, GError **error); - -gboolean mm_telit_update_2g_bands(gchar *band_list, GMatchInfo **match_info, GArray **bands, GError **error); -gboolean mm_telit_update_3g_bands(gchar *band_list, GMatchInfo **match_info, GArray **bands, GError **error); -gboolean mm_telit_update_4g_bands(GArray** bands, GMatchInfo *match_info, GError **error); - -void mm_telit_get_band_flag (GArray *bands_array, gint *flag_2g, gint *flag_3g, gint *flag_4g); +/* #BND response parsers and request builder */ +GArray *mm_telit_parse_bnd_query_response (const gchar *response, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error); +GArray *mm_telit_parse_bnd_test_response (const gchar *response, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error); +gchar *mm_telit_build_bnd_request (GArray *bands_array, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GError **error); /* #QSS? response parser */ typedef enum { /*< underscore_name=mm_telit_qss_status >*/ diff --git a/plugins/telit/mm-shared-telit.c b/plugins/telit/mm-shared-telit.c index c79f7ff0..f1eb0518 100644 --- a/plugins/telit/mm-shared-telit.c +++ b/plugins/telit/mm-shared-telit.c @@ -32,6 +32,59 @@ #include "mm-shared-telit.h" /*****************************************************************************/ +/* Private data context */ + +#define PRIVATE_TAG "shared-telit-private-tag" +static GQuark private_quark; + +typedef struct { + gboolean alternate_3g_bands; + GArray *supported_bands; +} Private; + +static void +private_free (Private *priv) +{ + if (priv->supported_bands) + g_array_unref (priv->supported_bands); + g_slice_free (Private, priv); +} + +static void +initialize_alternate_3g_band (MMSharedTelit *self, + Private *priv) +{ + MMPort *primary; + MMKernelDevice *port; + + primary = MM_PORT (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self))); + port = mm_port_peek_kernel_device (primary); + + /* Lookup for the tag specifying that we're using the alternate 3G band mapping */ + priv->alternate_3g_bands = mm_kernel_device_get_global_property_as_boolean (port, "ID_MM_TELIT_BND_ALTERNATE"); + if (priv->alternate_3g_bands) + mm_dbg ("Telit modem using alternate 3G band mask setup"); +} + +static Private * +get_private (MMSharedTelit *self) +{ + Private *priv; + + if (G_UNLIKELY (!private_quark)) + private_quark = g_quark_from_static_string (PRIVATE_TAG); + + priv = g_object_get_qdata (G_OBJECT (self), private_quark); + if (!priv) { + priv = g_slice_new0 (Private); + initialize_alternate_3g_band (self, priv); + g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free); + } + + return priv; +} + +/*****************************************************************************/ /* Load current mode (Modem interface) */ gboolean @@ -114,126 +167,133 @@ mm_shared_telit_load_current_modes (MMIfaceModem *self, /*****************************************************************************/ /* Load supported bands (Modem interface) */ -typedef struct { - gboolean mm_modem_is_2g; - gboolean mm_modem_is_3g; - gboolean mm_modem_is_4g; - MMTelitLoadBandsType band_type; -} LoadBandsContext; - -static void -mm_shared_telit_load_bands_context_free (LoadBandsContext *ctx) +GArray * +mm_shared_telit_modem_load_supported_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) { - g_slice_free (LoadBandsContext, ctx); + return g_task_propagate_pointer (G_TASK (res), error); } static void -mm_shared_telit_load_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) +mm_shared_telit_load_supported_bands_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) { const gchar *response; - GError *error = NULL; - GArray *bands = NULL; - LoadBandsContext *ctx; + GError *error = NULL; + Private *priv; - ctx = g_task_get_task_data (task); - response = mm_base_modem_at_command_finish (self, res, &error); + priv = get_private (MM_SHARED_TELIT (self)); + response = mm_base_modem_at_command_finish (self, res, &error); if (!response) g_task_return_error (task, error); - else if (!mm_telit_parse_bnd_response (response, - ctx->mm_modem_is_2g, - ctx->mm_modem_is_3g, - ctx->mm_modem_is_4g, - ctx->band_type, - &bands, - &error)) - g_task_return_error (task, error); - else - g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); + else { + GArray *bands; + + bands = mm_telit_parse_bnd_test_response (response, + mm_iface_modem_is_2g (MM_IFACE_MODEM (self)), + mm_iface_modem_is_3g (MM_IFACE_MODEM (self)), + mm_iface_modem_is_4g (MM_IFACE_MODEM (self)), + priv->alternate_3g_bands, + &error); + if (!bands) + g_task_return_error (task, error); + else { + /* Store supported bands to be able to build ANY when setting */ + priv->supported_bands = g_array_ref (bands); + g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); + } + } g_object_unref (task); } void -mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) { - GTask *task; - LoadBandsContext *ctx; - - ctx = g_slice_new0 (LoadBandsContext); - - ctx->mm_modem_is_2g = mm_iface_modem_is_2g (self); - ctx->mm_modem_is_3g = mm_iface_modem_is_3g (self); - ctx->mm_modem_is_4g = mm_iface_modem_is_4g (self); - ctx->band_type = LOAD_SUPPORTED_BANDS; - - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)mm_shared_telit_load_bands_context_free); - mm_base_modem_at_command (MM_BASE_MODEM (self), "#BND=?", 3, - FALSE, - (GAsyncReadyCallback) mm_shared_telit_load_bands_ready, - task); + TRUE, + (GAsyncReadyCallback) mm_shared_telit_load_supported_bands_ready, + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ /* Load current bands (Modem interface) */ GArray * -mm_shared_telit_modem_load_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) +mm_shared_telit_modem_load_current_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) { - return (GArray *) g_task_propagate_pointer (G_TASK (res), error); + return g_task_propagate_pointer (G_TASK (res), error); } -void -mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +static void +mm_shared_telit_load_current_bands_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) { - GTask *task; - LoadBandsContext *ctx; + const gchar *response; + GError *error = NULL; + Private *priv; - ctx = g_slice_new0 (LoadBandsContext); + priv = get_private (MM_SHARED_TELIT (self)); - ctx->mm_modem_is_2g = mm_iface_modem_is_2g (self); - ctx->mm_modem_is_3g = mm_iface_modem_is_3g (self); - ctx->mm_modem_is_4g = mm_iface_modem_is_4g (self); - ctx->band_type = LOAD_CURRENT_BANDS; + response = mm_base_modem_at_command_finish (self, res, &error); + if (!response) + g_task_return_error (task, error); + else { + GArray *bands; + + bands = mm_telit_parse_bnd_query_response (response, + mm_iface_modem_is_2g (MM_IFACE_MODEM (self)), + mm_iface_modem_is_3g (MM_IFACE_MODEM (self)), + mm_iface_modem_is_4g (MM_IFACE_MODEM (self)), + priv->alternate_3g_bands, + &error); + if (!bands) + g_task_return_error (task, error); + else + g_task_return_pointer (task, bands, (GDestroyNotify)g_array_unref); + } - task = g_task_new (self, NULL, callback, user_data); - g_task_set_task_data (task, ctx, (GDestroyNotify)mm_shared_telit_load_bands_context_free); + g_object_unref (task); +} +void +mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ mm_base_modem_at_command (MM_BASE_MODEM (self), "#BND?", 3, FALSE, - (GAsyncReadyCallback) mm_shared_telit_load_bands_ready, - task); + (GAsyncReadyCallback) mm_shared_telit_load_current_bands_ready, + g_task_new (self, NULL, callback, user_data)); } /*****************************************************************************/ /* Set current bands (Modem interface) */ gboolean -mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) +mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void -mm_shared_telit_modem_set_current_bands_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) +set_current_bands_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) { GError *error = NULL; @@ -247,88 +307,47 @@ mm_shared_telit_modem_set_current_bands_ready (MMBaseModem *self, } void -mm_shared_telit_modem_set_current_bands (MMIfaceModem *self, - GArray *bands_array, - GAsyncReadyCallback callback, - gpointer user_data) +mm_shared_telit_modem_set_current_bands (MMIfaceModem *self, + GArray *bands_array, + GAsyncReadyCallback callback, + gpointer user_data) { - gchar *cmd; - gint flag2g; - gint flag3g; - gint flag4g; - gboolean is_2g; - gboolean is_3g; - gboolean is_4g; - GTask *task; - - mm_telit_get_band_flag (bands_array, &flag2g, &flag3g, &flag4g); + GTask *task; + GError *error = NULL; + gchar *cmd; + Private *priv; - is_2g = mm_iface_modem_is_2g (self); - is_3g = mm_iface_modem_is_3g (self); - is_4g = mm_iface_modem_is_4g (self); + priv = get_private (MM_SHARED_TELIT (self)); - if (is_2g && flag2g == -1) { - g_task_report_new_error (self, - callback, - user_data, - mm_shared_telit_modem_set_current_bands, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "None or invalid 2G bands combination in the provided list"); - return; - } + task = g_task_new (self, NULL, callback, user_data); - if (is_3g && flag3g == -1) { - g_task_report_new_error (self, - callback, - user_data, - mm_shared_telit_modem_set_current_bands, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "None or invalid 3G bands combination in the provided list"); - return; + if (bands_array->len == 1 && g_array_index (bands_array, MMModemBand, 0) == MM_MODEM_BAND_ANY) { + if (!priv->supported_bands) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Couldn't build ANY band settings: unknown supported bands"); + g_object_unref (task); + return; + } + bands_array = priv->supported_bands; } - if (is_4g && flag4g == -1) { - g_task_report_new_error (self, - callback, - user_data, - mm_shared_telit_modem_set_current_bands, - MM_CORE_ERROR, - MM_CORE_ERROR_NOT_FOUND, - "None or invalid 4G bands combination in the provided list"); + cmd = mm_telit_build_bnd_request (bands_array, + mm_iface_modem_is_2g (self), + mm_iface_modem_is_3g (self), + mm_iface_modem_is_4g (self), + priv->alternate_3g_bands, + &error); + if (!cmd) { + g_task_return_error (task, error); + g_object_unref (task); return; } - cmd = NULL; - if (is_2g && !is_3g && !is_4g) - cmd = g_strdup_printf ("AT#BND=%d", flag2g); - else if (is_2g && is_3g && !is_4g) - cmd = g_strdup_printf ("AT#BND=%d,%d", flag2g, flag3g); - else if (is_2g && is_3g && is_4g) - cmd = g_strdup_printf ("AT#BND=%d,%d,%d", flag2g, flag3g, flag4g); - else if (!is_2g && !is_3g && is_4g) - cmd = g_strdup_printf ("AT#BND=0,0,%d", flag4g); - else if (!is_2g && is_3g && is_4g) - cmd = g_strdup_printf ("AT#BND=0,%d,%d", flag3g, flag4g); - else if (is_2g && !is_3g && is_4g) - cmd = g_strdup_printf ("AT#BND=%d,0,%d", flag2g, flag4g); - else { - g_task_report_new_error (self, - callback, - user_data, - mm_shared_telit_modem_set_current_bands, - MM_CORE_ERROR, - MM_CORE_ERROR_FAILED, - "Unexpected error: could not compose AT#BND command"); - return; - } - task = g_task_new (self, NULL, callback, user_data); mm_base_modem_at_command (MM_BASE_MODEM (self), cmd, 20, FALSE, - (GAsyncReadyCallback)mm_shared_telit_modem_set_current_bands_ready, + (GAsyncReadyCallback)set_current_bands_ready, task); g_free (cmd); } diff --git a/plugins/telit/mm-shared-telit.h b/plugins/telit/mm-shared-telit.h index 2eb6d515..4cfaeb51 100644 --- a/plugins/telit/mm-shared-telit.h +++ b/plugins/telit/mm-shared-telit.h @@ -66,14 +66,18 @@ void mm_shared_telit_modem_load_supported_bands (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data); -GArray * mm_shared_telit_modem_load_bands_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); +GArray * mm_shared_telit_modem_load_supported_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error); void mm_shared_telit_modem_load_current_bands (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data); +GArray * mm_shared_telit_modem_load_current_bands_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error); + gboolean mm_shared_telit_modem_set_current_bands_finish (MMIfaceModem *self, GAsyncResult *res, GError **error); diff --git a/plugins/telit/tests/test-mm-modem-helpers-telit.c b/plugins/telit/tests/test-mm-modem-helpers-telit.c index 6103a2c9..f95a97d2 100644 --- a/plugins/telit/tests/test-mm-modem-helpers-telit.c +++ b/plugins/telit/tests/test-mm-modem-helpers-telit.c @@ -10,7 +10,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2015 Telit + * Copyright (C) 2015-2019 Telit + * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> * */ #include <stdio.h> @@ -22,429 +23,489 @@ #define _LIBMM_INSIDE_MM #include <libmm-glib.h> +#include "mm-log.h" #include "mm-modem-helpers.h" #include "mm-modem-helpers-telit.h" -static void -test_mm_bands_contains (void) { - GArray* mm_bands; - guint i = 1; - - mm_bands = g_array_sized_new (FALSE, TRUE, sizeof (MMModemBand), 3); - - for (i = 0; i < 3; i++) - g_array_append_val (mm_bands, i); +#include "test-helpers.h" - g_assert (mm_telit_bands_contains (mm_bands, 2)); - g_assert (mm_telit_bands_contains (mm_bands, 2)); - g_assert (!mm_telit_bands_contains (mm_bands, 3)); +/******************************************************************************/ - g_array_free (mm_bands, TRUE); -} +#define MAX_BANDS_LIST_LEN 17 typedef struct { - gchar* band_flag_str; - guint band_flags_len; - guint band_flags [MAX_BANDS_LIST_LEN]; -} BNDFlagsTest; - -static BNDFlagsTest band_flag_test[] = { - {"0-3", 4, {0, 1, 2, 3} }, - {"0,3", 2, {0, 3} }, - {"0,2-3,5-7,9", 7, {0, 2, 3, 5, 6, 7, 9} }, - { NULL, 0, {}}, -}; - -static void -test_parse_band_flag_str (void) { - GError *error = NULL; - gboolean res = FALSE; - GArray *band_flags = NULL; - guint i, j; - - for (i = 0; band_flag_test[i].band_flag_str != NULL; i++) { - band_flags = g_array_new (FALSE, FALSE, sizeof (guint)); - res = mm_telit_get_band_flags_from_string (band_flag_test[i].band_flag_str, - &band_flags, - &error); - g_assert_no_error (error); - g_assert (res); - - for (j = 0; j < band_flag_test[i].band_flags_len; j++) { - guint ref; - guint cur; - - ref = band_flag_test[i].band_flags[j]; - cur = g_array_index (band_flags, guint, j); - - g_assert (ref == cur); - } - - g_array_free (band_flags, TRUE); + gchar *response; + gboolean modem_is_2g; + gboolean modem_is_3g; + gboolean modem_is_4g; + gboolean modem_alternate_3g_bands; + guint mm_bands_len; + MMModemBand mm_bands [MAX_BANDS_LIST_LEN]; +} BndResponseTest; + +static BndResponseTest supported_band_mapping_tests [] = { + { + "#BND: (0-3)", TRUE, FALSE, FALSE, FALSE, 4, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850 } + }, + { + "#BND: (0-3),(0,2,5,6)", TRUE, TRUE, FALSE, FALSE, 7, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } + }, + { + "#BND: (0,3),(0,2,5,6)", TRUE, TRUE, FALSE, FALSE, 7, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } + }, + { + "#BND: (0,2),(0,2,5,6)", TRUE, TRUE, FALSE, FALSE, 6, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } + }, + { + "#BND: (0,2),(0-4,5,6)", TRUE, TRUE, FALSE, FALSE, 7, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_2, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } + }, + { + "#BND: (0-3),(0,2,5,6),(1-1)", TRUE, TRUE, TRUE, FALSE, 8, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8, + MM_MODEM_BAND_EUTRAN_1 } + }, + { + "#BND: (0),(0),(1-3)", TRUE, TRUE, TRUE, FALSE, 5, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2 } + }, + { + "#BND: (0),(0),(1-3)", FALSE, FALSE, TRUE, FALSE, 2, + { MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2 } + }, + /* 3G alternate band settings: default */ + { + "#BND: (0),(0,2,5,6,12,25)", FALSE, TRUE, FALSE, FALSE, 5, + { MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8, + MM_MODEM_BAND_UTRAN_6, + MM_MODEM_BAND_UTRAN_19 } + }, + /* 3G alternate band settings: alternate */ + { + "#BND: (0),(0,2,5,6,12,13)", FALSE, TRUE, FALSE, TRUE, 4, + { MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_3, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } + }, + /* ME910 (2G+4G device) + * 168695967: 0xA0E189F: 0000 1010 0000 1110 0001 1000 1001 1111 + */ + { + "#BND: (0-5),(0),(1-168695967)", TRUE, FALSE, TRUE, FALSE, 17, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2, + MM_MODEM_BAND_EUTRAN_3, + MM_MODEM_BAND_EUTRAN_4, + MM_MODEM_BAND_EUTRAN_5, + MM_MODEM_BAND_EUTRAN_8, + MM_MODEM_BAND_EUTRAN_12, + MM_MODEM_BAND_EUTRAN_13, + MM_MODEM_BAND_EUTRAN_18, + MM_MODEM_BAND_EUTRAN_19, + MM_MODEM_BAND_EUTRAN_20, + MM_MODEM_BAND_EUTRAN_26, + MM_MODEM_BAND_EUTRAN_28 } } -} - -typedef struct { - gchar* response; - gboolean modem_is_2g; - gboolean modem_is_3g; - gboolean modem_is_4g; - guint mm_bands_len; - MMModemBand mm_bands [MAX_BANDS_LIST_LEN]; -} BNDResponseTest; - -static BNDResponseTest supported_band_mapping_tests [] = { - { "#BND: (0-3)", TRUE, FALSE, FALSE, 4, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850} }, - { "#BND: (0-3),(0,2,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8 } }, - { "#BND: (0,3),(0,2,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8} }, - { "#BND: (0,2),(0,2,5,6)", TRUE, TRUE, FALSE, 6, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8} }, - { "#BND: (0,2),(0-4,5,6)", TRUE, TRUE, FALSE, 7, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8} }, - { "#BND: (0-3),(0,2,5,6),(1-1)", TRUE, TRUE, TRUE, 8, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_5, - MM_MODEM_BAND_UTRAN_8, - MM_MODEM_BAND_EUTRAN_1} }, - { "#BND: (0),(0),(1-3)", TRUE, TRUE, TRUE, 5, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2} }, - { "#BND: (0),(0),(1-3)", FALSE, FALSE, TRUE, 2, { MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2} }, - { NULL, FALSE, FALSE, FALSE, 0, {}}, }; static void -test_parse_supported_bands_response (void) { - GError* error = NULL; - gboolean res = FALSE; - guint i, j; - GArray* bands = NULL; - - for (i = 0; supported_band_mapping_tests[i].response != NULL; i++) { - res = mm_telit_parse_bnd_response (supported_band_mapping_tests[i].response, - supported_band_mapping_tests[i].modem_is_2g, - supported_band_mapping_tests[i].modem_is_3g, - supported_band_mapping_tests[i].modem_is_4g, - LOAD_SUPPORTED_BANDS, - &bands, - &error); - g_assert_no_error (error); - g_assert (res); - +test_parse_supported_bands_response (void) +{ + guint i; - for (j = 0; j < supported_band_mapping_tests[i].mm_bands_len; j++) { - MMModemBand ref; - MMModemBand cur; + for (i = 0; i < G_N_ELEMENTS (supported_band_mapping_tests); i++) { + GError *error = NULL; + GArray *bands = NULL; - ref = supported_band_mapping_tests[i].mm_bands[j]; - cur = g_array_index (bands, MMModemBand, j); - g_assert_cmpint (cur, ==, ref); - } - - g_assert_cmpint (bands->len, ==, supported_band_mapping_tests[i].mm_bands_len); + bands = mm_telit_parse_bnd_test_response (supported_band_mapping_tests[i].response, + supported_band_mapping_tests[i].modem_is_2g, + supported_band_mapping_tests[i].modem_is_3g, + supported_band_mapping_tests[i].modem_is_4g, + supported_band_mapping_tests[i].modem_alternate_3g_bands, + &error); + g_assert_no_error (error); + g_assert (bands); - g_array_free (bands, TRUE); - bands = NULL; + mm_test_helpers_compare_bands (bands, + supported_band_mapping_tests[i].mm_bands, + supported_band_mapping_tests[i].mm_bands_len); + g_array_unref (bands); } } - -static BNDResponseTest current_band_mapping_tests [] = { - { "#BND: 0", TRUE, FALSE, FALSE, 2, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS - } +static BndResponseTest current_band_mapping_tests [] = { + { + "#BND: 0", TRUE, FALSE, FALSE, FALSE, 2, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS } + }, + { + "#BND: 0,5", TRUE, TRUE, FALSE, FALSE, 3, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_UTRAN_8 } + }, + { + "#BND: 1,3", TRUE, TRUE, FALSE, FALSE, 5, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_2, + MM_MODEM_BAND_UTRAN_5 } }, - { "#BND: 0,5", TRUE, TRUE, FALSE, 3, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_UTRAN_8 - } + { + "#BND: 2,7", TRUE, TRUE, FALSE, FALSE, 3, + { MM_MODEM_BAND_DCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_4 } }, - { "#BND: 1,3", TRUE, TRUE, FALSE, 5, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_PCS, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_UTRAN_2, - MM_MODEM_BAND_UTRAN_5, - } + { + "#BND: 3,0,1", TRUE, TRUE, TRUE, FALSE, 4, + { MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_EUTRAN_1 } }, - { "#BND: 2,7", TRUE, TRUE, FALSE, 3, { MM_MODEM_BAND_DCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_4 - } + { + "#BND: 0,0,3", TRUE, FALSE, TRUE, FALSE, 4, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2 } }, - { "#BND: 3,0,1", TRUE, TRUE, TRUE, 4, { MM_MODEM_BAND_PCS, - MM_MODEM_BAND_G850, - MM_MODEM_BAND_UTRAN_1, - MM_MODEM_BAND_EUTRAN_1 - } + { + "#BND: 0,0,3", FALSE, FALSE, TRUE, FALSE, 2, + { MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2 } }, - { "#BND: 0,0,3", TRUE, FALSE, TRUE, 4, { MM_MODEM_BAND_EGSM, - MM_MODEM_BAND_DCS, - MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 - } + /* 3G alternate band settings: default */ + { + "#BND: 0,12", FALSE, TRUE, FALSE, FALSE, 1, + { MM_MODEM_BAND_UTRAN_6 } }, - { "#BND: 0,0,3", FALSE, FALSE, TRUE, 2, { MM_MODEM_BAND_EUTRAN_1, - MM_MODEM_BAND_EUTRAN_2 - } + /* 3G alternate band settings: alternate */ + { + "#BND: 0,12", FALSE, TRUE, FALSE, TRUE, 4, + { MM_MODEM_BAND_UTRAN_1, + MM_MODEM_BAND_UTRAN_3, + MM_MODEM_BAND_UTRAN_5, + MM_MODEM_BAND_UTRAN_8 } }, - { NULL, FALSE, FALSE, FALSE, 0, {}}, + /* ME910 (2G+4G device) + * 168695967: 0xA0E189F: 0000 1010 0000 1110 0001 1000 1001 1111 + */ + { + "#BND: 5,0,168695967", TRUE, FALSE, TRUE, FALSE, 17, + { MM_MODEM_BAND_EGSM, + MM_MODEM_BAND_DCS, + MM_MODEM_BAND_PCS, + MM_MODEM_BAND_G850, + MM_MODEM_BAND_EUTRAN_1, + MM_MODEM_BAND_EUTRAN_2, + MM_MODEM_BAND_EUTRAN_3, + MM_MODEM_BAND_EUTRAN_4, + MM_MODEM_BAND_EUTRAN_5, + MM_MODEM_BAND_EUTRAN_8, + MM_MODEM_BAND_EUTRAN_12, + MM_MODEM_BAND_EUTRAN_13, + MM_MODEM_BAND_EUTRAN_18, + MM_MODEM_BAND_EUTRAN_19, + MM_MODEM_BAND_EUTRAN_20, + MM_MODEM_BAND_EUTRAN_26, + MM_MODEM_BAND_EUTRAN_28 } + } }; static void -test_parse_current_bands_response (void) { - GError* error = NULL; - gboolean res = FALSE; - guint i, j; - GArray* bands = NULL; - - for (i = 0; current_band_mapping_tests[i].response != NULL; i++) { - res = mm_telit_parse_bnd_response (current_band_mapping_tests[i].response, - current_band_mapping_tests[i].modem_is_2g, - current_band_mapping_tests[i].modem_is_3g, - current_band_mapping_tests[i].modem_is_4g, - LOAD_CURRENT_BANDS, - &bands, - &error); +test_parse_current_bands_response (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (current_band_mapping_tests); i++) { + GError *error = NULL; + GArray *bands = NULL; + + bands = mm_telit_parse_bnd_query_response (current_band_mapping_tests[i].response, + current_band_mapping_tests[i].modem_is_2g, + current_band_mapping_tests[i].modem_is_3g, + current_band_mapping_tests[i].modem_is_4g, + current_band_mapping_tests[i].modem_alternate_3g_bands, + &error); g_assert_no_error (error); - g_assert (res); + g_assert (bands); + mm_test_helpers_compare_bands (bands, + current_band_mapping_tests[i].mm_bands, + current_band_mapping_tests[i].mm_bands_len); + g_array_unref (bands); + } +} - for (j = 0; j < current_band_mapping_tests[i].mm_bands_len; j++) { - MMModemBand ref; - MMModemBand cur; +/******************************************************************************/ - ref = current_band_mapping_tests[i].mm_bands[j]; - cur = g_array_index (bands, MMModemBand, j); - g_assert_cmpint (cur, ==, ref); - } +static void +test_common_bnd_cmd (const gchar *expected_cmd, + gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + gboolean modem_alternate_3g_bands, + GArray *bands_array) +{ + gchar *cmd; + GError *error = NULL; - g_assert_cmpint (bands->len, ==, current_band_mapping_tests[i].mm_bands_len); + cmd = mm_telit_build_bnd_request (bands_array, + modem_is_2g, modem_is_3g, modem_is_4g, + modem_alternate_3g_bands, + &error); + g_assert_no_error (error); + g_assert_cmpstr (cmd, ==, expected_cmd); + g_free (cmd); +} - g_array_free (bands, TRUE); - bands = NULL; - } +#define test_common_bnd_cmd_2g(EXPECTED_CMD, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, TRUE, FALSE, FALSE, FALSE, BANDS_ARRAY) +#define test_common_bnd_cmd_3g(EXPECTED_CMD, ALTERNATE, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, FALSE, TRUE, FALSE, ALTERNATE, BANDS_ARRAY) +#define test_common_bnd_cmd_4g(EXPECTED_CMD, BANDS_ARRAY) test_common_bnd_cmd (EXPECTED_CMD, FALSE, FALSE, TRUE, FALSE, BANDS_ARRAY) + +static void +test_common_bnd_cmd_invalid (gboolean modem_is_2g, + gboolean modem_is_3g, + gboolean modem_is_4g, + GArray *bands_array) +{ + gchar *cmd; + GError *error = NULL; + + cmd = mm_telit_build_bnd_request (bands_array, + modem_is_2g, modem_is_3g, modem_is_4g, + FALSE, + &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED); + g_assert (!cmd); } +#define test_common_bnd_cmd_2g_invalid(BANDS_ARRAY) test_common_bnd_cmd_invalid (TRUE, FALSE, FALSE, BANDS_ARRAY) +#define test_common_bnd_cmd_3g_invalid(BANDS_ARRAY) test_common_bnd_cmd_invalid (FALSE, TRUE, FALSE, BANDS_ARRAY) +#define test_common_bnd_cmd_4g_invalid(BANDS_ARRAY) test_common_bnd_cmd_invalid (FALSE, FALSE, TRUE, BANDS_ARRAY) + static void test_telit_get_2g_bnd_flag (void) { - GArray *bands_array; - gint flag2g; - MMModemBand egsm = MM_MODEM_BAND_EGSM; - MMModemBand dcs = MM_MODEM_BAND_DCS; - MMModemBand pcs = MM_MODEM_BAND_PCS; - MMModemBand g850 = MM_MODEM_BAND_G850; + GArray *bands_array; + MMModemBand egsm = MM_MODEM_BAND_EGSM; + MMModemBand dcs = MM_MODEM_BAND_DCS; + MMModemBand pcs = MM_MODEM_BAND_PCS; + MMModemBand g850 = MM_MODEM_BAND_G850; /* Test Flag 0 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, egsm); g_array_append_val (bands_array, dcs); - - mm_telit_get_band_flag (bands_array, &flag2g, NULL, NULL); - g_assert_cmpuint (flag2g, ==, 0); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_2g ("#BND=0", bands_array); + g_array_unref (bands_array); /* Test flag 1 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, egsm); g_array_append_val (bands_array, pcs); - - mm_telit_get_band_flag (bands_array, &flag2g, NULL, NULL); - g_assert_cmpuint (flag2g, ==, 1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_2g ("#BND=1", bands_array); + g_array_unref (bands_array); /* Test flag 2 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, g850); g_array_append_val (bands_array, dcs); - - mm_telit_get_band_flag (bands_array, &flag2g, NULL, NULL); - g_assert_cmpuint (flag2g, ==, 2); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_2g ("#BND=2", bands_array); + g_array_unref (bands_array); /* Test flag 3 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, g850); g_array_append_val (bands_array, pcs); - - mm_telit_get_band_flag (bands_array, &flag2g, NULL, NULL); - g_assert_cmpuint (flag2g, ==, 3); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_2g ("#BND=3", bands_array); + g_array_unref (bands_array); /* Test invalid band array */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, g850); g_array_append_val (bands_array, egsm); - - mm_telit_get_band_flag (bands_array, &flag2g, NULL, NULL); - g_assert_cmpuint (flag2g, ==, -1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_2g_invalid (bands_array); + g_array_unref (bands_array); } - static void test_telit_get_3g_bnd_flag (void) { - GArray *bands_array; - MMModemBand u2100 = MM_MODEM_BAND_UTRAN_1; - MMModemBand u1900 = MM_MODEM_BAND_UTRAN_2; - MMModemBand u850 = MM_MODEM_BAND_UTRAN_5; - MMModemBand u900 = MM_MODEM_BAND_UTRAN_8; - MMModemBand u17iv = MM_MODEM_BAND_UTRAN_4; - MMModemBand u17ix = MM_MODEM_BAND_UTRAN_9; - gint flag; + GArray *bands_array; + MMModemBand u2100 = MM_MODEM_BAND_UTRAN_1; + MMModemBand u1900 = MM_MODEM_BAND_UTRAN_2; + MMModemBand u1800 = MM_MODEM_BAND_UTRAN_3; + MMModemBand u850 = MM_MODEM_BAND_UTRAN_5; + MMModemBand u800 = MM_MODEM_BAND_UTRAN_6; + MMModemBand u900 = MM_MODEM_BAND_UTRAN_8; + MMModemBand u17iv = MM_MODEM_BAND_UTRAN_4; + MMModemBand u17ix = MM_MODEM_BAND_UTRAN_9; /* Test flag 0 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u2100); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 0); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,0", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,0", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 1 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u1900); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,1", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,1", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 2 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u850); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 2); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,2", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,2", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 3 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 3); g_array_append_val (bands_array, u2100); g_array_append_val (bands_array, u1900); g_array_append_val (bands_array, u850); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 3); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,3", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,3", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 4 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, u1900); g_array_append_val (bands_array, u850); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 4); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,4", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,4", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 5 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u900); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 5); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,5", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,5", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 6 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, u2100); g_array_append_val (bands_array, u900); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 6); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g ("#BND=0,6", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,6", TRUE, bands_array); + g_array_unref (bands_array); /* Test flag 7 */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u17iv); + test_common_bnd_cmd_3g ("#BND=0,7", FALSE, bands_array); + test_common_bnd_cmd_3g ("#BND=0,7", TRUE, bands_array); + g_array_unref (bands_array); - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, 7); - g_array_free (bands_array, TRUE); + /* Test flag 12 in default */ + bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); + g_array_append_val (bands_array, u800); + test_common_bnd_cmd_3g ("#BND=0,12", FALSE, bands_array); + g_array_unref (bands_array); + + /* Test flag 12 in alternate */ + bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 4); + g_array_append_val (bands_array, u2100); + g_array_append_val (bands_array, u1800); + g_array_append_val (bands_array, u850); + g_array_append_val (bands_array, u900); + test_common_bnd_cmd_3g ("#BND=0,12", TRUE, bands_array); + g_array_unref (bands_array); /* Test invalid band array */ - flag = -1; bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, u17ix); - - mm_telit_get_band_flag (bands_array, NULL, &flag, NULL); - g_assert_cmpint (flag, ==, -1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_3g_invalid (bands_array); + g_array_unref (bands_array); } static void test_telit_get_4g_bnd_flag (void) { - GArray *bands_array; - MMModemBand eutran_i = MM_MODEM_BAND_EUTRAN_1; - MMModemBand eutran_ii = MM_MODEM_BAND_EUTRAN_2; - MMModemBand egsm = MM_MODEM_BAND_EGSM; - gint flag = -1; + GArray *bands_array; + MMModemBand eutran_i = MM_MODEM_BAND_EUTRAN_1; + MMModemBand eutran_ii = MM_MODEM_BAND_EUTRAN_2; + MMModemBand egsm = MM_MODEM_BAND_EGSM; /* Test flag 1 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, eutran_i); - - mm_telit_get_band_flag (bands_array, NULL, NULL, &flag); - g_assert_cmpint (flag, ==, 1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_4g ("#BND=0,0,1", bands_array); + g_array_unref (bands_array); /* Test flag 3 */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 2); g_array_append_val (bands_array, eutran_i); g_array_append_val (bands_array, eutran_ii); - - mm_telit_get_band_flag (bands_array, NULL, NULL, &flag); - g_assert_cmpint (flag, ==, 3); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_4g ("#BND=0,0,3", bands_array); + g_array_unref (bands_array); /* Test invalid bands array */ bands_array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), 1); g_array_append_val (bands_array, egsm); - - mm_telit_get_band_flag (bands_array, NULL, NULL, &flag); - g_assert_cmpint (flag, ==, -1); - g_array_free (bands_array, TRUE); + test_common_bnd_cmd_4g_invalid (bands_array); + g_array_unref (bands_array); } +/******************************************************************************/ + typedef struct { const char* response; MMTelitQssStatus expected_qss; @@ -483,14 +544,34 @@ test_telit_parse_qss_query (void) } } +/******************************************************************************/ + +void +_mm_log (const char *loc, + const char *func, + guint32 level, + const char *fmt, + ...) +{ +#if defined ENABLE_TEST_MESSAGE_TRACES + /* Dummy log function */ + va_list args; + gchar *msg; + + va_start (args, fmt); + msg = g_strdup_vprintf (fmt, args); + va_end (args); + g_print ("%s\n", msg); + g_free (msg); +#endif +} + int main (int argc, char **argv) { setlocale (LC_ALL, ""); g_test_init (&argc, &argv, NULL); - g_test_add_func ("/MM/telit/bands/supported/bands_contains", test_mm_bands_contains); - g_test_add_func ("/MM/telit/bands/supported/parse_band_flag", test_parse_band_flag_str); g_test_add_func ("/MM/telit/bands/supported/parse_bands_response", test_parse_supported_bands_response); g_test_add_func ("/MM/telit/bands/current/parse_bands_response", test_parse_current_bands_response); g_test_add_func ("/MM/telit/bands/current/set_bands/2g", test_telit_get_2g_bnd_flag); |