summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-10-21 00:10:06 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-10-21 00:10:06 +0200
commit53bcdaa8c3962abbf2a2f638c64173a7657ab560 (patch)
treed300154dd13082eaa5790c20157641a669ff4c17
parentbcdaaeddb00c13e29ba435d1bc4b4cb71101661d (diff)
broadband-modem-mbim: update extended signal info on MBIM notifications
We process the MBIM signal state notification and use it to update the extended signal quality information in the Signal interface.
-rw-r--r--src/mm-broadband-modem-mbim.c29
-rw-r--r--src/mm-modem-helpers-mbim.c236
-rw-r--r--src/mm-modem-helpers-mbim.h33
3 files changed, 291 insertions, 7 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index be2e7dd9..fef05d4a 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -3553,14 +3553,22 @@ basic_connect_notification_signal_state (MMBroadbandModemMbim *self,
g_autoptr(GError) error = NULL;
g_autoptr(MbimRsrpSnrInfoArray) rsrp_snr = NULL;
guint32 rsrp_snr_count = 0;
- guint32 rssi;
+ guint32 coded_rssi;
+ guint32 coded_error_rate;
guint32 quality;
+ MbimDataClass data_class;
+ g_autoptr(MMSignal) cdma = NULL;
+ g_autoptr(MMSignal) evdo = NULL;
+ g_autoptr(MMSignal) gsm = NULL;
+ g_autoptr(MMSignal) umts = NULL;
+ g_autoptr(MMSignal) lte = NULL;
+ g_autoptr(MMSignal) nr5g = NULL;
if (mbim_device_check_ms_mbimex_version (device, 2, 0)) {
if (!mbim_message_ms_basic_connect_v2_signal_state_notification_parse (
notification,
- &rssi,
- NULL, /* error_rate */
+ &coded_rssi,
+ &coded_error_rate,
NULL, /* signal_strength_interval */
NULL, /* rssi_threshold */
NULL, /* error_rate_threshold */
@@ -3574,8 +3582,8 @@ basic_connect_notification_signal_state (MMBroadbandModemMbim *self,
} else {
if (!mbim_message_signal_state_notification_parse (
notification,
- &rssi,
- NULL, /* error_rate */
+ &coded_rssi,
+ &coded_error_rate,
NULL, /* signal_strength_interval */
NULL, /* rssi_threshold */
NULL, /* error_rate_threshold */
@@ -3586,8 +3594,17 @@ basic_connect_notification_signal_state (MMBroadbandModemMbim *self,
mm_obj_dbg (self, "proccessed signal state indication");
}
- quality = mm_signal_quality_from_mbim_signal_state (rssi, rsrp_snr, rsrp_snr_count, self);
+ quality = mm_signal_quality_from_mbim_signal_state (coded_rssi, rsrp_snr, rsrp_snr_count, self);
mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
+
+ /* Best guess of current data class */
+ data_class = self->priv->highest_available_data_class;
+ if (data_class == 0)
+ data_class = self->priv->available_data_classes;
+
+ if (mm_signal_from_mbim_signal_state (data_class, coded_rssi, coded_error_rate, rsrp_snr, rsrp_snr_count,
+ self, &cdma, &evdo, &gsm, &umts, &lte, &nr5g))
+ mm_iface_modem_signal_update (MM_IFACE_MODEM_SIGNAL (self), cdma, evdo, gsm, umts, lte, nr5g);
}
static void
diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c
index 8157f9f6..25e87e0e 100644
--- a/src/mm-modem-helpers-mbim.c
+++ b/src/mm-modem-helpers-mbim.c
@@ -10,7 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ * Copyright (C) 2013-2021 Aleksander Morgado <aleksander@aleksander.es>
*/
#include "mm-modem-helpers-mbim.h"
@@ -558,6 +558,84 @@ mm_bearer_ip_family_to_mbim_context_ip_type (MMBearerIpFamily ip_family,
/*****************************************************************************/
+/* index in the array is the code point (8 possible values), and the actual
+ * value is the lower limit of the error rate range. */
+static const gdouble bit_error_rate_ranges[] = { 0.00, 0.20, 0.40, 0.80, 1.60, 3.20, 6.40, 12.80 };
+static const gdouble frame_error_rate_ranges[] = { 0.00, 0.01, 0.10, 0.50, 1.00, 2.00, 4.00, 8.00 };
+
+gboolean
+mm_signal_error_rate_percentage_from_coded_value (guint coded_value,
+ gdouble *out_percentage,
+ gboolean is_gsm,
+ GError **error)
+{
+ if ((is_gsm && (coded_value >= G_N_ELEMENTS (bit_error_rate_ranges))) ||
+ (!is_gsm && (coded_value >= G_N_ELEMENTS (frame_error_rate_ranges)))) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "error rate coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_percentage = (is_gsm ? bit_error_rate_ranges[coded_value] : frame_error_rate_ranges[coded_value]);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_rssi_from_coded_value (guint coded_value,
+ gdouble *out_rssi,
+ GError **error)
+{
+ /* expected values between 0 and 31 */
+ if (coded_value > 31) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "rssi coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_rssi = (gdouble)coded_value - 113;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_rsrp_from_coded_value (guint coded_value,
+ gdouble *out_rsrp,
+ GError **error)
+{
+ /* expected values between 0 and 126 */
+ if (coded_value > 126) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "rsrp coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_rsrp = (gdouble)coded_value - 156;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_snr_from_coded_value (guint coded_value,
+ gdouble *out_snr,
+ GError **error)
+{
+ /* expected values between 0 and 126 */
+ if (coded_value > 127) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "snr coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_snr = ((gdouble)coded_value)/2 - 23;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
MMSmsState
mm_sms_state_from_mbim_message_status (MbimSmsStatus status)
{
@@ -617,3 +695,159 @@ mm_signal_quality_from_mbim_signal_state (guint rssi,
return quality;
}
+
+static MMSignal **
+select_mbim_signal_with_data_class (MbimDataClass data_class,
+ MMSignal **cdma,
+ MMSignal **evdo,
+ MMSignal **gsm,
+ MMSignal **umts,
+ MMSignal **lte,
+ MMSignal **nr5g)
+{
+ switch (data_class) {
+ case MBIM_DATA_CLASS_5G_NSA:
+ case MBIM_DATA_CLASS_5G_SA:
+ return nr5g;
+ case MBIM_DATA_CLASS_LTE:
+ return lte;
+ case MBIM_DATA_CLASS_UMTS:
+ case MBIM_DATA_CLASS_HSDPA:
+ case MBIM_DATA_CLASS_HSUPA:
+ return umts;
+ case MBIM_DATA_CLASS_GPRS:
+ case MBIM_DATA_CLASS_EDGE:
+ return gsm;
+ case MBIM_DATA_CLASS_1XEVDO:
+ case MBIM_DATA_CLASS_1XEVDO_REVA:
+ case MBIM_DATA_CLASS_1XEVDV:
+ case MBIM_DATA_CLASS_3XRTT:
+ case MBIM_DATA_CLASS_1XEVDO_REVB:
+ return evdo;
+ case MBIM_DATA_CLASS_1XRTT:
+ return cdma;
+ case MBIM_DATA_CLASS_UMB:
+ case MBIM_DATA_CLASS_CUSTOM:
+ default:
+ return NULL;
+ }
+}
+
+gboolean
+mm_signal_from_mbim_signal_state (MbimDataClass data_class,
+ guint coded_rssi,
+ guint coded_error_rate,
+ MbimRsrpSnrInfoArray *rsrp_snr,
+ guint32 rsrp_snr_count,
+ gpointer log_object,
+ MMSignal **out_cdma,
+ MMSignal **out_evdo,
+ MMSignal **out_gsm,
+ MMSignal **out_umts,
+ MMSignal **out_lte,
+ MMSignal **out_nr5g)
+{
+ MMSignal **tmp;
+ MMSignal **last_updated = NULL;
+ guint n_out_updated = 0;
+
+ *out_cdma = NULL;
+ *out_evdo = NULL;
+ *out_gsm = NULL;
+ *out_umts = NULL;
+ *out_lte = NULL;
+ *out_nr5g = NULL;
+
+ /* When MBIMEx v2.0 is available, we get LTE+5GNR information reported
+ * in the RSRP/SNR list of items. */
+ if (rsrp_snr && rsrp_snr_count) {
+ guint i;
+
+ for (i = 0; i < rsrp_snr_count; i++) {
+ MbimRsrpSnrInfo *info;
+
+ info = rsrp_snr[i];
+
+ tmp = select_mbim_signal_with_data_class (info->system_type,
+ out_cdma, out_evdo,
+ out_gsm, out_umts, out_lte, out_nr5g);
+ if (!tmp || ((info->rsrp == 0xFFFFFFFF) && (info->snr == 0xFFFFFFFF)))
+ continue;
+
+ last_updated = tmp;
+ n_out_updated++;
+
+ *tmp = mm_signal_new ();
+
+ mm_signal_set_rsrp (*tmp, MM_SIGNAL_UNKNOWN);
+ if (info->rsrp != 0xFFFFFFFF) {
+ g_autoptr(GError) error = NULL;
+ gdouble rsrp;
+
+ if (!mm_signal_rsrp_from_coded_value (info->rsrp, &rsrp, &error))
+ mm_obj_dbg (log_object, "couldn't convert RSRP coded value '%u': %s", info->rsrp, error->message);
+ else
+ mm_signal_set_rsrp (*tmp, rsrp);
+ }
+
+ mm_signal_set_snr (*tmp, MM_SIGNAL_UNKNOWN);
+ if (info->snr != 0xFFFFFFFF) {
+ g_autoptr(GError) error = NULL;
+ gdouble snr;
+
+ if (!mm_signal_snr_from_coded_value (info->snr, &snr, &error))
+ mm_obj_dbg (log_object, "couldn't convert SNR coded value '%u': %s", info->snr, error->message);
+ else
+ mm_signal_set_snr (*tmp, snr);
+ }
+ }
+ }
+
+ /* The MBIM v1.0 details (RSSI, error rate) will only be set if
+ * the target access technology is known without any doubt.
+ * E.g. if we are in 5GNSA (4G+5G), we will only set the fields
+ * if one of them has valid values. If both have valid values,
+ * we'll skip updating RSSI and error rate, as we wouldn't know
+ * to which of them applies. */
+ if (n_out_updated > 1)
+ return TRUE;
+
+ if (n_out_updated == 0) {
+ tmp = select_mbim_signal_with_data_class (data_class,
+ out_cdma, out_evdo,
+ out_gsm, out_umts, out_lte, out_nr5g);
+ if (!tmp)
+ return FALSE;
+ *tmp = mm_signal_new ();
+ } else {
+ tmp = last_updated;
+ g_assert (tmp && *tmp);
+ }
+
+ mm_signal_set_error_rate (*tmp, MM_SIGNAL_UNKNOWN);
+ if (coded_error_rate != 99) {
+ g_autoptr(GError) error = NULL;
+ gdouble error_rate;
+
+ if (!mm_signal_error_rate_percentage_from_coded_value (coded_error_rate,
+ &error_rate,
+ data_class == (MBIM_DATA_CLASS_GPRS | MBIM_DATA_CLASS_EDGE),
+ &error))
+ mm_obj_dbg (log_object, "couldn't convert error rate coded value '%u': %s", coded_error_rate, error->message);
+ else
+ mm_signal_set_error_rate (*tmp, error_rate);
+ }
+
+ mm_signal_set_rssi (*tmp, MM_SIGNAL_UNKNOWN);
+ if (coded_rssi != 99) {
+ g_autoptr(GError) error = NULL;
+ gdouble rssi;
+
+ if (!mm_signal_rssi_from_coded_value (coded_rssi, &rssi, &error))
+ mm_obj_dbg (log_object, "couldn't convert RSSI coded value '%u': %s", coded_rssi, error->message);
+ else
+ mm_signal_set_rssi (*tmp, rssi);
+ }
+
+ return TRUE;
+}
diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h
index a2b9aee0..2c3d2bae 100644
--- a/src/mm-modem-helpers-mbim.h
+++ b/src/mm-modem-helpers-mbim.h
@@ -19,6 +19,9 @@
#include <config.h>
#include <ModemManager.h>
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
#include <libmbim-glib.h>
/*****************************************************************************/
@@ -61,6 +64,23 @@ MbimContextType mm_bearer_apn_type_to_mbim_context_type (MMBearerApnT
gpointer log_object,
GError **error);
+gboolean mm_signal_error_rate_percentage_from_coded_value (guint coded_value,
+ gdouble *out_percentage,
+ gboolean is_gsm,
+ GError **error);
+
+gboolean mm_signal_rssi_from_coded_value (guint coded_value,
+ gdouble *out_rssi,
+ GError **error);
+
+gboolean mm_signal_rsrp_from_coded_value (guint coded_value,
+ gdouble *out_rsrp,
+ GError **error);
+
+gboolean mm_signal_snr_from_coded_value (guint coded_value,
+ gdouble *out_snr,
+ GError **error);
+
/*****************************************************************************/
/* MBIM/SMS to MM translations */
@@ -73,4 +93,17 @@ guint mm_signal_quality_from_mbim_signal_state (guint rssi,
guint32 rsrp_snr_count,
gpointer log_object);
+gboolean mm_signal_from_mbim_signal_state (MbimDataClass data_class,
+ guint coded_rssi,
+ guint coded_error_rate,
+ MbimRsrpSnrInfoArray *rsrp_snr,
+ guint32 rsrp_snr_count,
+ gpointer log_object,
+ MMSignal **out_cdma,
+ MMSignal **out_evdo,
+ MMSignal **out_gsm,
+ MMSignal **out_umts,
+ MMSignal **out_lte,
+ MMSignal **out_nr5g);
+
#endif /* MM_MODEM_HELPERS_MBIM_H */