Merge "Merge cros/upstream to cros/master"
diff --git a/.gitignore b/.gitignore
index 05b9619..6b88d05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@
/src/tests/test-sms-part-cdma
/src/tests/test-udev-rules
/src/tests/test-error-helpers
+/src/tests/test-kernel-device-helpers
/cli/mmcli
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6d87f29..bfc73ba 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -265,7 +265,8 @@
- ninja -C build
- ninja -C build install
- popd
- - meson setup build --buildtype=release --prefix=/usr -Dwerror=true -Dgtk_doc=false -Dpolkit=strict -Dsystemdsystemunitdir=/lib/systemd/system
+ - meson setup build --buildtype=release --prefix=/usr -Dwerror=true -Dgtk_doc=true -Dpolkit=strict -Dsystemdsystemunitdir=/lib/systemd/system
- ninja -C build
+ - ninja -C build test
- ninja -C build install
- ninja -C build uninstall
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index 2ab6438..f8fa6c1 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -64,6 +64,7 @@
static gchar *set_preferred_mode_str;
static gchar *set_current_bands_str;
static gint set_primary_sim_slot_int;
+static gboolean get_cell_info_flag;
static gboolean inhibit_flag;
static GOptionEntry entries[] = {
@@ -131,6 +132,10 @@
"Switch to the selected SIM slot",
"[SLOT NUMBER]"
},
+ { "get-cell-info", 0, 0, G_OPTION_ARG_NONE, &get_cell_info_flag,
+ "Get cell info",
+ NULL
+ },
{ "inhibit", 0, 0, G_OPTION_ARG_NONE, &inhibit_flag,
"Inhibit the modem",
NULL
@@ -179,6 +184,7 @@
!!set_preferred_mode_str +
!!set_current_bands_str +
(set_primary_sim_slot_int > 0) +
+ get_cell_info_flag +
inhibit_flag);
if (n_actions == 0 && mmcli_get_common_modem_string ()) {
@@ -940,6 +946,35 @@
}
static void
+get_cell_info_process_reply (GList *list,
+ const GError *error)
+{
+ if (!list) {
+ g_printerr ("error: couldn't get cell info in the modem: '%s'\n",
+ error ? error->message : "unknown error");
+ exit (EXIT_FAILURE);
+ }
+
+ mmcli_output_cell_info (list);
+ mmcli_output_dump ();
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+}
+
+static void
+get_cell_info_ready (MMModem *modem,
+ GAsyncResult *result)
+{
+ GList *list;
+ g_autoptr(GError) error = NULL;
+
+ list = mm_modem_get_cell_info_finish (modem, result, &error);
+ get_cell_info_process_reply (list, error);
+
+ mmcli_async_operation_done ();
+}
+
+static void
state_changed (MMModem *modem,
MMModemState old_state,
MMModemState new_state,
@@ -1191,6 +1226,15 @@
return;
}
+ /* Request to get cell info? */
+ if (get_cell_info_flag) {
+ mm_modem_get_cell_info (ctx->modem,
+ ctx->cancellable,
+ (GAsyncReadyCallback)get_cell_info_ready,
+ NULL);
+ return;
+ }
+
/* Request to inhibit the modem? */
if (inhibit_flag) {
gchar *uid;
@@ -1459,5 +1503,14 @@
return;
}
+ /* Request to get cell info? */
+ if (get_cell_info_flag) {
+ GList *list;
+
+ list = mm_modem_get_cell_info_sync (ctx->modem, NULL, &error);
+ get_cell_info_process_reply (list, error);
+ return;
+ }
+
g_warn_if_reached ();
}
diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c
index 4d50daf..0b74246 100644
--- a/cli/mmcli-output.c
+++ b/cli/mmcli-output.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <string.h>
+#define _LIBMM_INSIDE_MMCLI
#include <libmm-glib.h>
#include "mm-common-helpers.h"
#include "mmcli-output.h"
@@ -41,6 +42,7 @@
[MMC_S_MODEM_MODES] = { "Modes" },
[MMC_S_MODEM_BANDS] = { "Bands" },
[MMC_S_MODEM_IP] = { "IP" },
+ [MMC_S_MODEM_CELL_INFO] = { "Cell info" },
[MMC_S_MODEM_3GPP] = { "3GPP" },
[MMC_S_MODEM_3GPP_EPS] = { "3GPP EPS" },
[MMC_S_MODEM_3GPP_5GNR] = { "3GPP 5GNR" },
@@ -127,6 +129,7 @@
[MMC_F_BANDS_SUPPORTED] = { "modem.generic.supported-bands", "supported", MMC_S_MODEM_BANDS, },
[MMC_F_BANDS_CURRENT] = { "modem.generic.current-bands", "current", MMC_S_MODEM_BANDS, },
[MMC_F_IP_SUPPORTED] = { "modem.generic.supported-ip-families", "supported", MMC_S_MODEM_IP, },
+ [MMC_F_CELL_INFO] = { "modem.generic.cell-info", "cells", MMC_S_MODEM_CELL_INFO, },
[MMC_F_3GPP_IMEI] = { "modem.3gpp.imei", "imei", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_ENABLED_LOCKS] = { "modem.3gpp.enabled-locks", "enabled locks", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_OPERATOR_ID] = { "modem.3gpp.operator-code", "operator id", MMC_S_MODEM_3GPP, },
@@ -1116,6 +1119,33 @@
}
/******************************************************************************/
+/* (Custom) Cell info output */
+
+void
+mmcli_output_cell_info (GList *cell_info_list)
+{
+ gchar **cell_infos = NULL;
+
+ if (cell_info_list) {
+ GPtrArray *aux;
+ GList *l;
+
+ aux = g_ptr_array_new ();
+ for (l = cell_info_list; l; l = g_list_next (l))
+ g_ptr_array_add (aux, mm_cell_info_build_string (MM_CELL_INFO (l->data)));
+ g_ptr_array_add (aux, NULL);
+ cell_infos = (gchar **) g_ptr_array_free (aux, FALSE);
+ }
+
+ /* When printing human result, we want to show some result even if no networks
+ * are found, so we force a explicit string result. */
+ if (selected_type == MMC_OUTPUT_TYPE_HUMAN && !cell_infos)
+ output_item_new_take_single (MMC_F_CELL_INFO, g_strdup ("n/a"));
+ else
+ output_item_new_take_multiple (MMC_F_CELL_INFO, cell_infos, TRUE);
+}
+
+/******************************************************************************/
/* Human-friendly output */
#define HUMAN_MAX_VALUE_LENGTH 60
diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h
index bd06045..180debd 100644
--- a/cli/mmcli-output.h
+++ b/cli/mmcli-output.h
@@ -38,6 +38,7 @@
MMC_S_MODEM_MODES,
MMC_S_MODEM_BANDS,
MMC_S_MODEM_IP,
+ MMC_S_MODEM_CELL_INFO,
MMC_S_MODEM_3GPP,
MMC_S_MODEM_3GPP_EPS,
MMC_S_MODEM_3GPP_5GNR,
@@ -127,6 +128,8 @@
MMC_F_BANDS_CURRENT,
/* IP section */
MMC_F_IP_SUPPORTED,
+ /* Cell info section */
+ MMC_F_CELL_INFO,
/* 3GPP section */
MMC_F_3GPP_IMEI,
MMC_F_3GPP_ENABLED_LOCKS,
@@ -392,6 +395,7 @@
void mmcli_output_preferred_networks (GList *preferred_nets_list);
void mmcli_output_profile_list (GList *profile_list);
void mmcli_output_profile_set (MM3gppProfile *profile);
+void mmcli_output_cell_info (GList *cell_info_list);
/******************************************************************************/
/* Dump output */
diff --git a/cli/mmcli.c b/cli/mmcli.c
index e10267a..b86c8d9 100644
--- a/cli/mmcli.c
+++ b/cli/mmcli.c
@@ -43,7 +43,7 @@
static GMainLoop *loop;
static GCancellable *cancellable;
-/* Context */
+/* Main context */
static gboolean output_keyvalue_flag;
static gboolean output_json_flag;
static gboolean verbose_flag;
@@ -79,6 +79,31 @@
{ NULL }
};
+/* Test context */
+static gboolean test_session_flag;
+
+static GOptionEntry test_entries[] = {
+ { "test-session", 0, 0, G_OPTION_ARG_NONE, &test_session_flag,
+ "Run in session DBus",
+ NULL
+ },
+ { NULL }
+};
+
+static GOptionGroup *
+test_get_option_group (void)
+{
+ GOptionGroup *group;
+
+ group = g_option_group_new ("test",
+ "Test options:",
+ "Show test options",
+ NULL,
+ NULL);
+ g_option_group_add_entries (group, test_entries);
+ return group;
+}
+
static void
signals_handler (int signum)
{
@@ -243,6 +268,8 @@
mmcli_sms_get_option_group ());
g_option_context_add_group (context,
mmcli_call_get_option_group ());
+ g_option_context_add_group (context,
+ test_get_option_group ());
g_option_context_add_main_entries (context, main_entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
@@ -281,7 +308,7 @@
signal (SIGTERM, signals_handler);
/* Setup dbus connection to use */
- connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ connection = g_bus_get_sync (test_session_flag ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM, NULL, &error);
if (!connection) {
g_printerr ("error: couldn't get bus: %s\n",
error ? error->message : "unknown error");
diff --git a/configure.ac b/configure.ac
index d1e9684..6ffa512 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@
m4_define([mm_major_version], [1])
m4_define([mm_minor_version], [19])
-m4_define([mm_micro_version], [0])
+m4_define([mm_micro_version], [1])
m4_define([mm_version],
[mm_major_version.mm_minor_version.mm_micro_version])
@@ -221,6 +221,12 @@
fi
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$SYSTEMD_UNIT_DIR" -a "$SYSTEMD_UNIT_DIR" != xno ])
+
+dnl subdir where plugins are built w.r.t abs_top_builddir, just because it's
+dnl different to what meson does
+PLUGIN_BUILD_SUBDIR="plugins/.libs"
+AC_SUBST(PLUGIN_BUILD_SUBDIR)
+
dnl-----------------------------------------------------------------------------
dnl udev support (enabled by default)
dnl
@@ -380,7 +386,7 @@
dnl MBIM support (enabled by default)
dnl
-LIBMBIM_VERSION=1.27.3
+LIBMBIM_VERSION=1.27.5
AC_ARG_WITH(mbim, AS_HELP_STRING([--without-mbim], [Build without MBIM support]), [], [with_mbim=yes])
AM_CONDITIONAL(WITH_MBIM, test "x$with_mbim" = "xyes")
diff --git a/data/fcc-unlock/105b b/data/fcc-unlock/105b
index 21fe532..f276050 100644
--- a/data/fcc-unlock/105b
+++ b/data/fcc-unlock/105b
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# SPDX-License-Identifier: CC0-1.0
# 2021 Aleksander Morgado <aleksander@aleksander.es>
diff --git a/data/fcc-unlock/1199 b/data/fcc-unlock/1199
index 0109c6a..e1d3804 100644
--- a/data/fcc-unlock/1199
+++ b/data/fcc-unlock/1199
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# SPDX-License-Identifier: CC0-1.0
# 2021 Aleksander Morgado <aleksander@aleksander.es>
diff --git a/data/fcc-unlock/1eac b/data/fcc-unlock/1eac
index 1068d9c..d934285 100644
--- a/data/fcc-unlock/1eac
+++ b/data/fcc-unlock/1eac
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# SPDX-License-Identifier: CC0-1.0
# 2021 Aleksander Morgado <aleksander@aleksander.es>
diff --git a/data/meson.build b/data/meson.build
index 820bec7..d2a36b7 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2021 Iñigo Martinez <inigomartinez@gmail.com>
+subdir('tests')
+
service_conf = {
'sbindir': mm_prefix / mm_sbindir,
'MM_POLKIT_SERVICE': (enable_polkit ? 'polkit.service' : ''),
diff --git a/data/tests/meson.build b/data/tests/meson.build
new file mode 100644
index 0000000..fa0b2c0
--- /dev/null
+++ b/data/tests/meson.build
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+
+test_conf = {
+ 'abs_top_builddir': build_root,
+ 'PLUGIN_BUILD_SUBDIR': 'plugins/',
+}
+
+configure_file(
+ input: 'org.freedesktop.ModemManager1.service.in',
+ output: '@BASENAME@',
+ configuration: test_conf,
+)
\ No newline at end of file
diff --git a/data/tests/org.freedesktop.ModemManager1.service.in b/data/tests/org.freedesktop.ModemManager1.service.in
index d7c1a00..d8a751b 100644
--- a/data/tests/org.freedesktop.ModemManager1.service.in
+++ b/data/tests/org.freedesktop.ModemManager1.service.in
@@ -2,4 +2,4 @@
[D-BUS Service]
Name=org.freedesktop.ModemManager1
-Exec=@abs_top_builddir@/src/ModemManager --test-session --no-auto-scan --test-enable --test-plugin-dir="@abs_top_builddir@/plugins/.libs" --debug
+Exec=@abs_top_builddir@/src/ModemManager --test-session --no-auto-scan --test-enable --test-plugin-dir="@abs_top_builddir@/@PLUGIN_BUILD_SUBDIR@" --debug
diff --git a/docs/reference/api/ModemManager-sections.txt b/docs/reference/api/ModemManager-sections.txt
index 5b155da..9635f35 100644
--- a/docs/reference/api/ModemManager-sections.txt
+++ b/docs/reference/api/ModemManager-sections.txt
@@ -63,6 +63,7 @@
MMSimType
MMSimEsimStatus
MMSimRemovability
+MMCellType
</SECTION>
<SECTION>
diff --git a/docs/reference/libmm-glib/libmm-glib-docs.xml b/docs/reference/libmm-glib/libmm-glib-docs.xml
index 942559b..d963221 100644
--- a/docs/reference/libmm-glib/libmm-glib-docs.xml
+++ b/docs/reference/libmm-glib/libmm-glib-docs.xml
@@ -92,7 +92,15 @@
<xi:include href="xml/mm-modem-cdma.xml"/>
<xi:include href="xml/mm-cdma-manual-activation-properties.xml"/>
<xi:include href="xml/mm-unlock-retries.xml"/>
+ <xi:include href="xml/mm-cell-info.xml"/>
+ <xi:include href="xml/mm-cell-info-cdma.xml"/>
+ <xi:include href="xml/mm-cell-info-gsm.xml"/>
+ <xi:include href="xml/mm-cell-info-umts.xml"/>
+ <xi:include href="xml/mm-cell-info-tdscdma.xml"/>
+ <xi:include href="xml/mm-cell-info-lte.xml"/>
+ <xi:include href="xml/mm-cell-info-nr5g.xml"/>
<xi:include href="xml/mm-pco.xml"/>
+ <xi:include href="xml/mm-nr5g-registration-settings.xml"/>
</section>
<section>
<title>Simple interface support</title>
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 26bc73e..4a04b3d 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -230,6 +230,9 @@
mm_modem_delete_bearer
mm_modem_delete_bearer_finish
mm_modem_delete_bearer_sync
+mm_modem_get_cell_info
+mm_modem_get_cell_info_finish
+mm_modem_get_cell_info_sync
<SUBSECTION DebugMethods>
mm_modem_command
mm_modem_command_finish
@@ -278,6 +281,245 @@
</SECTION>
<SECTION>
+<FILE>mm-cell-info</FILE>
+<TITLE>MMCellInfo</TITLE>
+MMCellInfo
+<SUBSECTION Getters>
+mm_cell_info_get_cell_type
+mm_cell_info_get_serving
+<SUBSECTION Private>
+mm_cell_info_set_cell_type
+mm_cell_info_set_serving
+mm_cell_info_build_string
+mm_cell_info_get_dictionary
+mm_cell_info_new_from_dictionary
+MM_CELL_INFO_GET_DICTIONARY_INSERT
+MM_CELL_INFO_BUILD_STRING_APPEND
+MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET
+MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET
+<SUBSECTION Standard>
+MMCellInfoClass
+MMCellInfoPrivate
+MM_IS_CELL_INFO
+MM_IS_CELL_INFO_CLASS
+MM_TYPE_CELL_INFO
+MM_CELL_INFO
+MM_CELL_INFO_CLASS
+MM_CELL_INFO_GET_CLASS
+mm_cell_info_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-cdma</FILE>
+<TITLE>MMCellInfoCdma</TITLE>
+MMCellInfoCdma
+<SUBSECTION Getters>
+mm_cell_info_cdma_get_nid
+mm_cell_info_cdma_get_sid
+mm_cell_info_cdma_get_base_station_id
+mm_cell_info_cdma_get_ref_pn
+mm_cell_info_cdma_get_pilot_strength
+<SUBSECTION Private>
+mm_cell_info_cdma_new_from_dictionary
+mm_cell_info_cdma_set_nid
+mm_cell_info_cdma_set_sid
+mm_cell_info_cdma_set_base_station_id
+mm_cell_info_cdma_set_ref_pn
+mm_cell_info_cdma_set_pilot_strength
+<SUBSECTION Standard>
+MMCellInfoCdmaClass
+MMCellInfoCdmaPrivate
+MM_IS_CELL_INFO_CDMA
+MM_IS_CELL_INFO_CDMA_CLASS
+MM_TYPE_CELL_INFO_CDMA
+MM_CELL_INFO_CDMA
+MM_CELL_INFO_CDMA_CLASS
+MM_CELL_INFO_CDMA_GET_CLASS
+mm_cell_info_cdma_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-gsm</FILE>
+<TITLE>MMCellInfoGsm</TITLE>
+MMCellInfoGsm
+<SUBSECTION Getters>
+mm_cell_info_gsm_get_operator_id
+mm_cell_info_gsm_get_lac
+mm_cell_info_gsm_get_ci
+mm_cell_info_gsm_get_timing_advance
+mm_cell_info_gsm_get_arfcn
+mm_cell_info_gsm_get_base_station_id
+mm_cell_info_gsm_get_rx_level
+<SUBSECTION Private>
+mm_cell_info_gsm_new_from_dictionary
+mm_cell_info_gsm_set_operator_id
+mm_cell_info_gsm_set_lac
+mm_cell_info_gsm_set_ci
+mm_cell_info_gsm_set_timing_advance
+mm_cell_info_gsm_set_arfcn
+mm_cell_info_gsm_set_base_station_id
+mm_cell_info_gsm_set_rx_level
+<SUBSECTION Standard>
+MMCellInfoGsmClass
+MMCellInfoGsmPrivate
+MM_IS_CELL_INFO_GSM
+MM_IS_CELL_INFO_GSM_CLASS
+MM_TYPE_CELL_INFO_GSM
+MM_CELL_INFO_GSM
+MM_CELL_INFO_GSM_CLASS
+MM_CELL_INFO_GSM_GET_CLASS
+mm_cell_info_gsm_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-umts</FILE>
+<TITLE>MMCellInfoUmts</TITLE>
+MMCellInfoUmts
+<SUBSECTION Getters>
+mm_cell_info_umts_get_operator_id
+mm_cell_info_umts_get_lac
+mm_cell_info_umts_get_ci
+mm_cell_info_umts_get_frequency_fdd_ul
+mm_cell_info_umts_get_frequency_fdd_dl
+mm_cell_info_umts_get_frequency_tdd
+mm_cell_info_umts_get_uarfcn
+mm_cell_info_umts_get_psc
+mm_cell_info_umts_get_rscp
+mm_cell_info_umts_get_ecio
+mm_cell_info_umts_get_path_loss
+<SUBSECTION Private>
+mm_cell_info_umts_new_from_dictionary
+mm_cell_info_umts_set_operator_id
+mm_cell_info_umts_set_lac
+mm_cell_info_umts_set_ci
+mm_cell_info_umts_set_frequency_fdd_ul
+mm_cell_info_umts_set_frequency_fdd_dl
+mm_cell_info_umts_set_frequency_tdd
+mm_cell_info_umts_set_uarfcn
+mm_cell_info_umts_set_psc
+mm_cell_info_umts_set_rscp
+mm_cell_info_umts_set_ecio
+mm_cell_info_umts_set_path_loss
+<SUBSECTION Standard>
+MMCellInfoUmtsClass
+MMCellInfoUmtsPrivate
+MM_IS_CELL_INFO_UMTS
+MM_IS_CELL_INFO_UMTS_CLASS
+MM_TYPE_CELL_INFO_UMTS
+MM_CELL_INFO_UMTS
+MM_CELL_INFO_UMTS_CLASS
+MM_CELL_INFO_UMTS_GET_CLASS
+mm_cell_info_umts_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-tdscdma</FILE>
+<TITLE>MMCellInfoTdscdma</TITLE>
+MMCellInfoTdscdma
+<SUBSECTION Getters>
+mm_cell_info_tdscdma_get_operator_id
+mm_cell_info_tdscdma_get_lac
+mm_cell_info_tdscdma_get_ci
+mm_cell_info_tdscdma_get_uarfcn
+mm_cell_info_tdscdma_get_cell_parameter_id
+mm_cell_info_tdscdma_get_timing_advance
+mm_cell_info_tdscdma_get_rscp
+mm_cell_info_tdscdma_get_path_loss
+<SUBSECTION Private>
+mm_cell_info_tdscdma_new_from_dictionary
+mm_cell_info_tdscdma_set_operator_id
+mm_cell_info_tdscdma_set_lac
+mm_cell_info_tdscdma_set_ci
+mm_cell_info_tdscdma_set_uarfcn
+mm_cell_info_tdscdma_set_cell_parameter_id
+mm_cell_info_tdscdma_set_timing_advance
+mm_cell_info_tdscdma_set_rscp
+mm_cell_info_tdscdma_set_path_loss
+<SUBSECTION Standard>
+MMCellInfoTdscdmaClass
+MMCellInfoTdscdmaPrivate
+MM_IS_CELL_INFO_TDSCDMA
+MM_IS_CELL_INFO_TDSCDMA_CLASS
+MM_TYPE_CELL_INFO_TDSCDMA
+MM_CELL_INFO_TDSCDMA
+MM_CELL_INFO_TDSCDMA_CLASS
+MM_CELL_INFO_TDSCDMA_GET_CLASS
+mm_cell_info_tdscdma_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-lte</FILE>
+<TITLE>MMCellInfoLte</TITLE>
+MMCellInfoLte
+<SUBSECTION Getters>
+mm_cell_info_lte_get_operator_id
+mm_cell_info_lte_get_tac
+mm_cell_info_lte_get_ci
+mm_cell_info_lte_get_physical_ci
+mm_cell_info_lte_get_earfcn
+mm_cell_info_lte_get_rsrp
+mm_cell_info_lte_get_rsrq
+mm_cell_info_lte_get_timing_advance
+<SUBSECTION Private>
+mm_cell_info_lte_new_from_dictionary
+mm_cell_info_lte_set_operator_id
+mm_cell_info_lte_set_tac
+mm_cell_info_lte_set_ci
+mm_cell_info_lte_set_physical_ci
+mm_cell_info_lte_set_earfcn
+mm_cell_info_lte_set_rsrp
+mm_cell_info_lte_set_rsrq
+mm_cell_info_lte_set_timing_advance
+<SUBSECTION Standard>
+MMCellInfoLteClass
+MMCellInfoLtePrivate
+MM_IS_CELL_INFO_LTE
+MM_IS_CELL_INFO_LTE_CLASS
+MM_TYPE_CELL_INFO_LTE
+MM_CELL_INFO_LTE
+MM_CELL_INFO_LTE_CLASS
+MM_CELL_INFO_LTE_GET_CLASS
+mm_cell_info_lte_get_type
+</SECTION>
+
+<SECTION>
+<FILE>mm-cell-info-nr5g</FILE>
+<TITLE>MMCellInfoNr5g</TITLE>
+MMCellInfoNr5g
+<SUBSECTION Getters>
+mm_cell_info_nr5g_get_operator_id
+mm_cell_info_nr5g_get_tac
+mm_cell_info_nr5g_get_ci
+mm_cell_info_nr5g_get_physical_ci
+mm_cell_info_nr5g_get_nrarfcn
+mm_cell_info_nr5g_get_rsrp
+mm_cell_info_nr5g_get_rsrq
+mm_cell_info_nr5g_get_sinr
+mm_cell_info_nr5g_get_timing_advance
+<SUBSECTION Private>
+mm_cell_info_nr5g_new_from_dictionary
+mm_cell_info_nr5g_set_operator_id
+mm_cell_info_nr5g_set_tac
+mm_cell_info_nr5g_set_ci
+mm_cell_info_nr5g_set_physical_ci
+mm_cell_info_nr5g_set_nrarfcn
+mm_cell_info_nr5g_set_rsrp
+mm_cell_info_nr5g_set_rsrq
+mm_cell_info_nr5g_set_sinr
+mm_cell_info_nr5g_set_timing_advance
+<SUBSECTION Standard>
+MMCellInfoNr5gClass
+MMCellInfoNr5gPrivate
+MM_IS_CELL_INFO_NR5G
+MM_IS_CELL_INFO_NR5G_CLASS
+MM_TYPE_CELL_INFO_NR5G
+MM_CELL_INFO_NR5G
+MM_CELL_INFO_NR5G_CLASS
+MM_CELL_INFO_NR5G_GET_CLASS
+mm_cell_info_nr5g_get_type
+</SECTION>
+
+<SECTION>
<FILE>mm-modem-3gpp</FILE>
<TITLE>MMModem3gpp</TITLE>
MMModem3gpp
@@ -311,6 +553,7 @@
mm_modem_3gpp_peek_initial_eps_bearer_settings
mm_modem_3gpp_get_packet_service_state
mm_modem_3gpp_get_nr5g_registration_settings
+mm_modem_3gpp_peek_nr5g_registration_settings
<SUBSECTION Methods>
mm_modem_3gpp_register
mm_modem_3gpp_register_finish
@@ -790,6 +1033,7 @@
mm_firmware_update_settings_new
mm_firmware_update_settings_new_from_variant
mm_firmware_update_settings_set_fastboot_at
+mm_firmware_update_settings_set_method
mm_firmware_update_settings_set_device_ids
mm_firmware_update_settings_set_version
<SUBSECTION Standard>
@@ -1171,6 +1415,7 @@
mm_bearer_get_stats
mm_bearer_get_connection_error
mm_bearer_peek_connection_error
+mm_bearer_get_reload_stats_supported
<SUBSECTION Methods>
mm_bearer_connect
mm_bearer_connect_finish
@@ -1684,6 +1929,8 @@
<SUBSECTION Getters>
mm_modem_3gpp_profile_manager_get_path
mm_modem_3gpp_profile_manager_dup_path
+mm_modem_3gpp_profile_manager_get_index_field
+mm_modem_3gpp_profile_manager_dup_index_field
<SUBSECTION Methods>
mm_modem_3gpp_profile_manager_list
mm_modem_3gpp_profile_manager_list_finish
@@ -1706,6 +1953,32 @@
</SECTION>
<SECTION>
+<FILE>mm-nr5g-registration-settings</FILE>
+<TITLE>MMNr5gRegistrationSettings</TITLE>
+MMNr5gRegistrationSettings
+mm_nr5g_registration_settings_new
+mm_nr5g_registration_settings_set_mico_mode
+mm_nr5g_registration_settings_get_mico_mode
+mm_nr5g_registration_settings_set_drx_cycle
+mm_nr5g_registration_settings_get_drx_cycle
+<SUBSECTION Private>
+mm_nr5g_registration_settings_new_from_string
+mm_nr5g_registration_settings_new_from_dictionary
+mm_nr5g_registration_settings_get_dictionary
+mm_nr5g_registration_settings_cmp
+<SUBSECTION Standard>
+MMNr5gRegistrationSettingsClass
+MMNr5gRegistrationSettingsPrivate
+MM_IS_NR5G_REGISTRATION_SETTINGS
+MM_IS_NR5G_REGISTRATION_SETTINGS_CLASS
+MM_NR5G_REGISTRATION_SETTINGS
+MM_NR5G_REGISTRATION_SETTINGS_CLASS
+MM_NR5G_REGISTRATION_SETTINGS_GET_CLASS
+MM_TYPE_NR5G_REGISTRATION_SETTINGS
+mm_nr5g_registration_settings_get_type
+</SECTION>
+
+<SECTION>
<FILE>mm-enums-types</FILE>
<TITLE>Flags and Enumerations</TITLE>
mm_bearer_type_get_string
@@ -1761,6 +2034,7 @@
mm_call_direction_get_string
mm_call_state_get_string
mm_call_state_reason_get_string
+mm_cell_type_get_string
<SUBSECTION Private>
mm_modem_capability_get_string
mm_modem_lock_build_string_from_mask
@@ -1815,6 +2089,7 @@
mm_call_state_build_string_from_mask
mm_call_state_reason_build_string_from_mask
mm_modem_firmware_update_method_get_string
+mm_cell_type_build_string_from_mask
<SUBSECTION Standard>
MM_TYPE_BEARER_TYPE
MM_TYPE_BEARER_IP_FAMILY
@@ -1823,8 +2098,8 @@
MM_TYPE_BEARER_MULTIPLEX_SUPPORT
MM_TYPE_BEARER_APN_TYPE
MM_TYPE_SIM_TYPE
-MM_TYPE_ESIM_STATUS
-MM_TYPE_SIM_REMOVAL_STATUS
+MM_TYPE_SIM_ESIM_STATUS
+MM_TYPE_SIM_REMOVABILITY
MM_TYPE_BEARER_ACCESS_TYPE_PREFERENCE
MM_TYPE_BEARER_ROAMING_ALLOWANCE
MM_TYPE_BEARER_PROFILE_SOURCE
@@ -1869,6 +2144,7 @@
MM_TYPE_CALL_STATE
MM_TYPE_CALL_STATE_REASON
MM_TYPE_MODEM_FIRMWARE_UPDATE_METHOD
+MM_TYPE_CELL_TYPE
mm_bearer_type_get_type
mm_bearer_ip_family_get_type
mm_bearer_ip_method_get_type
@@ -1922,6 +2198,7 @@
mm_call_state_get_type
mm_call_state_reason_get_type
mm_modem_firmware_update_method_get_type
+mm_cell_type_get_type
</SECTION>
<SECTION>
@@ -2007,6 +2284,7 @@
mm_gdbus_bearer_get_profile_id
mm_gdbus_bearer_get_stats
mm_gdbus_bearer_dup_stats
+mm_gdbus_bearer_get_reload_stats_supported
<SUBSECTION Methods>
mm_gdbus_bearer_call_connect
mm_gdbus_bearer_call_connect_finish
@@ -2028,6 +2306,7 @@
mm_gdbus_bearer_set_profile_id
mm_gdbus_bearer_set_stats
mm_gdbus_bearer_set_multiplexed
+mm_gdbus_bearer_set_reload_stats_supported
mm_gdbus_bearer_override_properties
mm_gdbus_bearer_complete_connect
mm_gdbus_bearer_complete_disconnect
@@ -2359,6 +2638,9 @@
<TITLE>MmGdbusModem3gppProfileManager</TITLE>
MmGdbusModem3gppProfileManager
MmGdbusModem3gppProfileManagerIface
+<SUBSECTION Getters>
+mm_gdbus_modem3gpp_profile_manager_dup_index_field
+mm_gdbus_modem3gpp_profile_manager_get_index_field
<SUBSECTION Methods>
mm_gdbus_modem3gpp_profile_manager_call_delete
mm_gdbus_modem3gpp_profile_manager_call_delete_finish
@@ -2376,6 +2658,7 @@
mm_gdbus_modem3gpp_profile_manager_complete_set
mm_gdbus_modem3gpp_profile_manager_interface_info
mm_gdbus_modem3gpp_profile_manager_override_properties
+mm_gdbus_modem3gpp_profile_manager_set_index_field
<SUBSECTION Standard>
MM_GDBUS_IS_MODEM3GPP_PROFILE_MANAGER
MM_GDBUS_MODEM3GPP_PROFILE_MANAGER
@@ -2527,6 +2810,9 @@
mm_gdbus_modem_call_command
mm_gdbus_modem_call_command_finish
mm_gdbus_modem_call_command_sync
+mm_gdbus_modem_call_get_cell_info
+mm_gdbus_modem_call_get_cell_info_finish
+mm_gdbus_modem_call_get_cell_info_sync
<SUBSECTION Private>
mm_gdbus_modem_set_access_technologies
mm_gdbus_modem_set_bearers
@@ -2576,6 +2862,7 @@
mm_gdbus_modem_complete_set_current_bands
mm_gdbus_modem_complete_set_current_capabilities
mm_gdbus_modem_complete_set_primary_sim_slot
+mm_gdbus_modem_complete_get_cell_info
mm_gdbus_modem_interface_info
mm_gdbus_modem_override_properties
<SUBSECTION Standard>
@@ -3626,6 +3913,9 @@
mm_gdbus_sim_complete_set_preferred_networks
mm_gdbus_sim_interface_info
mm_gdbus_sim_override_properties
+mm_gdbus_sim_set_esim_status
+mm_gdbus_sim_set_removability
+mm_gdbus_sim_set_sim_type
<SUBSECTION Standard>
MM_GDBUS_IS_SIM
MM_GDBUS_SIM
diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h
index bb3c5c0..46f9143 100644
--- a/include/ModemManager-enums.h
+++ b/include/ModemManager-enums.h
@@ -659,6 +659,30 @@
} MMModemPortType;
/**
+ * MMCellType:
+ * @MM_CELL_TYPE_UNKNOWN: Unknown.
+ * @MM_CELL_TYPE_CDMA: CDMA cell.
+ * @MM_CELL_TYPE_GSM: GSM cell.
+ * @MM_CELL_TYPE_UMTS: UMTS cell.
+ * @MM_CELL_TYPE_TDSCDMA: TD-SCDMA cell.
+ * @MM_CELL_TYPE_LTE: LTE cell.
+ * @MM_CELL_TYPE_5GNR: 5GNR cell.
+ *
+ * Type of cell information reported.
+ *
+ * Since: 1.20
+ */
+typedef enum { /*< underscore_name=mm_cell_type >*/
+ MM_CELL_TYPE_UNKNOWN = 0,
+ MM_CELL_TYPE_CDMA = 1,
+ MM_CELL_TYPE_GSM = 2,
+ MM_CELL_TYPE_UMTS = 3,
+ MM_CELL_TYPE_TDSCDMA = 4,
+ MM_CELL_TYPE_LTE = 5,
+ MM_CELL_TYPE_5GNR = 6,
+} MMCellType;
+
+/**
* MMSmsPduType:
* @MM_SMS_PDU_TYPE_UNKNOWN: Unknown type.
* @MM_SMS_PDU_TYPE_DELIVER: 3GPP Mobile-Terminated (MT) message.
@@ -1619,6 +1643,7 @@
* @MM_MODEM_FIRMWARE_UPDATE_METHOD_QMI_PDC: Device supports QMI PDC based update.
* @MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU: Device supports MBIM QDU based update. Since 1.18.
* @MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE: Device supports Firehose based update. Since 1.18.
+ * @MM_MODEM_FIRMWARE_UPDATE_METHOD_SAHARA: Device supports Sahara protocol. Usually used in combination with Firehose. Since 1.20.
*
* Type of firmware update method supported by the module.
*
@@ -1630,6 +1655,7 @@
MM_MODEM_FIRMWARE_UPDATE_METHOD_QMI_PDC = 1 << 1,
MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU = 1 << 2,
MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE = 1 << 3,
+ MM_MODEM_FIRMWARE_UPDATE_METHOD_SAHARA = 1 << 4,
} MMModemFirmwareUpdateMethod;
/**
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Signal.xml b/introspection/org.freedesktop.ModemManager1.Modem.Signal.xml
index 93b2996..213db49 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Signal.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Signal.xml
@@ -15,7 +15,7 @@
This interface provides access to extended signal quality information.
- This interface will only be available once the modem is ready to be
+ This interface will only be functional once the modem is ready to be
registered in the cellular network. 3GPP devices will require a valid
unlocked SIM card before any of the features in the interface can be
used.
@@ -27,6 +27,10 @@
Both Setup() and SetupThresholds() can also be used at the same time if
required, e.g. if they report different signal quality measurement types.
+
+ The thresholds and polling setup will only be in effect if the modem is
+ in enabled state. Changing the settings with Setup() or SetupThresholds()
+ is also possible while in disabled state, though.
-->
<interface name="org.freedesktop.ModemManager1.Modem.Signal">
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.xml b/introspection/org.freedesktop.ModemManager1.Modem.xml
index 80da06e..1e346b9 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.xml
@@ -186,14 +186,14 @@
@sim_slot: SIM slot number to set as primary.
Selects which SIM slot to be considered as primary, on devices that expose
- multiple slots in the #org.freedesktop.ModemManager1.Modem:SimSlots property.
+ multiple slots in the #org.freedesktop.ModemManager1.Modem:SimSlots property.
When the switch happens the modem may require a full device reprobe, so the modem
- object in DBus will get removed, and recreated once the selected SIM slot is in
- use.
+ object in DBus will get removed, and recreated once the selected SIM slot is in
+ use.
There is no limitation on which SIM slot to select, so the user may also set as
- primary a slot that doesn't currently have any valid SIM card inserted.
+ primary a slot that doesn't currently have any valid SIM card inserted.
Since: 1.16
-->
@@ -201,6 +201,423 @@
<arg name="sim_slot" type="u" direction="in" />
</method>
+
+ <!--
+ GetCellInfo:
+
+ Get information for available cells in different access technologies,
+ either serving or neighboring.
+
+ An array of dictionaries is returned, where each dictionary reports information for
+ one single cell.
+
+ The dictionaries have mandatory keys that are always given, including:
+
+ <variablelist>
+ <varlistentry><term><literal>"cell-type"</literal></term>
+ <listitem>
+ The <link linkend="MMCellType">MMCellType</link>, given as an unsigned integer
+ value (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"serving"</literal></term>
+ <listitem>
+ Flag specifying whether the cell is a serving cell or otherwise a neighboring cell,
+ given as a boolean value (signature <literal>"b"</literal>).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ For each different cell type, other optional keys may be given.
+
+ <variablelist>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-CDMA:CAPS">MM_CELL_TYPE_CDMA</link></term>
+ <listitem>
+ <para>
+ The CDMA cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"nid"</literal></term>
+ <listitem>
+ Network id, given as a string value (signature <literal>"s"</literal>)
+ in upper-case hexadecimal format without leading zeros. E.g. <literal>"12345"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"sid"</literal></term>
+ <listitem>
+ System id, given as a string value (signature <literal>"s"</literal>)
+ in upper-case hexadecimal format without leading zeros. E.g. <literal>"ABCD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"base-station-id"</literal></term>
+ <listitem>
+ Base station id, given as a string value (signature <literal>"s"</literal>)
+ in upper-case hexadecimal format without leading zeros. E.g. <literal>"3F"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ref-pn"</literal></term>
+ <listitem>
+ Base station PN number, given as a string value (signature <literal>"s"</literal>)
+ in upper-case hexadecimal format without leading zeros. E.g. <literal>"3F"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"pilot-strength"</literal></term>
+ <listitem>
+ The signal strength of the pilot, given in the same format and scale as the GSM
+ SINR level, given as an unsigned integer value (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-GSM:CAPS">MM_CELL_TYPE_GSM</link></term>
+ <listitem>
+ <para>
+ The GSM cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ PLMN MCC/MNC, given as a string value (signature <literal>"s"</literal>).
+ E.g. <literal>21034</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"lac"</literal></term>
+ <listitem>
+ This is the two-byte Location Area Code of the base station, given
+ as a string value (signature <literal>"s"</literal>) in upper-case
+ hexadecimal format without leading zeros, as specified in 3GPP TS
+ 27.007. E.g. <literal>"84CD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ci"</literal></term>
+ <listitem>
+ This is the two- or four-byte Cell Identifier, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros, as specified in 3GPP TS 27.007.
+ E.g. <literal>"2BAF"</literal> or <literal>"D30156"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"timing-advance"</literal></term>
+ <listitem>
+ Measured delay (in bit periods; 1 bit period = 48/13 microsecond)
+ of an access burst transmission on the RACH or PRACH to the expected
+ signal from a mobile station at zero distance under static channel
+ conditions, given as an unsigned integer value (signature
+ <literal>"u"</literal>). Only applicable for the serving cell (i.e.
+ "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"arfcn"</literal></term>
+ <listitem>
+ Absolute RF channel number, given as an unsigned integer value (signature
+ <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"base-station-id"</literal></term>
+ <listitem>
+ Base station id, given as a string value (signature <literal>"s"</literal>)
+ in upper-case hexadecimal format without leading zeros, as specified in
+ 3GPP TS 27.007. E.g. <literal>"3F"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rx-level"</literal></term>
+ <listitem>
+ Serving cell Rx measurement, given as a unsigned integer value
+ (signature <literal>"u"</literal>. Values range between 0 and 63.
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-UMTS:CAPS">MM_CELL_TYPE_UMTS</link></term>
+ <listitem>
+ <para>
+ The UMTS cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ PLMN MCC/MNC, given as a string value (signature <literal>"s"</literal>).
+ E.g. <literal>21034</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"lac"</literal></term>
+ <listitem>
+ This is the two-byte Location Area Code of the base station, given
+ as a string value (signature <literal>"s"</literal>) in upper-case
+ hexadecimal format without leading zeros, as specified in 3GPP TS
+ 27.007. E.g. <literal>"84CD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ci"</literal></term>
+ <listitem>
+ This is the two- or four-byte Cell Identifier, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros, as specified in 3GPP TS 27.007.
+ e.g. <literal>"2BAF"</literal> or <literal>"D30156"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"frequency-fdd-ul"</literal></term>
+ <listitem>
+ In FDD, the frequency of the uplink in kHz, given as an unsigned integer value
+ (signature <literal>"u"</literal>). Values range between 0 and 16383.
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"frequency-fdd-dl"</literal></term>
+ <listitem>
+ In FDD, the frequency of the downlink in kHz, given as an unsigned integer value
+ (signature <literal>"u"</literal>). Values range between 0 and 16383.
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"frequency-tdd"</literal></term>
+ <listitem>
+ In TDD, the frequency in kHz, given as an unsigned integer value
+ (signature <literal>"u"</literal>). Values range between 0 and 16383.
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"uarfcn"</literal></term>
+ <listitem>
+ UTRA absolute RF channel number, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"psc"</literal></term>
+ <listitem>
+ Primary scrambling code, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rscp"</literal></term>
+ <listitem>
+ Received signal code power; the received power on one code measured
+ in dBm on the primary CPICH channel of the cell, given as a
+ signed integer value (signature <literal>"d"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ecio"</literal></term>
+ <listitem>
+ ECIO; the received energy per chip divided by the power density in the
+ band measured in dBm on the primary CPICH channel of the cell, given as a
+ signed integer value (signature <literal>"d"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"path-loss"</literal></term>
+ <listitem>
+ The path loss of the cell, given as an unsigned integer value (signature
+ <literal>"u"</literal>.
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-TDSCDMA:CAPS">MM_CELL_TYPE_TDSCDMA</link></term>
+ <listitem>
+ <para>
+ The TD-SCDMA cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ PLMN MCC/MNC, given as a string value (signature <literal>"s"</literal>).
+ E.g. <literal>21034</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"lac"</literal></term>
+ <listitem>
+ This is the two-byte Location Area Code of the base station, given
+ as a string value (signature <literal>"s"</literal>) in upper-case
+ hexadecimal format without leading zeros, as specified in 3GPP TS
+ 27.007. E.g. <literal>"84CD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ci"</literal></term>
+ <listitem>
+ This is the two- or four-byte Cell Identifier, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros, as specified in 3GPP TS 27.007.
+ e.g. <literal>"2BAF"</literal> or <literal>"D30156"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"uarfcn"</literal></term>
+ <listitem>
+ UTRA absolute RF channel number, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"cell-parameter-id"</literal></term>
+ <listitem>
+ The cell parameter ID, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"timing-advance"</literal></term>
+ <listitem>
+ Measured delay (in bit periods; 1 bit period = 48/13 microsecond)
+ of an access burst transmission on the RACH or PRACH to the expected
+ signal from an MS at zero distance under static channel conditions,
+ given as a unsigned integer value (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rscp"</literal></term>
+ <listitem>
+ Received signal code power; the received power on one code measured
+ in dBm on the primary CPICH channel of the cell, given as a
+ signed integer value (signature <literal>"d"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"path-loss"</literal></term>
+ <listitem>
+ The path loss of the cell, given as an unsigned integer value (signature
+ <literal>"u"</literal>.
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-LTE:CAPS">MM_CELL_TYPE_LTE</link></term>
+ <listitem>
+ <para>
+ The LTE cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ PLMN MCC/MNC, given as a string value (signature <literal>"s"</literal>).
+ E.g. <literal>21034</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"tac"</literal></term>
+ <listitem>
+ This is the two- or three-byte Tracking Area Code of the base station, given
+ as a string value (signature <literal>"s"</literal>) in upper-case
+ hexadecimal format without leading zeros, as specified in 3GPP TS
+ 27.007. E.g. <literal>"84CD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ci"</literal></term>
+ <listitem>
+ This is the two- or four-byte Cell Identifier, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros, as specified in 3GPP TS 27.007.
+ e.g. <literal>"2BAF"</literal> or <literal>"D30156"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"physical-ci"</literal></term>
+ <listitem>
+ The physical cell id, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros. E.g. <literal>"1A0"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"earfcn"</literal></term>
+ <listitem>
+ E-UTRA absolute RF channel number, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rsrp"</literal></term>
+ <listitem>
+ The average reference signal received power in dBm, given as a signed
+ integer value (signature <literal>"d"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rsrq"</literal></term>
+ <listitem>
+ The average reference signal received quality in dB, given as a signed
+ integer value (signature <literal>"d"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"timing-advance"</literal></term>
+ <listitem>
+ The timing advance, given as an unsigned integer value (signature <literal>"u"</literal>).
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><link linkend="MM-CELL-TYPE-5GNR:CAPS">MM_CELL_TYPE_5GNR</link></term>
+ <listitem>
+ <para>
+ The 5GNR cell information may include the following additional keys:
+ </para>
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ PLMN MCC/MNC, given as a string value (signature <literal>"s"</literal>).
+ E.g. <literal>21034</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"tac"</literal></term>
+ <listitem>
+ This is the two- or three-byte Tracking Area Code of the base station, given
+ as a string value (signature <literal>"s"</literal>) in upper-case
+ hexadecimal format without leading zeros, as specified in 3GPP TS
+ 27.007. E.g. <literal>"84CD"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"ci"</literal></term>
+ <listitem>
+ This is the two- or four-byte Cell Identifier, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros, as specified in 3GPP TS 27.007.
+ e.g. <literal>"2BAF"</literal> or <literal>"D30156"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"physical-ci"</literal></term>
+ <listitem>
+ The physical cell id, given as a string value
+ (signature <literal>"s"</literal>) in upper-case hexadecimal format
+ without leading zeros. E.g. <literal>"1A0"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"nrarfcn"</literal></term>
+ <listitem>
+ NR absolute RF channel number, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rsrp"</literal></term>
+ <listitem>
+ The average reference signal received power in dBm, given as a signed
+ integer value (signature <literal>"d"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rsrq"</literal></term>
+ <listitem>
+ The average reference signal received quality in dB, given as a signed
+ integer value (signature <literal>"d"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"sinr"</literal></term>
+ <listitem>
+ The signal to interference and noise ratio, given as a signed integer value
+ (signature <literal>"d"</literal>.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"timing-advance"</literal></term>
+ <listitem>
+ The timing advance, given as an unsigned integer value (signature
+ <literal>"u"</literal>).
+ Only applicable for the serving cell (i.e. "serving" must be TRUE).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ Since: 1.20
+ -->
+ <method name="GetCellInfo">
+ <arg name="cell_info" type="aa{sv}" direction="out" />
+ </method>
+
<!--
Command:
@cmd: The command string, e.g. "AT+GCAP" or "+GCAP" (leading AT is inserted if necessary).
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am
index ff44074..08d5ee2 100644
--- a/libmm-glib/Makefile.am
+++ b/libmm-glib/Makefile.am
@@ -101,6 +101,20 @@
mm-signal-threshold-properties.c \
mm-nr5g-registration-settings.h \
mm-nr5g-registration-settings.c \
+ mm-cell-info.h \
+ mm-cell-info.c \
+ mm-cell-info-cdma.h \
+ mm-cell-info-cdma.c \
+ mm-cell-info-gsm.h \
+ mm-cell-info-gsm.c \
+ mm-cell-info-umts.h \
+ mm-cell-info-umts.c \
+ mm-cell-info-tdscdma.h \
+ mm-cell-info-tdscdma.c \
+ mm-cell-info-lte.h \
+ mm-cell-info-lte.c \
+ mm-cell-info-nr5g.h \
+ mm-cell-info-nr5g.c \
mm-compat.h \
mm-compat.c \
$(NULL)
@@ -180,6 +194,13 @@
mm-3gpp-profile.h \
mm-signal-threshold-properties.h \
mm-nr5g-registration-settings.h \
+ mm-cell-info.h \
+ mm-cell-info-cdma.h \
+ mm-cell-info-gsm.h \
+ mm-cell-info-umts.h \
+ mm-cell-info-tdscdma.h \
+ mm-cell-info-lte.h \
+ mm-cell-info-nr5g.h \
mm-compat.h \
$(NULL)
diff --git a/libmm-glib/generated/meson.build b/libmm-glib/generated/meson.build
index a44115e..798fd24 100644
--- a/libmm-glib/generated/meson.build
+++ b/libmm-glib/generated/meson.build
@@ -63,12 +63,12 @@
fhead: '#include <ModemManager.h>\n#include "mm-errors-types.h"\n',
)
-gdbus_ifaces = [
- ['bearer', mm_ifaces_bearer, [], false],
- ['call', mm_ifaces_call, [], false],
- ['manager', mm_ifaces, [], false],
- ['sim', mm_ifaces_sim, [], false],
-]
+gdbus_ifaces = {
+ 'bearer': {'sources': mm_ifaces_bearer, 'object_manager': false},
+ 'call': {'sources': mm_ifaces_call, 'object_manager': false},
+ 'manager': {'sources': mm_ifaces, 'object_manager': false},
+ 'sim': {'sources': mm_ifaces_sim, 'object_manager': false},
+}
annotations = [
['org.freedesktop.ModemManager1.Modem.ModemCdma', 'org.gtk.GDBus.C.Name', 'ModemCdma'],
@@ -77,22 +77,20 @@
['org.freedesktop.ModemManager1.Modem.Modem3gpp.ProfileManager', 'org.gtk.GDBus.C.Name', 'Modem3gppProfileManager'],
]
-gdbus_ifaces += [['modem', mm_ifaces_modem, annotations, true]]
+gdbus_ifaces += {'modem': {'sources': mm_ifaces_modem, 'annotations': annotations, 'object_manager': true}}
annotations = [['org.freedesktop.ModemManager1.Sms:Data', 'org.gtk.GDBus.C.ForceGVariant', 'True']]
-gdbus_ifaces += [['sms', mm_ifaces_sms, annotations, false]]
+gdbus_ifaces += {'sms': {'sources': mm_ifaces_sms, 'annotations': annotations, 'object_manager': false}}
-foreach gdbus_iface: gdbus_ifaces
+foreach name, kwargs: gdbus_ifaces
gdbus_sources = gnome.gdbus_codegen(
- 'mm-gdbus-' + gdbus_iface[0],
- sources: gdbus_iface[1],
+ 'mm-gdbus-' + name,
interface_prefix: 'org.freedesktop.ModemManager1.',
namespace: 'MmGdbus',
docbook: 'mm-gdbus-doc',
- annotations: gdbus_iface[2],
- object_manager: gdbus_iface[3],
autocleanup: 'objects',
+ kwargs: kwargs,
# FIXME: due to the lack of possibility to add `docbook targets` to the `expand_content_files`.
build_by_default: true,
install_header: true,
diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h
index fa47fa6..a6490fd 100644
--- a/libmm-glib/libmm-glib.h
+++ b/libmm-glib/libmm-glib.h
@@ -86,6 +86,13 @@
#include <mm-3gpp-profile.h>
#include <mm-signal-threshold-properties.h>
#include <mm-nr5g-registration-settings.h>
+#include <mm-cell-info.h>
+#include <mm-cell-info-cdma.h>
+#include <mm-cell-info-gsm.h>
+#include <mm-cell-info-umts.h>
+#include <mm-cell-info-tdscdma.h>
+#include <mm-cell-info-lte.h>
+#include <mm-cell-info-nr5g.h>
#include <mm-compat.h>
/* generated */
diff --git a/libmm-glib/meson.build b/libmm-glib/meson.build
index 30500ec..6451843 100644
--- a/libmm-glib/meson.build
+++ b/libmm-glib/meson.build
@@ -16,6 +16,13 @@
'mm-call.h',
'mm-call-properties.h',
'mm-cdma-manual-activation-properties.h',
+ 'mm-cell-info.h',
+ 'mm-cell-info-cdma.h',
+ 'mm-cell-info-gsm.h',
+ 'mm-cell-info-lte.h',
+ 'mm-cell-info-nr5g.h',
+ 'mm-cell-info-tdscdma.h',
+ 'mm-cell-info-umts.h',
'mm-compat.h',
'mm-firmware-properties.h',
'mm-firmware-update-settings.h',
@@ -71,6 +78,13 @@
'mm-call.c',
'mm-call-properties.c',
'mm-cdma-manual-activation-properties.c',
+ 'mm-cell-info.c',
+ 'mm-cell-info-cdma.c',
+ 'mm-cell-info-gsm.c',
+ 'mm-cell-info-lte.c',
+ 'mm-cell-info-nr5g.c',
+ 'mm-cell-info-tdscdma.c',
+ 'mm-cell-info-umts.c',
'mm-common-helpers.c',
'mm-compat.c',
'mm-firmware-properties.c',
@@ -113,8 +127,10 @@
deps = [include_dep]
+libname = 'mm-glib'
+
libmm_glib = shared_library(
- 'mm-glib',
+ libname,
version: mm_glib_version,
sources: sources,
include_directories: top_inc,
@@ -133,7 +149,7 @@
pkg.generate(
libraries: libmm_glib,
version: mm_version,
- name: 'mm-glib',
+ name: libname,
description: 'Library to control and monitor the ModemManager',
subdirs: mm_glib_name,
# FIXME: produced by the inhability of meson to use internal dependencies
@@ -166,7 +182,7 @@
symbol_prefix: gir_prefix.to_lower(),
extra_args: args,
header: 'libmm-glib.h',
- export_packages: gir_ns,
+ export_packages: libname,
install: true,
)
diff --git a/libmm-glib/mm-call-audio-format.c b/libmm-glib/mm-call-audio-format.c
index 452fa72..a3d617c 100644
--- a/libmm-glib/mm-call-audio-format.c
+++ b/libmm-glib/mm-call-audio-format.c
@@ -167,25 +167,24 @@
return NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- if (self) {
- if (self->priv->encoding)
- g_variant_builder_add (&builder,
- "{sv}",
- PROPERTY_ENCODING,
- g_variant_new_string (self->priv->encoding));
- if (self->priv->resolution)
- g_variant_builder_add (&builder,
- "{sv}",
- PROPERTY_RESOLUTION,
- g_variant_new_string (self->priv->resolution));
+ if (self->priv->encoding)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_ENCODING,
+ g_variant_new_string (self->priv->encoding));
- if (self->priv->rate)
- g_variant_builder_add (&builder,
- "{sv}",
- PROPERTY_RATE,
- g_variant_new_uint32 (self->priv->rate));
- }
+ if (self->priv->resolution)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_RESOLUTION,
+ g_variant_new_string (self->priv->resolution));
+
+ if (self->priv->rate)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_RATE,
+ g_variant_new_uint32 (self->priv->rate));
return g_variant_builder_end (&builder);
}
diff --git a/libmm-glib/mm-cell-info-cdma.c b/libmm-glib/mm-cell-info-cdma.c
new file mode 100644
index 0000000..f288ee2
--- /dev/null
+++ b/libmm-glib/mm-cell-info-cdma.c
@@ -0,0 +1,308 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-cdma.h"
+
+/**
+ * SECTION: mm-cell-info-cdma
+ * @title: MMCellInfoCdma
+ * @short_description: Helper object to report CDMA cell info
+ *
+ * The #MMCellInfoCdma is an object used to report CDMA cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoCdma, mm_cell_info_cdma, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_NID "nid"
+#define PROPERTY_SID "sid"
+#define PROPERTY_BASE_STATION_ID "base-station-id"
+#define PROPERTY_REF_PN "ref-pn"
+#define PROPERTY_PILOT_STRENGTH "pilot-strength"
+
+struct _MMCellInfoCdmaPrivate {
+ gchar *nid;
+ gchar *sid;
+ gchar *base_station_id;
+ gchar *ref_pn;
+ guint pilot_strength;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_cdma_get_nid:
+ * @self: a #MMCellInfoCdma.
+ *
+ * Get the CDMA network id.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros.
+ *
+ * Returns: (transfer none): the CDMA network id, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_cdma_get_nid (MMCellInfoCdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_CDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->nid);
+}
+
+/**
+ * mm_cell_info_cdma_set_nid: (skip)
+ */
+void
+mm_cell_info_cdma_set_nid (MMCellInfoCdma *self,
+ const gchar *nid)
+{
+ g_free (self->priv->nid);
+ self->priv->nid = g_strdup (nid);
+}
+
+/**
+ * mm_cell_info_cdma_get_sid:
+ * @self: a #MMCellInfoCdma.
+ *
+ * Get the CDMA system id.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros.
+ *
+ * Returns: (transfer none): the CDMA system id, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_cdma_get_sid (MMCellInfoCdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_CDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->sid);
+}
+
+/**
+ * mm_cell_info_cdma_set_sid: (skip)
+ */
+void
+mm_cell_info_cdma_set_sid (MMCellInfoCdma *self,
+ const gchar *sid)
+{
+ g_free (self->priv->sid);
+ self->priv->sid = g_strdup (sid);
+}
+
+/**
+ * mm_cell_info_cdma_get_base_station_id:
+ * @self: a #MMCellInfoCdma.
+ *
+ * Get the CDMA base station id.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros.
+ *
+ * Returns: (transfer none): the CDMA base station id, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_cdma_get_base_station_id (MMCellInfoCdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_CDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->base_station_id);
+}
+
+/**
+ * mm_cell_info_cdma_set_base_station_id: (skip)
+ */
+void
+mm_cell_info_cdma_set_base_station_id (MMCellInfoCdma *self,
+ const gchar *base_station_id)
+{
+ g_free (self->priv->base_station_id);
+ self->priv->base_station_id = g_strdup (base_station_id);
+}
+
+/**
+ * mm_cell_info_cdma_get_ref_pn:
+ * @self: a #MMCellInfoCdma.
+ *
+ * Get the CDMA base station PN number.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros.
+ *
+ * Returns: (transfer none): the CDMA base station PN number, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_cdma_get_ref_pn (MMCellInfoCdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_CDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ref_pn);
+}
+
+/**
+ * mm_cell_info_cdma_set_ref_pn: (skip)
+ */
+void
+mm_cell_info_cdma_set_ref_pn (MMCellInfoCdma *self,
+ const gchar *ref_pn)
+{
+ g_free (self->priv->ref_pn);
+ self->priv->ref_pn = g_strdup (ref_pn);
+}
+
+/**
+ * mm_cell_info_cdma_get_pilot_strength:
+ * @self: a #MMCellInfoCdma.
+ *
+ * Get the signal strength of the pilot.
+ *
+ * Given in the same format and scale as the GSM SINR level.
+ *
+ * Returns: the pilot strength, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_cdma_get_pilot_strength (MMCellInfoCdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_CDMA (self), G_MAXUINT);
+
+ return self->priv->pilot_strength;
+}
+
+/**
+ * mm_cell_info_cdma_set_pilot_strength: (skip)
+ */
+void
+mm_cell_info_cdma_set_pilot_strength (MMCellInfoCdma *self,
+ guint pilot_strength)
+{
+ self->priv->pilot_strength = pilot_strength;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoCdma *self = MM_CELL_INFO_CDMA (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("nid", "%s", nid, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("sid", "%s", sid, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("base station id", "%s", base_station_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ref pn", "%s", ref_pn, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("pilot strength", "%u", pilot_strength, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_cdma_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoCdma *self = MM_CELL_INFO_CDMA (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (NID, nid, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (SID, sid, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (BASE_STATION_ID, base_station_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (REF_PN, ref_pn, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PILOT_STRENGTH, pilot_strength, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_cdma_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_cdma_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoCdma *self;
+
+ self = MM_CELL_INFO_CDMA (g_object_new (MM_TYPE_CELL_INFO_CDMA, NULL));
+
+ if (dict) {
+
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (cdma, NID, nid);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (cdma, SID, sid);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (cdma, BASE_STATION_ID, base_station_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (cdma, REF_PN, ref_pn);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (cdma, PILOT_STRENGTH, pilot_strength, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_cdma_init (MMCellInfoCdma *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_CDMA, MMCellInfoCdmaPrivate);
+ self->priv->pilot_strength = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoCdma *self = MM_CELL_INFO_CDMA (object);
+
+ g_free (self->priv->sid);
+ g_free (self->priv->nid);
+ g_free (self->priv->base_station_id);
+ g_free (self->priv->ref_pn);
+
+ G_OBJECT_CLASS (mm_cell_info_cdma_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_cdma_class_init (MMCellInfoCdmaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoCdmaPrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-cdma.h b/libmm-glib/mm-cell-info-cdma.h
new file mode 100644
index 0000000..994fbcc
--- /dev/null
+++ b/libmm-glib/mm-cell-info-cdma.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_CDMA_H
+#define MM_CELL_INFO_CDMA_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_CDMA (mm_cell_info_cdma_get_type ())
+#define MM_CELL_INFO_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_CDMA, MMCellInfoCdma))
+#define MM_CELL_INFO_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_CDMA, MMCellInfoCdmaClass))
+#define MM_IS_CELL_INFO_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_CDMA))
+#define MM_IS_CELL_INFO_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_CDMA))
+#define MM_CELL_INFO_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_CDMA, MMCellInfoCdmaClass))
+
+typedef struct _MMCellInfoCdma MMCellInfoCdma;
+typedef struct _MMCellInfoCdmaClass MMCellInfoCdmaClass;
+typedef struct _MMCellInfoCdmaPrivate MMCellInfoCdmaPrivate;
+
+/**
+ * MMCellInfoCdma:
+ *
+ * The #MMCellInfoCdma structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoCdma {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoCdmaPrivate *priv;
+};
+
+struct _MMCellInfoCdmaClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_cdma_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoCdma, g_object_unref)
+
+const gchar *mm_cell_info_cdma_get_nid (MMCellInfoCdma *self);
+const gchar *mm_cell_info_cdma_get_sid (MMCellInfoCdma *self);
+const gchar *mm_cell_info_cdma_get_base_station_id (MMCellInfoCdma *self);
+const gchar *mm_cell_info_cdma_get_ref_pn (MMCellInfoCdma *self);
+guint mm_cell_info_cdma_get_pilot_strength (MMCellInfoCdma *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_cdma_set_nid (MMCellInfoCdma *self,
+ const gchar *nid);
+void mm_cell_info_cdma_set_sid (MMCellInfoCdma *self,
+ const gchar *sid);
+void mm_cell_info_cdma_set_base_station_id (MMCellInfoCdma *self,
+ const gchar *base_station_id);
+void mm_cell_info_cdma_set_ref_pn (MMCellInfoCdma *self,
+ const gchar *ref_pn);
+void mm_cell_info_cdma_set_pilot_strength (MMCellInfoCdma *self,
+ guint pilot_strength);
+
+MMCellInfo *mm_cell_info_cdma_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_CDMA_H */
diff --git a/libmm-glib/mm-cell-info-gsm.c b/libmm-glib/mm-cell-info-gsm.c
new file mode 100644
index 0000000..9b0b8e1
--- /dev/null
+++ b/libmm-glib/mm-cell-info-gsm.c
@@ -0,0 +1,374 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-gsm.h"
+
+/**
+ * SECTION: mm-cell-info-gsm
+ * @title: MMCellInfoGsm
+ * @short_description: Helper object to report GSM cell info
+ *
+ * The #MMCellInfoGsm is an object used to report GSM cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoGsm, mm_cell_info_gsm, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_LAC "lac"
+#define PROPERTY_CI "ci"
+#define PROPERTY_TIMING_ADVANCE "timing-advance"
+#define PROPERTY_ARFCN "arfcn"
+#define PROPERTY_BASE_STATION_ID "base-station-id"
+#define PROPERTY_RX_LEVEL "rx-level"
+
+struct _MMCellInfoGsmPrivate {
+ gchar *operator_id;
+ gchar *lac;
+ gchar *ci;
+ guint timing_advance;
+ guint arfcn;
+ gchar *base_station_id;
+ guint rx_level;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_gsm_get_operator_id:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the PLMN MCC/MNC.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_gsm_get_operator_id (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->operator_id);
+}
+
+/**
+ * mm_cell_info_gsm_set_operator_id: (skip)
+ */
+void
+mm_cell_info_gsm_set_operator_id (MMCellInfoGsm *self,
+ const gchar *operator_id)
+{
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/**
+ * mm_cell_info_gsm_get_lac:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the two-byte Location Area Code of the base station.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_gsm_get_lac (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->lac);
+}
+
+/**
+ * mm_cell_info_gsm_set_lac: (skip)
+ */
+void
+mm_cell_info_gsm_set_lac (MMCellInfoGsm *self,
+ const gchar *lac)
+{
+ g_free (self->priv->lac);
+ self->priv->lac = g_strdup (lac);
+}
+
+/**
+ * mm_cell_info_gsm_get_ci:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the two- or four-byte Cell Identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_gsm_get_ci (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ci);
+}
+
+/**
+ * mm_cell_info_gsm_set_ci: (skip)
+ */
+void
+mm_cell_info_gsm_set_ci (MMCellInfoGsm *self,
+ const gchar *ci)
+{
+ g_free (self->priv->ci);
+ self->priv->ci = g_strdup (ci);
+}
+
+/**
+ * mm_cell_info_gsm_get_timing_advance:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the measured delay (in bit periods) of an access burst transmission
+ * on the RACH or PRACH to the expected signal from a mobile station at zero
+ * distance under static channel conditions.
+ *
+ * Returns: the timing advance, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_gsm_get_timing_advance (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), G_MAXUINT);
+
+ return self->priv->timing_advance;
+}
+
+/**
+ * mm_cell_info_gsm_set_timing_advance: (skip)
+ */
+void
+mm_cell_info_gsm_set_timing_advance (MMCellInfoGsm *self,
+ guint timing_advance)
+{
+ self->priv->timing_advance = timing_advance;
+}
+
+/**
+ * mm_cell_info_gsm_get_arfcn:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the absolute RF channel number.
+ *
+ * Returns: the ARFCN, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_gsm_get_arfcn (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), G_MAXUINT);
+
+ return self->priv->arfcn;
+}
+
+/**
+ * mm_cell_info_gsm_set_arfcn: (skip)
+ */
+void
+mm_cell_info_gsm_set_arfcn (MMCellInfoGsm *self,
+ guint arfcn)
+{
+ self->priv->arfcn = arfcn;
+}
+
+/**
+ * mm_cell_info_gsm_get_base_station_id:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the GSM base station id, in upper-case hexadecimal format without leading
+ * zeros. E.g. "3F".
+ *
+ * Returns: (transfer none): the GSM base station id, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_gsm_get_base_station_id (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->base_station_id);
+}
+
+/**
+ * mm_cell_info_gsm_set_base_station_id: (skip)
+ */
+void
+mm_cell_info_gsm_set_base_station_id (MMCellInfoGsm *self,
+ const gchar *base_station_id)
+{
+ g_free (self->priv->base_station_id);
+ self->priv->base_station_id = g_strdup (base_station_id);
+}
+
+/**
+ * mm_cell_info_gsm_get_rx_level:
+ * @self: a #MMCellInfoGsm.
+ *
+ * Get the serving cell RX measurement.
+ *
+ * Returns: the rx level, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_gsm_get_rx_level (MMCellInfoGsm *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_GSM (self), G_MAXUINT);
+
+ return self->priv->rx_level;
+}
+
+/**
+ * mm_cell_info_gsm_set_rx_level: (skip)
+ */
+void
+mm_cell_info_gsm_set_rx_level (MMCellInfoGsm *self,
+ guint rx_level)
+{
+ self->priv->rx_level = rx_level;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoGsm *self = MM_CELL_INFO_GSM (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("operator id", "%s", operator_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("lac", "%s", lac, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ci", "%s", ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("timing advance", "%u", timing_advance, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("arfcn", "%u", arfcn, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("base station id", "%s", base_station_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rx level", "%u", rx_level, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_gsm_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoGsm *self = MM_CELL_INFO_GSM (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (OPERATOR_ID, operator_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (LAC, lac, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CI, ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TIMING_ADVANCE, timing_advance, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (ARFCN, arfcn, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (BASE_STATION_ID, base_station_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RX_LEVEL, rx_level, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_gsm_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_gsm_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoGsm *self;
+
+ self = MM_CELL_INFO_GSM (g_object_new (MM_TYPE_CELL_INFO_GSM, NULL));
+
+ if (dict) {
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (gsm, OPERATOR_ID, operator_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (gsm, LAC, lac);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (gsm, CI, ci);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (gsm, TIMING_ADVANCE, timing_advance, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (gsm, ARFCN, arfcn, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (gsm, BASE_STATION_ID, base_station_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (gsm, RX_LEVEL, rx_level, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_gsm_init (MMCellInfoGsm *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_GSM, MMCellInfoGsmPrivate);
+ self->priv->timing_advance = G_MAXUINT;
+ self->priv->arfcn = G_MAXUINT;
+ self->priv->rx_level = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoGsm *self = MM_CELL_INFO_GSM (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->lac);
+ g_free (self->priv->ci);
+ g_free (self->priv->base_station_id);
+
+ G_OBJECT_CLASS (mm_cell_info_gsm_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_gsm_class_init (MMCellInfoGsmClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoGsmPrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-gsm.h b/libmm-glib/mm-cell-info-gsm.h
new file mode 100644
index 0000000..a583e32
--- /dev/null
+++ b/libmm-glib/mm-cell-info-gsm.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_GSM_H
+#define MM_CELL_INFO_GSM_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_GSM (mm_cell_info_gsm_get_type ())
+#define MM_CELL_INFO_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_GSM, MMCellInfoGsm))
+#define MM_CELL_INFO_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_GSM, MMCellInfoGsmClass))
+#define MM_IS_CELL_INFO_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_GSM))
+#define MM_IS_CELL_INFO_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_GSM))
+#define MM_CELL_INFO_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_GSM, MMCellInfoGsmClass))
+
+typedef struct _MMCellInfoGsm MMCellInfoGsm;
+typedef struct _MMCellInfoGsmClass MMCellInfoGsmClass;
+typedef struct _MMCellInfoGsmPrivate MMCellInfoGsmPrivate;
+
+/**
+ * MMCellInfoGsm:
+ *
+ * The #MMCellInfoGsm structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoGsm {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoGsmPrivate *priv;
+};
+
+struct _MMCellInfoGsmClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_gsm_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoGsm, g_object_unref)
+
+const gchar *mm_cell_info_gsm_get_operator_id (MMCellInfoGsm *self);
+const gchar *mm_cell_info_gsm_get_lac (MMCellInfoGsm *self);
+const gchar *mm_cell_info_gsm_get_ci (MMCellInfoGsm *self);
+guint mm_cell_info_gsm_get_timing_advance (MMCellInfoGsm *self);
+guint mm_cell_info_gsm_get_arfcn (MMCellInfoGsm *self);
+const gchar *mm_cell_info_gsm_get_base_station_id (MMCellInfoGsm *self);
+guint mm_cell_info_gsm_get_rx_level (MMCellInfoGsm *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_gsm_set_operator_id (MMCellInfoGsm *self,
+ const gchar *operator_id);
+void mm_cell_info_gsm_set_lac (MMCellInfoGsm *self,
+ const gchar *lac);
+void mm_cell_info_gsm_set_ci (MMCellInfoGsm *self,
+ const gchar *ci);
+void mm_cell_info_gsm_set_timing_advance (MMCellInfoGsm *self,
+ guint timing_advance);
+void mm_cell_info_gsm_set_arfcn (MMCellInfoGsm *self,
+ guint arfcn);
+void mm_cell_info_gsm_set_base_station_id (MMCellInfoGsm *self,
+ const gchar *base_station_id);
+void mm_cell_info_gsm_set_rx_level (MMCellInfoGsm *self,
+ guint rx_level);
+
+MMCellInfo *mm_cell_info_gsm_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_GSM_H */
diff --git a/libmm-glib/mm-cell-info-lte.c b/libmm-glib/mm-cell-info-lte.c
new file mode 100644
index 0000000..1768c04
--- /dev/null
+++ b/libmm-glib/mm-cell-info-lte.c
@@ -0,0 +1,410 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-lte.h"
+
+/**
+ * SECTION: mm-cell-info-lte
+ * @title: MMCellInfoLte
+ * @short_description: Helper object to report LTE cell info
+ *
+ * The #MMCellInfoLte is an object used to report LTE cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoLte, mm_cell_info_lte, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_TAC "tac"
+#define PROPERTY_CI "ci"
+#define PROPERTY_PHYSICAL_CI "physical-ci"
+#define PROPERTY_EARFCN "earfcn"
+#define PROPERTY_RSRP "rsrp"
+#define PROPERTY_RSRQ "rsrq"
+#define PROPERTY_TIMING_ADVANCE "timing-advance"
+
+
+struct _MMCellInfoLtePrivate {
+ gchar *operator_id;
+ gchar *tac;
+ gchar *ci;
+ gchar *physical_ci;
+ guint earfcn;
+ gdouble rsrp;
+ gdouble rsrq;
+ guint timing_advance;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_lte_get_operator_id:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the PLMN MCC/MNC.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_lte_get_operator_id (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->operator_id);
+}
+
+/**
+ * mm_cell_info_lte_set_operator_id: (skip)
+ */
+void
+mm_cell_info_lte_set_operator_id (MMCellInfoLte *self,
+ const gchar *operator_id)
+{
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/**
+ * mm_cell_info_lte_get_tac:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the two- or three- byte Tracking Area Code of the base station.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_lte_get_tac (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->tac);
+}
+
+/**
+ * mm_cell_info_lte_set_tac: (skip)
+ */
+void
+mm_cell_info_lte_set_tac (MMCellInfoLte *self,
+ const gchar *tac)
+{
+ g_free (self->priv->tac);
+ self->priv->tac = g_strdup (tac);
+}
+
+/**
+ * mm_cell_info_lte_get_ci:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the two- or four-byte Cell Identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_lte_get_ci (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ci);
+}
+
+/**
+ * mm_cell_info_lte_set_ci: (skip)
+ */
+void
+mm_cell_info_lte_set_ci (MMCellInfoLte *self,
+ const gchar *ci)
+{
+ g_free (self->priv->ci);
+ self->priv->ci = g_strdup (ci);
+}
+
+/**
+ * mm_cell_info_lte_get_physical_ci:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the physical cell identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_lte_get_physical_ci (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->physical_ci);
+}
+
+/**
+ * mm_cell_info_lte_set_physical_ci: (skip)
+ */
+void
+mm_cell_info_lte_set_physical_ci (MMCellInfoLte *self,
+ const gchar *physical_ci)
+{
+ g_free (self->priv->physical_ci);
+ self->priv->physical_ci = g_strdup (physical_ci);
+}
+
+/**
+ * mm_cell_info_lte_get_earfcn:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the E-UTRA absolute RF channel number.
+ *
+ * Returns: the EARFCN, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_lte_get_earfcn (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), G_MAXUINT);
+
+ return self->priv->earfcn;
+}
+
+/**
+ * mm_cell_info_lte_set_earfcn: (skip)
+ */
+void
+mm_cell_info_lte_set_earfcn (MMCellInfoLte *self,
+ guint earfcn)
+{
+ self->priv->earfcn = earfcn;
+}
+
+/**
+ * mm_cell_info_lte_get_rsrp:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the average reference signal received power in dBm.
+ *
+ * Returns: the RSRP, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_lte_get_rsrp (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), -G_MAXDOUBLE);
+
+ return self->priv->rsrp;
+}
+
+/**
+ * mm_cell_info_lte_set_rsrp: (skip)
+ */
+void
+mm_cell_info_lte_set_rsrp (MMCellInfoLte *self,
+ gdouble rsrp)
+{
+ self->priv->rsrp = rsrp;
+}
+
+/**
+ * mm_cell_info_lte_get_rsrq:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the average reference signal received quality in dB.
+ *
+ * Returns: the RSRQ, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_lte_get_rsrq (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), -G_MAXDOUBLE);
+
+ return self->priv->rsrq;
+}
+
+/**
+ * mm_cell_info_lte_set_rsrq: (skip)
+ */
+void
+mm_cell_info_lte_set_rsrq (MMCellInfoLte *self,
+ gdouble rsrq)
+{
+ self->priv->rsrq = rsrq;
+}
+
+/**
+ * mm_cell_info_lte_get_timing_advance:
+ * @self: a #MMCellInfoLte.
+ *
+ * Get the timing advance.
+ *
+ * Returns: the timing advance, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_lte_get_timing_advance (MMCellInfoLte *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_LTE (self), G_MAXUINT);
+
+ return self->priv->timing_advance;
+}
+
+/**
+ * mm_cell_info_lte_set_timing_advance: (skip)
+ */
+void
+mm_cell_info_lte_set_timing_advance (MMCellInfoLte *self,
+ guint timing_advance)
+{
+ self->priv->timing_advance = timing_advance;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoLte *self = MM_CELL_INFO_LTE (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("operator id", "%s", operator_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("tac", "%s", tac, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ci", "%s", ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("physical ci", "%s", physical_ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("earfcn", "%u", earfcn, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rsrp", "%lf", rsrp, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rsrq", "%lf", rsrq, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("timing advance", "%u", timing_advance, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_lte_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoLte *self = MM_CELL_INFO_LTE (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (OPERATOR_ID, operator_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TAC, tac, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CI, ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PHYSICAL_CI, physical_ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (EARFCN, earfcn, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSRP, rsrp, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSRQ, rsrq, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TIMING_ADVANCE, timing_advance, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_lte_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_lte_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoLte *self;
+
+ self = MM_CELL_INFO_LTE (g_object_new (MM_TYPE_CELL_INFO_LTE, NULL));
+
+ if (dict) {
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (lte, OPERATOR_ID, operator_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (lte, TAC, tac);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (lte, CI, ci);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (lte, PHYSICAL_CI, physical_ci);
+
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (lte, EARFCN, earfcn, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (lte, RSRP, rsrp, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (lte, RSRQ, rsrq, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (lte, TIMING_ADVANCE, timing_advance, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_lte_init (MMCellInfoLte *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_LTE, MMCellInfoLtePrivate);
+ self->priv->earfcn = G_MAXUINT;
+ self->priv->rsrp = -G_MAXDOUBLE;
+ self->priv->rsrq = -G_MAXDOUBLE;
+ self->priv->timing_advance = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoLte *self = MM_CELL_INFO_LTE (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->tac);
+ g_free (self->priv->ci);
+ g_free (self->priv->physical_ci);
+
+ G_OBJECT_CLASS (mm_cell_info_lte_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_lte_class_init (MMCellInfoLteClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoLtePrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-lte.h b/libmm-glib/mm-cell-info-lte.h
new file mode 100644
index 0000000..b58625f
--- /dev/null
+++ b/libmm-glib/mm-cell-info-lte.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_LTE_H
+#define MM_CELL_INFO_LTE_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_LTE (mm_cell_info_lte_get_type ())
+#define MM_CELL_INFO_LTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_LTE, MMCellInfoLte))
+#define MM_CELL_INFO_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_LTE, MMCellInfoLteClass))
+#define MM_IS_CELL_INFO_LTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_LTE))
+#define MM_IS_CELL_INFO_LTE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_LTE))
+#define MM_CELL_INFO_LTE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_LTE, MMCellInfoLteClass))
+
+typedef struct _MMCellInfoLte MMCellInfoLte;
+typedef struct _MMCellInfoLteClass MMCellInfoLteClass;
+typedef struct _MMCellInfoLtePrivate MMCellInfoLtePrivate;
+
+/**
+ * MMCellInfoLte:
+ *
+ * The #MMCellInfoLte structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoLte {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoLtePrivate *priv;
+};
+
+struct _MMCellInfoLteClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_lte_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoLte, g_object_unref)
+
+const gchar *mm_cell_info_lte_get_operator_id (MMCellInfoLte *self);
+const gchar *mm_cell_info_lte_get_tac (MMCellInfoLte *self);
+const gchar *mm_cell_info_lte_get_ci (MMCellInfoLte *self);
+const gchar *mm_cell_info_lte_get_physical_ci (MMCellInfoLte *self);
+guint mm_cell_info_lte_get_earfcn (MMCellInfoLte *self);
+gdouble mm_cell_info_lte_get_rsrp (MMCellInfoLte *self);
+gdouble mm_cell_info_lte_get_rsrq (MMCellInfoLte *self);
+guint mm_cell_info_lte_get_timing_advance (MMCellInfoLte *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_lte_set_operator_id (MMCellInfoLte *self,
+ const gchar *operator_id);
+void mm_cell_info_lte_set_tac (MMCellInfoLte *self,
+ const gchar *tac);
+void mm_cell_info_lte_set_ci (MMCellInfoLte *self,
+ const gchar *ci);
+void mm_cell_info_lte_set_physical_ci (MMCellInfoLte *self,
+ const gchar *ci);
+void mm_cell_info_lte_set_earfcn (MMCellInfoLte *self,
+ guint earfcn);
+void mm_cell_info_lte_set_rsrp (MMCellInfoLte *self,
+ gdouble rsrp);
+void mm_cell_info_lte_set_rsrq (MMCellInfoLte *self,
+ gdouble rsrq);
+void mm_cell_info_lte_set_timing_advance (MMCellInfoLte *self,
+ guint earfcn);
+
+MMCellInfo *mm_cell_info_lte_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_LTE_H */
diff --git a/libmm-glib/mm-cell-info-nr5g.c b/libmm-glib/mm-cell-info-nr5g.c
new file mode 100644
index 0000000..67b5338
--- /dev/null
+++ b/libmm-glib/mm-cell-info-nr5g.c
@@ -0,0 +1,444 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-nr5g.h"
+
+/**
+ * SECTION: mm-cell-info-nr5g
+ * @title: MMCellInfoNr5g
+ * @short_description: Helper object to report 5GNR cell info
+ *
+ * The #MMCellInfoNr5g is an object used to report 5GNR cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoNr5g, mm_cell_info_nr5g, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_TAC "tac"
+#define PROPERTY_CI "ci"
+#define PROPERTY_PHYSICAL_CI "physical-ci"
+#define PROPERTY_NRARFCN "nrarfcn"
+#define PROPERTY_RSRP "rsrp"
+#define PROPERTY_RSRQ "rsrq"
+#define PROPERTY_SINR "sinr"
+#define PROPERTY_TIMING_ADVANCE "timing-advance"
+
+
+struct _MMCellInfoNr5gPrivate {
+ gchar *operator_id;
+ gchar *tac;
+ gchar *ci;
+ gchar *physical_ci;
+ guint nrarfcn;
+ gdouble rsrp;
+ gdouble rsrq;
+ gdouble sinr;
+ guint timing_advance;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_nr5g_get_operator_id:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the PLMN MCC/MNC.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_nr5g_get_operator_id (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->operator_id);
+}
+
+/**
+ * mm_cell_info_nr5g_set_operator_id: (skip)
+ */
+void
+mm_cell_info_nr5g_set_operator_id (MMCellInfoNr5g *self,
+ const gchar *operator_id)
+{
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/**
+ * mm_cell_info_nr5g_get_tac:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the two- or three- byte Tracking Area Code of the base station.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_nr5g_get_tac (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->tac);
+}
+
+/**
+ * mm_cell_info_nr5g_set_tac: (skip)
+ */
+void
+mm_cell_info_nr5g_set_tac (MMCellInfoNr5g *self,
+ const gchar *tac)
+{
+ g_free (self->priv->tac);
+ self->priv->tac = g_strdup (tac);
+}
+
+/**
+ * mm_cell_info_nr5g_get_ci:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the two- or four-byte Cell Identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_nr5g_get_ci (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ci);
+}
+
+/**
+ * mm_cell_info_nr5g_set_ci: (skip)
+ */
+void
+mm_cell_info_nr5g_set_ci (MMCellInfoNr5g *self,
+ const gchar *ci)
+{
+ g_free (self->priv->ci);
+ self->priv->ci = g_strdup (ci);
+}
+
+/**
+ * mm_cell_info_nr5g_get_physical_ci:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the physical cell identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_nr5g_get_physical_ci (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->physical_ci);
+}
+
+/**
+ * mm_cell_info_nr5g_set_physical_ci: (skip)
+ */
+void
+mm_cell_info_nr5g_set_physical_ci (MMCellInfoNr5g *self,
+ const gchar *physical_ci)
+{
+ g_free (self->priv->physical_ci);
+ self->priv->physical_ci = g_strdup (physical_ci);
+}
+
+/**
+ * mm_cell_info_nr5g_get_nrarfcn:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the NR absolute RF channel number.
+ *
+ * Returns: the NRARFCN, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_nr5g_get_nrarfcn (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), G_MAXUINT);
+
+ return self->priv->nrarfcn;
+}
+
+/**
+ * mm_cell_info_nr5g_set_nrarfcn: (skip)
+ */
+void
+mm_cell_info_nr5g_set_nrarfcn (MMCellInfoNr5g *self,
+ guint nrarfcn)
+{
+ self->priv->nrarfcn = nrarfcn;
+}
+
+/**
+ * mm_cell_info_nr5g_get_rsrp:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the average reference signal received power in dBm.
+ *
+ * Returns: the RSRP, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_nr5g_get_rsrp (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), -G_MAXDOUBLE);
+
+ return self->priv->rsrp;
+}
+
+/**
+ * mm_cell_info_nr5g_set_rsrp: (skip)
+ */
+void
+mm_cell_info_nr5g_set_rsrp (MMCellInfoNr5g *self,
+ gdouble rsrp)
+{
+ self->priv->rsrp = rsrp;
+}
+
+/**
+ * mm_cell_info_nr5g_get_rsrq:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the average reference signal received quality in dB.
+ *
+ * Returns: the RSRQ, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_nr5g_get_rsrq (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), -G_MAXDOUBLE);
+
+ return self->priv->rsrq;
+}
+
+/**
+ * mm_cell_info_nr5g_set_rsrq: (skip)
+ */
+void
+mm_cell_info_nr5g_set_rsrq (MMCellInfoNr5g *self,
+ gdouble rsrq)
+{
+ self->priv->rsrq = rsrq;
+}
+
+/**
+ * mm_cell_info_nr5g_get_sinr:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the signal to interference and noise ratio.
+ *
+ * Returns: the SINR, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_nr5g_get_sinr (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), -G_MAXDOUBLE);
+
+ return self->priv->sinr;
+}
+
+/**
+ * mm_cell_info_nr5g_set_sinr: (skip)
+ */
+void
+mm_cell_info_nr5g_set_sinr (MMCellInfoNr5g *self,
+ gdouble sinr)
+{
+ self->priv->sinr = sinr;
+}
+
+/**
+ * mm_cell_info_nr5g_get_timing_advance:
+ * @self: a #MMCellInfoNr5g.
+ *
+ * Get the timing advance.
+ *
+ * Returns: the timing advance, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_nr5g_get_timing_advance (MMCellInfoNr5g *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_NR5G (self), G_MAXUINT);
+
+ return self->priv->timing_advance;
+}
+
+/**
+ * mm_cell_info_nr5g_set_timing_advance: (skip)
+ */
+void
+mm_cell_info_nr5g_set_timing_advance (MMCellInfoNr5g *self,
+ guint timing_advance)
+{
+ self->priv->timing_advance = timing_advance;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoNr5g *self = MM_CELL_INFO_NR5G (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("operator id", "%s", operator_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("tac", "%s", tac, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ci", "%s", ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("physical ci", "%s", physical_ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("nrarfcn", "%u", nrarfcn, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rsrp", "%lf", rsrp, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rsrq", "%lf", rsrq, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("sinr", "%lf", sinr, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("timing advance", "%u", timing_advance, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_nr5g_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoNr5g *self = MM_CELL_INFO_NR5G (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (OPERATOR_ID, operator_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TAC, tac, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CI, ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PHYSICAL_CI, physical_ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (NRARFCN, nrarfcn, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSRP, rsrp, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSRQ, rsrq, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (SINR, sinr, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TIMING_ADVANCE, timing_advance, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_nr5g_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_nr5g_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoNr5g *self;
+
+ self = MM_CELL_INFO_NR5G (g_object_new (MM_TYPE_CELL_INFO_NR5G, NULL));
+
+ if (dict) {
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (nr5g, OPERATOR_ID, operator_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (nr5g, TAC, tac);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (nr5g, CI, ci);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (nr5g, PHYSICAL_CI, physical_ci);
+
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (nr5g, NRARFCN, nrarfcn, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (nr5g, RSRP, rsrp, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (nr5g, RSRQ, rsrq, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (nr5g, SINR, sinr, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (nr5g, TIMING_ADVANCE, timing_advance, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_nr5g_init (MMCellInfoNr5g *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_NR5G, MMCellInfoNr5gPrivate);
+ self->priv->nrarfcn = G_MAXUINT;
+ self->priv->rsrp = -G_MAXDOUBLE;
+ self->priv->rsrq = -G_MAXDOUBLE;
+ self->priv->sinr = -G_MAXDOUBLE;
+ self->priv->timing_advance = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoNr5g *self = MM_CELL_INFO_NR5G (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->tac);
+ g_free (self->priv->ci);
+ g_free (self->priv->physical_ci);
+
+ G_OBJECT_CLASS (mm_cell_info_nr5g_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_nr5g_class_init (MMCellInfoNr5gClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoNr5gPrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-nr5g.h b/libmm-glib/mm-cell-info-nr5g.h
new file mode 100644
index 0000000..8b807bc
--- /dev/null
+++ b/libmm-glib/mm-cell-info-nr5g.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_NR5G_H
+#define MM_CELL_INFO_NR5G_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_NR5G (mm_cell_info_nr5g_get_type ())
+#define MM_CELL_INFO_NR5G(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_NR5G, MMCellInfoNr5g))
+#define MM_CELL_INFO_NR5G_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_NR5G, MMCellInfoNr5gClass))
+#define MM_IS_CELL_INFO_NR5G(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_NR5G))
+#define MM_IS_CELL_INFO_NR5G_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_NR5G))
+#define MM_CELL_INFO_NR5G_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_NR5G, MMCellInfoNr5gClass))
+
+typedef struct _MMCellInfoNr5g MMCellInfoNr5g;
+typedef struct _MMCellInfoNr5gClass MMCellInfoNr5gClass;
+typedef struct _MMCellInfoNr5gPrivate MMCellInfoNr5gPrivate;
+
+/**
+ * MMCellInfoNr5g:
+ *
+ * The #MMCellInfoNr5g structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoNr5g {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoNr5gPrivate *priv;
+};
+
+struct _MMCellInfoNr5gClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_nr5g_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoNr5g, g_object_unref)
+
+const gchar *mm_cell_info_nr5g_get_operator_id (MMCellInfoNr5g *self);
+const gchar *mm_cell_info_nr5g_get_tac (MMCellInfoNr5g *self);
+const gchar *mm_cell_info_nr5g_get_ci (MMCellInfoNr5g *self);
+const gchar *mm_cell_info_nr5g_get_physical_ci (MMCellInfoNr5g *self);
+guint mm_cell_info_nr5g_get_nrarfcn (MMCellInfoNr5g *self);
+gdouble mm_cell_info_nr5g_get_rsrp (MMCellInfoNr5g *self);
+gdouble mm_cell_info_nr5g_get_rsrq (MMCellInfoNr5g *self);
+gdouble mm_cell_info_nr5g_get_sinr (MMCellInfoNr5g *self);
+guint mm_cell_info_nr5g_get_timing_advance (MMCellInfoNr5g *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_nr5g_set_operator_id (MMCellInfoNr5g *self,
+ const gchar *operator_id);
+void mm_cell_info_nr5g_set_tac (MMCellInfoNr5g *self,
+ const gchar *tac);
+void mm_cell_info_nr5g_set_ci (MMCellInfoNr5g *self,
+ const gchar *ci);
+void mm_cell_info_nr5g_set_physical_ci (MMCellInfoNr5g *self,
+ const gchar *ci);
+void mm_cell_info_nr5g_set_nrarfcn (MMCellInfoNr5g *self,
+ guint earfcn);
+void mm_cell_info_nr5g_set_rsrp (MMCellInfoNr5g *self,
+ gdouble rsrp);
+void mm_cell_info_nr5g_set_rsrq (MMCellInfoNr5g *self,
+ gdouble rsrq);
+void mm_cell_info_nr5g_set_sinr (MMCellInfoNr5g *self,
+ gdouble sinr);
+void mm_cell_info_nr5g_set_timing_advance (MMCellInfoNr5g *self,
+ guint earfcn);
+
+MMCellInfo *mm_cell_info_nr5g_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_NR5G_H */
diff --git a/libmm-glib/mm-cell-info-tdscdma.c b/libmm-glib/mm-cell-info-tdscdma.c
new file mode 100644
index 0000000..dcf16e6
--- /dev/null
+++ b/libmm-glib/mm-cell-info-tdscdma.c
@@ -0,0 +1,407 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-tdscdma.h"
+
+/**
+ * SECTION: mm-cell-info-tdscdma
+ * @title: MMCellInfoTdscdma
+ * @short_description: Helper object to report TDSCDMA cell info
+ *
+ * The #MMCellInfoTdscdma is an object used to report TDSCDMA cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoTdscdma, mm_cell_info_tdscdma, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_LAC "lac"
+#define PROPERTY_CI "ci"
+#define PROPERTY_UARFCN "uarfcn"
+#define PROPERTY_CELL_PARAMETER_ID "cell-parameter-id"
+#define PROPERTY_TIMING_ADVANCE "timing-advance"
+#define PROPERTY_RSCP "rscp"
+#define PROPERTY_PATH_LOSS "path-loss"
+
+struct _MMCellInfoTdscdmaPrivate {
+ gchar *operator_id;
+ gchar *lac;
+ gchar *ci;
+ guint uarfcn;
+ guint cell_parameter_id;
+ guint timing_advance;
+ gdouble rscp;
+ guint path_loss;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_tdscdma_get_operator_id:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the PLMN MCC/MNC.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_tdscdma_get_operator_id (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->operator_id);
+}
+
+/**
+ * mm_cell_info_tdscdma_set_operator_id: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_operator_id (MMCellInfoTdscdma *self,
+ const gchar *operator_id)
+{
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/**
+ * mm_cell_info_tdscdma_get_lac:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the two-byte Location Area Code of the base station.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_tdscdma_get_lac (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->lac);
+}
+
+/**
+ * mm_cell_info_tdscdma_set_lac: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_lac (MMCellInfoTdscdma *self,
+ const gchar *lac)
+{
+ g_free (self->priv->lac);
+ self->priv->lac = g_strdup (lac);
+}
+
+/**
+ * mm_cell_info_tdscdma_get_ci:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the two- or four-byte Cell Identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_tdscdma_get_ci (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ci);
+}
+
+/**
+ * mm_cell_info_tdscdma_set_ci: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_ci (MMCellInfoTdscdma *self,
+ const gchar *ci)
+{
+ g_free (self->priv->ci);
+ self->priv->ci = g_strdup (ci);
+}
+
+/**
+ * mm_cell_info_tdscdma_get_uarfcn:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the UTRA absolute RF channel number.
+ *
+ * Returns: the UARFCN, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_tdscdma_get_uarfcn (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), G_MAXUINT);
+
+ return self->priv->uarfcn;
+}
+
+/**
+ * mm_cell_info_tdscdma_set_uarfcn: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_uarfcn (MMCellInfoTdscdma *self,
+ guint uarfcn)
+{
+ self->priv->uarfcn = uarfcn;
+}
+
+/**
+ * mm_cell_info_tdscdma_get_cell_parameter_id:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the cell parameter id.
+ *
+ * Returns: the cell parameter id, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_tdscdma_get_cell_parameter_id (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), G_MAXUINT);
+
+ return self->priv->cell_parameter_id;
+}
+
+/**
+ * mm_cell_info_tdscdma_set_cell_parameter_id: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_cell_parameter_id (MMCellInfoTdscdma *self,
+ guint cell_parameter_id)
+{
+ self->priv->cell_parameter_id = cell_parameter_id;
+}
+
+/**
+ * mm_cell_info_tdscdma_get_timing_advance:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the measured delay (in bit periods) of an access burst transmission
+ * on the RACH or PRACH to the expected signal from a mobile station at zero
+ * distance under static channel conditions.
+ *
+ * Returns: the timing advance, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_tdscdma_get_timing_advance (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), G_MAXUINT);
+
+ return self->priv->timing_advance;
+}
+
+/**
+ * mm_cell_info_tdscdma_set_timing_advance: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_timing_advance (MMCellInfoTdscdma *self,
+ guint timing_advance)
+{
+ self->priv->timing_advance = timing_advance;
+}
+
+/**
+ * mm_cell_info_tdscdma_get_rscp:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the received signal code power.
+ *
+ * Returns: the RSCP, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_tdscdma_get_rscp (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), -G_MAXDOUBLE);
+
+ return self->priv->rscp;
+}
+
+/**
+ * mm_cell_info_tdscdma_set_rscp: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_rscp (MMCellInfoTdscdma *self,
+ gdouble rscp)
+{
+ self->priv->rscp = rscp;
+}
+
+/**
+ * mm_cell_info_tdscdma_get_path_loss:
+ * @self: a #MMCellInfoTdscdma.
+ *
+ * Get the path loss of the cell.
+ *
+ * Returns: the path loss, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_tdscdma_get_path_loss (MMCellInfoTdscdma *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_TDSCDMA (self), G_MAXUINT);
+
+ return self->priv->path_loss;
+}
+
+/**
+ * mm_cell_info_tdscdma_set_path_loss: (skip)
+ */
+void
+mm_cell_info_tdscdma_set_path_loss (MMCellInfoTdscdma *self,
+ guint path_loss)
+{
+ self->priv->path_loss = path_loss;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoTdscdma *self = MM_CELL_INFO_TDSCDMA (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("operator id", "%s", operator_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("lac", "%s", lac, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ci", "%s", ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("uarfcn", "%u", uarfcn, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("cell parameter id", "%u", cell_parameter_id, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("timing advance", "%u", timing_advance, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rscp", "%lf", rscp, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("path loss", "%u", path_loss, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_tdscdma_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoTdscdma *self = MM_CELL_INFO_TDSCDMA (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (OPERATOR_ID, operator_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (LAC, lac, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CI, ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (UARFCN, uarfcn, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CELL_PARAMETER_ID, cell_parameter_id, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (TIMING_ADVANCE, timing_advance, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSCP, rscp, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PATH_LOSS, path_loss, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_tdscdma_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_tdscdma_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoTdscdma *self;
+
+ self = MM_CELL_INFO_TDSCDMA (g_object_new (MM_TYPE_CELL_INFO_TDSCDMA, NULL));
+
+ if (dict) {
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (tdscdma, OPERATOR_ID, operator_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (tdscdma, LAC, lac);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (tdscdma, CI, ci);
+
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (tdscdma, UARFCN, uarfcn, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (tdscdma, CELL_PARAMETER_ID, cell_parameter_id, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (tdscdma, TIMING_ADVANCE, timing_advance, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (tdscdma, RSCP, rscp, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (tdscdma, PATH_LOSS, path_loss, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_tdscdma_init (MMCellInfoTdscdma *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_TDSCDMA, MMCellInfoTdscdmaPrivate);
+ self->priv->uarfcn = G_MAXUINT;
+ self->priv->cell_parameter_id = G_MAXUINT;
+ self->priv->timing_advance = G_MAXUINT;
+ self->priv->rscp = -G_MAXDOUBLE;
+ self->priv->path_loss = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoTdscdma *self = MM_CELL_INFO_TDSCDMA (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->lac);
+ g_free (self->priv->ci);
+
+ G_OBJECT_CLASS (mm_cell_info_tdscdma_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_tdscdma_class_init (MMCellInfoTdscdmaClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoTdscdmaPrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-tdscdma.h b/libmm-glib/mm-cell-info-tdscdma.h
new file mode 100644
index 0000000..098a6be
--- /dev/null
+++ b/libmm-glib/mm-cell-info-tdscdma.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_TDSCDMA_H
+#define MM_CELL_INFO_TDSCDMA_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_TDSCDMA (mm_cell_info_tdscdma_get_type ())
+#define MM_CELL_INFO_TDSCDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_TDSCDMA, MMCellInfoTdscdma))
+#define MM_CELL_INFO_TDSCDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_TDSCDMA, MMCellInfoTdscdmaClass))
+#define MM_IS_CELL_INFO_TDSCDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_TDSCDMA))
+#define MM_IS_CELL_INFO_TDSCDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_TDSCDMA))
+#define MM_CELL_INFO_TDSCDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_TDSCDMA, MMCellInfoTdscdmaClass))
+
+typedef struct _MMCellInfoTdscdma MMCellInfoTdscdma;
+typedef struct _MMCellInfoTdscdmaClass MMCellInfoTdscdmaClass;
+typedef struct _MMCellInfoTdscdmaPrivate MMCellInfoTdscdmaPrivate;
+
+/**
+ * MMCellInfoTdscdma:
+ *
+ * The #MMCellInfoTdscdma structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoTdscdma {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoTdscdmaPrivate *priv;
+};
+
+struct _MMCellInfoTdscdmaClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_tdscdma_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoTdscdma, g_object_unref)
+
+const gchar *mm_cell_info_tdscdma_get_operator_id (MMCellInfoTdscdma *self);
+const gchar *mm_cell_info_tdscdma_get_lac (MMCellInfoTdscdma *self);
+const gchar *mm_cell_info_tdscdma_get_ci (MMCellInfoTdscdma *self);
+guint mm_cell_info_tdscdma_get_uarfcn (MMCellInfoTdscdma *self);
+guint mm_cell_info_tdscdma_get_cell_parameter_id (MMCellInfoTdscdma *self);
+guint mm_cell_info_tdscdma_get_timing_advance (MMCellInfoTdscdma *self);
+gdouble mm_cell_info_tdscdma_get_rscp (MMCellInfoTdscdma *self);
+guint mm_cell_info_tdscdma_get_path_loss (MMCellInfoTdscdma *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_tdscdma_set_operator_id (MMCellInfoTdscdma *self,
+ const gchar *operator_id);
+void mm_cell_info_tdscdma_set_lac (MMCellInfoTdscdma *self,
+ const gchar *lac);
+void mm_cell_info_tdscdma_set_ci (MMCellInfoTdscdma *self,
+ const gchar *ci);
+void mm_cell_info_tdscdma_set_uarfcn (MMCellInfoTdscdma *self,
+ guint uarfcn);
+void mm_cell_info_tdscdma_set_cell_parameter_id (MMCellInfoTdscdma *self,
+ guint cell_parameter_id);
+void mm_cell_info_tdscdma_set_timing_advance (MMCellInfoTdscdma *self,
+ guint timing_advance);
+void mm_cell_info_tdscdma_set_rscp (MMCellInfoTdscdma *self,
+ gdouble rscp);
+void mm_cell_info_tdscdma_set_path_loss (MMCellInfoTdscdma *self,
+ guint path_loss);
+
+MMCellInfo *mm_cell_info_tdscdma_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_TDSCDMA_H */
diff --git a/libmm-glib/mm-cell-info-umts.c b/libmm-glib/mm-cell-info-umts.c
new file mode 100644
index 0000000..ccb6884
--- /dev/null
+++ b/libmm-glib/mm-cell-info-umts.c
@@ -0,0 +1,509 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-helpers.h"
+#include "mm-cell-info-umts.h"
+
+/**
+ * SECTION: mm-cell-info-umts
+ * @title: MMCellInfoUmts
+ * @short_description: Helper object to report UMTS cell info
+ *
+ * The #MMCellInfoUmts is an object used to report UMTS cell
+ * information.
+ *
+ * The object inherits from the generic #MMCellInfo.
+ */
+
+G_DEFINE_TYPE (MMCellInfoUmts, mm_cell_info_umts, MM_TYPE_CELL_INFO)
+
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_LAC "lac"
+#define PROPERTY_CI "ci"
+#define PROPERTY_FREQUENCY_FDD_UL "frequency-fdd-ul"
+#define PROPERTY_FREQUENCY_FDD_DL "frequency-fdd-dl"
+#define PROPERTY_FREQUENCY_TDD "frequency-tdd"
+#define PROPERTY_UARFCN "uarfcn"
+#define PROPERTY_PSC "psc"
+#define PROPERTY_RSCP "rscp"
+#define PROPERTY_ECIO "ecio"
+#define PROPERTY_PATH_LOSS "path-loss"
+
+struct _MMCellInfoUmtsPrivate {
+ gchar *operator_id;
+ gchar *lac;
+ gchar *ci;
+ guint frequency_fdd_ul;
+ guint frequency_fdd_dl;
+ guint frequency_tdd;
+ guint uarfcn;
+ guint psc;
+ gdouble rscp;
+ gdouble ecio;
+ guint path_loss;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_umts_get_operator_id:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the PLMN MCC/MNC.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_umts_get_operator_id (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->operator_id);
+}
+
+/**
+ * mm_cell_info_umts_set_operator_id: (skip)
+ */
+void
+mm_cell_info_umts_set_operator_id (MMCellInfoUmts *self,
+ const gchar *operator_id)
+{
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/**
+ * mm_cell_info_umts_get_lac:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the two-byte Location Area Code of the base station.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_umts_get_lac (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->lac);
+}
+
+/**
+ * mm_cell_info_umts_set_lac: (skip)
+ */
+void
+mm_cell_info_umts_set_lac (MMCellInfoUmts *self,
+ const gchar *lac)
+{
+ g_free (self->priv->lac);
+ self->priv->lac = g_strdup (lac);
+}
+
+/**
+ * mm_cell_info_umts_get_ci:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the two- or four-byte Cell Identifier.
+ *
+ * Encoded in upper-case hexadecimal format without leading zeros,
+ * as specified in 3GPP TS 27.007.
+ *
+ * Returns: (transfer none): the MCCMNC, or %NULL if not available.
+ *
+ * Since: 1.20
+ */
+const gchar *
+mm_cell_info_umts_get_ci (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (self->priv->ci);
+}
+
+/**
+ * mm_cell_info_umts_set_ci: (skip)
+ */
+void
+mm_cell_info_umts_set_ci (MMCellInfoUmts *self,
+ const gchar *ci)
+{
+ g_free (self->priv->ci);
+ self->priv->ci = g_strdup (ci);
+}
+
+/**
+ * mm_cell_info_umts_get_frequency_fdd_ul:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the frequency of the uplink in kHz while in FDD.
+ *
+ * Returns: the frequency, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_frequency_fdd_ul (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->frequency_fdd_ul;
+}
+
+/**
+ * mm_cell_info_umts_set_frequency_fdd_ul: (skip)
+ */
+void
+mm_cell_info_umts_set_frequency_fdd_ul (MMCellInfoUmts *self,
+ guint frequency_fdd_ul)
+{
+ self->priv->frequency_fdd_ul = frequency_fdd_ul;
+}
+
+/**
+ * mm_cell_info_umts_get_frequency_fdd_dl:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the frequency of the downlink in kHz while in FDD.
+ *
+ * Returns: the frequency, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_frequency_fdd_dl (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->frequency_fdd_dl;
+}
+
+/**
+ * mm_cell_info_umts_set_frequency_fdd_dl: (skip)
+ */
+void
+mm_cell_info_umts_set_frequency_fdd_dl (MMCellInfoUmts *self,
+ guint frequency_fdd_dl)
+{
+ self->priv->frequency_fdd_dl = frequency_fdd_dl;
+}
+
+
+/**
+ * mm_cell_info_umts_get_frequency_tdd:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the frequency in kHz while in TDD.
+ *
+ * Returns: the frequency, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_frequency_tdd (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->frequency_tdd;
+}
+
+/**
+ * mm_cell_info_umts_set_frequency_tdd: (skip)
+ */
+void
+mm_cell_info_umts_set_frequency_tdd (MMCellInfoUmts *self,
+ guint frequency_tdd)
+{
+ self->priv->frequency_tdd = frequency_tdd;
+}
+
+/**
+ * mm_cell_info_umts_get_uarfcn:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the UTRA absolute RF channel number.
+ *
+ * Returns: the UARFCN, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_uarfcn (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->uarfcn;
+}
+
+/**
+ * mm_cell_info_umts_set_uarfcn: (skip)
+ */
+void
+mm_cell_info_umts_set_uarfcn (MMCellInfoUmts *self,
+ guint uarfcn)
+{
+ self->priv->uarfcn = uarfcn;
+}
+
+/**
+ * mm_cell_info_umts_get_psc:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the primary scrambling code.
+ *
+ * Returns: the PSC, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_psc (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->psc;
+}
+
+/**
+ * mm_cell_info_umts_set_psc: (skip)
+ */
+void
+mm_cell_info_umts_set_psc (MMCellInfoUmts *self,
+ guint psc)
+{
+ self->priv->psc = psc;
+}
+
+/**
+ * mm_cell_info_umts_get_rscp:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the received signal code power.
+ *
+ * Returns: the RSCP, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_umts_get_rscp (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), -G_MAXDOUBLE);
+
+ return self->priv->rscp;
+}
+
+/**
+ * mm_cell_info_umts_set_rscp: (skip)
+ */
+void
+mm_cell_info_umts_set_rscp (MMCellInfoUmts *self,
+ gdouble rscp)
+{
+ self->priv->rscp = rscp;
+}
+
+/**
+ * mm_cell_info_umts_get_ecio:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the ECIO, the received energy per chip divided by the power density
+ * in the band measured in dBm on the primary CPICH channel of the cell.
+ *
+ * Returns: the ECIO, or -%G_MAXDOUBLE if not available.
+ *
+ * Since: 1.20
+ */
+gdouble
+mm_cell_info_umts_get_ecio (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), -G_MAXDOUBLE);
+
+ return self->priv->ecio;
+}
+
+/**
+ * mm_cell_info_umts_set_ecio: (skip)
+ */
+void
+mm_cell_info_umts_set_ecio (MMCellInfoUmts *self,
+ gdouble ecio)
+{
+ self->priv->ecio = ecio;
+}
+
+/**
+ * mm_cell_info_umts_get_path_loss:
+ * @self: a #MMCellInfoUmts.
+ *
+ * Get the path loss of the cell.
+ *
+ * Returns: the path loss, or %G_MAXUINT if not available.
+ *
+ * Since: 1.20
+ */
+guint
+mm_cell_info_umts_get_path_loss (MMCellInfoUmts *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO_UMTS (self), G_MAXUINT);
+
+ return self->priv->path_loss;
+}
+
+/**
+ * mm_cell_info_umts_set_path_loss: (skip)
+ */
+void
+mm_cell_info_umts_set_path_loss (MMCellInfoUmts *self,
+ guint path_loss)
+{
+ self->priv->path_loss = path_loss;
+}
+
+/*****************************************************************************/
+
+static GString *
+build_string (MMCellInfo *_self)
+{
+ MMCellInfoUmts *self = MM_CELL_INFO_UMTS (_self);
+ GString *str;
+
+ str = g_string_new (NULL);
+
+ MM_CELL_INFO_BUILD_STRING_APPEND ("operator id", "%s", operator_id, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("lac", "%s", lac, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ci", "%s", ci, NULL);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("frequency fdd ul", "%u", frequency_fdd_ul, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("frequency fdd dl", "%u", frequency_fdd_dl, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("frequency tdd", "%u", frequency_tdd, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("uarfcn", "%u", uarfcn, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("psc", "%u", psc, G_MAXUINT);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("rscp", "%lf", rscp, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("ecio", "%lf", ecio, -G_MAXDOUBLE);
+ MM_CELL_INFO_BUILD_STRING_APPEND ("path loss", "%u", path_loss, G_MAXUINT);
+
+ return str;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_umts_get_dictionary: (skip)
+ */
+static GVariantDict *
+get_dictionary (MMCellInfo *_self)
+{
+ MMCellInfoUmts *self = MM_CELL_INFO_UMTS (_self);
+ GVariantDict *dict;
+
+ dict = g_variant_dict_new (NULL);
+
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (OPERATOR_ID, operator_id, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (LAC, lac, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (CI, ci, string, NULL);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (FREQUENCY_FDD_UL, frequency_fdd_ul, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (FREQUENCY_FDD_DL, frequency_fdd_dl, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (FREQUENCY_TDD, frequency_tdd, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (UARFCN, uarfcn, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PSC, psc, uint32, G_MAXUINT);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (RSCP, rscp, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (ECIO, ecio, double, -G_MAXDOUBLE);
+ MM_CELL_INFO_GET_DICTIONARY_INSERT (PATH_LOSS, path_loss, uint32, G_MAXUINT);
+
+ return dict;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_umts_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_umts_new_from_dictionary (GVariantDict *dict)
+{
+ MMCellInfoUmts *self;
+
+ self = MM_CELL_INFO_UMTS (g_object_new (MM_TYPE_CELL_INFO_UMTS, NULL));
+
+ if (dict) {
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (umts, OPERATOR_ID, operator_id);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (umts, LAC, lac);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET (umts, CI, ci);
+
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, FREQUENCY_FDD_UL, frequency_fdd_ul, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, FREQUENCY_FDD_DL, frequency_fdd_dl, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, FREQUENCY_TDD, frequency_tdd, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, UARFCN, uarfcn, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, PSC, psc, UINT32, uint32);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, RSCP, rscp, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, ECIO, ecio, DOUBLE, double);
+ MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET (umts, PATH_LOSS, path_loss, UINT32, uint32);
+ }
+
+ return MM_CELL_INFO (self);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_umts_init (MMCellInfoUmts *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO_UMTS, MMCellInfoUmtsPrivate);
+ self->priv->frequency_fdd_ul = G_MAXUINT;
+ self->priv->frequency_fdd_dl = G_MAXUINT;
+ self->priv->frequency_tdd = G_MAXUINT;
+ self->priv->uarfcn = G_MAXUINT;
+ self->priv->psc = G_MAXUINT;
+ self->priv->rscp = -G_MAXDOUBLE;
+ self->priv->ecio = -G_MAXDOUBLE;
+ self->priv->path_loss = G_MAXUINT;
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCellInfoUmts *self = MM_CELL_INFO_UMTS (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->lac);
+ g_free (self->priv->ci);
+
+ G_OBJECT_CLASS (mm_cell_info_umts_parent_class)->finalize (object);
+}
+
+static void
+mm_cell_info_umts_class_init (MMCellInfoUmtsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMCellInfoClass *cell_info_class = MM_CELL_INFO_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoUmtsPrivate));
+
+ object_class->finalize = finalize;
+ cell_info_class->get_dictionary = get_dictionary;
+ cell_info_class->build_string = build_string;
+
+}
diff --git a/libmm-glib/mm-cell-info-umts.h b/libmm-glib/mm-cell-info-umts.h
new file mode 100644
index 0000000..d320fd8
--- /dev/null
+++ b/libmm-glib/mm-cell-info-umts.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_UMTS_H
+#define MM_CELL_INFO_UMTS_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+#include "mm-cell-info.h"
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO_UMTS (mm_cell_info_umts_get_type ())
+#define MM_CELL_INFO_UMTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO_UMTS, MMCellInfoUmts))
+#define MM_CELL_INFO_UMTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO_UMTS, MMCellInfoUmtsClass))
+#define MM_IS_CELL_INFO_UMTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO_UMTS))
+#define MM_IS_CELL_INFO_UMTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO_UMTS))
+#define MM_CELL_INFO_UMTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO_UMTS, MMCellInfoUmtsClass))
+
+typedef struct _MMCellInfoUmts MMCellInfoUmts;
+typedef struct _MMCellInfoUmtsClass MMCellInfoUmtsClass;
+typedef struct _MMCellInfoUmtsPrivate MMCellInfoUmtsPrivate;
+
+/**
+ * MMCellInfoUmts:
+ *
+ * The #MMCellInfoUmts structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfoUmts {
+ /*< private >*/
+ MMCellInfo parent;
+ MMCellInfoUmtsPrivate *priv;
+};
+
+struct _MMCellInfoUmtsClass {
+ /*< private >*/
+ MMCellInfoClass parent;
+};
+
+GType mm_cell_info_umts_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfoUmts, g_object_unref)
+
+const gchar *mm_cell_info_umts_get_operator_id (MMCellInfoUmts *self);
+const gchar *mm_cell_info_umts_get_lac (MMCellInfoUmts *self);
+const gchar *mm_cell_info_umts_get_ci (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_frequency_fdd_ul (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_frequency_fdd_dl (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_frequency_tdd (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_uarfcn (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_psc (MMCellInfoUmts *self);
+gdouble mm_cell_info_umts_get_rscp (MMCellInfoUmts *self);
+gdouble mm_cell_info_umts_get_ecio (MMCellInfoUmts *self);
+guint mm_cell_info_umts_get_path_loss (MMCellInfoUmts *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_umts_set_operator_id (MMCellInfoUmts *self,
+ const gchar *operator_id);
+void mm_cell_info_umts_set_lac (MMCellInfoUmts *self,
+ const gchar *lac);
+void mm_cell_info_umts_set_ci (MMCellInfoUmts *self,
+ const gchar *ci);
+void mm_cell_info_umts_set_frequency_fdd_ul (MMCellInfoUmts *self,
+ guint frequency_fdd_ul);
+void mm_cell_info_umts_set_frequency_fdd_dl (MMCellInfoUmts *self,
+ guint frequency_fdd_ul);
+void mm_cell_info_umts_set_frequency_tdd (MMCellInfoUmts *self,
+ guint frequency_tdd);
+void mm_cell_info_umts_set_uarfcn (MMCellInfoUmts *self,
+ guint uarfcn);
+void mm_cell_info_umts_set_psc (MMCellInfoUmts *self,
+ guint psc);
+void mm_cell_info_umts_set_rscp (MMCellInfoUmts *self,
+ gdouble rscp);
+void mm_cell_info_umts_set_ecio (MMCellInfoUmts *self,
+ gdouble ecio);
+void mm_cell_info_umts_set_path_loss (MMCellInfoUmts *self,
+ guint path_loss);
+
+MMCellInfo *mm_cell_info_umts_new_from_dictionary (GVariantDict *dict);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_UMTS_H */
diff --git a/libmm-glib/mm-cell-info.c b/libmm-glib/mm-cell-info.c
new file mode 100644
index 0000000..9ba7755
--- /dev/null
+++ b/libmm-glib/mm-cell-info.c
@@ -0,0 +1,248 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include "mm-cell-info.h"
+#include "mm-cell-info-cdma.h"
+#include "mm-cell-info-gsm.h"
+#include "mm-cell-info-umts.h"
+#include "mm-cell-info-tdscdma.h"
+#include "mm-cell-info-lte.h"
+#include "mm-cell-info-nr5g.h"
+
+#include "mm-enums-types.h"
+#include "mm-errors-types.h"
+
+/**
+ * SECTION: mm-cell-info
+ * @title: MMCellInfo
+ * @short_description: Helper base object to report cell info
+ *
+ * The #MMCellInfo is a base object used to report cell information.
+ *
+ * This object is retrieved from the #MMModem object with
+ * mm_modem_get_cell_info() or mm_modem_get_cell_info_sync().
+ */
+
+G_DEFINE_TYPE (MMCellInfo, mm_cell_info, G_TYPE_OBJECT)
+
+#define PROPERTY_CELL_TYPE "cell-type"
+#define PROPERTY_SERVING "serving"
+
+struct _MMCellInfoPrivate {
+ MMCellType cell_type;
+ gboolean serving;
+};
+
+/*****************************************************************************/
+
+static void
+ensure_cell_type (MMCellInfo *self)
+{
+ if (self->priv->cell_type != MM_CELL_TYPE_UNKNOWN)
+ return;
+
+ if (MM_IS_CELL_INFO_CDMA (self))
+ self->priv->cell_type = MM_CELL_TYPE_CDMA;
+ else if (MM_IS_CELL_INFO_GSM (self))
+ self->priv->cell_type = MM_CELL_TYPE_GSM;
+ else if (MM_IS_CELL_INFO_UMTS (self))
+ self->priv->cell_type = MM_CELL_TYPE_UMTS;
+ else if (MM_IS_CELL_INFO_TDSCDMA (self))
+ self->priv->cell_type = MM_CELL_TYPE_TDSCDMA;
+ else if (MM_IS_CELL_INFO_LTE (self))
+ self->priv->cell_type = MM_CELL_TYPE_LTE;
+ else if (MM_IS_CELL_INFO_NR5G (self))
+ self->priv->cell_type = MM_CELL_TYPE_5GNR;
+}
+
+/**
+ * mm_cell_info_get_cell_type:
+ * @self: a #MMCellInfo.
+ *
+ * Get the type of cell.
+ *
+ * Returns: a #MMCellType.
+ *
+ * Since: 1.20
+ */
+MMCellType
+mm_cell_info_get_cell_type (MMCellInfo *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO (self), MM_CELL_TYPE_UNKNOWN);
+
+ ensure_cell_type (self);
+
+ return self->priv->cell_type;
+}
+
+/**
+ * mm_cell_info_get_serving:
+ * @self: a #MMCellInfo.
+ *
+ * Get whether the cell is a serving cell or a neighboring cell.a
+ *
+ * Returns: %TRUE if the cell is a serving cell, %FALSE otherwise.
+ *
+ * Since: 1.20
+ */
+gboolean
+mm_cell_info_get_serving (MMCellInfo *self)
+{
+ g_return_val_if_fail (MM_IS_CELL_INFO (self), FALSE);
+
+ return self->priv->serving;
+}
+
+/**
+ * mm_cell_info_set_serving: (skip)
+ */
+void
+mm_cell_info_set_serving (MMCellInfo *self,
+ gboolean serving)
+{
+ g_return_if_fail (MM_IS_CELL_INFO (self));
+
+ self->priv->serving = serving;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_get_dictionary: (skip)
+ */
+GVariant *
+mm_cell_info_get_dictionary (MMCellInfo *self)
+{
+ g_autoptr(GVariantDict) dict = NULL;
+
+ dict = MM_CELL_INFO_GET_CLASS (self)->get_dictionary (self);
+ g_assert (dict);
+
+ g_variant_dict_insert_value (dict, PROPERTY_SERVING, g_variant_new_boolean (self->priv->serving));
+ g_variant_dict_insert_value (dict, PROPERTY_CELL_TYPE, g_variant_new_uint32 (mm_cell_info_get_cell_type (self)));
+
+ return g_variant_ref_sink (g_variant_dict_end (dict));
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_new_from_dictionary: (skip)
+ */
+MMCellInfo *
+mm_cell_info_new_from_dictionary (GVariant *dictionary,
+ GError **error)
+{
+ g_autoptr(MMCellInfo) self = NULL;
+ g_autoptr(GVariantDict) dict = NULL;
+ GVariant *aux;
+
+ dict = g_variant_dict_new (dictionary);
+
+ aux = g_variant_dict_lookup_value (dict, PROPERTY_CELL_TYPE, G_VARIANT_TYPE_UINT32);
+ if (!aux) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "missing '" PROPERTY_CELL_TYPE "' key in cell info");
+ return NULL;
+ }
+ switch (g_variant_get_uint32 (aux)) {
+ case MM_CELL_TYPE_CDMA:
+ self = mm_cell_info_cdma_new_from_dictionary (dict);
+ break;
+ case MM_CELL_TYPE_GSM:
+ self = mm_cell_info_gsm_new_from_dictionary (dict);
+ break;
+ case MM_CELL_TYPE_UMTS:
+ self = mm_cell_info_umts_new_from_dictionary (dict);
+ break;
+ case MM_CELL_TYPE_TDSCDMA:
+ self = mm_cell_info_tdscdma_new_from_dictionary (dict);
+ break;
+ case MM_CELL_TYPE_LTE:
+ self = mm_cell_info_lte_new_from_dictionary (dict);
+ break;
+ case MM_CELL_TYPE_5GNR:
+ self = mm_cell_info_nr5g_new_from_dictionary (dict);
+ break;
+ default:
+ break;
+ }
+ g_variant_unref (aux);
+
+ if (!self) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "unknown '" PROPERTY_CELL_TYPE "' key value in cell info");
+ return NULL;
+ }
+
+ aux = g_variant_dict_lookup_value (dict, PROPERTY_SERVING, G_VARIANT_TYPE_BOOLEAN);
+ if (aux) {
+ mm_cell_info_set_serving (self, g_variant_get_boolean (aux));
+ g_variant_unref (aux);
+ }
+
+ return g_steal_pointer (&self);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_cell_info_build_string: (skip)
+ */
+gchar *
+mm_cell_info_build_string (MMCellInfo *self)
+{
+ GString *str;
+ GString *substr;
+
+ substr = MM_CELL_INFO_GET_CLASS (self)->build_string (self);
+ g_assert (substr);
+
+ ensure_cell_type (self);
+
+ str = g_string_new (NULL);
+ g_string_append_printf (str, "cell type: %s, serving: %s",
+ mm_cell_type_get_string (self->priv->cell_type),
+ self->priv->serving ? "yes" : "no");
+ g_string_append_len (str, substr->str, (gssize)substr->len);
+
+ g_string_free (substr, TRUE);
+
+ return g_string_free (str, FALSE);
+}
+
+/*****************************************************************************/
+
+static void
+mm_cell_info_init (MMCellInfo *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_CELL_INFO, MMCellInfoPrivate);
+ self->priv->cell_type = MM_CELL_TYPE_UNKNOWN;
+}
+
+static void
+mm_cell_info_class_init (MMCellInfoClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCellInfoPrivate));
+}
diff --git a/libmm-glib/mm-cell-info.h b/libmm-glib/mm-cell-info.h
new file mode 100644
index 0000000..0720552
--- /dev/null
+++ b/libmm-glib/mm-cell-info.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2022 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#ifndef MM_CELL_INFO_H
+#define MM_CELL_INFO_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CELL_INFO (mm_cell_info_get_type ())
+#define MM_CELL_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CELL_INFO, MMCellInfo))
+#define MM_CELL_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CELL_INFO, MMCellInfoClass))
+#define MM_IS_CELL_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CELL_INFO))
+#define MM_IS_CELL_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CELL_INFO))
+#define MM_CELL_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CELL_INFO, MMCellInfoClass))
+
+typedef struct _MMCellInfo MMCellInfo;
+typedef struct _MMCellInfoClass MMCellInfoClass;
+typedef struct _MMCellInfoPrivate MMCellInfoPrivate;
+
+/**
+ * MMCellInfo:
+ *
+ * The #MMCellInfo structure contains private data and should only be
+ * accessed using the provided API.
+ */
+struct _MMCellInfo {
+ /*< private >*/
+ GObject parent;
+ MMCellInfoPrivate *priv;
+};
+
+struct _MMCellInfoClass {
+ /*< private >*/
+ GObjectClass parent;
+
+ GVariantDict * (* get_dictionary) (MMCellInfo *self);
+ GString * (* build_string) (MMCellInfo *self);
+
+ /* class padding */
+ gpointer padding [5];
+};
+
+GType mm_cell_info_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCellInfo, g_object_unref)
+
+MMCellType mm_cell_info_get_cell_type (MMCellInfo *self);
+gboolean mm_cell_info_get_serving (MMCellInfo *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+void mm_cell_info_set_serving (MMCellInfo *self,
+ gboolean serving);
+GVariant *mm_cell_info_get_dictionary (MMCellInfo *self);
+MMCellInfo *mm_cell_info_new_from_dictionary (GVariant *dictionary,
+ GError **error);
+gchar *mm_cell_info_build_string (MMCellInfo *self);
+
+/* helpers to implement methods */
+
+#define MM_CELL_INFO_NEW_FROM_DICTIONARY_STRING_SET(celltype,NAME,name) do { \
+ GVariant *aux; \
+ \
+ aux = g_variant_dict_lookup_value (dict, PROPERTY_##NAME, G_VARIANT_TYPE_STRING); \
+ if (aux) { \
+ mm_cell_info_##celltype##_set_##name (self, g_variant_get_string (aux, NULL)); \
+ g_variant_unref (aux); \
+ } \
+ } while (0)
+
+#define MM_CELL_INFO_NEW_FROM_DICTIONARY_NUM_SET(celltype,NAME,name,NUMTYPE,numtype) do { \
+ GVariant *aux; \
+ \
+ aux = g_variant_dict_lookup_value (dict, PROPERTY_##NAME, G_VARIANT_TYPE_##NUMTYPE); \
+ if (aux) { \
+ mm_cell_info_##celltype##_set_##name (self, g_variant_get_##numtype (aux)); \
+ g_variant_unref (aux); \
+ } \
+ } while (0)
+
+#define MM_CELL_INFO_GET_DICTIONARY_INSERT(NAME,name,vartype,INVALID) do { \
+ if (self->priv->name != INVALID) \
+ g_variant_dict_insert_value (dict, PROPERTY_##NAME, g_variant_new_##vartype (self->priv->name)); \
+ } while (0)
+
+#define MM_CELL_INFO_BUILD_STRING_APPEND(STR,FORMAT,name,INVALID) do { \
+ if (self->priv->name != INVALID) \
+ g_string_append_printf (str, ", " STR ": " FORMAT, self->priv->name); \
+ } while (0)
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CELL_INFO_H */
diff --git a/libmm-glib/mm-firmware-update-settings.c b/libmm-glib/mm-firmware-update-settings.c
index 459aa89..3ed9246 100644
--- a/libmm-glib/mm-firmware-update-settings.c
+++ b/libmm-glib/mm-firmware-update-settings.c
@@ -70,6 +70,18 @@
return self->priv->method;
}
+/**
+ * mm_firmware_update_settings_set_method: (skip)
+ */
+void
+mm_firmware_update_settings_set_method (MMFirmwareUpdateSettings *self,
+ MMModemFirmwareUpdateMethod method)
+{
+ g_return_if_fail (MM_IS_FIRMWARE_UPDATE_SETTINGS (self));
+
+ self->priv->method = method;
+}
+
/*****************************************************************************/
/**
diff --git a/libmm-glib/mm-firmware-update-settings.h b/libmm-glib/mm-firmware-update-settings.h
index 9c0c896..459d57c 100644
--- a/libmm-glib/mm-firmware-update-settings.h
+++ b/libmm-glib/mm-firmware-update-settings.h
@@ -87,10 +87,12 @@
GVariant *mm_firmware_update_settings_get_variant (MMFirmwareUpdateSettings *self);
/* Generic */
-void mm_firmware_update_settings_set_device_ids (MMFirmwareUpdateSettings *self,
- const gchar **device_ids);
-void mm_firmware_update_settings_set_version (MMFirmwareUpdateSettings *self,
- const gchar *version);
+void mm_firmware_update_settings_set_device_ids (MMFirmwareUpdateSettings *self,
+ const gchar **device_ids);
+void mm_firmware_update_settings_set_version (MMFirmwareUpdateSettings *self,
+ const gchar *version);
+void mm_firmware_update_settings_set_method (MMFirmwareUpdateSettings *self,
+ MMModemFirmwareUpdateMethod method);
/* Fastboot specific */
void mm_firmware_update_settings_set_fastboot_at (MMFirmwareUpdateSettings *self,
diff --git a/libmm-glib/mm-modem-3gpp.c b/libmm-glib/mm-modem-3gpp.c
index 83a74a9..0d3944e 100644
--- a/libmm-glib/mm-modem-3gpp.c
+++ b/libmm-glib/mm-modem-3gpp.c
@@ -741,6 +741,8 @@
g_variant_unref (dict);
}
+ g_variant_unref (variant);
+
return list;
}
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c
index 5e24431..8e1a80f 100644
--- a/libmm-glib/mm-modem.c
+++ b/libmm-glib/mm-modem.c
@@ -23,7 +23,6 @@
#include <gio/gio.h>
#include <string.h>
-
#include "mm-common-helpers.h"
#include "mm-errors-types.h"
#include "mm-helpers.h"
@@ -3247,6 +3246,135 @@
/*****************************************************************************/
+static GList *
+create_cell_info_list (GVariant *variant,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ GList *list = NULL;
+ GVariantIter dict_iter;
+ GVariant *dict;
+
+ /* Input is aa{sv} */
+ g_variant_iter_init (&dict_iter, variant);
+ while ((dict = g_variant_iter_next_value (&dict_iter))) {
+ MMCellInfo *cell_info;
+
+ cell_info = mm_cell_info_new_from_dictionary (dict, &inner_error);
+ if (inner_error)
+ break;
+
+ list = g_list_prepend (list, cell_info);
+ g_variant_unref (dict);
+ }
+
+ if (inner_error) {
+ g_list_free_full (g_steal_pointer (&list), g_object_unref);
+ g_propagate_error (error, inner_error);
+ }
+
+ g_variant_unref (variant);
+
+ return list;
+}
+
+/**
+ * mm_modem_get_cell_info_finish:
+ * @self: A #MMModem.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ * mm_modem_get_cell_info().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with mm_modem_get_cell_info().
+ *
+ * Returns: (transfer full) (element-type ModemManager.CellInfo): a list
+ * of #MMCellInfo objects, or #NULL if @error is set. The returned value
+ * should be freed with g_list_free_full() using g_object_unref() as
+ * #GDestroyNotify function.
+ *
+ * Since: 1.20
+ */
+GList *
+mm_modem_get_cell_info_finish (MMModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *result = NULL;
+
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+
+ if (!mm_gdbus_modem_call_get_cell_info_finish (MM_GDBUS_MODEM (self), &result, res, error))
+ return NULL;
+
+ return create_cell_info_list (result, error);
+}
+
+/**
+ * mm_modem_get_cell_info:
+ * @self: A #MMModem.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or
+ * %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously requests to get info about serving and neighboring cells.
+ *
+ * When the operation is finished, @callback will be invoked in the
+ * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * of the thread you are calling this method from. You can then call
+ * mm_modem_get_cell_info_finish() to get the result of the operation.
+ *
+ * See mm_modem_get_cell_info_sync() for the synchronous, blocking version of this
+ * method.
+ *
+ * Since: 1.20
+ */
+void
+mm_modem_get_cell_info (MMModem *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM (self));
+
+ mm_gdbus_modem_call_get_cell_info (MM_GDBUS_MODEM (self), cancellable, callback, user_data);
+}
+
+/**
+ * mm_modem_get_cell_info_sync:
+ * @self: A #MMModem.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously requests to get info about serving and neighboring cells.
+ *
+ * The calling thread is blocked until a reply is received. See
+ * mm_modem_get_cell_info() for the asynchronous version of this method.
+ *
+ * Returns: (transfer full) (element-type ModemManager.CellInfo): a list
+ * of #MMCellInfo objects, or #NULL if @error is set. The returned value
+ * should be freed with g_list_free_full() using g_object_unref() as
+ * #GDestroyNotify function.
+ *
+ * Since: 1.20
+ */
+GList *
+mm_modem_get_cell_info_sync (MMModem *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *result = NULL;
+
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+
+ if (!mm_gdbus_modem_call_get_cell_info_sync (MM_GDBUS_MODEM (self), &result, cancellable, error))
+ return NULL;
+
+ return create_cell_info_list (result, error);
+}
+
+/*****************************************************************************/
+
static void
mm_modem_init (MMModem *self)
{
diff --git a/libmm-glib/mm-modem.h b/libmm-glib/mm-modem.h
index 655e6f4..9d1a733 100644
--- a/libmm-glib/mm-modem.h
+++ b/libmm-glib/mm-modem.h
@@ -34,6 +34,7 @@
#include "mm-unlock-retries.h"
#include "mm-sim.h"
#include "mm-bearer.h"
+#include "mm-cell-info.h"
#include "mm-helper-types.h"
G_BEGIN_DECLS
@@ -372,6 +373,17 @@
GCancellable *cancellable,
GError **error);
+void mm_modem_get_cell_info (MMModem *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GList *mm_modem_get_cell_info_finish (MMModem *self,
+ GAsyncResult *res,
+ GError **error);
+GList *mm_modem_get_cell_info_sync (MMModem *self,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif /* _MM_MODEM_H_ */
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index a97cb9a..cd21281 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -156,7 +156,7 @@
static char *
bin2hexstr (const uint8_t *bytes, int len)
{
- static char hex_digits[] = "0123456789abcdef";
+ const char hex_digits[] = "0123456789abcdef";
char *result;
int i;
size_t buflen = (len * 2) + 1;
diff --git a/libqcdm/src/errors.c b/libqcdm/src/errors.c
index 12b8d55..dd789d8 100644
--- a/libqcdm/src/errors.c
+++ b/libqcdm/src/errors.c
@@ -23,8 +23,8 @@
_qcdm_log (const char *file,
int line,
const char *func,
- int level,
int domain,
+ int level,
const char *format,
...)
{
@@ -53,7 +53,7 @@
prefix = "dbg";
if (n >= 0) {
- fprintf (stderr, "<%s> [%s:%u] %s(): %s\n", prefix, file, line, func, message);
+ fprintf (stderr, "<%s> [%s:%d] %s(): %s\n", prefix, file, line, func, message);
free (message);
}
}
diff --git a/meson.build b/meson.build
index 5a1485a..17a11b3 100644
--- a/meson.build
+++ b/meson.build
@@ -3,7 +3,7 @@
project(
'ModemManager', 'c',
- version: '1.19.0',
+ version: '1.19.1',
license: 'GPL2',
default_options: [
'buildtype=debugoptimized',
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 5e2d4a1..93a9ce2 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -690,9 +690,19 @@
pkglib_LTLIBRARIES += libmm-plugin-fibocom.la
libmm_plugin_fibocom_la_SOURCES = \
+ fibocom/mm-broadband-bearer-fibocom-ecm.c \
+ fibocom/mm-broadband-bearer-fibocom-ecm.h \
+ fibocom/mm-broadband-modem-fibocom.c \
+ fibocom/mm-broadband-modem-fibocom.h \
fibocom/mm-plugin-fibocom.c \
fibocom/mm-plugin-fibocom.h \
$(NULL)
+if WITH_MBIM
+libmm_plugin_fibocom_la_SOURCES += \
+ fibocom/mm-broadband-modem-mbim-xmm-fibocom.c \
+ fibocom/mm-broadband-modem-mbim-xmm-fibocom.h \
+ $(NULL)
+endif
libmm_plugin_fibocom_la_CPPFLAGS = \
$(PLUGIN_COMMON_COMPILER_FLAGS) \
$(XMM_COMMON_COMPILER_FLAGS) \
diff --git a/plugins/fibocom/77-mm-fibocom-port-types.rules b/plugins/fibocom/77-mm-fibocom-port-types.rules
index 790520c..544dc25 100755
--- a/plugins/fibocom/77-mm-fibocom-port-types.rules
+++ b/plugins/fibocom/77-mm-fibocom-port-types.rules
@@ -1,12 +1,16 @@
# do not edit this file, it will be overwritten on update
ACTION!="add|change|move|bind", GOTO="mm_fibocom_port_types_end"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2cb7", GOTO="mm_fibocom_port_types"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="1782", GOTO="mm_fibocom_port_types"
GOTO="mm_fibocom_port_types_end"
LABEL="mm_fibocom_port_types"
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
+# Fibocom L850-GL attach APN with toggle modem power
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1"
+
# Fibocom L850-GL
# ttyACM0 (if #2): AT port
# ttyACM1 (if #4): debug port (ignore)
@@ -53,4 +57,28 @@
ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1"
ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a4", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
+# Fibocom MA510-GL (GTUSBMODE=31)
+# ttyUSB0 (if #0): debug port (ignore)
+# ttyUSB1 (if #1): AT port
+# ttyUSB2 (if #2): AT port
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0106", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
+
+# Fibocom L610 (GTUSBMODE=32)
+# ttyUSB0 (if #2): AT port
+# ttyUSB1 (if #3): NV
+# ttyUSB2 (if #4): MOS
+# ttyUSB3 (if #5): Diagnostic
+# ttyUSB4 (if #6): Logging
+# ttyUSB5 (if #7): AT port
+# ttyUSB6 (if #8): AT port
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="07", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
+ATTRS{idVendor}=="1782", ATTRS{idProduct}=="4d11", ENV{.MM_USBIFNUM}=="08", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
+
LABEL="mm_fibocom_port_types_end"
diff --git a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c
new file mode 100644
index 0000000..0cad000
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.c
@@ -0,0 +1,270 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Disruptive Technologies Research AS
+ */
+
+#include <config.h>
+
+#include "mm-broadband-bearer-fibocom-ecm.h"
+#include "mm-broadband-modem-fibocom.h"
+#include "mm-base-modem-at.h"
+#include "mm-iface-modem-3gpp.h"
+
+G_DEFINE_TYPE (MMBroadbandBearerFibocomEcm, mm_broadband_bearer_fibocom_ecm, MM_TYPE_BROADBAND_BEARER)
+
+/*****************************************************************************/
+/* Dial context and task */
+
+typedef struct {
+ MMBroadbandModem *modem;
+ MMPortSerialAt *primary;
+ guint cid;
+ MMPort *data;
+} DialContext;
+
+static void
+dial_task_free (DialContext *ctx)
+{
+ g_object_unref (ctx->modem);
+ g_object_unref (ctx->primary);
+ if (ctx->data)
+ g_object_unref (ctx->data);
+ g_slice_free (DialContext, ctx);
+}
+
+static GTask *
+dial_task_new (MMBroadbandBearerFibocomEcm *self,
+ MMBroadbandModem *modem,
+ MMPortSerialAt *primary,
+ guint cid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ DialContext *ctx;
+ GTask *task;
+
+ ctx = g_slice_new0 (DialContext);
+ ctx->modem = g_object_ref (modem);
+ ctx->primary = g_object_ref (primary);
+ ctx->cid = cid;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, ctx, (GDestroyNotify) dial_task_free);
+
+ ctx->data = mm_base_modem_get_best_data_port (MM_BASE_MODEM (modem), MM_PORT_TYPE_NET);
+ if (!ctx->data) {
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_NOT_FOUND,
+ "No valid data port found to launch connection");
+ g_object_unref (task);
+ return NULL;
+ }
+
+ return task;
+}
+
+/*****************************************************************************/
+/* 3GPP Dialing (sub-step of the 3GPP Connection sequence) */
+
+static MMPort *
+dial_3gpp_finish (MMBroadbandBearer *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+gtrndis_verify_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ DialContext *ctx;
+ GError *error = NULL;
+ const gchar *response;
+
+ ctx = g_task_get_task_data (task);
+ response = mm_base_modem_at_command_finish (modem, res, &error);
+
+ if (!response)
+ g_task_return_error (task, error);
+ else {
+ response = mm_strip_tag (response, "+GTRNDIS:");
+ if (strtol (response, NULL, 10) != 1)
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Connection status verification failed");
+ else
+ g_task_return_pointer (task, g_object_ref (ctx->data), g_object_unref);
+ }
+
+ g_object_unref (task);
+}
+
+static void
+gtrndis_activate_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_at_command_finish (modem, res, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ mm_base_modem_at_command (modem,
+ "+GTRNDIS?",
+ 6, /* timeout [s] */
+ FALSE, /* allow_cached */
+ (GAsyncReadyCallback) gtrndis_verify_ready,
+ task);
+}
+
+static void
+dial_3gpp (MMBroadbandBearer *self,
+ MMBaseModem *modem,
+ MMPortSerialAt *primary,
+ guint cid,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ g_autofree gchar *cmd = NULL;
+
+ task = dial_task_new (MM_BROADBAND_BEARER_FIBOCOM_ECM (self),
+ MM_BROADBAND_MODEM (modem),
+ primary,
+ cid,
+ cancellable,
+ callback,
+ user_data);
+ if (!task)
+ return;
+
+ cmd = g_strdup_printf ("+GTRNDIS=1,%u", cid);
+ mm_base_modem_at_command (modem,
+ cmd,
+ MM_BASE_BEARER_DEFAULT_CONNECTION_TIMEOUT,
+ FALSE, /* allow_cached */
+ (GAsyncReadyCallback) gtrndis_activate_ready,
+ task);
+}
+
+/*****************************************************************************/
+/* 3GPP Disconnect sequence */
+
+static gboolean
+disconnect_3gpp_finish (MMBroadbandBearer *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+gtrndis_deactivate_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_at_command_finish (modem, res, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+disconnect_3gpp (MMBroadbandBearer *self,
+ MMBroadbandModem *modem,
+ MMPortSerialAt *primary,
+ MMPortSerialAt *secondary,
+ MMPort *data,
+ guint cid,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ g_autofree gchar *cmd = NULL;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ cmd = g_strdup_printf ("+GTRNDIS=0,%u", cid);
+ mm_base_modem_at_command (MM_BASE_MODEM (modem),
+ cmd,
+ MM_BASE_BEARER_DEFAULT_DISCONNECTION_TIMEOUT,
+ FALSE, /* allow_cached */
+ (GAsyncReadyCallback) gtrndis_deactivate_ready,
+ task);
+}
+
+/*****************************************************************************/
+
+MMBaseBearer *
+mm_broadband_bearer_fibocom_ecm_new_finish (GAsyncResult *res,
+ GError **error)
+{
+ GObject *bearer;
+ GObject *source;
+
+ source = g_async_result_get_source_object (res);
+ bearer = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error);
+ g_object_unref (source);
+
+ if (!bearer)
+ return NULL;
+
+ /* Only export valid bearers */
+ mm_base_bearer_export (MM_BASE_BEARER (bearer));
+
+ return MM_BASE_BEARER (bearer);
+}
+
+void
+mm_broadband_bearer_fibocom_ecm_new (MMBroadbandModemFibocom *modem,
+ MMBearerProperties *config,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (
+ MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ callback,
+ user_data,
+ MM_BASE_BEARER_MODEM, modem,
+ MM_BASE_BEARER_CONFIG, config,
+ NULL);
+}
+
+static void
+mm_broadband_bearer_fibocom_ecm_init (MMBroadbandBearerFibocomEcm *self)
+{
+}
+
+static void
+mm_broadband_bearer_fibocom_ecm_class_init (MMBroadbandBearerFibocomEcmClass *klass)
+{
+ MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass);
+
+ broadband_bearer_class->dial_3gpp = dial_3gpp;
+ broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish;
+ broadband_bearer_class->disconnect_3gpp = disconnect_3gpp;
+ broadband_bearer_class->disconnect_3gpp_finish = disconnect_3gpp_finish;
+}
diff --git a/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h
new file mode 100644
index 0000000..ea367ae
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-bearer-fibocom-ecm.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Disruptive Technologies Research AS
+ */
+
+#ifndef MM_BROADBAND_BEARER_FIBOCOM_ECM_H
+#define MM_BROADBAND_BEARER_FIBOCOM_ECM_H
+
+#include "mm-broadband-bearer.h"
+#include "mm-broadband-modem-fibocom.h"
+
+#define MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM (mm_broadband_bearer_fibocom_ecm_get_type ())
+#define MM_BROADBAND_BEARER_FIBOCOM_ECM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcm))
+#define MM_BROADBAND_BEARER_FIBOCOM_ECM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcmClass))
+#define MM_IS_BROADBAND_BEARER_FIBOCOM_ECM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM))
+#define MM_IS_BROADBAND_BEARER_FIBOCOM_ECM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM))
+#define MM_BROADBAND_BEARER_FIBOCOM_ECM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_FIBOCOM_ECM, MMBroadbandBearerFibocomEcmClass))
+
+typedef struct _MMBroadbandBearerFibocomEcm MMBroadbandBearerFibocomEcm;
+typedef struct _MMBroadbandBearerFibocomEcmClass MMBroadbandBearerFibocomEcmClass;
+
+struct _MMBroadbandBearerFibocomEcm {
+ MMBroadbandBearer parent;
+};
+
+struct _MMBroadbandBearerFibocomEcmClass {
+ MMBroadbandBearerClass parent;
+};
+
+GType mm_broadband_bearer_fibocom_ecm_get_type (void);
+
+void mm_broadband_bearer_fibocom_ecm_new (MMBroadbandModemFibocom *modem,
+ MMBearerProperties *properties,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+MMBaseBearer *mm_broadband_bearer_fibocom_ecm_new_finish (GAsyncResult *res,
+ GError **error);
+
+#endif /* MM_BROADBAND_BEARER_FIBOCOM_ECM_H */
diff --git a/plugins/fibocom/mm-broadband-modem-fibocom.c b/plugins/fibocom/mm-broadband-modem-fibocom.c
new file mode 100644
index 0000000..8292c18
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-modem-fibocom.c
@@ -0,0 +1,207 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Disruptive Technologies Research AS
+ */
+
+#include <config.h>
+
+#include "mm-broadband-modem-fibocom.h"
+#include "mm-broadband-bearer-fibocom-ecm.h"
+#include "mm-broadband-modem.h"
+#include "mm-iface-modem.h"
+#include "mm-base-modem-at.h"
+#include "mm-log.h"
+
+static void iface_modem_init (MMIfaceModem *iface);
+
+G_DEFINE_TYPE_EXTENDED (MMBroadbandModemFibocom, mm_broadband_modem_fibocom, MM_TYPE_BROADBAND_MODEM, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init))
+
+typedef enum {
+ FEATURE_SUPPORT_UNKNOWN,
+ FEATURE_NOT_SUPPORTED,
+ FEATURE_SUPPORTED,
+} FeatureSupport;
+
+struct _MMBroadbandModemFibocomPrivate {
+ FeatureSupport gtrndis_support;
+};
+
+/*****************************************************************************/
+/* Create Bearer (Modem interface) */
+
+static MMBaseBearer *
+modem_create_bearer_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+broadband_bearer_fibocom_ecm_new_ready (GObject *source,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBaseBearer *bearer = NULL;
+ GError *error = NULL;
+
+ bearer = mm_broadband_bearer_fibocom_ecm_new_finish (res, &error);
+ if (!bearer)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, bearer, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+broadband_bearer_new_ready (GObject *source,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBaseBearer *bearer = NULL;
+ GError *error = NULL;
+
+ bearer = mm_broadband_bearer_new_finish (res, &error);
+ if (!bearer)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, bearer, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+common_create_bearer (GTask *task)
+{
+ MMBroadbandModemFibocom *self;
+
+ self = g_task_get_source_object (task);
+
+ switch (self->priv->gtrndis_support) {
+ case FEATURE_SUPPORTED:
+ mm_obj_dbg (self, "+GTRNDIS supported, creating Fibocom ECM bearer");
+ mm_broadband_bearer_fibocom_ecm_new (self,
+ g_task_get_task_data (task),
+ NULL, /* cancellable */
+ (GAsyncReadyCallback) broadband_bearer_fibocom_ecm_new_ready,
+ task);
+ return;
+ case FEATURE_NOT_SUPPORTED:
+ mm_obj_dbg (self, "+GTRNDIS not supported, creating generic PPP bearer");
+ mm_broadband_bearer_new (MM_BROADBAND_MODEM (self),
+ g_task_get_task_data (task),
+ NULL, /* cancellable */
+ (GAsyncReadyCallback) broadband_bearer_new_ready,
+ task);
+ return;
+ case FEATURE_SUPPORT_UNKNOWN:
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+gtrndis_test_ready (MMBaseModem *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self);
+
+ if (!mm_base_modem_at_command_finish (_self, res, NULL)) {
+ mm_obj_dbg (self, "+GTRNDIS unsupported");
+ self->priv->gtrndis_support = FEATURE_NOT_SUPPORTED;
+ } else {
+ mm_obj_dbg (self, "+GTRNDIS supported");
+ self->priv->gtrndis_support = FEATURE_SUPPORTED;
+ }
+
+ /* Go on and create the bearer */
+ common_create_bearer (task);
+}
+
+static void
+modem_create_bearer (MMIfaceModem *_self,
+ MMBearerProperties *properties,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemFibocom *self = MM_BROADBAND_MODEM_FIBOCOM (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ g_task_set_task_data (task, g_object_ref (properties), g_object_unref);
+
+ if (self->priv->gtrndis_support != FEATURE_SUPPORT_UNKNOWN) {
+ common_create_bearer (task);
+ return;
+ }
+
+ if (!mm_base_modem_peek_best_data_port (MM_BASE_MODEM (self), MM_PORT_TYPE_NET)) {
+ mm_obj_dbg (self, "skipping +GTRNDIS check as no data port is available");
+ self->priv->gtrndis_support = FEATURE_NOT_SUPPORTED;
+ common_create_bearer (task);
+ return;
+ }
+
+ mm_obj_dbg (self, "checking +GTRNDIS support...");
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+GTRNDIS=?",
+ 6, /* timeout [s] */
+ TRUE, /* allow_cached */
+ (GAsyncReadyCallback) gtrndis_test_ready,
+ task);
+}
+
+/*****************************************************************************/
+
+MMBroadbandModemFibocom *
+mm_broadband_modem_fibocom_new (const gchar *device,
+ const gchar **drivers,
+ const gchar *plugin,
+ guint16 vendor_id,
+ guint16 product_id)
+{
+ return g_object_new (MM_TYPE_BROADBAND_MODEM_FIBOCOM,
+ MM_BASE_MODEM_DEVICE, device,
+ MM_BASE_MODEM_DRIVERS, drivers,
+ MM_BASE_MODEM_PLUGIN, plugin,
+ MM_BASE_MODEM_VENDOR_ID, vendor_id,
+ MM_BASE_MODEM_PRODUCT_ID, product_id,
+ MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE,
+ MM_BASE_MODEM_DATA_TTY_SUPPORTED, TRUE,
+ NULL);
+}
+
+static void
+mm_broadband_modem_fibocom_init (MMBroadbandModemFibocom *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ MM_TYPE_BROADBAND_MODEM_FIBOCOM,
+ MMBroadbandModemFibocomPrivate);
+
+ self->priv->gtrndis_support = FEATURE_SUPPORT_UNKNOWN;
+}
+
+static void
+iface_modem_init (MMIfaceModem *iface)
+{
+ iface->create_bearer = modem_create_bearer;
+ iface->create_bearer_finish = modem_create_bearer_finish;
+}
+
+static void
+mm_broadband_modem_fibocom_class_init (MMBroadbandModemFibocomClass *klass)
+{
+ g_type_class_add_private (G_OBJECT_CLASS (klass),
+ sizeof (MMBroadbandModemFibocomPrivate));
+}
diff --git a/plugins/fibocom/mm-broadband-modem-fibocom.h b/plugins/fibocom/mm-broadband-modem-fibocom.h
new file mode 100644
index 0000000..958841b
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-modem-fibocom.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Disruptive Technologies Research AS
+ */
+
+#ifndef MM_BROADBAND_MODEM_FIBOCOM_H
+#define MM_BROADBAND_MODEM_FIBOCOM_H
+
+#include "mm-broadband-modem.h"
+
+#define MM_TYPE_BROADBAND_MODEM_FIBOCOM (mm_broadband_modem_fibocom_get_type ())
+#define MM_BROADBAND_MODEM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocom))
+#define MM_BROADBAND_MODEM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocomClass))
+#define MM_IS_BROADBAND_MODEM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM))
+#define MM_IS_BROADBAND_MODEM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_FIBOCOM))
+#define MM_BROADBAND_MODEM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_FIBOCOM, MMBroadbandModemFibocomClass))
+
+typedef struct _MMBroadbandModemFibocom MMBroadbandModemFibocom;
+typedef struct _MMBroadbandModemFibocomClass MMBroadbandModemFibocomClass;
+typedef struct _MMBroadbandModemFibocomPrivate MMBroadbandModemFibocomPrivate;
+
+struct _MMBroadbandModemFibocom {
+ MMBroadbandModem parent;
+ MMBroadbandModemFibocomPrivate *priv;
+};
+
+struct _MMBroadbandModemFibocomClass{
+ MMBroadbandModemClass parent;
+};
+
+GType mm_broadband_modem_fibocom_get_type (void);
+
+MMBroadbandModemFibocom *mm_broadband_modem_fibocom_new (const gchar *device,
+ const gchar **drivers,
+ const gchar *plugin,
+ guint16 vendor_id,
+ guint16 product_id);
+
+#endif /* MM_BROADBAND_MODEM_FIBOCOM_H */
diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c
new file mode 100755
index 0000000..a434d4c
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c
@@ -0,0 +1,225 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Fibocom Wireless Inc.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "ModemManager.h"
+#include "mm-log-object.h"
+#include "mm-iface-modem.h"
+#include "mm-iface-modem-3gpp.h"
+#include "mm-broadband-modem-mbim-xmm-fibocom.h"
+
+static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
+
+static MMIfaceModem3gpp *iface_modem_3gpp_parent;
+
+G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmmFibocom, mm_broadband_modem_mbim_xmm_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM_XMM, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init))
+
+/*****************************************************************************/
+
+typedef struct {
+ MMBearerProperties *config;
+ gboolean initial_eps_off_on;
+} SetInitialEpsBearerSettingsContext;
+
+static void
+set_initial_eps_bearer_settings_context_free (SetInitialEpsBearerSettingsContext *ctx)
+{
+ g_clear_object (&ctx->config);
+ g_slice_free (SetInitialEpsBearerSettingsContext, ctx);
+}
+
+static gboolean
+modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+after_attach_apn_modem_power_up_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!mm_iface_modem_set_power_state_finish (self, res, &error)) {
+ mm_obj_warn (self, "failed to power up modem after attach APN settings update: %s", error->message);
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ mm_obj_dbg (self, "success toggling modem power up after attach APN");
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+parent_set_initial_eps_bearer_settings_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ SetInitialEpsBearerSettingsContext *ctx;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ if (!iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish (self, res, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (ctx->initial_eps_off_on) {
+ mm_obj_dbg (self, "toggle modem power up after attach APN");
+ mm_iface_modem_set_power_state (MM_IFACE_MODEM (self),
+ MM_MODEM_POWER_STATE_ON,
+ (GAsyncReadyCallback) after_attach_apn_modem_power_up_ready,
+ task);
+ return;
+ }
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+parent_set_initial_eps_bearer_settings (GTask *task)
+{
+ MMBroadbandModemMbimXmmFibocom *self;
+ SetInitialEpsBearerSettingsContext *ctx;
+
+ self = g_task_get_source_object (task);
+ ctx = g_task_get_task_data (task);
+
+ g_assert (iface_modem_3gpp_parent->set_initial_eps_bearer_settings);
+ g_assert (iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish);
+
+ iface_modem_3gpp_parent->set_initial_eps_bearer_settings (MM_IFACE_MODEM_3GPP (self),
+ ctx->config,
+ (GAsyncReadyCallback)parent_set_initial_eps_bearer_settings_ready,
+ task);
+}
+
+static void
+before_attach_apn_modem_power_down_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!mm_iface_modem_set_power_state_finish (self, res, &error)) {
+ mm_obj_warn (self, "failed to power down modem before attach APN settings update: %s", error->message);
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+ mm_obj_dbg (self, "success toggling modem power down before attach APN");
+
+ parent_set_initial_eps_bearer_settings (task);
+}
+
+static void
+modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self,
+ MMBearerProperties *config,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SetInitialEpsBearerSettingsContext *ctx;
+ GTask *task;
+ MMPortMbim *port;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self));
+ if (!port) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "No valid MBIM port found");
+ g_object_unref (task);
+ return;
+ }
+
+ ctx = g_slice_new0 (SetInitialEpsBearerSettingsContext);
+ ctx->config = g_object_ref (config);
+ ctx->initial_eps_off_on = mm_kernel_device_get_property_as_boolean (mm_port_peek_kernel_device (MM_PORT (port)), "ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON");
+ g_task_set_task_data (task, ctx, (GDestroyNotify)set_initial_eps_bearer_settings_context_free);
+
+
+ if (ctx->initial_eps_off_on) {
+ mm_obj_dbg (self, "toggle modem power down before attach APN");
+ mm_iface_modem_set_power_state (MM_IFACE_MODEM (self),
+ MM_MODEM_POWER_STATE_LOW,
+ (GAsyncReadyCallback) before_attach_apn_modem_power_down_ready,
+ task);
+ return;
+ }
+
+ parent_set_initial_eps_bearer_settings (task);
+}
+
+/******************************************************************************/
+
+MMBroadbandModemMbimXmmFibocom *
+mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device,
+ const gchar **drivers,
+ const gchar *plugin,
+ guint16 vendor_id,
+ guint16 product_id)
+{
+ return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM,
+ MM_BASE_MODEM_DEVICE, device,
+ MM_BASE_MODEM_DRIVERS, drivers,
+ MM_BASE_MODEM_PLUGIN, plugin,
+ MM_BASE_MODEM_VENDOR_ID, vendor_id,
+ MM_BASE_MODEM_PRODUCT_ID, product_id,
+ /* MBIM bearer supports NET only */
+ MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE,
+ MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE,
+ MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE,
+ MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED, FALSE,
+ MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE,
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
+ MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE,
+#endif
+ NULL);
+}
+
+static void
+mm_broadband_modem_mbim_xmm_fibocom_init (MMBroadbandModemMbimXmmFibocom *self)
+{
+}
+
+static void
+iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
+{
+ iface_modem_3gpp_parent = g_type_interface_peek_parent (iface);
+
+ iface->set_initial_eps_bearer_settings = modem_3gpp_set_initial_eps_bearer_settings;
+ iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish;
+}
+
+static void
+mm_broadband_modem_mbim_xmm_fibocom_class_init (MMBroadbandModemMbimXmmFibocomClass *klass)
+{
+}
diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h
new file mode 100755
index 0000000..db51cfc
--- /dev/null
+++ b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2022 Fibocom Wireless Inc.
+ */
+
+#ifndef MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H
+#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H
+
+#include "mm-broadband-modem-mbim-xmm.h"
+
+#define MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM (mm_broadband_modem_mbim_xmm_fibocom_get_type ())
+#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocom))
+#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass))
+#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM))
+#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM))
+#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass))
+
+typedef struct _MMBroadbandModemMbimXmmFibocom MMBroadbandModemMbimXmmFibocom;
+typedef struct _MMBroadbandModemMbimXmmFibocomClass MMBroadbandModemMbimXmmFibocomClass;
+
+struct _MMBroadbandModemMbimXmmFibocom {
+ MMBroadbandModemMbimXmm parent;
+};
+
+struct _MMBroadbandModemMbimXmmFibocomClass{
+ MMBroadbandModemMbimXmmClass parent;
+};
+
+GType mm_broadband_modem_mbim_xmm_fibocom_get_type (void);
+
+MMBroadbandModemMbimXmmFibocom *mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device,
+ const gchar **drivers,
+ const gchar *plugin,
+ guint16 vendor_id,
+ guint16 product_id);
+
+#endif /* MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H */
diff --git a/plugins/fibocom/mm-plugin-fibocom.c b/plugins/fibocom/mm-plugin-fibocom.c
index 1ff9f17..a9816d9 100644
--- a/plugins/fibocom/mm-plugin-fibocom.c
+++ b/plugins/fibocom/mm-plugin-fibocom.c
@@ -23,10 +23,12 @@
#include "mm-plugin-fibocom.h"
#include "mm-broadband-modem.h"
#include "mm-broadband-modem-xmm.h"
+#include "mm-broadband-modem-fibocom.h"
#if defined WITH_MBIM
#include "mm-broadband-modem-mbim.h"
#include "mm-broadband-modem-mbim-xmm.h"
+#include "mm-broadband-modem-mbim-xmm-fibocom.h"
#endif
#if defined WITH_QMI
@@ -53,11 +55,11 @@
if (mm_port_probe_list_has_mbim_port (probes)) {
if (mm_port_probe_list_is_xmm (probes)) {
mm_obj_dbg (self, "MBIM-powered XMM-based Fibocom modem found...");
- return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_new (uid,
- drivers,
- mm_plugin_get_name (self),
- vendor,
- product));
+ return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_fibocom_new (uid,
+ drivers,
+ mm_plugin_get_name (self),
+ vendor,
+ product));
}
mm_obj_dbg (self, "MBIM-powered Fibocom modem found...");
return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid,
@@ -89,11 +91,11 @@
}
mm_obj_dbg (self, "Fibocom modem found...");
- return MM_BASE_MODEM (mm_broadband_modem_new (uid,
- drivers,
- mm_plugin_get_name (self),
- vendor,
- product));
+ return MM_BASE_MODEM (mm_broadband_modem_fibocom_new (uid,
+ drivers,
+ mm_plugin_get_name (self),
+ vendor,
+ product));
}
/*****************************************************************************/
@@ -102,8 +104,8 @@
mm_plugin_create (void)
{
static const gchar *subsystems[] = { "tty", "net", "usbmisc", NULL };
- static const guint16 vendor_ids[] = { 0x2cb7, 0 };
- static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", NULL };
+ static const guint16 vendor_ids[] = { 0x2cb7, 0x1782, 0 };
+ static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", "cdc_ether", NULL };
return MM_PLUGIN (
g_object_new (MM_TYPE_PLUGIN_FIBOCOM,
diff --git a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c b/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c
index de69457..22ab0be 100644
--- a/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c
+++ b/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c
@@ -33,21 +33,21 @@
#include "mm-iface-modem-location.h"
#include "mm-broadband-modem-mbim-foxconn.h"
-#if defined WITH_QMI
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
# include "mm-iface-modem-firmware.h"
# include "mm-shared-qmi.h"
#endif
static void iface_modem_location_init (MMIfaceModemLocation *iface);
-#if defined WITH_QMI
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
#endif
static MMIfaceModemLocation *iface_modem_location_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimFoxconn, mm_broadband_modem_mbim_foxconn, MM_TYPE_BROADBAND_MODEM_MBIM, 0,
-#if defined WITH_QMI
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)
#endif
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init))
@@ -63,7 +63,7 @@
};
-#if defined WITH_QMI
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
/*****************************************************************************/
/* Firmware update settings
@@ -497,7 +497,7 @@
iface->disable_location_gathering_finish = disable_location_gathering_finish;
}
-#if defined WITH_QMI
+#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
static void
iface_modem_firmware_init (MMIfaceModemFirmware *iface)
diff --git a/plugins/meson.build b/plugins/meson.build
index ea40eba..6bcb364 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -21,7 +21,7 @@
sources: sources,
include_directories: top_inc,
dependencies: deps + [gio_unix_dep],
- c_args: '-DTEST_SERVICES="@0@"'.format(source_root / 'data/tests'),
+ c_args: '-DTEST_SERVICES="@0@"'.format(build_root / 'data/tests'),
)
libmm_test_common_dep = declare_dependency(
@@ -337,9 +337,17 @@
'-DTESTUDEVRULESDIR_FIBOCOM="@0@"'.format(plugins_dir / 'fibocom'),
]
+ sources = files(
+ 'fibocom/mm-broadband-bearer-fibocom-ecm.c',
+ 'fibocom/mm-broadband-modem-fibocom.c',
+ 'fibocom/mm-plugin-fibocom.c',
+ )
+ if enable_mbim
+ sources += files('fibocom/mm-broadband-modem-mbim-xmm-fibocom.c')
+ endif
plugins += {'plugin-fibocom': {
'plugin': true,
- 'module': {'sources': files('fibocom/mm-plugin-fibocom.c'), 'include_directories': plugins_incs + [xmm_inc], 'c_args': c_args},
+ 'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc], 'c_args': c_args},
}}
plugins_udev_rules += files('fibocom/77-mm-fibocom-port-types.rules')
@@ -368,24 +376,6 @@
# plugin: generic
if plugins_options['generic']
- # FIXME
- '''
- 15/16 test-service-generic FAIL 0.02s killed by signal 5 SIGTRAP
- >>> MALLOC_PERTURB_=124 /ModemManager/_build/plugins/test-service-generic
- ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― ✀ ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
- stdout:
- # random seed: R02S5d0d577043f61f2806f319a6510e83a4
- 1..1
- # Start of MM tests
- # Start of Service tests
- # Start of Generic tests
- Bail out! FATAL-ERROR: Error starting ModemManager in test bus: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.ModemManager1 was not provided by any .service files
- stderr:
-
- ** (/ModemManager/_build/plugins/test-service-generic:36444): ERROR **: 21:06:16.248: Error starting ModemManager in test bus: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.ModemManager1 was not provided by any .service files
- cleaning up pid 36446
- '''
-
plugins += {'plugin-generic': {
'plugin': true,
'module': {'sources': files('generic/mm-plugin-generic.c'), 'include_directories': plugins_incs, 'c_args': '-DMM_MODULE_NAME="generic"'},
diff --git a/plugins/quectel/77-mm-quectel-port-types.rules b/plugins/quectel/77-mm-quectel-port-types.rules
index ce49416..65993a2 100644
--- a/plugins/quectel/77-mm-quectel-port-types.rules
+++ b/plugins/quectel/77-mm-quectel-port-types.rules
@@ -1,9 +1,10 @@
# do not edit this file, it will be overwritten on update
-ACTION!="add|change|move|bind", GOTO="mm_quectel_port_types_end"
-SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c7c", GOTO="mm_quectel_port_types"
-GOTO="mm_quectel_port_types_end"
+ACTION!="add|change|move|bind", GOTO="mm_quectel_end"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="2c7c", GOTO="mm_quectel_usb"
+SUBSYSTEMS=="pci", ATTRS{vendor}=="0x1eac", GOTO="mm_quectel_pci"
+GOTO="mm_quectel_end"
-LABEL="mm_quectel_port_types"
+LABEL="mm_quectel_usb"
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
@@ -67,4 +68,18 @@
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0800", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
-LABEL="mm_quectel_port_types_end"
+# Quectel EM05-G and EM05-CE with firehose support
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030a", ENV{ID_MM_QUECTEL_FIREHOSE}="1"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="030a", ENV{ID_MM_QUECTEL_SAHARA}="1"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0127", ENV{ID_MM_QUECTEL_FIREHOSE}="1"
+ATTRS{idVendor}=="2c7c", ATTRS{idProduct}=="0127", ENV{ID_MM_QUECTEL_SAHARA}="1"
+
+GOTO="mm_quectel_end"
+
+LABEL="mm_quectel_pci"
+
+# Quectel EM120 and EM160 with firehose support
+ATTRS{vendor}=="0x1eac", ATTRS{device}=="0x1001", ENV{ID_MM_QUECTEL_FIREHOSE}="1"
+ATTRS{vendor}=="0x1eac", ATTRS{device}=="0x1002", ENV{ID_MM_QUECTEL_FIREHOSE}="1"
+
+LABEL="mm_quectel_end"
diff --git a/plugins/quectel/mm-broadband-modem-mbim-quectel.c b/plugins/quectel/mm-broadband-modem-mbim-quectel.c
index 2874e54..b3a3300 100644
--- a/plugins/quectel/mm-broadband-modem-mbim-quectel.c
+++ b/plugins/quectel/mm-broadband-modem-mbim-quectel.c
@@ -35,51 +35,6 @@
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init))
/*****************************************************************************/
-/* Firmware update settings */
-
-static MMFirmwareUpdateSettings *
-firmware_load_update_settings_finish (MMIfaceModemFirmware *self,
- GAsyncResult *res,
- GError **error)
-{
- return g_task_propagate_pointer (G_TASK (res), error);
-}
-
-static void
-quectel_get_firmware_version_ready (MMBaseModem *modem,
- GAsyncResult *res,
- GTask *task)
-{
- MMFirmwareUpdateSettings *update_settings;
- const gchar *version;
-
- update_settings = mm_firmware_update_settings_new (MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE);
-
- version = mm_base_modem_at_command_finish (modem, res, NULL);
- if (version)
- mm_firmware_update_settings_set_version (update_settings, version);
- g_task_return_pointer (task, update_settings, g_object_unref);
- g_object_unref (task);
-}
-
-static void
-firmware_load_update_settings (MMIfaceModemFirmware *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GTask *task;
-
- task = g_task_new (self, NULL, callback, user_data);
-
- mm_base_modem_at_command (MM_BASE_MODEM (self),
- "+QGMR?",
- 3,
- FALSE,
- (GAsyncReadyCallback) quectel_get_firmware_version_ready,
- task);
-}
-
-/*****************************************************************************/
MMBroadbandModemMbimQuectel *
mm_broadband_modem_mbim_quectel_new (const gchar *device,
@@ -110,8 +65,8 @@
static void
iface_modem_firmware_init (MMIfaceModemFirmware *iface)
{
- iface->load_update_settings = firmware_load_update_settings;
- iface->load_update_settings_finish = firmware_load_update_settings_finish;
+ iface->load_update_settings = mm_shared_quectel_firmware_load_update_settings;
+ iface->load_update_settings_finish = mm_shared_quectel_firmware_load_update_settings_finish;
}
static void
diff --git a/plugins/quectel/mm-broadband-modem-qmi-quectel.c b/plugins/quectel/mm-broadband-modem-qmi-quectel.c
index 8cb290c..676006f 100644
--- a/plugins/quectel/mm-broadband-modem-qmi-quectel.c
+++ b/plugins/quectel/mm-broadband-modem-qmi-quectel.c
@@ -52,6 +52,8 @@
MM_BASE_MODEM_PLUGIN, plugin,
MM_BASE_MODEM_VENDOR_ID, vendor_id,
MM_BASE_MODEM_PRODUCT_ID, product_id,
+ /* exclude carrier information */
+ MM_IFACE_MODEM_FIRMWARE_IGNORE_CARRIER, TRUE,
/* QMI bearer supports NET only */
MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE,
MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE,
diff --git a/plugins/quectel/mm-plugin-quectel.c b/plugins/quectel/mm-plugin-quectel.c
index 4550615..9a7a1c6 100644
--- a/plugins/quectel/mm-plugin-quectel.c
+++ b/plugins/quectel/mm-plugin-quectel.c
@@ -61,21 +61,12 @@
#if defined WITH_MBIM
if (mm_port_probe_list_has_mbim_port (probes)) {
- if (vendor == 0x1eac) {
- mm_obj_dbg (self, "MBIM-powered PCI Quectel modem found...");
- return MM_BASE_MODEM (mm_broadband_modem_mbim_quectel_new (uid,
- drivers,
- mm_plugin_get_name (self),
- vendor,
- product));
- } else {
- mm_obj_dbg (self, "MBIM-powered Quectel modem found...");
- return MM_BASE_MODEM (mm_broadband_modem_mbim_new (uid,
- drivers,
- mm_plugin_get_name (self),
- vendor,
- product));
- }
+ mm_obj_dbg (self, "MBIM-powered Quectel modem found...");
+ return MM_BASE_MODEM (mm_broadband_modem_mbim_quectel_new (uid,
+ drivers,
+ mm_plugin_get_name (self),
+ vendor,
+ product));
}
#endif
diff --git a/plugins/quectel/mm-shared-quectel.c b/plugins/quectel/mm-shared-quectel.c
index f8ccbbe..547775b 100644
--- a/plugins/quectel/mm-shared-quectel.c
+++ b/plugins/quectel/mm-shared-quectel.c
@@ -30,6 +30,10 @@
#include "mm-shared-quectel.h"
#include "mm-modem-helpers-quectel.h"
+#if defined WITH_MBIM
+#include "mm-broadband-modem-mbim.h"
+#endif
+
/*****************************************************************************/
/* Private context */
@@ -143,6 +147,78 @@
return g_task_propagate_pointer (G_TASK (res), error);
}
+static gboolean
+quectel_is_sahara_supported (MMBaseModem *modem,
+ MMPort *port)
+{
+ return mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_QUECTEL_SAHARA");
+}
+
+static gboolean
+quectel_is_firehose_supported (MMBaseModem *modem,
+ MMPort *port)
+{
+ return mm_kernel_device_get_global_property_as_boolean (mm_port_peek_kernel_device (port), "ID_MM_QUECTEL_FIREHOSE");
+}
+
+static MMModemFirmwareUpdateMethod
+quectel_get_firmware_update_methods (MMBaseModem *modem,
+ MMPort *port)
+{
+ MMModemFirmwareUpdateMethod update_methods;
+
+ update_methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE;
+
+ if (quectel_is_firehose_supported (modem, port))
+ update_methods |= MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE;
+ if (quectel_is_sahara_supported (modem, port))
+ update_methods |= MM_MODEM_FIRMWARE_UPDATE_METHOD_SAHARA;
+
+ return update_methods;
+}
+
+static void
+quectel_at_port_get_firmware_version_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMFirmwareUpdateSettings *update_settings;
+ const gchar *version;
+
+ update_settings = g_task_get_task_data (task);
+
+ version = mm_base_modem_at_command_finish (modem, res, NULL);
+ if (version)
+ mm_firmware_update_settings_set_version (update_settings, version);
+
+ g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref);
+ g_object_unref (task);
+}
+
+#if defined WITH_MBIM
+static void
+quectel_mbim_port_get_firmware_version_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autoptr(MbimMessage) response = NULL;
+ guint32 version_id;
+ g_autofree gchar *version_str = NULL;
+ MMFirmwareUpdateSettings *update_settings;
+
+ update_settings = g_task_get_task_data (task);
+
+ response = mbim_device_command_finish (device, res, NULL);
+ if (response && mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, NULL) &&
+ mbim_message_qdu_quectel_read_version_response_parse (response, &version_id, &version_str, NULL)) {
+ mm_firmware_update_settings_set_version (update_settings, version_str);
+ }
+
+ g_task_return_pointer (task, g_object_ref (update_settings), g_object_unref);
+ g_object_unref (task);
+}
+#endif
+
static void
qfastboot_test_ready (MMBaseModem *self,
GAsyncResult *res,
@@ -150,15 +226,78 @@
{
MMFirmwareUpdateSettings *update_settings;
- if (!mm_base_modem_at_command_finish (self, res, NULL))
- update_settings = mm_firmware_update_settings_new (MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE);
- else {
- update_settings = mm_firmware_update_settings_new (MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT);
+ update_settings = g_task_get_task_data (task);
+
+ /* Set update method */
+ if (mm_base_modem_at_command_finish (self, res, NULL)) {
+ mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT);
mm_firmware_update_settings_set_fastboot_at (update_settings, "AT+QFASTBOOT");
+ } else
+ mm_firmware_update_settings_set_method (update_settings, MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE);
+
+ /* Fetch full firmware info */
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+QGMR?",
+ 3,
+ FALSE,
+ (GAsyncReadyCallback) quectel_at_port_get_firmware_version_ready,
+ task);
+}
+
+static void
+quectel_at_port_get_firmware_revision_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMFirmwareUpdateSettings *update_settings;
+ MMModemFirmwareUpdateMethod update_methods;
+ const gchar *revision;
+ const gchar *name;
+ const gchar *id;
+ g_autoptr(GPtrArray) ids = NULL;
+ GError *error = NULL;
+
+ update_settings = g_task_get_task_data (task);
+ update_methods = mm_firmware_update_settings_get_method (update_settings);
+
+ /* Set device ids */
+ ids = mm_iface_firmware_build_generic_device_ids (MM_IFACE_MODEM_FIRMWARE (self), &error);
+ if (error) {
+ mm_obj_warn (self, "failed to build generic device ids: %s", error->message);
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
- g_task_return_pointer (task, update_settings, g_object_unref);
- g_object_unref (task);
+ /* Add device id based on modem name */
+ revision = mm_base_modem_at_command_finish (self, res, NULL);
+ if (revision && g_utf8_validate (revision, -1, NULL)) {
+ name = g_strndup (revision, 7);
+ mm_obj_dbg (self, "revision %s converted to modem name %s", revision, name);
+ id = (const gchar *) g_ptr_array_index (ids, 0);
+ g_ptr_array_insert (ids, 0, g_strdup_printf ("%s&NAME_%s", id, name));
+ }
+
+ mm_firmware_update_settings_set_device_ids (update_settings, (const gchar **)ids->pdata);
+
+ /* Set update methods */
+ if (update_methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FIREHOSE) {
+ /* Fetch full firmware info */
+ mm_base_modem_at_command (self,
+ "+QGMR?",
+ 3,
+ TRUE,
+ (GAsyncReadyCallback) quectel_at_port_get_firmware_version_ready,
+ task);
+ } else {
+ /* Check fastboot support */
+ mm_base_modem_at_command (self,
+ "AT+QFASTBOOT=?",
+ 3,
+ TRUE,
+ (GAsyncReadyCallback) qfastboot_test_ready,
+ task);
+ }
}
void
@@ -167,14 +306,58 @@
gpointer user_data)
{
GTask *task;
+ MMPortSerialAt *at_port;
+ MMModemFirmwareUpdateMethod update_methods;
+ MMFirmwareUpdateSettings *update_settings;
+#if defined WITH_MBIM
+ MMPortMbim *mbim;
+#endif
task = g_task_new (self, NULL, callback, user_data);
- mm_base_modem_at_command (MM_BASE_MODEM (self),
- "AT+QFASTBOOT=?",
- 3,
- TRUE,
- (GAsyncReadyCallback)qfastboot_test_ready,
- task);
+
+ at_port = mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL);
+ if (at_port) {
+ update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (at_port));
+ update_settings = mm_firmware_update_settings_new (update_methods);
+ g_task_set_task_data (task, update_settings, g_object_unref);
+
+ /* Fetch modem name */
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CGMR",
+ 3,
+ TRUE,
+ (GAsyncReadyCallback) quectel_at_port_get_firmware_revision_ready,
+ task);
+
+ return;
+ }
+
+#if defined WITH_MBIM
+ mbim = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self));
+ if (mbim) {
+ g_autoptr(MbimMessage) message = NULL;
+
+ update_methods = quectel_get_firmware_update_methods (MM_BASE_MODEM (self), MM_PORT (mbim));
+ update_settings = mm_firmware_update_settings_new (update_methods);
+
+ /* Fetch firmware info */
+ g_task_set_task_data (task, update_settings, g_object_unref);
+ message = mbim_message_qdu_quectel_read_version_set_new (MBIM_QDU_QUECTEL_VERSION_TYPE_FW_BUILD_ID, NULL);
+ mbim_device_command (mm_port_mbim_peek_device (mbim),
+ message,
+ 5,
+ NULL,
+ (GAsyncReadyCallback) quectel_mbim_port_get_firmware_version_ready,
+ task);
+ return;
+ }
+#endif
+
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't find a port to fetch firmware info");
+ g_object_unref (task);
}
/*****************************************************************************/
diff --git a/plugins/telit/77-mm-telit-port-types.rules b/plugins/telit/77-mm-telit-port-types.rules
index 212cce4..9ecc3f3 100644
--- a/plugins/telit/77-mm-telit-port-types.rules
+++ b/plugins/telit/77-mm-telit-port-types.rules
@@ -34,6 +34,18 @@
# CE910-DUAL
ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1011", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
+# LE910C1-EUX
+# The following port is ignored since it's a diagnostic port
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1031", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
+
+# LE910C1-EUX (ECM composition)
+# The following port is ignored since it's a diagnostic port
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="01", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
+ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1033", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
+
# LE922, LM9x0
ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="00", ENV{ID_MM_PORT_IGNORE}="1"
ATTRS{idVendor}=="1bc7", ATTRS{idProduct}=="1040", ENV{.MM_USBIFNUM}=="03", ENV{ID_MM_PORT_IGNORE}="1"
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 134f197..3a09257 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -121,6 +121,7 @@
gboolean is_pco_supported;
gboolean is_lte_attach_info_supported;
gboolean is_nr5g_registration_settings_supported;
+ gboolean is_base_stations_info_supported;
gboolean is_ussd_supported;
gboolean is_atds_location_supported;
gboolean is_atds_signal_supported;
@@ -168,6 +169,8 @@
/* Multi-SIM support */
guint32 executor_index;
guint active_slot_index;
+
+ MMUnlockRetries *unlock_retries;
};
/*****************************************************************************/
@@ -1653,51 +1656,14 @@
NULL,
&remaining_attempts,
&error)) {
- MMIfaceModem *self;
+ MMBroadbandModemMbim *self;
MMModemLock lock;
- MMUnlockRetries *retries;
- self = g_task_get_source_object (task);
+ self = MM_BROADBAND_MODEM_MBIM (g_task_get_source_object (task));
lock = mm_modem_lock_from_mbim_pin_type (pin_type);
- retries = mm_unlock_retries_new ();
- /* If PIN1 is disabled and we have tried to enable it with a wrong PIN,
- * the modem would have indicated the number of remaining attempts for
- * PIN1 (unless PUK1 is engaged) in the response to the failed
- * MBIM_CID_PIN set operation. Thus, MMSimMbim would have updated
- * MMIfaceModem's MMUnlockRetries with information about PIN1.
- *
- * However, a MBIM_CID_PIN query may be issued (e.g. MMBaseSim calls
- * mm_iface_modem_update_lock_info()) after the MBIM_CID_PIN set
- * operation to query the number of remaining attempts for a PIN type.
- * Unfortunately, we can't specify a particular PIN type in a
- * MBIM_CID_PIN query. The modem may not reply with information about
- * PIN1 if PIN1 is disabled. When that happens, we would like to
- * preserve our knowledge about the number of remaining attempts for
- * PIN1. Here we thus carry over any existing information on PIN1 from
- * MMIfaceModem's MMUnlockRetries if the MBIM_CID_PIN query reports
- * something other than PIN1. */
- if (lock != MM_MODEM_LOCK_SIM_PIN) {
- MMUnlockRetries *previous_retries;
- guint previous_sim_pin_retries;
-
- previous_retries = mm_iface_modem_get_unlock_retries (self);
- previous_sim_pin_retries = mm_unlock_retries_get (previous_retries,
- MM_MODEM_LOCK_SIM_PIN);
- if (previous_sim_pin_retries != MM_UNLOCK_RETRIES_UNKNOWN) {
- mm_unlock_retries_set (retries,
- MM_MODEM_LOCK_SIM_PIN,
- previous_sim_pin_retries);
- }
- g_object_unref (previous_retries);
- }
-
- /* According to the MBIM specification, RemainingAttempts is set to
- * 0xffffffff if the device does not support this information. */
- if (remaining_attempts != G_MAXUINT32)
- mm_unlock_retries_set (retries, lock, remaining_attempts);
-
- g_task_return_pointer (task, retries, g_object_unref);
+ mm_broadband_modem_mbim_set_unlock_retries (self, lock, remaining_attempts);
+ g_task_return_pointer (task, g_object_ref (self->priv->unlock_retries), g_object_unref);
} else
g_task_return_error (task, error);
@@ -1731,6 +1697,24 @@
mbim_message_unref (message);
}
+void
+mm_broadband_modem_mbim_set_unlock_retries (MMBroadbandModemMbim *self,
+ MMModemLock lock_type,
+ guint32 remaining_attempts)
+{
+ g_assert (MM_IS_BROADBAND_MODEM_MBIM (self));
+
+ if (!self->priv->unlock_retries)
+ self->priv->unlock_retries = mm_unlock_retries_new ();
+
+ /* According to the MBIM specification, RemainingAttempts is set to
+ * 0xffffffff if the device does not support this information. */
+ if (remaining_attempts != G_MAXUINT32)
+ mm_unlock_retries_set (self->priv->unlock_retries,
+ lock_type,
+ remaining_attempts);
+}
+
/*****************************************************************************/
/* Own numbers loading */
@@ -2234,6 +2218,400 @@
}
/*****************************************************************************/
+/* Cell info retrieval */
+
+static GList *
+modem_get_cell_info_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+cell_info_list_free (GList *list)
+{
+ g_list_free_full (list, (GDestroyNotify)g_object_unref);
+}
+
+static void
+base_stations_info_query_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBroadbandModemMbim *self;
+ g_autoptr(MbimMessage) response = NULL;
+ GError *error = NULL;
+ GList *list = NULL;
+ MMCellInfo *info = NULL;
+ g_autoptr(MbimCellInfoServingGsm) gsm_serving_cell = NULL;
+ g_autoptr(MbimCellInfoServingUmts) umts_serving_cell = NULL;
+ g_autoptr(MbimCellInfoServingTdscdma) tdscdma_serving_cell = NULL;
+ g_autoptr(MbimCellInfoServingLte) lte_serving_cell = NULL;
+ guint32 gsm_neighboring_cells_count = 0;
+ g_autoptr(MbimCellInfoNeighboringGsmArray) gsm_neighboring_cells = NULL;
+ guint32 umts_neighboring_cells_count = 0;
+ g_autoptr(MbimCellInfoNeighboringUmtsArray) umts_neighboring_cells = NULL;
+ guint32 tdscdma_neighboring_cells_count = 0;
+ g_autoptr(MbimCellInfoNeighboringTdscdmaArray) tdscdma_neighboring_cells = NULL;
+ guint32 lte_neighboring_cells_count = 0;
+ g_autoptr(MbimCellInfoNeighboringLteArray) lte_neighboring_cells = NULL;
+ guint32 cdma_cells_count = 0;
+ g_autoptr(MbimCellInfoCdmaArray) cdma_cells = NULL;
+ guint32 nr_serving_cells_count = 0;
+ g_autoptr(MbimCellInfoServingNrArray) nr_serving_cells = NULL;
+ guint32 nr_neighboring_cells_count = 0;
+ g_autoptr(MbimCellInfoNeighboringNrArray) nr_neighboring_cells = NULL;
+
+ self = g_task_get_source_object (task);
+
+ response = mbim_device_command_finish (device, res, &error);
+ if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ /* MBIMEx 3.0 support */
+ if (mbim_device_check_ms_mbimex_version (device, 3, 0)) {
+ if (!mbim_message_ms_basic_connect_extensions_v3_base_stations_info_response_parse (
+ response,
+ NULL, /* system_type_v3 */
+ NULL, /* system_subtype */
+ &gsm_serving_cell,
+ &umts_serving_cell,
+ &tdscdma_serving_cell,
+ <e_serving_cell,
+ &gsm_neighboring_cells_count,
+ &gsm_neighboring_cells,
+ &umts_neighboring_cells_count,
+ &umts_neighboring_cells,
+ &tdscdma_neighboring_cells_count,
+ &tdscdma_neighboring_cells,
+ <e_neighboring_cells_count,
+ <e_neighboring_cells,
+ &cdma_cells_count,
+ &cdma_cells,
+ &nr_serving_cells_count,
+ &nr_serving_cells,
+ &nr_neighboring_cells_count,
+ &nr_neighboring_cells,
+ &error))
+ g_prefix_error (&error, "Failed processing MBIMEx v3.0 base stations info response: ");
+ else
+ mm_obj_dbg (self, "processed MBIMEx v3.0 base stations info response");
+ }
+ /* MBIMEx 1.0 support */
+ else {
+ if (!mbim_message_ms_basic_connect_extensions_base_stations_info_response_parse (
+ response,
+ NULL, /* system_type */
+ &gsm_serving_cell,
+ &umts_serving_cell,
+ &tdscdma_serving_cell,
+ <e_serving_cell,
+ &gsm_neighboring_cells_count,
+ &gsm_neighboring_cells,
+ &umts_neighboring_cells_count,
+ &umts_neighboring_cells,
+ &tdscdma_neighboring_cells_count,
+ &tdscdma_neighboring_cells,
+ <e_neighboring_cells_count,
+ <e_neighboring_cells,
+ &cdma_cells_count,
+ &cdma_cells,
+ &error))
+ g_prefix_error (&error, "Failed processing MBIMEx v1.0 base stations info response: ");
+ else
+ mm_obj_dbg (self, "processed MBIMEx v1.0 base stations info response");
+ }
+
+ if (error) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+#define CELL_INFO_SET_STR(VALUE, SETTER, CELL_TYPE) do { \
+ if (VALUE) { \
+ mm_cell_info_##SETTER (CELL_TYPE (info), VALUE); \
+ } \
+ } while (0)
+
+#define CELL_INFO_SET_HEXSTR(VALUE, UNKNOWN, MODIFIER, SETTER, CELL_TYPE) do { \
+ if (VALUE != UNKNOWN) { \
+ g_autofree gchar *str = NULL; \
+ \
+ str = g_strdup_printf ("%" MODIFIER "X", VALUE); \
+ mm_cell_info_##SETTER (CELL_TYPE (info), str); \
+ } \
+ } while (0)
+
+#define CELL_INFO_SET_UINT(VALUE, UNKNOWN, SETTER, CELL_TYPE) do { \
+ if (VALUE != UNKNOWN) { \
+ mm_cell_info_##SETTER (CELL_TYPE (info), VALUE); \
+ } \
+ } while (0)
+
+#define CELL_INFO_SET_INT_DOUBLE(VALUE, UNKNOWN, SETTER, CELL_TYPE) do { \
+ if (VALUE != (gint)UNKNOWN) { \
+ mm_cell_info_##SETTER (CELL_TYPE (info), (gdouble)VALUE); \
+ } \
+ } while (0)
+
+#define CELL_INFO_SET_UINT_DOUBLE_SCALED(VALUE, UNKNOWN, SCALE, SETTER, CELL_TYPE) do { \
+ if (VALUE != UNKNOWN) { \
+ mm_cell_info_##SETTER (CELL_TYPE (info), (gdouble)(VALUE + SCALE)); \
+ } \
+ } while (0)
+
+ if (gsm_serving_cell) {
+ info = mm_cell_info_gsm_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, TRUE);
+
+ CELL_INFO_SET_STR (gsm_serving_cell->provider_id, gsm_set_operator_id, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_serving_cell->location_area_code, 0xFFFFFFFF, "", gsm_set_lac, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_serving_cell->cell_id, 0xFFFFFFFF, "", gsm_set_ci, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_UINT (gsm_serving_cell->timing_advance, 0xFFFFFFFF, gsm_set_timing_advance, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_UINT (gsm_serving_cell->arfcn, 0xFFFFFFFF, gsm_set_arfcn, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_serving_cell->base_station_id, 0xFFFFFFFF, "", gsm_set_base_station_id, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_UINT (gsm_serving_cell->rx_level, 0xFFFFFFFF, gsm_set_rx_level, MM_CELL_INFO_GSM);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+
+ if (gsm_neighboring_cells_count && gsm_neighboring_cells) {
+ guint i;
+
+ for (i = 0; i < gsm_neighboring_cells_count; i++) {
+ info = mm_cell_info_gsm_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, FALSE);
+
+ CELL_INFO_SET_STR (gsm_neighboring_cells[i]->provider_id, gsm_set_operator_id, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", gsm_set_lac, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", gsm_set_ci, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_UINT (gsm_neighboring_cells[i]->arfcn, 0xFFFFFFFF, gsm_set_arfcn, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_HEXSTR (gsm_neighboring_cells[i]->base_station_id, 0xFFFFFFFF, "", gsm_set_base_station_id, MM_CELL_INFO_GSM);
+ CELL_INFO_SET_UINT (gsm_neighboring_cells[i]->rx_level, 0xFFFFFFFF, gsm_set_rx_level, MM_CELL_INFO_GSM);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (umts_serving_cell) {
+ info = mm_cell_info_umts_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, TRUE);
+
+ CELL_INFO_SET_STR (umts_serving_cell->provider_id, umts_set_operator_id, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_HEXSTR (umts_serving_cell->location_area_code, 0xFFFFFFFF, "", umts_set_lac, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_HEXSTR (umts_serving_cell->cell_id, 0xFFFFFFFF, "", umts_set_ci, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_ul, 0xFFFFFFFF, umts_set_frequency_fdd_ul, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_dl, 0xFFFFFFFF, umts_set_frequency_fdd_dl, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->frequency_info_nt, 0xFFFFFFFF, umts_set_frequency_tdd, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->uarfcn, 0xFFFFFFFF, umts_set_uarfcn, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->primary_scrambling_code, 0xFFFFFFFF, umts_set_psc, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_INT_DOUBLE (umts_serving_cell->rscp, 0, umts_set_rscp, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_INT_DOUBLE (umts_serving_cell->ecno, 1, umts_set_ecio, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_serving_cell->path_loss, 0xFFFFFFFF, umts_set_path_loss, MM_CELL_INFO_UMTS);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+
+ if (umts_neighboring_cells_count && umts_neighboring_cells) {
+ guint i;
+
+ for (i = 0; i < umts_neighboring_cells_count; i++) {
+ info = mm_cell_info_umts_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, FALSE);
+
+ CELL_INFO_SET_STR (umts_neighboring_cells[i]->provider_id, umts_set_operator_id, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_HEXSTR (umts_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", umts_set_lac, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_HEXSTR (umts_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", umts_set_ci, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, umts_set_uarfcn, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_neighboring_cells[i]->primary_scrambling_code, 0xFFFFFFFF, umts_set_psc, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_INT_DOUBLE (umts_neighboring_cells[i]->rscp, 0, umts_set_rscp, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_INT_DOUBLE (umts_neighboring_cells[i]->ecno, 1, umts_set_ecio, MM_CELL_INFO_UMTS);
+ CELL_INFO_SET_UINT (umts_neighboring_cells[i]->path_loss, 0xFFFFFFFF, umts_set_path_loss, MM_CELL_INFO_UMTS);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (tdscdma_serving_cell) {
+ info = mm_cell_info_tdscdma_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, TRUE);
+
+ CELL_INFO_SET_STR (tdscdma_serving_cell->provider_id, tdscdma_set_operator_id, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_HEXSTR (tdscdma_serving_cell->location_area_code, 0xFFFFFFFF, "", tdscdma_set_lac, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_HEXSTR (tdscdma_serving_cell->cell_id, 0xFFFFFFFF, "", tdscdma_set_ci, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_serving_cell->uarfcn, 0xFFFFFFFF, tdscdma_set_uarfcn, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_serving_cell->cell_parameter_id, 0xFFFFFFFF, tdscdma_set_cell_parameter_id, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_serving_cell->timing_advance, 0xFFFFFFFF, tdscdma_set_timing_advance, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_INT_DOUBLE (tdscdma_serving_cell->rscp, 0xFFFFFFFF, tdscdma_set_rscp, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_serving_cell->path_loss, 0xFFFFFFFF, tdscdma_set_path_loss, MM_CELL_INFO_TDSCDMA);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+
+ if (tdscdma_neighboring_cells_count && tdscdma_neighboring_cells) {
+ guint i;
+
+ for (i = 0; i < tdscdma_neighboring_cells_count; i++) {
+ info = mm_cell_info_tdscdma_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, FALSE);
+
+ CELL_INFO_SET_STR (tdscdma_neighboring_cells[i]->provider_id, tdscdma_set_operator_id, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_HEXSTR (tdscdma_neighboring_cells[i]->location_area_code, 0xFFFFFFFF, "", tdscdma_set_lac, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_HEXSTR (tdscdma_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", tdscdma_set_ci, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->uarfcn, 0xFFFFFFFF, tdscdma_set_uarfcn, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->cell_parameter_id, 0xFFFFFFFF, tdscdma_set_cell_parameter_id, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->timing_advance, 0xFFFFFFFF, tdscdma_set_timing_advance, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_INT_DOUBLE (tdscdma_neighboring_cells[i]->rscp, 0xFFFFFFFF, tdscdma_set_rscp, MM_CELL_INFO_TDSCDMA);
+ CELL_INFO_SET_UINT (tdscdma_neighboring_cells[i]->path_loss, 0xFFFFFFFF, tdscdma_set_path_loss, MM_CELL_INFO_TDSCDMA);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (lte_serving_cell) {
+ info = mm_cell_info_lte_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, TRUE);
+
+ CELL_INFO_SET_STR (lte_serving_cell->provider_id, lte_set_operator_id, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_serving_cell->tac, 0xFFFFFFFF, "", lte_set_tac, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_serving_cell->cell_id, 0xFFFFFFFF, "", lte_set_ci, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_serving_cell->physical_cell_id, 0xFFFFFFFF, "", lte_set_physical_ci, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_UINT (lte_serving_cell->earfcn, 0xFFFFFFFF, lte_set_earfcn, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_INT_DOUBLE (lte_serving_cell->rsrp, 0xFFFFFFFF, lte_set_rsrp, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_INT_DOUBLE (lte_serving_cell->rsrq, 0xFFFFFFFF, lte_set_rsrq, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_UINT (lte_serving_cell->timing_advance, 0xFFFFFFFF, lte_set_timing_advance, MM_CELL_INFO_LTE);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+
+ if (lte_neighboring_cells_count && lte_neighboring_cells) {
+ guint i;
+
+ for (i = 0; i < lte_neighboring_cells_count; i++) {
+ info = mm_cell_info_lte_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, FALSE);
+
+ CELL_INFO_SET_STR (lte_neighboring_cells[i]->provider_id, lte_set_operator_id, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->tac, 0xFFFFFFFF, "", lte_set_tac, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->cell_id, 0xFFFFFFFF, "", lte_set_ci, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_HEXSTR (lte_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "", lte_set_physical_ci, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_UINT (lte_neighboring_cells[i]->earfcn, 0xFFFFFFFF, lte_set_earfcn, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_INT_DOUBLE (lte_neighboring_cells[i]->rsrp, 0xFFFFFFFF, lte_set_rsrp, MM_CELL_INFO_LTE);
+ CELL_INFO_SET_INT_DOUBLE (lte_neighboring_cells[i]->rsrq, 0xFFFFFFFF, lte_set_rsrq, MM_CELL_INFO_LTE);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (cdma_cells_count && cdma_cells) {
+ guint i;
+
+ for (i = 0; i < cdma_cells_count; i++) {
+ info = mm_cell_info_cdma_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, cdma_cells[i]->serving_cell_flag);
+
+ CELL_INFO_SET_HEXSTR (cdma_cells[i]->nid, 0xFFFFFFFF, "", cdma_set_nid, MM_CELL_INFO_CDMA);
+ CELL_INFO_SET_HEXSTR (cdma_cells[i]->sid, 0xFFFFFFFF, "", cdma_set_sid, MM_CELL_INFO_CDMA);
+ CELL_INFO_SET_HEXSTR (cdma_cells[i]->base_station_id, 0xFFFFFFFF, "", cdma_set_base_station_id, MM_CELL_INFO_CDMA);
+ CELL_INFO_SET_HEXSTR (cdma_cells[i]->ref_pn, 0xFFFFFFFF, "", cdma_set_ref_pn, MM_CELL_INFO_CDMA);
+ CELL_INFO_SET_UINT (cdma_cells[i]->pilot_strength, 0xFFFFFFFF, cdma_set_pilot_strength, MM_CELL_INFO_CDMA);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (nr_serving_cells_count && nr_serving_cells) {
+ guint i;
+
+ for (i = 0; i < nr_serving_cells_count; i++) {
+ info = mm_cell_info_nr5g_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, TRUE);
+
+ CELL_INFO_SET_STR (nr_serving_cells[i]->provider_id, nr5g_set_operator_id, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->tac, 0xFFFFFFFF, "", nr5g_set_tac, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->nci, 0xFFFFFFFFFFFFFFFF, G_GINT64_MODIFIER, nr5g_set_ci, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_HEXSTR (nr_serving_cells[i]->physical_cell_id, 0xFFFFFFFF, "", nr5g_set_physical_ci, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT (nr_serving_cells[i]->nrarfcn, 0xFFFFFFFF, nr5g_set_nrarfcn, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->rsrp, 0xFFFFFFFF, -156, nr5g_set_rsrp, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->rsrq, 0xFFFFFFFF, -43, nr5g_set_rsrq, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_serving_cells[i]->sinr, 0xFFFFFFFF, -23, nr5g_set_sinr, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT (nr_serving_cells[i]->timing_advance, 0xFFFFFFFFFFFFFFFF, nr5g_set_timing_advance, MM_CELL_INFO_NR5G);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+ if (nr_neighboring_cells_count && nr_neighboring_cells) {
+ guint i;
+
+ for (i = 0; i < nr_neighboring_cells_count; i++) {
+ info = mm_cell_info_nr5g_new_from_dictionary (NULL);
+ mm_cell_info_set_serving (info, FALSE);
+
+ CELL_INFO_SET_STR (nr_neighboring_cells[i]->provider_id, nr5g_set_operator_id, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_HEXSTR (nr_neighboring_cells[i]->tac, 0xFFFFFFFF, "", nr5g_set_tac, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_STR (nr_neighboring_cells[i]->cell_id, nr5g_set_ci, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_HEXSTR (nr_neighboring_cells[i]->physical_cell_id, 0xFFFFFFFF, "", nr5g_set_physical_ci, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->rsrp, 0xFFFFFFFF, -156, nr5g_set_rsrp, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->rsrq, 0xFFFFFFFF, -43, nr5g_set_rsrq, MM_CELL_INFO_NR5G);
+ CELL_INFO_SET_UINT_DOUBLE_SCALED (nr_neighboring_cells[i]->sinr, 0xFFFFFFFF, -23, nr5g_set_sinr, MM_CELL_INFO_NR5G);
+
+ list = g_list_append (list, g_steal_pointer (&info));
+ }
+ }
+
+#undef CELL_INFO_SET_STR
+#undef CELL_INFO_SET_HEXSTR
+#undef CELL_INFO_SET_UINT
+#undef CELL_INFO_SET_INT_DOUBLE
+#undef CELL_INFO_SET_UINT_DOUBLE_SCALED
+
+ g_task_return_pointer (task, list, (GDestroyNotify)cell_info_list_free);
+ g_object_unref (task);
+}
+
+static void
+modem_get_cell_info (MMIfaceModem *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
+ GTask *task;
+ MbimDevice *device;
+ MbimMessage *message;
+
+ if (!peek_device (self, &device, callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (!self->priv->is_base_stations_info_supported) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "base stations info is not supported");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Default capacity is 15 */
+ if (mbim_device_check_ms_mbimex_version (device, 3, 0))
+ message = mbim_message_ms_basic_connect_extensions_v3_base_stations_info_query_new (15, 15, 15, 15, 15, 15, NULL);
+ else
+ message = mbim_message_ms_basic_connect_extensions_base_stations_info_query_new (15, 15, 15, 15, 15, NULL);
+
+ mbim_device_command (device,
+ message,
+ 300,
+ NULL,
+ (GAsyncReadyCallback)base_stations_info_query_ready,
+ task);
+}
+
+/*****************************************************************************/
/* Create Bearer (Modem interface) */
static MMBaseBearer *
@@ -2635,6 +3013,9 @@
} else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_REGISTRATION_PARAMETERS) {
mm_obj_dbg (self, "5GNR registration settings are supported");
self->priv->is_nr5g_registration_settings_supported = TRUE;
+ } else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_BASE_STATIONS_INFO) {
+ mm_obj_dbg (self, "Base stations info is supported");
+ self->priv->is_base_stations_info_supported = TRUE;
} else if (device_services[i]->cids[j] == MBIM_CID_MS_BASIC_CONNECT_EXTENSIONS_PROVISIONED_CONTEXTS) {
if (mm_context_get_test_mbimex_profile_management ()) {
mm_obj_dbg (self, "Profile management extension is supported");
@@ -4306,10 +4687,19 @@
if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED)
mm_iface_modem_update_own_numbers (MM_IFACE_MODEM (self), telephone_numbers);
+ if ((self->priv->last_ready_state != MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE &&
+ ready_state == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE) ||
+ (self->priv->last_ready_state == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE &&
+ ready_state != MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE)) {
+ /* eSIM profiles have been added or removed, re-probe to ensure correct interfaces are exposed */
+ mm_obj_dbg (self, "eSIM profile updates detected");
+ mm_broadband_modem_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
+ }
+
if ((self->priv->last_ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED &&
ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) ||
(self->priv->last_ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED &&
- ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED)) {
+ ready_state != MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED)) {
/* SIM has been removed or reinserted, re-probe to ensure correct interfaces are exposed */
mm_obj_dbg (self, "SIM hot swap detected");
mm_broadband_modem_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
@@ -8640,6 +9030,8 @@
mm_port_mbim_close (mbim, NULL, NULL);
}
+ g_clear_object (&self->priv->unlock_retries);
+
G_OBJECT_CLASS (mm_broadband_modem_mbim_parent_class)->dispose (object);
}
@@ -8721,6 +9113,8 @@
/* Additional actions */
iface->load_signal_quality = modem_load_signal_quality;
iface->load_signal_quality_finish = modem_load_signal_quality_finish;
+ iface->get_cell_info = modem_get_cell_info;
+ iface->get_cell_info_finish = modem_get_cell_info_finish;
/* Unneeded things */
iface->modem_after_power_up = NULL;
diff --git a/src/mm-broadband-modem-mbim.h b/src/mm-broadband-modem-mbim.h
index 529b337..9e92390 100644
--- a/src/mm-broadband-modem-mbim.h
+++ b/src/mm-broadband-modem-mbim.h
@@ -62,4 +62,8 @@
MMPortMbim *mm_broadband_modem_mbim_get_port_mbim_for_data (MMBroadbandModemMbim *self,
MMPort *data,
GError **error);
+
+void mm_broadband_modem_mbim_set_unlock_retries (MMBroadbandModemMbim *self,
+ MMModemLock lock_type,
+ guint32 remaining_attempts);
#endif /* MM_BROADBAND_MODEM_MBIM_H */
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 25b18da..db94e68 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -12,7 +12,7 @@
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2014 Aleksander Morgado <aleksander@aleksander.es>
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <config.h>
@@ -170,6 +170,14 @@
/* For notifying when the qmi-proxy connection is dead */
guint qmi_device_removed_id;
+
+ /* Power Set Operating Mode Helper */
+ GTask *set_operating_mode_task;
+
+ /* PDC Refresh notifications ID (3gpp Profile Manager) */
+ gboolean profile_manager_unsolicited_events_enabled;
+ gboolean profile_manager_unsolicited_events_setup;
+ guint refresh_indication_id;
};
/*****************************************************************************/
@@ -1708,7 +1716,23 @@
}
/*****************************************************************************/
-/* Powering up the modem (Modem interface) */
+/* Powering up/down/off the modem (Modem interface) */
+
+typedef struct {
+ QmiDmsOperatingMode mode;
+ QmiClientDms *client;
+ guint indication_id;
+ guint timeout_id;
+} SetOperatingModeContext;
+
+static void
+set_operating_mode_context_free (SetOperatingModeContext *ctx)
+{
+ g_assert (ctx->indication_id == 0);
+ g_assert (ctx->timeout_id == 0);
+ g_clear_object (&ctx->client);
+ g_slice_free (SetOperatingModeContext, ctx);
+}
static gboolean
modem_power_up_down_off_finish (MMIfaceModem *self,
@@ -1719,28 +1743,99 @@
}
static void
-dms_set_operating_mode_ready (QmiClientDms *client,
- GAsyncResult *res,
- GTask *task)
+set_operating_mode_complete (MMBroadbandModemQmi *self,
+ GError *error)
{
- MMBroadbandModemQmi *self;
- QmiDmsOperatingMode mode;
- GError *error = NULL;
- g_autoptr(QmiMessageDmsSetOperatingModeOutput) output = NULL;
+ GTask *task;
+ SetOperatingModeContext *ctx;
- self = g_task_get_source_object (task);
- mode = GPOINTER_TO_UINT (g_task_get_task_data (task));
+ g_assert (self->priv->set_operating_mode_task);
+ task = g_steal_pointer (&self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (task);
+
+ if (ctx->timeout_id) {
+ g_source_remove (ctx->timeout_id);
+ ctx->timeout_id = 0;
+ }
+
+ if (ctx->indication_id) {
+ g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
+
+ g_signal_handler_disconnect (ctx->client, ctx->indication_id);
+ ctx->indication_id = 0;
+
+ input = qmi_message_dms_set_event_report_input_new ();
+ qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, FALSE, NULL);
+ qmi_client_dms_set_event_report (ctx->client, input, 5, NULL, NULL, NULL);
+ }
+
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+dms_set_operating_mode_timeout_cb (MMBroadbandModemQmi *self)
+{
+ GError *error = NULL;
+
+ error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Power update operation timed out");
+ set_operating_mode_complete (self, error);
+}
+
+static void
+power_event_report_indication_cb (QmiClientDms *client,
+ QmiIndicationDmsEventReportOutput *output,
+ MMBroadbandModemQmi *self)
+{
+ QmiDmsOperatingMode state;
+ GError *error = NULL;
+ SetOperatingModeContext *ctx;
+
+ if (!qmi_indication_dms_event_report_output_get_operating_mode (output, &state, NULL)) {
+ error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid power indication received");
+ set_operating_mode_complete (self, error);
+ return;
+ }
+
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
+
+ if (ctx->mode == state) {
+ mm_obj_dbg (self, "Power state successfully updated: '%s'", qmi_dms_operating_mode_get_string (state));
+ set_operating_mode_complete (self, NULL);
+ return;
+ }
+
+ error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Requested mode (%s) and mode received (%s) did not match",
+ qmi_dms_operating_mode_get_string (ctx->mode),
+ qmi_dms_operating_mode_get_string (state));
+ set_operating_mode_complete (self, error);
+}
+
+static void
+dms_set_operating_mode_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ MMBroadbandModemQmi *self) /* full reference */
+{
+ g_autoptr (QmiMessageDmsSetOperatingModeOutput) output = NULL;
+ GError *error = NULL;
+ SetOperatingModeContext *ctx;
+
+ if (!self->priv->set_operating_mode_task) {
+ /* We completed the operation already via indication */
+ g_object_unref (self);
+ return;
+ }
+
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
output = qmi_client_dms_set_operating_mode_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- /* If unsupported, just complete without errors */
- if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_UNSUPPORTED)) {
- mm_obj_dbg (self, "device doesn't support operating mode setting: ignoring power update");
- g_clear_error (&error);
- }
- } else if (!qmi_message_dms_set_operating_mode_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't set operating mode: ");
+ if (!output || !qmi_message_dms_set_operating_mode_output_get_result (output, &error)) {
/*
* Some new devices, like the Dell DW5770, will return an internal error when
* trying to bring the power mode to online.
@@ -1752,47 +1847,142 @@
* retrying. Notify this to upper layers with the special MM_CORE_ERROR_RETRY
* error.
*/
- if ((mode == QMI_DMS_OPERATING_MODE_ONLINE) &&
+ if ((ctx->mode == QMI_DMS_OPERATING_MODE_ONLINE) &&
((g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INTERNAL) ||
g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_TRANSITION)))) {
g_clear_error (&error);
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_RETRY, "Invalid transition");
- }
+ } else
+ g_prefix_error (&error, "Couldn't set operating mode: ");
}
- if (error)
- g_task_return_error (task, error);
+ /* If unsupported, just complete without errors */
+ if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_UNSUPPORTED)) {
+ mm_obj_dbg (self, "device doesn't support operating mode setting: ignoring power update");
+ g_clear_error (&error);
+ set_operating_mode_complete (self, NULL);
+ } else if (error)
+ set_operating_mode_complete (self, error);
else
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+ mm_obj_dbg (self, "operating mode request sent, waiting for power update indication");
+
+ g_object_unref (self);
}
static void
-common_power_up_down_off (MMIfaceModem *self,
- QmiDmsOperatingMode mode,
- GAsyncReadyCallback callback,
- gpointer user_data)
+dms_set_operating_mode (MMBroadbandModemQmi *self)
{
- GTask *task;
- QmiClient *client = NULL;
- g_autoptr(QmiMessageDmsSetOperatingModeInput) input = NULL;
+ g_autoptr (QmiMessageDmsSetOperatingModeInput) input = NULL;
+ SetOperatingModeContext *ctx;
- if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
- QMI_SERVICE_DMS, &client,
- callback, user_data))
- return;
-
- task = g_task_new (self, NULL, callback, user_data);
- g_task_set_task_data (task, GUINT_TO_POINTER (mode), NULL);
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
input = qmi_message_dms_set_operating_mode_input_new ();
- qmi_message_dms_set_operating_mode_input_set_mode (input, mode, NULL);
- qmi_client_dms_set_operating_mode (QMI_CLIENT_DMS (client),
+ qmi_message_dms_set_operating_mode_input_set_mode (input, ctx->mode, NULL);
+ qmi_client_dms_set_operating_mode (ctx->client,
input,
20,
NULL,
(GAsyncReadyCallback)dms_set_operating_mode_ready,
- task);
+ g_object_ref (self));
+
+ mm_obj_dbg (self, "Starting timeout for indication receiving for 10 seconds");
+ ctx->timeout_id = g_timeout_add_seconds (10,
+ (GSourceFunc) dms_set_operating_mode_timeout_cb,
+ self);
+}
+
+static void
+dms_set_event_report_operating_mode_activate_ready (QmiClientDms *client,
+ GAsyncResult *res,
+ MMBroadbandModemQmi *self) /* full reference */
+{
+ g_autoptr(QmiMessageDmsSetEventReportOutput) output = NULL;
+ GError *error = NULL;
+ SetOperatingModeContext *ctx;
+
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
+
+ output = qmi_client_dms_set_event_report_finish (client, res, &error);
+ if (!output || !qmi_message_dms_set_event_report_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't register for power indications: ");
+ set_operating_mode_complete (self, error);
+ g_object_unref (self);
+ return;
+ }
+
+ g_assert (ctx->indication_id == 0);
+ ctx->indication_id = g_signal_connect (client,
+ "event-report",
+ G_CALLBACK (power_event_report_indication_cb),
+ self);
+
+ mm_obj_dbg (self, "Power operation is pending");
+ dms_set_operating_mode (self);
+ g_object_unref (self);
+}
+
+static void
+modem_power_indication_register (MMBroadbandModemQmi *self)
+{
+ g_autoptr(QmiMessageDmsSetEventReportInput) input = NULL;
+ SetOperatingModeContext *ctx;
+
+ g_assert (self->priv->set_operating_mode_task);
+ ctx = g_task_get_task_data (self->priv->set_operating_mode_task);
+
+ input = qmi_message_dms_set_event_report_input_new ();
+ qmi_message_dms_set_event_report_input_set_operating_mode_reporting (input, TRUE, NULL);
+ mm_obj_dbg (self, "Power indication registration request is sent");
+ qmi_client_dms_set_event_report (
+ ctx->client,
+ input,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)dms_set_event_report_operating_mode_activate_ready,
+ g_object_ref (self));
+}
+
+static void
+common_power_up_down_off (MMIfaceModem *_self,
+ QmiDmsOperatingMode mode,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
+ GError *error = NULL;
+ GTask *task;
+ SetOperatingModeContext *ctx;
+ QmiClient *client;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (self->priv->set_operating_mode_task) {
+ error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_IN_PROGRESS, "Another operation in progress");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_DMS,
+ MM_PORT_QMI_FLAG_DEFAULT,
+ &error);
+ if (!client) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ ctx = g_slice_new0 (SetOperatingModeContext);
+ ctx->mode = mode;
+ ctx->client = QMI_CLIENT_DMS (g_object_ref (client));
+ g_task_set_task_data (task, ctx, (GDestroyNotify)set_operating_mode_context_free);
+
+ self->priv->set_operating_mode_task = task;
+ modem_power_indication_register (self);
}
static void
@@ -6416,6 +6606,200 @@
}
/*****************************************************************************/
+/* PDC Refresh events (3gppProfileManager interface) */
+
+static void
+pdc_refresh_received (QmiClientPdc *client,
+ QmiIndicationPdcRefreshOutput *output,
+ MMBroadbandModemQmi *self)
+{
+ mm_obj_dbg (self, "profile refresh indication was received");
+ mm_iface_modem_3gpp_profile_manager_updated (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self));
+}
+
+/*****************************************************************************/
+/* Enable/Disable unsolicited events (3gppProfileManager interface) */
+
+static gboolean
+modem_3gpp_profile_manager_enable_disable_unsolicited_events_finish (MMIfaceModem3gppProfileManager *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+register_pdc_refresh_ready (QmiClientPdc *client,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autoptr(QmiMessagePdcRegisterOutput) output = NULL;
+ MMBroadbandModemQmi *self;
+ gboolean enable;
+ GError *error = NULL;
+
+ self = g_task_get_source_object (task);
+ enable = GPOINTER_TO_UINT (g_task_get_task_data (task));
+
+ output = qmi_client_pdc_register_finish (client, res, &error);
+ if (!output) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!qmi_message_pdc_register_output_get_result (output, &error)) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ self->priv->profile_manager_unsolicited_events_enabled = enable;
+ mm_obj_dbg (self, "%s for refresh events", enable ? "registered" : "unregistered");
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+common_enable_disable_unsolicited_events_3gpp_profile_manager (MMBroadbandModemQmi *self,
+ gboolean enable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(QmiMessagePdcRegisterInput) input = NULL;
+ GTask *task;
+ QmiClient *client = NULL;
+
+ if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_PDC, &client,
+ callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+ g_task_set_task_data (task, GUINT_TO_POINTER (enable), NULL);
+
+ if (enable == self->priv->profile_manager_unsolicited_events_enabled) {
+ mm_obj_dbg (self, "profile manager unsolicited events already %s; skipping",
+ enable ? "enabled" : "disabled");
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ input = qmi_message_pdc_register_input_new ();
+ qmi_message_pdc_register_input_set_enable_reporting (input, enable, NULL);
+ qmi_message_pdc_register_input_set_enable_refresh (input, enable, NULL);
+ qmi_client_pdc_register (QMI_CLIENT_PDC (client),
+ input,
+ 10,
+ NULL,
+ (GAsyncReadyCallback) register_pdc_refresh_ready,
+ task);
+}
+
+static void
+modem_3gpp_profile_manager_disable_unsolicited_events (MMIfaceModem3gppProfileManager *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ common_enable_disable_unsolicited_events_3gpp_profile_manager (MM_BROADBAND_MODEM_QMI (self),
+ FALSE,
+ callback,
+ user_data);
+}
+
+static void
+modem_3gpp_profile_manager_enable_unsolicited_events (MMIfaceModem3gppProfileManager *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ common_enable_disable_unsolicited_events_3gpp_profile_manager (MM_BROADBAND_MODEM_QMI (self),
+ TRUE,
+ callback,
+ user_data);
+}
+
+/*****************************************************************************/
+/* Setup/cleanup unsolicited events (3gppProfileManager interface) */
+
+static gboolean
+modem_3gpp_profile_manager_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gppProfileManager *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+common_setup_cleanup_unsolicited_events_3gpp_profile_manager (MMBroadbandModemQmi *self,
+ gboolean enable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+
+{
+ GTask *task;
+ QmiClient *client = NULL;
+
+ if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+ QMI_SERVICE_PDC, &client,
+ callback, user_data))
+ return;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (enable == self->priv->profile_manager_unsolicited_events_setup) {
+ mm_obj_dbg (self, "profile manager unsolicited events already %s; skipping",
+ enable ? "set up" : "cleaned up");
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ self->priv->profile_manager_unsolicited_events_setup = enable;
+
+ if (enable) {
+ g_assert (self->priv->refresh_indication_id == 0);
+ self->priv->refresh_indication_id =
+ g_signal_connect (client,
+ "refresh",
+ G_CALLBACK (pdc_refresh_received),
+ self);
+ } else {
+ g_assert (self->priv->refresh_indication_id != 0);
+ g_signal_handler_disconnect (client, self->priv->refresh_indication_id);
+ self->priv->refresh_indication_id = 0;
+ }
+
+ mm_obj_dbg (self, "%s profile events handler", enable ? "set up" : "cleaned up");
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+modem_3gpp_profile_manager_cleanup_unsolicited_events (MMIfaceModem3gppProfileManager *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ common_setup_cleanup_unsolicited_events_3gpp_profile_manager (MM_BROADBAND_MODEM_QMI (self),
+ FALSE,
+ callback,
+ user_data);
+}
+
+static void
+modem_3gpp_profile_manager_setup_unsolicited_events (MMIfaceModem3gppProfileManager *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ common_setup_cleanup_unsolicited_events_3gpp_profile_manager (MM_BROADBAND_MODEM_QMI (self),
+ TRUE,
+ callback,
+ user_data);
+}
+
+/*****************************************************************************/
/* Check support (Messaging interface) */
static gboolean
@@ -12716,6 +13100,15 @@
iface->check_support = NULL;
iface->check_support_finish = NULL;
+ iface->setup_unsolicited_events = modem_3gpp_profile_manager_setup_unsolicited_events;
+ iface->setup_unsolicited_events_finish = modem_3gpp_profile_manager_setup_cleanup_unsolicited_events_finish;
+ iface->cleanup_unsolicited_events = modem_3gpp_profile_manager_cleanup_unsolicited_events;
+ iface->cleanup_unsolicited_events_finish = modem_3gpp_profile_manager_setup_cleanup_unsolicited_events_finish;
+ iface->enable_unsolicited_events = modem_3gpp_profile_manager_enable_unsolicited_events;
+ iface->enable_unsolicited_events_finish = modem_3gpp_profile_manager_enable_disable_unsolicited_events_finish;
+ iface->disable_unsolicited_events = modem_3gpp_profile_manager_disable_unsolicited_events;
+ iface->disable_unsolicited_events_finish = modem_3gpp_profile_manager_enable_disable_unsolicited_events_finish;
+
/* Additional actions */
iface->get_profile = modem_3gpp_profile_manager_get_profile;
iface->get_profile_finish = modem_3gpp_profile_manager_get_profile_finish;
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 40a5dd1..c1fa0e8 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -734,7 +734,7 @@
g_variant_builder_close (&builder);
}
- return g_variant_ref (g_variant_builder_end (&builder));
+ return g_variant_ref_sink (g_variant_builder_end (&builder));
}
static void
diff --git a/src/mm-iface-modem-firmware.c b/src/mm-iface-modem-firmware.c
index 1b4a07a..fe1feb1 100644
--- a/src/mm-iface-modem-firmware.c
+++ b/src/mm-iface-modem-firmware.c
@@ -325,10 +325,9 @@
return TRUE;
}
-static gboolean
-add_generic_device_ids (MMBaseModem *self,
- MMFirmwareUpdateSettings *update_settings,
- GError **error)
+GPtrArray *
+mm_iface_firmware_build_generic_device_ids (MMIfaceModemFirmware *self,
+ GError **error)
{
static const gchar *supported_subsystems[] = { "USB", "PCI" };
guint16 vid;
@@ -341,8 +340,8 @@
guint i;
gboolean ignore_carrier = FALSE;
- vid = mm_base_modem_get_vendor_id (self);
- pid = mm_base_modem_get_product_id (self);
+ vid = mm_base_modem_get_vendor_id (MM_BASE_MODEM (self));
+ pid = mm_base_modem_get_product_id (MM_BASE_MODEM (self));
#if defined WITH_QMI
if (MM_IS_BROADBAND_MODEM_QMI (self))
@@ -353,16 +352,15 @@
primary = MM_PORT (mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)));
#endif
if (!primary)
- primary = MM_PORT (mm_base_modem_peek_port_primary (self));
+ primary = MM_PORT (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)));
g_assert (primary != NULL);
rid = mm_kernel_device_get_physdev_revision (mm_port_peek_kernel_device (primary));
-
subsystem = mm_kernel_device_get_physdev_subsystem (mm_port_peek_kernel_device (primary));
if (!subsystem) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Unknown device subsystem");
- return FALSE;
+ return NULL;
}
for (i = 0; i < G_N_ELEMENTS (supported_subsystems); i++) {
@@ -372,7 +370,7 @@
if (i == G_N_ELEMENTS (supported_subsystems)) {
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Unsupported subsystem: %s", subsystem);
- return FALSE;
+ return NULL;
}
g_object_get (self,
@@ -398,8 +396,7 @@
supported_subsystems[i], vid));
g_ptr_array_add (ids, NULL);
- mm_firmware_update_settings_set_device_ids (update_settings, (const gchar **)ids->pdata);
- return TRUE;
+ return g_steal_pointer (&ids);
}
static void
@@ -411,6 +408,7 @@
MMFirmwareUpdateSettings *update_settings;
GError *error = NULL;
GVariant *variant = NULL;
+ g_autoptr(GPtrArray) ids = NULL;
ctx = g_task_get_task_data (task);
@@ -422,12 +420,17 @@
}
/* If the plugin didn't specify custom device ids, add the default ones ourselves */
- if (!mm_firmware_update_settings_get_device_ids (update_settings) &&
- !add_generic_device_ids (MM_BASE_MODEM (self), update_settings, &error)) {
- mm_obj_warn (self, "couldn't build device ids: %s", error->message);
- g_error_free (error);
- g_clear_object (&update_settings);
- goto out;
+ if (!mm_firmware_update_settings_get_device_ids (update_settings)) {
+ mm_obj_dbg (self, "No device ids set by plugin, adding generic ids");
+ ids = mm_iface_firmware_build_generic_device_ids (self, &error);
+ if (error) {
+ mm_obj_warn (self, "couldn't build device ids: %s", error->message);
+ g_error_free (error);
+ g_clear_object (&update_settings);
+ goto out;
+ }
+
+ mm_firmware_update_settings_set_device_ids (update_settings, (const gchar **)ids->pdata);
}
/* If the plugin didn't specify custom version, add the default one ourselves */
diff --git a/src/mm-iface-modem-firmware.h b/src/mm-iface-modem-firmware.h
index 365bfb1..0e82382 100644
--- a/src/mm-iface-modem-firmware.h
+++ b/src/mm-iface-modem-firmware.h
@@ -72,6 +72,10 @@
GType mm_iface_modem_firmware_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMIfaceModemFirmware, g_object_unref)
+/* Get generic device ids */
+GPtrArray *mm_iface_firmware_build_generic_device_ids (MMIfaceModemFirmware *self,
+ GError **error);
+
/* Initialize Firmware interface (async) */
void mm_iface_modem_firmware_initialize (MMIfaceModemFirmware *self,
GCancellable *cancellable,
diff --git a/src/mm-iface-modem-signal.c b/src/mm-iface-modem-signal.c
index d204039..1116057 100644
--- a/src/mm-iface-modem-signal.c
+++ b/src/mm-iface-modem-signal.c
@@ -35,10 +35,12 @@
static GQuark private_quark;
typedef struct {
- /* polling-based reporting enabled */
+ /* interface enabled */
+ gboolean enabled;
+ /* polling-based reporting */
guint rate;
guint timeout_source;
- /* threshold-based reporting enabled */
+ /* threshold-based reporting */
guint rssi_threshold;
gboolean error_rate_threshold;
} Private;
@@ -155,7 +157,7 @@
Private *priv;
priv = get_private (self);
- if (!priv->rate && !priv->rssi_threshold && !priv->error_rate_threshold) {
+ if (!priv->enabled || (!priv->rate && !priv->rssi_threshold && !priv->error_rate_threshold)) {
mm_obj_dbg (self, "skipping extended signal information update...");
return;
}
@@ -172,13 +174,14 @@
priv = get_private (self);
- if (!priv->rate && !priv->rssi_threshold && !priv->error_rate_threshold) {
+ if (!priv->enabled || (!priv->rate && !priv->rssi_threshold && !priv->error_rate_threshold)) {
mm_obj_dbg (self, "reseting extended signal information...");
- mm_iface_modem_signal_update (self, NULL, NULL, NULL, NULL, NULL, NULL);
+ internal_signal_update (self, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
/*****************************************************************************/
+/* Polling setup management */
static void
load_values_ready (MMIfaceModemSignal *self,
@@ -220,51 +223,96 @@
return G_SOURCE_CONTINUE;
}
-static gboolean
-polling_restart (MMIfaceModemSignal *self,
- guint rate,
- GError **error)
+static void
+polling_restart (MMIfaceModemSignal *self)
{
- Private *priv;
+ Private *priv;
+ gboolean polling_setup;
priv = get_private (self);
+ polling_setup = (priv->enabled && priv->rate);
- /* Update the rate in the interface if it changed */
- if (priv->rate != rate) {
- g_autoptr(MmGdbusModemSignalSkeleton) skeleton = NULL;
+ mm_obj_dbg (self, "%s extended signal information polling: interface %s, rate %u seconds",
+ polling_setup ? "setting up" : "cleaning up",
+ priv->enabled ? "enabled" : "disabled",
+ priv->rate);
- g_object_get (self,
- MM_IFACE_MODEM_SIGNAL_DBUS_SKELETON, &skeleton,
- NULL);
- if (!skeleton) {
- g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
- "Couldn't get interface skeleton");
- return FALSE;
- }
- mm_gdbus_modem_signal_set_rate (MM_GDBUS_MODEM_SIGNAL (skeleton), rate);
- priv->rate = rate;
- }
-
- /* Polling disabled by user? */
- if (rate == 0) {
- mm_obj_dbg (self, "extended signal information polling disabled (rate: 0 seconds)");
+ /* Stop polling */
+ if (!polling_setup) {
if (priv->timeout_source) {
g_source_remove (priv->timeout_source);
priv->timeout_source = 0;
}
- check_interface_reset (self);
- return TRUE;
+ return;
}
- /* Restart polling */
- mm_obj_dbg (self, "extended signal information reporting enabled (rate: %u seconds)", rate);
+ /* Start/restart polling */
if (priv->timeout_source)
g_source_remove (priv->timeout_source);
- priv->timeout_source = g_timeout_add_seconds (rate, (GSourceFunc) polling_context_cb, self);
+ priv->timeout_source = g_timeout_add_seconds (priv->rate, (GSourceFunc) polling_context_cb, self);
/* Also launch right away */
polling_context_cb (self);
- return TRUE;
+}
+
+/*****************************************************************************/
+/* Thresholds setup management */
+
+static gboolean
+thresholds_restart_finish (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+setup_thresholds_ready (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds_finish (self, res, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+thresholds_restart (MMIfaceModemSignal *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ Private *priv;
+ gboolean threshold_setup;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds ||
+ !MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds_finish) {
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+ return;
+ }
+
+ priv = get_private (self);
+ threshold_setup = (priv->enabled && (priv->rssi_threshold || priv->error_rate_threshold));
+
+ mm_obj_dbg (self, "%s extended signal information thresholds: interface %s, rssi threshold %u dBm, error rate threshold %s",
+ threshold_setup ? "setting up" : "cleaning up",
+ priv->enabled ? "enabled" : "disabled",
+ priv->rssi_threshold,
+ priv->error_rate_threshold ? "enabled" : "disabled");
+
+ MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds (
+ self,
+ priv->rssi_threshold,
+ priv->error_rate_threshold,
+ (GAsyncReadyCallback)setup_thresholds_ready,
+ task);
}
/*****************************************************************************/
@@ -272,7 +320,6 @@
typedef struct {
GDBusMethodInvocation *invocation;
MmGdbusModemSignal *skeleton;
- MMIfaceModemSignal *self;
guint rate;
} HandleSetupContext;
@@ -281,18 +328,19 @@
{
g_object_unref (ctx->invocation);
g_object_unref (ctx->skeleton);
- g_object_unref (ctx->self);
g_slice_free (HandleSetupContext, ctx);
}
static void
-handle_setup_auth_ready (MMBaseModem *self,
- GAsyncResult *res,
+handle_setup_auth_ready (MMBaseModem *_self,
+ GAsyncResult *res,
HandleSetupContext *ctx)
{
- GError *error = NULL;
+ MMIfaceModemSignal *self = MM_IFACE_MODEM_SIGNAL (_self);
+ GError *error = NULL;
+ Private *priv;
- if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ if (!mm_base_modem_authorize_finish (_self, res, &error)) {
g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_setup_context_free (ctx);
return;
@@ -300,15 +348,17 @@
if (mm_iface_modem_abort_invocation_if_state_not_reached (MM_IFACE_MODEM (self),
ctx->invocation,
- MM_MODEM_STATE_ENABLED)) {
+ MM_MODEM_STATE_DISABLED)) {
handle_setup_context_free (ctx);
return;
}
- if (!polling_restart (ctx->self, ctx->rate, &error))
- g_dbus_method_invocation_take_error (ctx->invocation, error);
- else
- mm_gdbus_modem_signal_complete_setup (ctx->skeleton, ctx->invocation);
+ priv = get_private (self);
+ priv->rate = ctx->rate;
+ polling_restart (self);
+ check_interface_reset (self);
+ mm_gdbus_modem_signal_set_rate (ctx->skeleton, ctx->rate);
+ mm_gdbus_modem_signal_complete_setup (ctx->skeleton, ctx->invocation);
handle_setup_context_free (ctx);
}
@@ -320,10 +370,9 @@
{
HandleSetupContext *ctx;
- ctx = g_slice_new (HandleSetupContext);
+ ctx = g_slice_new0 (HandleSetupContext);
ctx->invocation = g_object_ref (invocation);
ctx->skeleton = g_object_ref (skeleton);
- ctx->self = g_object_ref (self);
ctx->rate = rate;
mm_base_modem_authorize (MM_BASE_MODEM (self),
@@ -339,10 +388,9 @@
typedef struct {
GDBusMethodInvocation *invocation;
MmGdbusModemSignal *skeleton;
- MMIfaceModemSignal *self;
GVariant *settings;
- guint32 rssi_threshold;
- gboolean error_rate_threshold;
+ guint previous_rssi_threshold;
+ gboolean previous_error_rate_threshold;
} HandleSetupThresholdsContext;
static void
@@ -350,32 +398,29 @@
{
g_object_unref (ctx->invocation);
g_object_unref (ctx->skeleton);
- g_object_unref (ctx->self);
if (ctx->settings)
g_variant_unref (ctx->settings);
g_slice_free (HandleSetupThresholdsContext, ctx);
}
static void
-setup_thresholds_ready (MMIfaceModemSignal *self,
- GAsyncResult *res,
- HandleSetupThresholdsContext *ctx)
+setup_thresholds_restart_ready (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ HandleSetupThresholdsContext *ctx)
{
GError *error = NULL;
Private *priv;
- priv = get_private (MM_IFACE_MODEM_SIGNAL (self));
+ priv = get_private (self);
- if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds_finish (ctx->self, res, &error))
+ if (!thresholds_restart_finish (self, res, &error)) {
+ priv->rssi_threshold = ctx->previous_rssi_threshold;
+ priv->error_rate_threshold = ctx->previous_error_rate_threshold;
g_dbus_method_invocation_take_error (ctx->invocation, error);
- else {
- /* Update the properties with the latest threshold setting */
- mm_gdbus_modem_signal_set_rssi_threshold (ctx->skeleton, ctx->rssi_threshold);
- mm_gdbus_modem_signal_set_error_rate_threshold (ctx->skeleton, ctx->error_rate_threshold);
- priv->rssi_threshold = ctx->rssi_threshold;
- priv->error_rate_threshold = ctx->error_rate_threshold;
+ } else {
check_interface_reset (self);
-
+ mm_gdbus_modem_signal_set_rssi_threshold (ctx->skeleton, priv->rssi_threshold);
+ mm_gdbus_modem_signal_set_error_rate_threshold (ctx->skeleton, priv->error_rate_threshold);
mm_gdbus_modem_signal_complete_setup_thresholds (ctx->skeleton, ctx->invocation);
}
@@ -383,24 +428,27 @@
}
static void
-handle_setup_thresholds_auth_ready (MMBaseModem *self,
+handle_setup_thresholds_auth_ready (MMBaseModem *_self,
GAsyncResult *res,
HandleSetupThresholdsContext *ctx)
{
g_autoptr(MMSignalThresholdProperties) properties = NULL;
+ MMIfaceModemSignal *self = MM_IFACE_MODEM_SIGNAL (_self);
GError *error = NULL;
Private *priv;
+ guint new_rssi_threshold;
+ gboolean new_error_rate_threshold;
- priv = get_private (MM_IFACE_MODEM_SIGNAL (self));
+ priv = get_private (self);
- if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ if (!mm_base_modem_authorize_finish (_self, res, &error)) {
g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_setup_thresholds_context_free (ctx);
return;
}
- if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds ||
- !MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds_finish) {
+ if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds ||
+ !MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->setup_thresholds_finish) {
g_dbus_method_invocation_return_error (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot setup thresholds: operation not supported");
handle_setup_thresholds_context_free (ctx);
@@ -409,7 +457,7 @@
if (mm_iface_modem_abort_invocation_if_state_not_reached (MM_IFACE_MODEM (self),
ctx->invocation,
- MM_MODEM_STATE_ENABLED)) {
+ MM_MODEM_STATE_DISABLED)) {
handle_setup_thresholds_context_free (ctx);
return;
}
@@ -420,31 +468,24 @@
handle_setup_thresholds_context_free (ctx);
return;
}
- ctx->rssi_threshold = mm_signal_threshold_properties_get_rssi (properties);
- ctx->error_rate_threshold = mm_signal_threshold_properties_get_error_rate (properties);
+ new_rssi_threshold = mm_signal_threshold_properties_get_rssi (properties);
+ new_error_rate_threshold = mm_signal_threshold_properties_get_error_rate (properties);
- /* Already there? */
- if ((ctx->rssi_threshold == mm_gdbus_modem_signal_get_rssi_threshold (ctx->skeleton)) &&
- (ctx->error_rate_threshold == mm_gdbus_modem_signal_get_error_rate_threshold (ctx->skeleton))) {
+ if ((new_rssi_threshold == priv->rssi_threshold) &&
+ (new_error_rate_threshold == priv->error_rate_threshold)) {
mm_gdbus_modem_signal_complete_setup_thresholds (ctx->skeleton, ctx->invocation);
handle_setup_thresholds_context_free (ctx);
return;
}
- /* Same settings? */
- if ((ctx->rssi_threshold == priv->rssi_threshold) &&
- (ctx->error_rate_threshold == priv->error_rate_threshold)) {
- mm_gdbus_modem_signal_complete_setup_thresholds (ctx->skeleton, ctx->invocation);
- handle_setup_thresholds_context_free (ctx);
- return;
- }
+ ctx->previous_rssi_threshold = priv->rssi_threshold;
+ ctx->previous_error_rate_threshold = priv->error_rate_threshold;
+ priv->rssi_threshold = new_rssi_threshold;
+ priv->error_rate_threshold = new_error_rate_threshold;
- MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds (
- ctx->self,
- ctx->rssi_threshold,
- ctx->error_rate_threshold,
- (GAsyncReadyCallback)setup_thresholds_ready,
- ctx);
+ thresholds_restart (self,
+ (GAsyncReadyCallback)setup_thresholds_restart_ready,
+ ctx);
}
static gboolean
@@ -458,7 +499,6 @@
ctx = g_slice_new0 (HandleSetupThresholdsContext);
ctx->invocation = g_object_ref (invocation);
ctx->skeleton = g_object_ref (skeleton);
- ctx->self = g_object_ref (self);
ctx->settings = g_variant_ref (settings);
mm_base_modem_authorize (MM_BASE_MODEM (self),
@@ -470,13 +510,62 @@
}
/*****************************************************************************/
+/* Common enable/disable */
+
+static gboolean
+common_enable_disable_finish (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+enable_disable_thresholds_restart_ready (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ if (!thresholds_restart_finish (self, res, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+static void
+common_enable_disable (MMIfaceModemSignal *self,
+ gboolean enabled,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ Private *priv;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ priv = get_private (MM_IFACE_MODEM_SIGNAL (self));
+ priv->enabled = enabled;
+
+ check_interface_reset (self);
+
+ polling_restart (self);
+
+ thresholds_restart (self,
+ (GAsyncReadyCallback)enable_disable_thresholds_restart_ready,
+ task);
+}
+
+/*****************************************************************************/
gboolean
mm_iface_modem_signal_disable_finish (MMIfaceModemSignal *self,
GAsyncResult *res,
GError **error)
{
- return g_task_propagate_boolean (G_TASK (res), error);
+ return common_enable_disable_finish (self, res, error);
}
void
@@ -484,13 +573,7 @@
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
-
- mm_iface_modem_signal_update (self, NULL, NULL, NULL, NULL, NULL, NULL);
-
- task = g_task_new (self, NULL, callback, user_data);
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+ common_enable_disable (self, FALSE, NULL, callback, user_data);
}
/*****************************************************************************/
@@ -500,7 +583,7 @@
GAsyncResult *res,
GError **error)
{
- return g_task_propagate_boolean (G_TASK (res), error);
+ return common_enable_disable_finish (self, res, error);
}
void
@@ -509,19 +592,7 @@
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
- GError *error = NULL;
- Private *priv;
-
- priv = get_private (self);
- task = g_task_new (self, cancellable, callback, user_data);
-
- /* same rate as we had before */
- if (!polling_restart (self, priv->rate, &error))
- g_task_return_error (task, error);
- else
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
+ common_enable_disable (self, TRUE, cancellable, callback, user_data);
}
/*****************************************************************************/
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 1426b44..140af48 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -1234,6 +1234,115 @@
/*****************************************************************************/
+typedef struct {
+ MmGdbusModem *skeleton;
+ GDBusMethodInvocation *invocation;
+ MMIfaceModem *self;
+} HandleGetCellInfoContext;
+
+static void
+handle_get_cell_info_context_free (HandleGetCellInfoContext *ctx)
+{
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->self);
+ g_free (ctx);
+}
+
+static GVariant *
+get_cell_info_build_result (GList *info_list)
+{
+ GList *l;
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ for (l = info_list; l; l = g_list_next (l)) {
+ g_autoptr(GVariant) dict = NULL;
+
+ dict = mm_cell_info_get_dictionary (MM_CELL_INFO (l->data));
+ g_variant_builder_add_value (&builder, dict);
+ }
+
+ return g_variant_ref_sink (g_variant_builder_end (&builder));
+}
+
+static void
+get_cell_info_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ HandleGetCellInfoContext *ctx)
+{
+ GError *error = NULL;
+ GList *info_list;
+
+ info_list = MM_IFACE_MODEM_GET_INTERFACE (self)->get_cell_info_finish (self, res, &error);
+ if (error)
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ else {
+ g_autoptr(GVariant) dict_array = NULL;
+
+ dict_array = get_cell_info_build_result (info_list);
+ mm_gdbus_modem_complete_get_cell_info (ctx->skeleton, ctx->invocation, dict_array);
+ }
+
+ g_list_free_full (info_list, (GDestroyNotify)g_object_unref);
+ handle_get_cell_info_context_free (ctx);
+}
+
+static void
+handle_get_cell_info_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleGetCellInfoContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_get_cell_info_context_free (ctx);
+ return;
+ }
+
+ /* If getting cell info is not implemented, report an error */
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->get_cell_info ||
+ !MM_IFACE_MODEM_GET_INTERFACE (self)->get_cell_info_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot get cell info: operation not supported");
+ handle_get_cell_info_context_free (ctx);
+ return;
+ }
+
+ if (mm_iface_modem_abort_invocation_if_state_not_reached (ctx->self, ctx->invocation, MM_MODEM_STATE_ENABLED)) {
+ handle_get_cell_info_context_free (ctx);
+ return;
+ }
+
+ MM_IFACE_MODEM_GET_INTERFACE (self)->get_cell_info (ctx->self,
+ (GAsyncReadyCallback)get_cell_info_ready,
+ ctx);
+}
+
+static gboolean
+handle_get_cell_info (MmGdbusModem *skeleton,
+ GDBusMethodInvocation *invocation,
+ MMIfaceModem *self)
+{
+ HandleGetCellInfoContext *ctx;
+
+ ctx = g_new (HandleGetCellInfoContext, 1);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->self = g_object_ref (self);
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_get_cell_info_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
void
mm_iface_modem_update_access_technologies (MMIfaceModem *self,
MMModemAccessTechnology new_access_tech,
@@ -3477,9 +3586,9 @@
return unlock_retries;
}
-void
-mm_iface_modem_update_unlock_retries (MMIfaceModem *self,
- MMUnlockRetries *unlock_retries)
+static void
+update_unlock_retries (MMIfaceModem *self,
+ MMUnlockRetries *unlock_retries)
{
MmGdbusModem *skeleton = NULL;
GVariant *previous_dictionary;
@@ -3565,7 +3674,7 @@
g_error_free (error);
} else {
/* Update the dictionary in the DBus interface */
- mm_iface_modem_update_unlock_retries (self, unlock_retries);
+ update_unlock_retries (self, unlock_retries);
g_object_unref (unlock_retries);
}
@@ -5891,6 +6000,7 @@
"signal::handle-set-current-bands", G_CALLBACK (handle_set_current_bands), self,
"signal::handle-set-current-modes", G_CALLBACK (handle_set_current_modes), self,
"signal::handle-set-primary-sim-slot", G_CALLBACK (handle_set_primary_sim_slot), self,
+ "signal::handle-get-cell-info", G_CALLBACK (handle_get_cell_info), self,
NULL);
/* Finally, export the new interface, even if we got errors, but only if not
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 2abadf2..a182d6d 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -405,6 +405,14 @@
gboolean (* setup_carrier_config_finish) (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
+
+ /* Asynchronous cell info retrieval operation */
+ void (* get_cell_info) (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GList * (* get_cell_info_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_iface_modem_get_type (void);
@@ -510,9 +518,6 @@
MMModemLock mm_iface_modem_get_unlock_required (MMIfaceModem *self);
MMUnlockRetries *mm_iface_modem_get_unlock_retries (MMIfaceModem *self);
-void mm_iface_modem_update_unlock_retries (MMIfaceModem *self,
- MMUnlockRetries *unlock_retries);
-
/* Request signal quality check update.
* It will not only return the signal quality status, but also set the property
* values in the DBus interface. */
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c
index d531636..d95fd50 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -1832,8 +1832,8 @@
* as there would be no capability switching support.
*/
MMModemCapability
-mm_modem_capability_from_qmi_capabilities_context (MMQmiCapabilitiesContext *ctx,
- gpointer log_object)
+mm_current_capability_from_qmi_current_capabilities_context (MMQmiCurrentCapabilitiesContext *ctx,
+ gpointer log_object)
{
MMModemCapability tmp = MM_MODEM_CAPABILITY_NONE;
g_autofree gchar *nas_ssp_mode_preference_str = NULL;
@@ -1842,8 +1842,7 @@
g_autofree gchar *tmp_str = NULL;
/* If not a multimode device, we're done */
-#define MULTIMODE (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO)
- if ((ctx->dms_capabilities & MULTIMODE) != MULTIMODE)
+ if (!ctx->multimode)
tmp = ctx->dms_capabilities;
else {
/* We have a multimode CDMA/EVDO+GSM/UMTS device, check SSP and TP */
@@ -1856,15 +1855,15 @@
else if (ctx->nas_tp_mask != QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO)
tmp = mm_modem_capability_from_qmi_radio_technology_preference (ctx->nas_tp_mask);
- /* Final capabilities are the intersection between the Technology
- * Preference or SSP and the device's capabilities.
+ /* Final capabilities are the union of the active multimode capability
+ * (GSM/UMTS or CDMA/EVDO or both or none) in TP or SSP and other supported device's capabilities.
* If the Technology Preference was "auto" or unknown we just fall back
* to the Get Capabilities response.
*/
if (tmp == MM_MODEM_CAPABILITY_NONE)
tmp = ctx->dms_capabilities;
else
- tmp &= ctx->dms_capabilities;
+ tmp = (tmp & MM_MODEM_CAPABILITY_MULTIMODE) | (MM_MODEM_CAPABILITY_MULTIMODE ^ ctx->dms_capabilities);
}
/* Log about the logic applied */
@@ -1886,6 +1885,147 @@
}
/*****************************************************************************/
+/* Utility to build list of supported capabilities */
+
+GArray *
+mm_supported_capabilities_from_qmi_supported_capabilities_context (MMQmiSupportedCapabilitiesContext *ctx,
+ gpointer log_object)
+{
+ GArray *supported_combinations;
+
+ supported_combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemCapability), 4);
+
+ /* Add all possible supported capability combinations.
+ * In order to avoid unnecessary modem reboots, we will only implement capabilities
+ * switching only when switching GSM/UMTS+CDMA/EVDO multimode devices, and only if
+ * we have support for the commands doing it.
+ */
+ if ((ctx->nas_tp_supported || ctx->nas_ssp_supported) && ctx->multimode) {
+ MMModemCapability single;
+
+ /* Multimode GSM/UMTS+CDMA/EVDO+(LTE/5GNR) device switched to GSM/UMTS+(LTE/5GNR) device */
+ single = MM_MODEM_CAPABILITY_GSM_UMTS | (MM_MODEM_CAPABILITY_MULTIMODE ^ ctx->dms_capabilities);
+ g_array_append_val (supported_combinations, single);
+ /* Multimode GSM/UMTS+CDMA/EVDO+(LTE/5GNR) device switched to CDMA/EVDO+(LTE/5GNR) device */
+ single = MM_MODEM_CAPABILITY_CDMA_EVDO | (MM_MODEM_CAPABILITY_MULTIMODE ^ ctx->dms_capabilities);
+ g_array_append_val (supported_combinations, single);
+ /*
+ * Multimode GSM/UMTS+CDMA/EVDO+(LTE/5GNR) device switched to (LTE/5GNR) device
+ *
+ * This case is required because we use the same methods and operations to
+ * switch capabilities and modes.
+ */
+ if ((single = (MM_MODEM_CAPABILITY_MULTIMODE ^ ctx->dms_capabilities)))
+ g_array_append_val (supported_combinations, single);
+ }
+
+ /* Add the full mask itself */
+ g_array_append_val (supported_combinations, ctx->dms_capabilities);
+
+ return supported_combinations;
+}
+
+/*****************************************************************************/
+/* Utility to build list of supported modes */
+
+GArray *
+mm_supported_modes_from_qmi_supported_modes_context (MMQmiSupportedModesContext *ctx,
+ gpointer log_object)
+{
+ g_autoptr(GArray) combinations = NULL;
+ g_autoptr(GArray) all = NULL;
+ MMModemModeCombination mode;
+
+ /* Start with a mode including ALL */
+ mode.allowed = ctx->all;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ g_array_append_val (all, mode);
+
+ /* If SSP and TP are not supported, ignore supported mode management */
+ if (!ctx->nas_ssp_supported && !ctx->nas_tp_supported)
+ return g_steal_pointer (&all);
+
+ combinations = g_array_new (FALSE, FALSE, sizeof (MMModemModeCombination));
+
+#define ADD_MODE_PREFERENCE(MODE1, MODE2, MODE3, MODE4) do { \
+ mode.allowed = MODE1; \
+ if (MODE2 != MM_MODEM_MODE_NONE) { \
+ mode.allowed |= MODE2; \
+ if (MODE3 != MM_MODEM_MODE_NONE) { \
+ mode.allowed |= MODE3; \
+ if (MODE4 != MM_MODEM_MODE_NONE) \
+ mode.allowed |= MODE4; \
+ } \
+ if (ctx->nas_ssp_supported) { \
+ if (MODE3 != MM_MODEM_MODE_NONE) { \
+ if (MODE4 != MM_MODEM_MODE_NONE) { \
+ mode.preferred = MODE4; \
+ g_array_append_val (combinations, mode); \
+ } \
+ mode.preferred = MODE3; \
+ g_array_append_val (combinations, mode); \
+ } \
+ mode.preferred = MODE2; \
+ g_array_append_val (combinations, mode); \
+ mode.preferred = MODE1; \
+ g_array_append_val (combinations, mode); \
+ } else { \
+ mode.preferred = MM_MODEM_MODE_NONE; \
+ g_array_append_val (combinations, mode); \
+ } \
+ } else { \
+ mode.allowed = MODE1; \
+ mode.preferred = MM_MODEM_MODE_NONE; \
+ g_array_append_val (combinations, mode); \
+ } \
+ } while (0)
+
+ /* 2G-only, 3G-only */
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+
+ /*
+ * This case is required because we use the same methods and operations to
+ * switch capabilities and modes. For the LTE capability there is a direct
+ * related 4G mode, and so we cannot select a '4G only' mode in this device
+ * because we wouldn't be able to know the full list of current capabilities
+ * if the device was rebooted, as we would only see LTE capability. So,
+ * handle this special case so that the LTE/4G-only mode can exclusively be
+ * selected as capability switching in this kind of devices.
+ */
+ if (!ctx->multimode || !(ctx->current_capabilities & MM_MODEM_CAPABILITY_MULTIMODE)) {
+ /* 4G-only */
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ }
+
+ /* 2G, 3G, 4G combinations */
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE);
+
+ /* 5G related mode combinations are only supported when NAS SSP is supported,
+ * as there is no 5G support in NAS TP. */
+ if (ctx->nas_ssp_supported) {
+ /* Same reasoning as for the special 4G-only case above */
+ if (!ctx->multimode || !(ctx->current_capabilities & MM_MODEM_CAPABILITY_MULTIMODE)) {
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ }
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
+ ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G);
+ }
+
+ /* Filter out unsupported modes */
+ return mm_filter_supported_modes (all, combinations, log_object);
+}
+
+/*****************************************************************************/
MMOmaSessionType
mm_oma_session_type_from_qmi_oma_session_type (QmiOmaSessionType qmi_session_type)
diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h
index b9682ab..e4eb9c7 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -24,6 +24,8 @@
#include "mm-port.h"
+#define MM_MODEM_CAPABILITY_MULTIMODE (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO)
+
/*****************************************************************************/
/* QMI/DMS to MM translations */
@@ -160,16 +162,54 @@
/* Utility to gather current capabilities from various sources */
typedef struct {
+ /* Whether this is a multimode device or not */
+ gboolean multimode;
/* NAS System Selection Preference */
QmiNasRatModePreference nas_ssp_mode_preference_mask;
/* NAS Technology Preference */
QmiNasRadioTechnologyPreference nas_tp_mask;
/* DMS Capabilities */
MMModemCapability dms_capabilities;
-} MMQmiCapabilitiesContext;
+} MMQmiCurrentCapabilitiesContext;
-MMModemCapability mm_modem_capability_from_qmi_capabilities_context (MMQmiCapabilitiesContext *ctx,
- gpointer log_object);
+MMModemCapability mm_current_capability_from_qmi_current_capabilities_context (MMQmiCurrentCapabilitiesContext *ctx,
+ gpointer log_object);
+
+/*****************************************************************************/
+/* Utility to build list of supported capabilities from various sources */
+
+typedef struct {
+ /* Whether this is a multimode device or not */
+ gboolean multimode;
+ /* NAS System Selection Preference */
+ gboolean nas_ssp_supported;
+ /* NAS Technology Preference */
+ gboolean nas_tp_supported;
+ /* DMS Capabilities */
+ MMModemCapability dms_capabilities;
+} MMQmiSupportedCapabilitiesContext;
+
+GArray *mm_supported_capabilities_from_qmi_supported_capabilities_context (MMQmiSupportedCapabilitiesContext *ctx,
+ gpointer log_object);
+
+/*****************************************************************************/
+/* Utility to build list of supported modes from various sources */
+
+typedef struct {
+ /* Whether this is a multimode device or not */
+ gboolean multimode;
+ /* NAS System Selection Preference */
+ gboolean nas_ssp_supported;
+ /* NAS Technology Preference */
+ gboolean nas_tp_supported;
+ /* Mask with all supported modes */
+ MMModemMode all;
+ /* Current Capabilities */
+ MMModemCapability current_capabilities;
+} MMQmiSupportedModesContext;
+
+GArray *mm_supported_modes_from_qmi_supported_modes_context (MMQmiSupportedModesContext *ctx,
+ gpointer log_object);
/*****************************************************************************/
/* QMI unique id manipulation */
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 3e22262..c969b66 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -13,6 +13,7 @@
* Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2009 - 2012 Red Hat, Inc.
* Copyright (C) 2012 Google, Inc.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <config.h>
@@ -393,7 +394,6 @@
MMModemModeCombination all_item;
guint i;
GArray *filtered_combinations;
- gboolean all_item_added = FALSE;
g_return_val_if_fail (all != NULL, NULL);
g_return_val_if_fail (all->len == 1, NULL);
@@ -416,8 +416,6 @@
* containing all supported modes, we're already good to go. This allows us to have a
* default with preferred != NONE (e.g. Wavecom 2G modem with allowed=CS+2G and
* preferred=2G */
- if (all_item.allowed == mode->allowed)
- all_item_added = TRUE;
g_array_append_val (filtered_combinations, *mode);
}
}
@@ -425,12 +423,6 @@
if (filtered_combinations->len == 0)
mm_obj_warn (log_object, "all supported mode combinations were filtered out");
- /* Add default entry with the generic mask including all items */
- if (!all_item_added) {
- mm_obj_dbg (log_object, "adding an explicit item with all supported modes allowed");
- g_array_append_val (filtered_combinations, all_item);
- }
-
mm_obj_dbg (log_object, "device supports %u different mode combinations",
filtered_combinations->len);
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c
index f0bdba0..8ec85a5 100644
--- a/src/mm-plugin-manager.c
+++ b/src/mm-plugin-manager.c
@@ -22,6 +22,8 @@
#include <gmodule.h>
#include <gio/gio.h>
+#include <config.h>
+
#include <ModemManager.h>
#include <mm-errors-types.h>
@@ -713,8 +715,14 @@
#define MIN_PROBING_TIME_MSECS 2500
/* Additional time to wait for other ports to appear after the last port is
- * exposed in the system. */
-#define EXTRA_PROBING_TIME_MSECS 1500
+ * exposed in the system. Longer time when not using udev, as we rely on
+ * mmcli --report-kernel-event events to report new port additions, e.g.
+ * via openwrt hotplug scripts. */
+#if defined WITH_UDEV
+# define EXTRA_PROBING_TIME_MSECS 1500
+#else
+# define EXTRA_PROBING_TIME_MSECS 3000
+#endif
/* The wait time we define must always be less than the probing time */
G_STATIC_ASSERT (MIN_WAIT_TIME_MSECS < MIN_PROBING_TIME_MSECS);
diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c
index c9a9081..1447a7c 100644
--- a/src/mm-shared-qmi.c
+++ b/src/mm-shared-qmi.c
@@ -70,6 +70,7 @@
typedef struct {
/* Capabilities & modes helpers */
+ gboolean multimode;
MMModemCapability current_capabilities;
GArray *supported_radio_interfaces;
Feature feature_nas_tp;
@@ -77,7 +78,6 @@
Feature feature_nas_ssp_extended_lte_band_preference;
Feature feature_nas_ssp_acquisition_order_preference;
GArray *feature_nas_ssp_acquisition_order_preference_array;
- gboolean disable_4g_only_mode;
GArray *supported_bands;
/* Location helpers */
@@ -799,10 +799,10 @@
} LoadCurrentCapabilitiesStep;
typedef struct {
- QmiClientNas *nas_client;
- QmiClientDms *dms_client;
- LoadCurrentCapabilitiesStep step;
- MMQmiCapabilitiesContext capabilities_context;
+ QmiClientNas *nas_client;
+ QmiClientDms *dms_client;
+ LoadCurrentCapabilitiesStep step;
+ MMQmiCurrentCapabilitiesContext capabilities_context;
} LoadCurrentCapabilitiesContext;
MMModemCapability
@@ -1024,7 +1024,13 @@
case LOAD_CURRENT_CAPABILITIES_STEP_LAST:
g_assert (priv->feature_nas_tp != FEATURE_UNKNOWN);
g_assert (priv->feature_nas_ssp != FEATURE_UNKNOWN);
- priv->current_capabilities = mm_modem_capability_from_qmi_capabilities_context (&ctx->capabilities_context, self);
+
+ /* At this point we can already know if this is a multimode device or not */
+ if ((ctx->capabilities_context.dms_capabilities & MM_MODEM_CAPABILITY_MULTIMODE) == MM_MODEM_CAPABILITY_MULTIMODE)
+ priv->multimode = ctx->capabilities_context.multimode = TRUE;
+
+ priv->current_capabilities = mm_current_capability_from_qmi_current_capabilities_context (&ctx->capabilities_context, self);
+
g_task_return_int (task, priv->current_capabilities);
g_object_unref (task);
return;
@@ -1103,12 +1109,11 @@
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
- Private *priv;
- MMModemCapability mask;
- MMModemCapability single;
- GArray *supported_combinations;
- guint i;
+ GTask *task;
+ Private *priv;
+ GArray *supported_combinations;
+ guint i;
+ MMQmiSupportedCapabilitiesContext ctx = { 0 };
task = g_task_new (self, NULL, callback, user_data);
@@ -1122,53 +1127,16 @@
}
/* Build mask with all supported capabilities */
- mask = MM_MODEM_CAPABILITY_NONE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_NONE;
for (i = 0; i < priv->supported_radio_interfaces->len; i++)
- mask |= mm_modem_capability_from_qmi_radio_interface (g_array_index (priv->supported_radio_interfaces, QmiDmsRadioInterface, i), self);
+ ctx.dms_capabilities |= mm_modem_capability_from_qmi_radio_interface (g_array_index (priv->supported_radio_interfaces, QmiDmsRadioInterface, i), self);
- supported_combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemCapability), 3);
+ ctx.nas_tp_supported = (priv->feature_nas_tp == FEATURE_SUPPORTED);
+ ctx.nas_ssp_supported = (priv->feature_nas_ssp == FEATURE_SUPPORTED);
+ ctx.multimode = priv->multimode;
- /* Add all possible supported capability combinations.
- * In order to avoid unnecessary modem reboots, we will only implement capabilities
- * switching only when switching GSM/UMTS+CDMA/EVDO multimode devices, and only if
- * we have support for the commands doing it.
- */
- if (priv->feature_nas_tp == FEATURE_SUPPORTED || priv->feature_nas_ssp == FEATURE_SUPPORTED) {
- if (mask == (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO)) {
- /* Multimode GSM/UMTS+CDMA/EVDO device switched to GSM/UMTS only */
- single = MM_MODEM_CAPABILITY_GSM_UMTS;
- g_array_append_val (supported_combinations, single);
- /* Multimode GSM/UMTS+CDMA/EVDO device switched to CDMA/EVDO only */
- single = MM_MODEM_CAPABILITY_CDMA_EVDO;
- g_array_append_val (supported_combinations, single);
- } else if (mask == (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE)) {
- /* Multimode GSM/UMTS+CDMA/EVDO+LTE device switched to GSM/UMTS+LTE only */
- single = MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE;
- g_array_append_val (supported_combinations, single);
- /* Multimode GSM/UMTS+CDMA/EVDO+LTE device switched to CDMA/EVDO+LTE only */
- single = MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE;
- g_array_append_val (supported_combinations, single);
- /*
- * Multimode GSM/UMTS+CDMA/EVDO+LTE device switched to LTE only.
- *
- * This case is required because we use the same methods and operations to
- * switch capabilities and modes. For the LTE capability there is a direct
- * related 4G mode, and so we cannot select a '4G only' mode in this device
- * because we wouldn't be able to know the full list of current capabilities
- * if the device was rebooted, as we would only see LTE capability. So,
- * handle this special case so that the LTE/4G-only mode can exclusively be
- * selected as capability switching in this kind of devices.
- */
- priv->disable_4g_only_mode = TRUE;
- single = MM_MODEM_CAPABILITY_LTE;
- g_array_append_val (supported_combinations, single);
- }
- }
-
- /* Add the full mask itself */
- single = mask;
- g_array_append_val (supported_combinations, single);
-
+ /* Build list of supported combinations */
+ supported_combinations = mm_supported_capabilities_from_qmi_supported_capabilities_context (&ctx, self);
g_task_return_pointer (task, supported_combinations, (GDestroyNotify) g_array_unref);
g_object_unref (task);
}
@@ -1718,106 +1686,38 @@
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
- GArray *combinations;
- MMModemModeCombination mode;
- Private *priv;
- MMModemMode mask_all;
- guint i;
- GArray *all;
- GArray *filtered;
+ GTask *task;
+ Private *priv;
+ MMQmiSupportedModesContext ctx = { 0 };
+ guint i;
+ GArray *combinations;
task = g_task_new (self, NULL, callback, user_data);
priv = get_private (MM_SHARED_QMI (self));
g_assert (priv->supported_radio_interfaces);
+ g_assert (priv->current_capabilities);
/* Build all, based on the supported radio interfaces */
- mask_all = MM_MODEM_MODE_NONE;
+ ctx.all = MM_MODEM_MODE_NONE;
for (i = 0; i < priv->supported_radio_interfaces->len; i++)
- mask_all |= mm_modem_mode_from_qmi_radio_interface (g_array_index (priv->supported_radio_interfaces, QmiDmsRadioInterface, i), self);
- mode.allowed = mask_all;
- mode.preferred = MM_MODEM_MODE_NONE;
- all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
- g_array_append_val (all, mode);
+ ctx.all |= mm_modem_mode_from_qmi_radio_interface (g_array_index (priv->supported_radio_interfaces, QmiDmsRadioInterface, i), self);
- /* If SSP and TP are not supported, ignore supported mode management */
- if (priv->feature_nas_ssp == FEATURE_UNSUPPORTED && priv->feature_nas_tp == FEATURE_UNSUPPORTED) {
- g_task_return_pointer (task, all, (GDestroyNotify) g_array_unref);
- g_object_unref (task);
- return;
- }
+ /* Filter out those unsupported by the current capabilities */
+ if (!(priv->current_capabilities & (MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO)))
+ ctx.all &= ~(MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ else if (!(priv->current_capabilities & MM_MODEM_CAPABILITY_LTE))
+ ctx.all &= ~MM_MODEM_MODE_4G;
+ else if (!(priv->current_capabilities & MM_MODEM_CAPABILITY_5GNR))
+ ctx.all &= ~MM_MODEM_MODE_5G;
- combinations = g_array_new (FALSE, FALSE, sizeof (MMModemModeCombination));
+ ctx.nas_ssp_supported = (priv->feature_nas_ssp == FEATURE_SUPPORTED);
+ ctx.nas_tp_supported = (priv->feature_nas_tp == FEATURE_SUPPORTED);
+ ctx.current_capabilities = priv->current_capabilities;
+ ctx.multimode = priv->multimode;
-#define ADD_MODE_PREFERENCE(MODE1, MODE2, MODE3, MODE4) do { \
- mode.allowed = MODE1; \
- if (MODE2 != MM_MODEM_MODE_NONE) { \
- mode.allowed |= MODE2; \
- if (MODE3 != MM_MODEM_MODE_NONE) { \
- mode.allowed |= MODE3; \
- if (MODE4 != MM_MODEM_MODE_NONE) \
- mode.allowed |= MODE4; \
- } \
- if (priv->feature_nas_ssp != FEATURE_UNSUPPORTED) { \
- if (MODE3 != MM_MODEM_MODE_NONE) { \
- if (MODE4 != MM_MODEM_MODE_NONE) { \
- mode.preferred = MODE4; \
- g_array_append_val (combinations, mode); \
- } \
- mode.preferred = MODE3; \
- g_array_append_val (combinations, mode); \
- } \
- mode.preferred = MODE2; \
- g_array_append_val (combinations, mode); \
- mode.preferred = MODE1; \
- g_array_append_val (combinations, mode); \
- } else { \
- mode.preferred = MM_MODEM_MODE_NONE; \
- g_array_append_val (combinations, mode); \
- } \
- } else { \
- mode.allowed = MODE1; \
- mode.preferred = MM_MODEM_MODE_NONE; \
- g_array_append_val (combinations, mode); \
- } \
- } while (0)
-
- /* 2G-only, 3G-only */
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
-
- /* 4G-only mode is not possible in multimode GSM/UMTS+CDMA/EVDO+LTE
- * devices. This configuration may be selected as "LTE only" capability
- * instead. */
- if (!priv->disable_4g_only_mode)
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
-
- /* 2G, 3G, 4G combinations */
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE);
-
- /* 5G related mode combinations are only supported when NAS SSP is supported,
- * as there is no 5G support in NAS TP. */
- if (priv->feature_nas_ssp != FEATURE_UNSUPPORTED) {
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G, MM_MODEM_MODE_NONE);
- ADD_MODE_PREFERENCE (MM_MODEM_MODE_2G, MM_MODEM_MODE_3G, MM_MODEM_MODE_4G, MM_MODEM_MODE_5G);
- }
-
- /* Filter out unsupported modes */
- filtered = mm_filter_supported_modes (all, combinations, self);
- g_array_unref (all);
- g_array_unref (combinations);
-
- g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref);
+ combinations = mm_supported_modes_from_qmi_supported_modes_context (&ctx, self);
+ g_task_return_pointer (task, combinations, (GDestroyNotify) g_array_unref);
g_object_unref (task);
}
diff --git a/src/mm-sim-mbim.c b/src/mm-sim-mbim.c
index b04c35f..b0addb2 100644
--- a/src/mm-sim-mbim.c
+++ b/src/mm-sim-mbim.c
@@ -78,6 +78,24 @@
return TRUE;
}
+static void
+update_modem_unlock_retries (MMSimMbim *self,
+ MbimPinType pin_type,
+ guint32 remaining_attempts)
+{
+ MMBaseModem *modem = NULL;
+
+ g_object_get (G_OBJECT (self),
+ MM_BASE_SIM_MODEM, &modem,
+ NULL);
+ g_assert (MM_IS_BASE_MODEM (modem));
+
+ mm_broadband_modem_mbim_set_unlock_retries (MM_BROADBAND_MODEM_MBIM (modem),
+ mm_modem_lock_from_mbim_pin_type (pin_type),
+ remaining_attempts);
+ g_object_unref (modem);
+}
+
/*****************************************************************************/
/* Preload subscriber info */
@@ -786,6 +804,8 @@
&pin_state,
&remaining_attempts,
NULL)) {
+ update_modem_unlock_retries (self, pin_type, remaining_attempts);
+
if (!success) {
/* Sending PIN failed, build a better error to report */
if (pin_type == MBIM_PIN_TYPE_PIN1 && pin_state == MBIM_PIN_STATE_LOCKED) {
@@ -881,6 +901,8 @@
&pin_state,
&remaining_attempts,
NULL)) {
+ update_modem_unlock_retries (self, pin_type, remaining_attempts);
+
if (!success) {
/* Sending PUK failed, build a better error to report */
if (pin_type == MBIM_PIN_TYPE_PUK1 && pin_state == MBIM_PIN_STATE_LOCKED) {
@@ -958,12 +980,25 @@
GAsyncResult *res,
GTask *task)
{
+ MMSimMbim *self;
GError *error = NULL;
MbimMessage *response;
+ MbimPinType pin_type;
+ guint32 remaining_attempts;
+
+ self = g_task_get_source_object (task);
response = mbim_device_command_finish (device, res, &error);
if (response) {
mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error);
+
+ if (mbim_message_pin_response_parse (response,
+ &pin_type,
+ NULL,
+ &remaining_attempts,
+ NULL))
+ update_modem_unlock_retries (self, pin_type, remaining_attempts);
+
mbim_message_unref (response);
}
@@ -1036,12 +1071,25 @@
GAsyncResult *res,
GTask *task)
{
+ MMSimMbim *self;
GError *error = NULL;
MbimMessage *response;
+ MbimPinType pin_type;
+ guint32 remaining_attempts;
+
+ self = g_task_get_source_object (task);
response = mbim_device_command_finish (device, res, &error);
if (response) {
mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error);
+
+ if (mbim_message_pin_response_parse (response,
+ &pin_type,
+ NULL,
+ &remaining_attempts,
+ NULL))
+ update_modem_unlock_retries (self, pin_type, remaining_attempts);
+
mbim_message_unref (response);
}
diff --git a/src/tests/test-modem-helpers-qmi.c b/src/tests/test-modem-helpers-qmi.c
index fbd6cdb..f49e1e8 100644
--- a/src/tests/test-modem-helpers-qmi.c
+++ b/src/tests/test-modem-helpers-qmi.c
@@ -11,6 +11,7 @@
* GNU General Public License for more details:
*
* Copyright (C) 2012 Lanedo GmbH.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <glib.h>
@@ -19,28 +20,65 @@
#include <stdlib.h>
#include <locale.h>
+#include <ModemManager.h>
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
#include "mm-enums-types.h"
#include "mm-modem-helpers-qmi.h"
#include "mm-log-test.h"
static void
-test_capabilities_expected (MMQmiCapabilitiesContext *ctx,
- MMModemCapability expected)
+test_current_capabilities_expected (MMQmiCurrentCapabilitiesContext *ctx,
+ MMModemCapability expected)
{
- MMModemCapability built;
- gchar *expected_str;
- gchar *built_str;
+ MMModemCapability built;
+ g_autofree gchar *expected_str = NULL;
+ g_autofree gchar *built_str = NULL;
- built = mm_modem_capability_from_qmi_capabilities_context (ctx, NULL);
+ built = mm_current_capability_from_qmi_current_capabilities_context (ctx, NULL);
expected_str = mm_modem_capability_build_string_from_mask (expected);
built_str = mm_modem_capability_build_string_from_mask (built);
/* compare strings, so that the error shows the string values as well */
g_assert_cmpstr (built_str, ==, expected_str);
+}
- g_free (expected_str);
- g_free (built_str);
+static void
+test_supported_capabilities_expected (MMQmiSupportedCapabilitiesContext *ctx,
+ const MMModemCapability *expected_capabilities,
+ guint n_expected_capabilities)
+{
+ g_autoptr(GArray) built = NULL;
+ g_autofree gchar *expected_str = NULL;
+ g_autofree gchar *built_str = NULL;
+
+ built = mm_supported_capabilities_from_qmi_supported_capabilities_context (ctx, NULL);
+
+ expected_str = mm_common_build_capabilities_string (expected_capabilities, n_expected_capabilities);
+ built_str = mm_common_build_capabilities_string ((MMModemCapability *)built->data, built->len);
+
+ /* compare strings, so that the error shows the string values as well */
+ g_assert_cmpstr (built_str, ==, expected_str);
+}
+
+static void
+test_supported_modes_expected (MMQmiSupportedModesContext *ctx,
+ const MMModemModeCombination *expected_modes,
+ guint n_expected_modes)
+{
+ g_autoptr(GArray) built = NULL;
+ g_autofree gchar *expected_str = NULL;
+ g_autofree gchar *built_str = NULL;
+
+ built = mm_supported_modes_from_qmi_supported_modes_context (ctx, NULL);
+
+ expected_str = mm_common_build_mode_combinations_string (expected_modes, n_expected_modes);
+ built_str = mm_common_build_mode_combinations_string ((MMModemModeCombination *)built->data, built->len);
+
+ /* compare strings, so that the error shows the string values as well */
+ g_assert_cmpstr (built_str, ==, expected_str);
}
/*****************************************************************************/
@@ -57,9 +95,11 @@
*/
static void
-test_uml290 (void)
+test_current_capabilities_uml290 (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = TRUE;
/* QCDM -> CDMA/EVDO */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X |
@@ -68,7 +108,9 @@
ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
MM_MODEM_CAPABILITY_CDMA_EVDO |
MM_MODEM_CAPABILITY_LTE);
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE));
/* QCDM -> GSM/UMTS */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_GSM |
@@ -77,7 +119,9 @@
ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
MM_MODEM_CAPABILITY_CDMA_EVDO |
MM_MODEM_CAPABILITY_LTE);
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE));
/* QCDM -> Automatic */
ctx.nas_ssp_mode_preference_mask = 0;
@@ -85,10 +129,147 @@
ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
MM_MODEM_CAPABILITY_CDMA_EVDO |
MM_MODEM_CAPABILITY_LTE);
- test_capabilities_expected (&ctx,
- (MM_MODEM_CAPABILITY_GSM_UMTS |
- MM_MODEM_CAPABILITY_CDMA_EVDO |
- MM_MODEM_CAPABILITY_LTE));
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE));
+}
+
+static void
+test_supported_capabilities_uml290 (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE,
+ MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE,
+ MM_MODEM_CAPABILITY_LTE,
+ MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE,
+ };
+
+ ctx.multimode = TRUE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_uml290_cdma_evdo_gsm_umts_lte (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ /* we MUST not have 4G-only in multimode devices */
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_supported_modes_uml290_cdma_evdo_lte (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ /* we MUST not have 4G-only in multimode devices */
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_supported_modes_uml290_gsm_umts_lte (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ /* we MUST not have 4G-only in multimode devices */
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_supported_modes_uml290_lte (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ /* we MUST only have 4G-only in a multimode device with only LTE capability */
+ { .allowed = MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_4G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_LTE;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -102,19 +283,60 @@
*/
static void
-test_adu960s (void)
+test_current_capabilities_adu960s (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
- ctx.nas_ssp_mode_preference_mask = 0;
+ ctx.multimode = TRUE;
+ ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = 0; /* Unsupported */
ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
MM_MODEM_CAPABILITY_CDMA_EVDO |
MM_MODEM_CAPABILITY_LTE);
- test_capabilities_expected (&ctx,
- (MM_MODEM_CAPABILITY_GSM_UMTS |
- MM_MODEM_CAPABILITY_CDMA_EVDO |
- MM_MODEM_CAPABILITY_LTE));
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE));
+}
+
+static void
+test_supported_capabilities_adu960s (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE,
+ };
+
+ ctx.multimode = TRUE;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_adu960s (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = FALSE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -127,14 +349,54 @@
*/
static void
-test_gobi1k_gsm (void)
+test_current_capabilities_gobi1k_gsm (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+ ctx.multimode = FALSE;
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+}
+
+static void
+test_supported_capabilities_gobi1k_gsm (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi1k_gsm (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -147,14 +409,54 @@
*/
static void
-test_gobi1k_cdma (void)
+test_current_capabilities_gobi1k_cdma (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+ ctx.multimode = FALSE;
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+}
+
+static void
+test_supported_capabilities_gobi1k_cdma (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_CDMA_EVDO,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi1k_cdma (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -169,27 +471,68 @@
*/
static void
-test_gobi2k_gsm (void)
+test_current_capabilities_gobi2k_gsm (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
/* QCDM -> Automatic */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
/* QCDM -> UMTS only */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
/* QCDM -> GPRS only */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+}
+
+static void
+test_supported_capabilities_gobi2k_gsm (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi2k_gsm (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -204,27 +547,68 @@
*/
static void
-test_gobi2k_cdma (void)
+test_current_capabilities_gobi2k_cdma (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
/* QCDM -> Automatic */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
/* QCDM -> CDMA only */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
/* QCDM -> EVDO only */
ctx.nas_ssp_mode_preference_mask = 0; /* Unsupported */
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+}
+
+static void
+test_supported_capabilities_gobi2k_cdma (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_CDMA_EVDO,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi2k_cdma (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = FALSE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -241,9 +625,11 @@
*/
static void
-test_gobi3k_gsm (void)
+test_current_capabilities_gobi3k_gsm (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
/* QCDM -> Automatic */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X |
@@ -252,19 +638,59 @@
QMI_NAS_RAT_MODE_PREFERENCE_UMTS);
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
/* QCDM -> GSM only */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_GSM);
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
/* QCDM -> UMTS only */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_UMTS);
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_GSM_UMTS);
+}
+
+static void
+test_supported_capabilities_gobi3k_gsm (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi3k_gsm (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -281,9 +707,11 @@
*/
static void
-test_gobi3k_cdma (void)
+test_current_capabilities_gobi3k_cdma (void)
{
- MMQmiCapabilitiesContext ctx;
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
/* QCDM -> Automatic */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X |
@@ -292,19 +720,615 @@
QMI_NAS_RAT_MODE_PREFERENCE_UMTS);
ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
/* QCDM -> CDMA only */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X);
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
/* QCDM -> EVDO only */
ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO);
ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR);
ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
- test_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_CDMA_EVDO);
+}
+
+static void
+test_supported_capabilities_gobi3k_cdma (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_CDMA_EVDO,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_gobi3k_cdma (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_CDMA_EVDO;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+/*****************************************************************************/
+/* Generic with NR5G:
+ * ∘ +GCAP: +CGSM
+ * ∘ +WS46: (12,22,25,28,29,30,31)
+ * ∘ DMS GetCapa: Networks: 'cdma20001x, evdo, gsm, umts, lte, 5gnr'
+ * ∘ QMI -> Automatic = NAS TP: Active: 'auto', duration: 'permanent'
+ * NAS SSP: Mode preference: 'cdma-1x, cdma-1xevdo, gsm, umts, lte, td-scdma, 5gnr'
+ * ∘ QMI -> GSM only = NAS TP: Active: '3gpp, amps-or-gsm', duration: 'permanent'
+ * NAS SSP: Mode preference: 'gsm'
+ * ∘ QMI -> UMTS only = NAS TP: Active: '3gpp, cdma-or-wcdma', duration: 'permanent'
+ * NAS SSP: Mode preference: 'umts'
+ * ∘ QMI -> EVDO only = NAS TP: Active: '3gpp2, hdr', duration: 'permanent'
+ * NAS SSP: Mode preference: 'cdma-1xevdo'
+ * ∘ QMI -> CDMA only = NAS TP: Active: '3gpp2, cdma-or-wcdma', duration: 'permanent'
+ * NAS SSP: Mode preference: 'cdma-1x'
+ * ∘ QMI -> LTE only = NAS TP: Active: '3gpp, lte', duration: 'permanent'
+ * NAS SSP: Mode preference: 'lte'
+ * ∘ QMI -> 5GNR only = NAS TP: Active: 'auto', duration: 'permanent'
+ * NAS SSP: Mode preference: '5gnr'
+ */
+
+static void
+test_current_capabilities_generic_nr5g_multimode (void)
+{
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = TRUE;
+
+ /* QMI -> Automatic */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X |
+ QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO |
+ QMI_NAS_RAT_MODE_PREFERENCE_GSM |
+ QMI_NAS_RAT_MODE_PREFERENCE_UMTS |
+ QMI_NAS_RAT_MODE_PREFERENCE_LTE |
+ QMI_NAS_RAT_MODE_PREFERENCE_TD_SCDMA |
+ QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> GSM only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_GSM);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AMPS_OR_GSM);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> UMTS only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_UMTS);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> EVDO only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> CDMA only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1X);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> LTE only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_LTE);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> 5GNR only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+}
+
+static void
+test_supported_capabilities_generic_nr5g_multimode (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_CDMA_EVDO | MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ };
+
+ ctx.multimode = TRUE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_generic_nr5g_multimode (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ /* we MUST not have 4G-only in multimode devices */
+ /* we MUST not have 5G-only in multimode devices */
+ /* we MUST not have 4G+5G in multimode devices */
+ { .allowed = MM_MODEM_MODE_2G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_2G },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_2G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_2G },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_2G },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+ { .allowed = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_2G },
+ };
+
+ ctx.multimode = TRUE;
+ ctx.all = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_current_capabilities_generic_nr5g_only (void)
+{
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_mode_preference_mask = QMI_NAS_RAT_MODE_PREFERENCE_5GNR;
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_5GNR;
+ test_current_capabilities_expected (&ctx, MM_MODEM_CAPABILITY_5GNR);
+}
+
+static void
+test_supported_capabilities_generic_nr5g_only (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_5GNR,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = MM_MODEM_CAPABILITY_5GNR;
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_generic_nr5g_only (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_NONE },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_5G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = MM_MODEM_CAPABILITY_5GNR;
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_current_capabilities_generic_nr5g_lte (void)
+{
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
+
+ /* QMI -> Automatic */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_LTE |
+ QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> LTE only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_LTE);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> 5GNR only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+}
+
+static void
+test_supported_capabilities_generic_nr5g_lte (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_generic_nr5g_lte (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_NONE },
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_current_capabilities_generic_nr5g_lte_umts (void)
+{
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
+
+ /* QMI -> Automatic */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_UMTS |
+ QMI_NAS_RAT_MODE_PREFERENCE_LTE |
+ QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> UMTS only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_UMTS);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_CDMA_OR_WCDMA);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> LTE only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_LTE);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> 5GNR only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+}
+
+static void
+test_supported_capabilities_generic_nr5g_lte_umts (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_GSM_UMTS |MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_generic_nr5g_lte_umts (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ /* we MUST have 4G-only in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_NONE },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+
+ /* we MUST have 5G-only in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_NONE },
+
+ /* we MUST have 4G+5G in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_GSM_UMTS |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
+}
+
+static void
+test_current_capabilities_generic_nr5g_lte_evdo (void)
+{
+ MMQmiCurrentCapabilitiesContext ctx;
+
+ ctx.multimode = FALSE;
+
+ /* QMI -> Automatic */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO |
+ QMI_NAS_RAT_MODE_PREFERENCE_LTE |
+ QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> EVDO only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_CDMA_1XEVDO);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP2 | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_HDR);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> LTE only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_LTE);
+ ctx.nas_tp_mask = (QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_3GPP | QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_LTE);
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+
+ /* QMI -> 5GNR only */
+ ctx.nas_ssp_mode_preference_mask = (QMI_NAS_RAT_MODE_PREFERENCE_5GNR);
+ ctx.nas_tp_mask = QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+ test_current_capabilities_expected (&ctx,
+ (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR));
+}
+
+static void
+test_supported_capabilities_generic_nr5g_lte_evdo (void)
+{
+ MMQmiSupportedCapabilitiesContext ctx;
+ static const MMModemCapability expected_capabilities[] = {
+ MM_MODEM_CAPABILITY_CDMA_EVDO |MM_MODEM_CAPABILITY_LTE | MM_MODEM_CAPABILITY_5GNR,
+ };
+
+ ctx.multimode = FALSE;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.dms_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_capabilities_expected (&ctx,
+ expected_capabilities,
+ G_N_ELEMENTS (expected_capabilities));
+}
+
+static void
+test_supported_modes_generic_nr5g_lte_evdo (void)
+{
+ MMQmiSupportedModesContext ctx;
+ static const MMModemModeCombination expected_modes[] = {
+ { .allowed = MM_MODEM_MODE_3G, .preferred = MM_MODEM_MODE_NONE },
+ /* we MUST have 4G-only in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_NONE },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, .preferred = MM_MODEM_MODE_3G },
+
+ /* we MUST have 5G-only in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_NONE },
+
+ /* we MUST have 4G+5G in non-multimode devices */
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_5G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_4G },
+ { .allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G, .preferred = MM_MODEM_MODE_3G },
+ };
+
+ ctx.multimode = FALSE;
+ ctx.all = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G | MM_MODEM_MODE_5G;
+ ctx.nas_ssp_supported = TRUE;
+ ctx.nas_tp_supported = TRUE;
+ ctx.current_capabilities = (MM_MODEM_CAPABILITY_CDMA_EVDO |
+ MM_MODEM_CAPABILITY_LTE |
+ MM_MODEM_CAPABILITY_5GNR);
+
+ test_supported_modes_expected (&ctx,
+ expected_modes,
+ G_N_ELEMENTS (expected_modes));
}
/*****************************************************************************/
@@ -315,14 +1339,60 @@
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/MM/QMI/Current-Capabilities/UML290", test_uml290);
- g_test_add_func ("/MM/QMI/Current-Capabilities/ADU960S", test_adu960s);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi1k/GSM", test_gobi1k_gsm);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi1k/CDMA", test_gobi1k_cdma);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi2k/GSM", test_gobi2k_gsm);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi2k/CDMA", test_gobi2k_cdma);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi3k/GSM", test_gobi3k_gsm);
- g_test_add_func ("/MM/QMI/Current-Capabilities/Gobi3k/CDMA", test_gobi3k_cdma);
+ g_test_add_func ("/MM/qmi/current-capabilities/UML290", test_current_capabilities_uml290);
+ g_test_add_func ("/MM/qmi/supported-capabilities/UML290", test_supported_capabilities_uml290);
+ g_test_add_func ("/MM/qmi/supported-modes/UML290/cdma-evdo-gsm-umts-lte", test_supported_modes_uml290_cdma_evdo_gsm_umts_lte);
+ g_test_add_func ("/MM/qmi/supported-modes/UML290/cdma-evdo-lte", test_supported_modes_uml290_cdma_evdo_lte);
+ g_test_add_func ("/MM/qmi/supported-modes/UML290/gsm-umts-lte", test_supported_modes_uml290_gsm_umts_lte);
+ g_test_add_func ("/MM/qmi/supported-modes/UML290/lte", test_supported_modes_uml290_lte);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/ADU960S", test_current_capabilities_adu960s);
+ g_test_add_func ("/MM/qmi/supported-capabilities/ADU960S", test_supported_capabilities_adu960s);
+ g_test_add_func ("/MM/qmi/supported-modes/ADU960S", test_supported_modes_adu960s);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi1k/GSM", test_current_capabilities_gobi1k_gsm);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi1k/GSM", test_supported_capabilities_gobi1k_gsm);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi1k/GSM", test_supported_modes_gobi1k_gsm);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi1k/CDMA", test_current_capabilities_gobi1k_cdma);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi1k/CDMA", test_supported_capabilities_gobi1k_cdma);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi1k/CDMA", test_supported_modes_gobi1k_cdma);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi2k/GSM", test_current_capabilities_gobi2k_gsm);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi2k/GSM", test_supported_capabilities_gobi2k_gsm);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi2k/GSM", test_supported_modes_gobi2k_gsm);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi2k/CDMA", test_current_capabilities_gobi2k_cdma);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi2k/CDMA", test_supported_capabilities_gobi2k_cdma);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi2k/CDMA", test_supported_modes_gobi2k_cdma);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi3k/GSM", test_current_capabilities_gobi3k_gsm);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi3k/GSM", test_supported_capabilities_gobi3k_gsm);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi3k/GSM", test_supported_modes_gobi3k_gsm);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/Gobi3k/CDMA", test_current_capabilities_gobi3k_cdma);
+ g_test_add_func ("/MM/qmi/supported-capabilities/Gobi3k/CDMA", test_supported_capabilities_gobi3k_cdma);
+ g_test_add_func ("/MM/qmi/supported-modes/Gobi3k/CDMA", test_supported_modes_gobi3k_cdma);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/generic/nr5g-multimode", test_current_capabilities_generic_nr5g_multimode);
+ g_test_add_func ("/MM/qmi/supported-capabilities/generic/nr5g-multimode", test_supported_capabilities_generic_nr5g_multimode);
+ g_test_add_func ("/MM/qmi/supported-modes/generic/nr5g-multimode", test_supported_modes_generic_nr5g_multimode);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/generic/nr5g-only", test_current_capabilities_generic_nr5g_only);
+ g_test_add_func ("/MM/qmi/supported-capabilities/generic/nr5g-only", test_supported_capabilities_generic_nr5g_only);
+ g_test_add_func ("/MM/qmi/supported-modes/generic/nr5g-only", test_supported_modes_generic_nr5g_only);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/generic/nr5g-lte", test_current_capabilities_generic_nr5g_lte);
+ g_test_add_func ("/MM/qmi/supported-capabilities/generic/nr5g-lte", test_supported_capabilities_generic_nr5g_lte);
+ g_test_add_func ("/MM/qmi/supported-modes/generic/nr5g-lte", test_supported_modes_generic_nr5g_lte);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/generic/nr5g-lte-umts", test_current_capabilities_generic_nr5g_lte_umts);
+ g_test_add_func ("/MM/qmi/supported-capabilities/generic/nr5g-lte-umts", test_supported_capabilities_generic_nr5g_lte_umts);
+ g_test_add_func ("/MM/qmi/supported-modes/generic/nr5g-lte-umts", test_supported_modes_generic_nr5g_lte_umts);
+
+ g_test_add_func ("/MM/qmi/current-capabilities/generic/nr5g-lte-evdo", test_current_capabilities_generic_nr5g_lte_evdo);
+ g_test_add_func ("/MM/qmi/supported-capabilities/generic/nr5g-lte-evdo", test_supported_capabilities_generic_nr5g_lte_evdo);
+ g_test_add_func ("/MM/qmi/supported-modes/generic/nr5g-lte-evdo", test_supported_modes_generic_nr5g_lte_evdo);
return g_test_run ();
}
diff --git a/test/mmcli-test-sms b/test/mmcli-test-sms
index 038d777..8229d36 100755
--- a/test/mmcli-test-sms
+++ b/test/mmcli-test-sms
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
print_usage () {
echo "usage: $0 [MODEM INDEX] [all|ucs2|gsm7|data] [NUMBER]"
diff --git a/tools/tests/test-wrapper.sh.in b/tools/tests/test-wrapper.sh.in
old mode 100644
new mode 100755
index d64ea4c..fcdb56d
--- a/tools/tests/test-wrapper.sh.in
+++ b/tools/tests/test-wrapper.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# For debugging behavior of test-modemmanager-service.py, you can modify
# this line to add --log-file option