aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-04-09 14:10:32 -0500
committerDan Williams <dcbw@redhat.com>2013-04-09 14:10:32 -0500
commit243360caacc7ab96d8aac9c481df0a2c961a67ba (patch)
tree5a6f8727a8d4ac7c54f5f4ec3d17cf6663229481
parent4d31315b959ce87e242070842cd9fe3c234fa7e7 (diff)
broadband-modem-qmi: ignore invalid signal strengthsdcbw/qmi-signal-strength
Sometimes invalid signal strengths will be returned by the modem, which we should ignore. Otherwise they make the reported signal quality bounce around from eg 21% -> 100%, or cause access technology updates for radio interfaces that can't possible have a usable signal.
-rw-r--r--src/mm-broadband-modem-qmi.c158
1 files changed, 109 insertions, 49 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index c33f707d..6afecdeb 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -1824,6 +1824,22 @@ modem_load_supported_modes (MMIfaceModem *self,
#define STRENGTH_TO_QUALITY(strength) \
(guint8)(100 - ((CLAMP (strength, -113, -51) + 51) * 100 / (-113 + 51)))
+static gboolean
+qmi_dbm_valid (gint8 dbm, QmiNasRadioInterface radio_interface)
+{
+ /* Different radio interfaces have different signal quality bounds */
+ switch (radio_interface) {
+ case QMI_NAS_RADIO_INTERFACE_CDMA_1X:
+ case QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO:
+ return (dbm > -125 && dbm < -30);
+ case QMI_NAS_RADIO_INTERFACE_UMTS:
+ return (dbm > -125 && dbm < -30);
+ default:
+ break;
+ }
+ return TRUE;
+}
+
typedef struct {
MMBroadbandModemQmi *self;
QmiClient *client;
@@ -1854,47 +1870,55 @@ load_signal_quality_finish (MMIfaceModem *self,
#if defined WITH_NEWEST_QMI_COMMANDS
-static gint8
+static gboolean
signal_info_get_quality (MMBroadbandModemQmi *self,
- QmiMessageNasGetSignalInfoOutput *output)
+ QmiMessageNasGetSignalInfoOutput *output,
+ gint8 *out_quality)
{
gint8 rssi_max = 0;
gint8 rssi;
- guint8 quality;
+
+ g_assert (out_quality != NULL);
/* We do not report per-technology signal quality, so just get the highest
* one of the ones reported. */
if (qmi_message_nas_get_signal_info_output_get_cdma_signal_strength (output, &rssi, NULL, NULL)) {
mm_dbg ("RSSI (CDMA): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_CDMA_1X))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_message_nas_get_signal_info_output_get_hdr_signal_strength (output, &rssi, NULL, NULL, NULL, NULL)) {
mm_dbg ("RSSI (HDR): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_message_nas_get_signal_info_output_get_gsm_signal_strength (output, &rssi, NULL)) {
mm_dbg ("RSSI (GSM): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_GSM))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_message_nas_get_signal_info_output_get_wcdma_signal_strength (output, &rssi, NULL, NULL)) {
mm_dbg ("RSSI (WCDMA): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_UMTS))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_message_nas_get_signal_info_output_get_lte_signal_strength (output, &rssi, NULL, NULL, NULL, NULL)) {
mm_dbg ("RSSI (LTE): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_LTE))
+ rssi = MAX (rssi, rssi_max);
}
/* This RSSI comes as negative dBms */
- quality = STRENGTH_TO_QUALITY (rssi_max);
+ *out_quality = STRENGTH_TO_QUALITY (rssi_max);
+
+ mm_dbg ("RSSI: %d dBm --> %u%%", rssi_max, *out_quality);
- mm_dbg ("RSSI: %d dBm --> %u%%", rssi_max, quality);
- return quality;
+ return (rssi_max < 0);
}
static void
@@ -1904,7 +1928,7 @@ get_signal_info_ready (QmiClientNas *client,
{
QmiMessageNasGetSignalInfoOutput *output;
GError *error = NULL;
- guint quality;
+ guint quality = 0;
output = qmi_client_nas_get_signal_info_finish (client, res, &error);
if (!output) {
@@ -1920,7 +1944,15 @@ get_signal_info_ready (QmiClientNas *client,
return;
}
- quality = signal_info_get_quality (ctx->self, output);
+ if (!signal_info_get_quality (ctx->self, output, &quality)) {
+ qmi_message_nas_get_signal_info_output_unref (output);
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Signal info reported invalid signal strength.");
+ load_signal_quality_context_complete_and_free (ctx);
+ return;
+ }
g_simple_async_result_set_op_res_gpointer (
ctx->result,
@@ -1933,17 +1965,16 @@ get_signal_info_ready (QmiClientNas *client,
#endif /* WITH_NEWEST_QMI_COMMANDS */
-static void
+static gboolean
signal_strength_get_quality_and_access_tech (MMBroadbandModemQmi *self,
QmiMessageNasGetSignalStrengthOutput *output,
guint8 *o_quality,
MMModemAccessTechnology *o_act)
{
GArray *array = NULL;
- gint8 signal_max;
+ gint8 signal_max = 0;
QmiNasRadioInterface main_interface;
MMModemAccessTechnology act;
- guint8 quality;
/* We do not report per-technology signal quality, so just get the highest
* one of the ones reported. */
@@ -1954,6 +1985,10 @@ signal_strength_get_quality_and_access_tech (MMBroadbandModemQmi *self,
qmi_nas_radio_interface_get_string (main_interface),
signal_max);
+ /* Treat results as invalid if main signal strength is invalid */
+ if (!qmi_dbm_valid (signal_max, main_interface))
+ return FALSE;
+
act = mm_modem_access_technology_from_qmi_radio_interface (main_interface);
/* On multimode devices we may get more */
@@ -1969,19 +2004,22 @@ signal_strength_get_quality_and_access_tech (MMBroadbandModemQmi *self,
qmi_nas_radio_interface_get_string (element->radio_interface),
element->strength);
- signal_max = MAX (element->strength, signal_max);
-
- act |= mm_modem_access_technology_from_qmi_radio_interface (element->radio_interface);
+ if (qmi_dbm_valid (element->strength, element->radio_interface)) {
+ signal_max = MAX (element->strength, signal_max);
+ act |= mm_modem_access_technology_from_qmi_radio_interface (element->radio_interface);
+ }
}
}
- /* This signal strength comes as negative dBms */
- quality = STRENGTH_TO_QUALITY (signal_max);
+ if (signal_max < 0) {
+ /* This signal strength comes as negative dBms */
+ *o_quality = STRENGTH_TO_QUALITY (signal_max);
+ *o_act = act;
- mm_dbg ("Signal strength: %d dBm --> %u%%", signal_max, quality);
+ mm_dbg ("Signal strength: %d dBm --> %u%%", signal_max, *o_quality);
+ }
- *o_quality = quality;
- *o_act = act;
+ return (signal_max < 0);
}
static void
@@ -2008,7 +2046,15 @@ get_signal_strength_ready (QmiClientNas *client,
return;
}
- signal_strength_get_quality_and_access_tech (ctx->self, output, &quality, &act);
+ if (!signal_strength_get_quality_and_access_tech (ctx->self, output, &quality, &act)) {
+ qmi_message_nas_get_signal_strength_output_unref (output);
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "GetSignalStrength signal strength invalid.");
+ load_signal_quality_context_complete_and_free (ctx);
+ return;
+ }
/* We update the access technologies directly here when loading signal
* quality. It goes a bit out of context, but we can do it nicely */
@@ -5607,21 +5653,27 @@ event_report_indication_cb (QmiClientNas *client,
&signal_strength,
&signal_strength_radio_interface,
NULL)) {
- guint8 quality;
-
- /* This signal strength comes as negative dBms */
- quality = STRENGTH_TO_QUALITY (signal_strength);
-
- mm_dbg ("Signal strength indication (%s): %d dBm --> %u%%",
- qmi_nas_radio_interface_get_string (signal_strength_radio_interface),
- signal_strength,
- quality);
-
- mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
- mm_iface_modem_update_access_technologies (
- MM_IFACE_MODEM (self),
- mm_modem_access_technology_from_qmi_radio_interface (signal_strength_radio_interface),
- (MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK | MM_IFACE_MODEM_CDMA_ALL_ACCESS_TECHNOLOGIES_MASK));
+ if (qmi_dbm_valid (signal_strength, signal_strength_radio_interface)) {
+ guint8 quality;
+
+ /* This signal strength comes as negative dBms */
+ quality = STRENGTH_TO_QUALITY (signal_strength);
+
+ mm_dbg ("Signal strength indication (%s): %d dBm --> %u%%",
+ qmi_nas_radio_interface_get_string (signal_strength_radio_interface),
+ signal_strength,
+ quality);
+
+ mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
+ mm_iface_modem_update_access_technologies (
+ MM_IFACE_MODEM (self),
+ mm_modem_access_technology_from_qmi_radio_interface (signal_strength_radio_interface),
+ (MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK | MM_IFACE_MODEM_CDMA_ALL_ACCESS_TECHNOLOGIES_MASK));
+ } else {
+ mm_dbg ("Ignoring invalid signal strength (%s): %d dBm",
+ qmi_nas_radio_interface_get_string (signal_strength_radio_interface),
+ signal_strength);
+ }
}
}
@@ -5644,35 +5696,43 @@ signal_info_indication_cb (QmiClientNas *client,
if (qmi_indication_nas_signal_info_output_get_cdma_signal_strength (output, &rssi, NULL, NULL)) {
mm_dbg ("RSSI (CDMA): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_CDMA_1X))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_indication_nas_signal_info_output_get_hdr_signal_strength (output, &rssi, NULL, NULL, NULL, NULL)) {
mm_dbg ("RSSI (HDR): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_indication_nas_signal_info_output_get_gsm_signal_strength (output, &rssi, NULL)) {
mm_dbg ("RSSI (GSM): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_GSM))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_indication_nas_signal_info_output_get_wcdma_signal_strength (output, &rssi, NULL, NULL)) {
mm_dbg ("RSSI (WCDMA): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_UMTS))
+ rssi = MAX (rssi, rssi_max);
}
if (qmi_indication_nas_signal_info_output_get_lte_signal_strength (output, &rssi, NULL, NULL, NULL, NULL)) {
mm_dbg ("RSSI (LTE): %d dBm", rssi);
- rssi = MAX (rssi, rssi_max);
+ if (qmi_dbm_valid (rssi, QMI_NAS_RADIO_INTERFACE_LTE))
+ rssi = MAX (rssi, rssi_max);
}
- /* This RSSI comes as negative dBms */
- quality = STRENGTH_TO_QUALITY (rssi_max);
+ if (rssi_max < 0) {
+ /* This RSSI comes as negative dBms */
+ quality = STRENGTH_TO_QUALITY (rssi_max);
- mm_dbg ("RSSI: %d dBm --> %u%%", rssi_max, quality);
+ mm_dbg ("RSSI: %d dBm --> %u%%", rssi_max, quality);
- mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
+ mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
+ } else
+ mm_dbg ("Ignoring invalid signal strength: %d dBm", rssi_max);
}
#endif /* WITH_NEWEST_QMI_COMMANDS */