diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-08-09 11:59:25 +0200 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2018-08-10 04:26:12 +0000 |
commit | ab9130682c0b529d68d4281fcf52bcf51f5dc43e (patch) | |
tree | 8f85e4e4d86a55adfe95fd91cf677cb217626de3 /src | |
parent | 7a941466c29342b1ebb30fbd54f41f4f7005d0b0 (diff) |
broadband-modem-mbim: implement extended signal support with ATDS
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 202 |
1 files changed, 197 insertions, 5 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index 062cf21d..7d5d0339 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -82,6 +82,7 @@ struct _MMBroadbandModemMbimPrivate { gboolean is_pco_supported; gboolean is_ussd_supported; gboolean is_atds_location_supported; + gboolean is_atds_signal_supported; /* Process unsolicited notifications */ guint notification_id; @@ -1797,7 +1798,9 @@ query_device_services_ready (MbimDevice *device, if (device_services[i]->cids[j] == MBIM_CID_ATDS_LOCATION) { mm_dbg ("ATDS location is supported"); self->priv->is_atds_location_supported = TRUE; - break; + } else if (device_services[i]->cids[j] == MBIM_CID_ATDS_SIGNAL) { + mm_dbg ("ATDS signal is supported"); + self->priv->is_atds_signal_supported = TRUE; } } break; @@ -3334,6 +3337,195 @@ modem_3gpp_scan_networks (MMIfaceModem3gpp *self, } /*****************************************************************************/ +/* Check support (Signal interface) */ + +static gboolean +modem_signal_check_support_finish (MMIfaceModemSignal *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +modem_signal_check_support (MMIfaceModemSignal *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + g_task_return_boolean (task, MM_BROADBAND_MODEM_MBIM (self)->priv->is_atds_signal_supported); + g_object_unref (task); +} + +/*****************************************************************************/ +/* Load extended signal information (Signal interface) */ + +typedef struct { + MMSignal *gsm; + MMSignal *umts; + MMSignal *lte; +} SignalLoadValuesResult; + +static void +signal_load_values_result_free (SignalLoadValuesResult *result) +{ + g_clear_object (&result->gsm); + g_clear_object (&result->umts); + g_clear_object (&result->lte); + g_slice_free (SignalLoadValuesResult, result); +} + +static gboolean +modem_signal_load_values_finish (MMIfaceModemSignal *self, + GAsyncResult *res, + MMSignal **cdma, + MMSignal **evdo, + MMSignal **gsm, + MMSignal **umts, + MMSignal **lte, + GError **error) +{ + SignalLoadValuesResult *result; + + result = g_task_propagate_pointer (G_TASK (res), error); + if (!result) + return FALSE; + + if (gsm && result->gsm) { + *gsm = result->gsm; + result->gsm = NULL; + } + + if (umts && result->umts) { + *umts = result->umts; + result->umts = NULL; + } + + if (lte && result->lte) { + *lte = result->lte; + result->lte = NULL; + } + + signal_load_values_result_free (result); + + /* No 3GPP2 support */ + if (cdma) + *cdma = NULL; + if (evdo) + *evdo = NULL; + return TRUE; +} + +static void +atds_signal_query_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + MbimMessage *response; + SignalLoadValuesResult *result; + GError *error = NULL; + guint32 rssi; + guint32 error_rate; + guint32 rscp; + guint32 ecno; + guint32 rsrq; + guint32 rsrp; + guint32 snr; + + response = mbim_device_command_finish (device, res, &error); + if (!response || + !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) || + !mbim_message_atds_signal_response_parse (response, &rssi, &error_rate, &rscp, &ecno, &rsrq, &rsrp, &snr, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + result = g_slice_new0 (SignalLoadValuesResult); + + if (rscp <= 96) { + result->umts = mm_signal_new (); + mm_signal_set_rscp (result->umts, -120.0 + rscp); + } + + if (ecno <= 49) { + if (!result->umts) + result->umts = mm_signal_new (); + mm_signal_set_ecio (result->umts, -24.0 + ((float) ecno / 2)); + } + + if (rsrq <= 34) { + result->lte = mm_signal_new (); + mm_signal_set_rsrq (result->lte, -19.5 + ((float) rsrq / 2)); + } + + if (rsrp <= 97) { + if (!result->lte) + result->lte = mm_signal_new (); + mm_signal_set_rsrp (result->lte, -140.0 + rsrp); + } + + if (snr <= 35) { + if (!result->lte) + result->lte = mm_signal_new (); + mm_signal_set_snr (result->lte, -5.0 + snr); + } + + /* RSSI may be given for all 2G, 3G or 4G so we detect to which one applies */ + if (rssi <= 31) { + gdouble value; + + value = -113.0 + (2 * rssi); + if (result->lte) + mm_signal_set_rssi (result->lte, value); + else if (result->umts) + mm_signal_set_rssi (result->umts, value); + else { + result->gsm = mm_signal_new (); + mm_signal_set_rssi (result->gsm, value); + } + } + + if (!result->gsm && !result->umts && !result->lte) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "No signal details given"); + g_object_unref (task); + signal_load_values_result_free (result); + return; + } + + g_task_return_pointer (task, result, (GDestroyNotify) signal_load_values_result_free); + g_object_unref (task); +} + +static void +modem_signal_load_values (MMIfaceModemSignal *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MbimDevice *device; + MbimMessage *message; + GTask *task; + + if (!peek_device (self, &device, callback, user_data)) + return; + + task = g_task_new (self, NULL, callback, user_data); + + message = mbim_message_atds_signal_query_new (NULL); + mbim_device_command (device, + message, + 5, + NULL, + (GAsyncReadyCallback)atds_signal_query_ready, + task); + mbim_message_unref (message); +} + +/*****************************************************************************/ /* Check support (Messaging interface) */ static gboolean @@ -3774,10 +3966,10 @@ iface_modem_messaging_init (MMIfaceModemMessaging *iface) static void iface_modem_signal_init (MMIfaceModemSignal *iface) { - iface->check_support = NULL; - iface->check_support_finish = NULL; - iface->load_values = NULL; - iface->load_values_finish = NULL; + iface->check_support = modem_signal_check_support; + iface->check_support_finish = modem_signal_check_support_finish; + iface->load_values = modem_signal_load_values; + iface->load_values_finish = modem_signal_load_values_finish; } static void |