diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index aa31f33f..48547e23 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -68,6 +68,9 @@ struct _MMBroadbandModemQmiPrivate { /* 3GPP and CDMA share unsolicited events setup/enable/disable/cleanup */ gboolean unsolicited_events_enabled; + gboolean unsolicited_events_setup; + guint event_report_indication_id; + guint signal_info_indication_id; }; /*****************************************************************************/ @@ -3107,6 +3110,222 @@ modem_cdma_enable_unsolicited_events (MMIfaceModemCdma *self, } /*****************************************************************************/ +/* Setup/Cleanup unsolicited event handlers (3GPP and CDMA interface) */ + +static gboolean +common_setup_cleanup_unsolicited_events_finish (MMBroadbandModemQmi *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +event_report_indication_cb (QmiClientNas *client, + MMBroadbandModemQmi *self, + QmiIndicationNasEventReportOutput *output) +{ + gint8 signal_strength; + QmiNasRadioInterface signal_strength_radio_interface; + + if (qmi_indication_nas_event_report_output_get_signal_strength ( + output, + &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); + } +} + +static void +signal_info_indication_cb (QmiClientNas *client, + MMBroadbandModemQmi *self, + QmiIndicationNasSignalInfoOutput *output) +{ + gint8 rssi_max = 0; + gint8 rssi; + guint8 quality; + + /* We do not report per-technology signal quality, so just get the highest + * one of the ones reported. TODO: When several technologies are in use, if + * the indication only contains the data of the one which passed a threshold + * value, we'll need to have an internal cache of per-technology values, in + * order to report always the one with the maximum value. */ + + 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_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_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_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_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); + } + + /* This RSSI comes as negative dBms */ + quality = STRENGTH_TO_QUALITY (rssi_max); + + mm_dbg ("RSSI: %d dBm --> %u%%", rssi_max, quality); + + mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality); +} + +static void +common_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self, + gboolean enable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + QmiClient *client = NULL; + + 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, + common_enable_disable_unsolicited_events); + + if (enable == self->priv->unsolicited_events_setup) { + mm_dbg ("Unsolicited events already %s; skipping", + enable ? "setup" : "cleanup"); + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + return; + } + + /* Store new state */ + self->priv->unsolicited_events_setup = enable; + + /* Connect/Disconnect "Event Report" indications */ + if (enable) { + g_assert (self->priv->event_report_indication_id == 0); + self->priv->event_report_indication_id = + g_signal_connect (client, + "event-report", + G_CALLBACK (event_report_indication_cb), + self); + } else { + g_assert (self->priv->event_report_indication_id != 0); + g_signal_handler_disconnect (client, self->priv->event_report_indication_id); + self->priv->event_report_indication_id = 0; + } + + /* Connect/Disconnect "Signal Info" indications */ + if (enable) { + g_assert (self->priv->signal_info_indication_id == 0); + self->priv->signal_info_indication_id = + g_signal_connect (client, + "signal-info", + G_CALLBACK (signal_info_indication_cb), + self); + } else { + g_assert (self->priv->signal_info_indication_id != 0); + g_signal_handler_disconnect (client, self->priv->signal_info_indication_id); + self->priv->signal_info_indication_id = 0; + } + + g_simple_async_result_set_op_res_gboolean (result, TRUE); + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); +} + +/*****************************************************************************/ +/* Enable/Disable unsolicited events (3GPP interface) */ + +static gboolean +modem_3gpp_setup_cleanup_unsolicited_events_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) +{ + return common_setup_cleanup_unsolicited_events_finish (MM_BROADBAND_MODEM_QMI (self), res, error); +} + +static void +modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + FALSE, + callback, + user_data); +} + +static void +modem_3gpp_setup_unsolicited_events (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + TRUE, + callback, + user_data); +} + +/*****************************************************************************/ +/* Enable/Disable unsolicited events (CDMA interface) */ + +static gboolean +modem_cdma_setup_cleanup_unsolicited_events_finish (MMIfaceModemCdma *self, + GAsyncResult *res, + GError **error) +{ + return common_setup_cleanup_unsolicited_events_finish (MM_BROADBAND_MODEM_QMI (self), res, error); +} + +static void +modem_cdma_cleanup_unsolicited_events (MMIfaceModemCdma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + FALSE, + callback, + user_data); +} + +static void +modem_cdma_setup_unsolicited_events (MMIfaceModemCdma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + common_setup_cleanup_unsolicited_events (MM_BROADBAND_MODEM_QMI (self), + TRUE, + callback, + user_data); +} + +/*****************************************************************************/ /* First initialization step */ typedef struct { @@ -3378,6 +3597,10 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish; /* Enabling steps */ + iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events; + iface->setup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish; + iface->cleanup_unsolicited_events = modem_3gpp_cleanup_unsolicited_events; + iface->cleanup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish; iface->enable_unsolicited_events = modem_3gpp_enable_unsolicited_events; iface->enable_unsolicited_events_finish = modem_3gpp_enable_disable_unsolicited_events_finish; iface->disable_unsolicited_events = modem_3gpp_disable_unsolicited_events; @@ -3397,6 +3620,10 @@ iface_modem_cdma_init (MMIfaceModemCdma *iface) iface->load_esn_finish = modem_cdma_load_esn_finish; /* Enabling steps */ + iface->setup_unsolicited_events = modem_cdma_setup_unsolicited_events; + iface->setup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; + iface->cleanup_unsolicited_events = modem_cdma_cleanup_unsolicited_events; + iface->cleanup_unsolicited_events_finish = modem_cdma_setup_cleanup_unsolicited_events_finish; iface->enable_unsolicited_events = modem_cdma_enable_unsolicited_events; iface->enable_unsolicited_events_finish = modem_cdma_enable_disable_unsolicited_events_finish; iface->disable_unsolicited_events = modem_cdma_disable_unsolicited_events; |