diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-07-08 21:37:18 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-08-21 12:33:10 +0200 |
commit | e8ce650ed0bd271681fae881f8b597ebe739fb7b (patch) | |
tree | d5f7c2f5b9c63d66f7789dee27ae00d4696e7930 | |
parent | 5ef439e2d696e0c9acb9f146ed541848fd8db0ce (diff) |
broadband-modem-qmi: implement extended signal quality reporting
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 207 |
1 files changed, 206 insertions, 1 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 9a6ad92e..6529df5a 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -35,6 +35,7 @@ #include "mm-iface-modem-messaging.h" #include "mm-iface-modem-location.h" #include "mm-iface-modem-firmware.h" +#include "mm-iface-modem-signal.h" #include "mm-sim-qmi.h" #include "mm-bearer-qmi.h" #include "mm-sms-qmi.h" @@ -46,6 +47,7 @@ static void iface_modem_cdma_init (MMIfaceModemCdma *iface); static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); static void iface_modem_location_init (MMIfaceModemLocation *iface); static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); +static void iface_modem_signal_init (MMIfaceModemSignal *iface); static MMIfaceModemMessaging *iface_modem_messaging_parent; static MMIfaceModemLocation *iface_modem_location_parent; @@ -57,7 +59,8 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmi, mm_broadband_modem_qmi, MM_TYPE_BRO G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init)) struct _MMBroadbandModemQmiPrivate { /* Cached device IDs, retrieved by the modem interface when loading device @@ -8616,6 +8619,201 @@ firmware_change_current (MMIfaceModemFirmware *self, } /*****************************************************************************/ +/* Load extended signal information */ + +static gdouble +get_db_from_sinr_level (QmiNasEvdoSinrLevel level) +{ + switch (level) { + case QMI_NAS_EVDO_SINR_LEVEL_0: return -9.0; + case QMI_NAS_EVDO_SINR_LEVEL_1: return -6; + case QMI_NAS_EVDO_SINR_LEVEL_2: return -4.5; + case QMI_NAS_EVDO_SINR_LEVEL_3: return -3; + case QMI_NAS_EVDO_SINR_LEVEL_4: return -2; + case QMI_NAS_EVDO_SINR_LEVEL_5: return 1; + case QMI_NAS_EVDO_SINR_LEVEL_6: return 3; + case QMI_NAS_EVDO_SINR_LEVEL_7: return 6; + case QMI_NAS_EVDO_SINR_LEVEL_8: return +9; + default: + mm_warn ("Invalid SINR level '%u'", level); + return -G_MAXDOUBLE; + } +} + +static gboolean +signal_load_values_finish (MMIfaceModemSignal *self, + GAsyncResult *res, + gboolean *cdma_available, + gdouble *cdma_rssi, + gdouble *cdma_ecio, + gboolean *evdo_available, + gdouble *evdo_rssi, + gdouble *evdo_ecio, + gdouble *evdo_sinr, + gdouble *evdo_io, + gboolean *gsm_available, + gdouble *gsm_rssi, + gboolean *umts_available, + gdouble *umts_rssi, + gdouble *umts_ecio, + gboolean *lte_available, + gdouble *lte_rssi, + gdouble *lte_rsrq, + gdouble *lte_rsrp, + gdouble *lte_snr, + GError **error) +{ + QmiMessageNasGetSignalInfoOutput *output; + gint8 rssi; + gint16 ecio; + QmiNasEvdoSinrLevel sinr_level; + gint32 io; + gint8 rsrq; + gint16 rsrp; + gint16 snr; + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return FALSE; + + output = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); + + /* CDMA */ + if (qmi_message_nas_get_signal_info_output_get_cdma_signal_strength (output, + &rssi, + &ecio, + NULL)) { + *cdma_available = TRUE; + *cdma_rssi = (double)rssi; + *cdma_ecio = ((double)ecio) * (-0.5); + } else { + *cdma_available = FALSE; + *cdma_rssi = 0.0; + *cdma_ecio = 0.0; + } + + /* HDR... */ + if (qmi_message_nas_get_signal_info_output_get_hdr_signal_strength (output, + &rssi, + &ecio, + &sinr_level, + &io, + NULL)) { + *evdo_available = TRUE; + *evdo_rssi = (double)rssi; + *evdo_ecio = ((double)ecio) * (-0.5); + *evdo_sinr = get_db_from_sinr_level (sinr_level); + *evdo_io = (double)io; + } else { + *evdo_available = FALSE; + *evdo_rssi = 0.0; + *evdo_ecio = 0.0; + *evdo_sinr = 0.0; + *evdo_io = 0.0; + } + + /* GSM */ + if (qmi_message_nas_get_signal_info_output_get_gsm_signal_strength (output, + &rssi, + NULL)) { + *gsm_available = TRUE; + *gsm_rssi = (double)rssi; + } else { + *gsm_available = FALSE; + *gsm_rssi = 0.0; + } + + /* WCDMA... */ + if (qmi_message_nas_get_signal_info_output_get_wcdma_signal_strength (output, + &rssi, + &ecio, + NULL)) { + *umts_available = TRUE; + *umts_rssi = (double)rssi; + *umts_ecio = ((double)ecio) * (-0.5); + } else { + *umts_available = FALSE; + *umts_rssi = 0.0; + *umts_ecio = 0.0; + } + + /* LTE... */ + if (qmi_message_nas_get_signal_info_output_get_lte_signal_strength (output, + &rssi, + &rsrq, + &rsrp, + &snr, + NULL)) { + *lte_available = TRUE; + *lte_rssi = (double)rssi; + *lte_rsrq = (gdouble)rsrq; + *lte_rsrp = (gdouble)rsrp; + *lte_snr = (0.1) * ((gdouble)snr); + } else { + *lte_available = FALSE; + *lte_rssi = 0.0; + *lte_rsrq = 0.0; + *lte_rsrp = 0.0; + *lte_snr = 0.0; + } + + return TRUE; +} + +static void +signal_load_values_get_signal_info_ready (QmiClientNas *client, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + QmiMessageNasGetSignalInfoOutput *output; + GError *error = NULL; + + output = qmi_client_nas_get_signal_info_finish (client, res, &error); + if (!output) + g_simple_async_result_take_error (simple, error); + else if (!qmi_message_nas_get_signal_info_output_get_result (output, &error)) + g_simple_async_result_take_error (simple, error); + else + /* set the output bundle as result, we'll read the values directly in finish() */ + g_simple_async_result_set_op_res_gpointer (simple, + qmi_message_nas_get_signal_info_output_ref (output), + (GDestroyNotify)qmi_message_nas_get_signal_info_output_unref); + + if (output) + qmi_message_nas_get_signal_info_output_unref (output); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +signal_load_values (MMIfaceModemSignal *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + QmiClient *client = NULL; + + mm_dbg ("loading extended signal information..."); + + if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), + QMI_SERVICE_NAS, &client, + callback, user_data)) + return; + + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + signal_load_values); + + qmi_client_nas_get_signal_info (QMI_CLIENT_NAS (client), + NULL, + 5, + NULL, + (GAsyncReadyCallback)signal_load_values_get_signal_info_ready, + result); +} + +/*****************************************************************************/ /* First enabling step */ static gboolean @@ -9117,6 +9315,13 @@ iface_modem_location_init (MMIfaceModemLocation *iface) } static void +iface_modem_signal_init (MMIfaceModemSignal *iface) +{ + iface->load_values = signal_load_values; + iface->load_values_finish = signal_load_values_finish; +} + +static void iface_modem_firmware_init (MMIfaceModemFirmware *iface) { iface->check_support = firmware_check_support; |