aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-broadband-modem-qmi.c405
1 files changed, 162 insertions, 243 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index f2c4d1a8..be3d83c5 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -49,22 +49,7 @@ struct _MMBroadbandModemQmiPrivate {
gchar *esn;
/* Allowed mode related */
- gboolean has_system_selection_preference;
gboolean has_mode_preference_in_system_selection_preference;
- gboolean has_technology_preference;
-
- /* Signal quality related.
- * We assume that the presence of all these items can be controlled by the
- * same flag:
- * - 'Get Signal Info'
- * - 'Config Signal Info'
- * - 'Signal Info' indications
- * - 'Signal Info' TLV in 'Register Indications'
- */
- gboolean has_signal_info;
-
- /* Common */
- gboolean has_register_indications;
/* 3GPP and CDMA share unsolicited events setup/enable/disable/cleanup */
gboolean unsolicited_events_enabled;
@@ -1212,8 +1197,6 @@ load_signal_quality_finish (MMIfaceModem *self,
G_SIMPLE_ASYNC_RESULT (res)));
}
-static void load_signal_quality_context_step (LoadSignalQualityContext *ctx);
-
static gint8
signal_info_get_quality (MMBroadbandModemQmi *self,
QmiMessageNasGetSignalInfoOutput *output)
@@ -1268,16 +1251,6 @@ get_signal_info_ready (QmiClientNas *client,
output = qmi_client_nas_get_signal_info_finish (client, res, &error);
if (!output) {
- /* If the command is not supported, fallback to the deprecated one */
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED)) {
- g_error_free (error);
- ctx->self->priv->has_signal_info = FALSE;
- load_signal_quality_context_step (ctx);
- return;
- }
-
g_simple_async_result_take_error (ctx->result, error);
load_signal_quality_context_complete_and_free (ctx);
return;
@@ -1378,28 +1351,6 @@ get_signal_strength_ready (QmiClientNas *client,
}
static void
-load_signal_quality_context_step (LoadSignalQualityContext *ctx)
-{
- if (ctx->self->priv->has_signal_info) {
- qmi_client_nas_get_signal_info (QMI_CLIENT_NAS (ctx->client),
- NULL,
- 10,
- NULL,
- (GAsyncReadyCallback)get_signal_info_ready,
- ctx);
- return;
- }
-
- /* Fallback to the deprecated mode if the new one not supported */
- qmi_client_nas_get_signal_strength (QMI_CLIENT_NAS (ctx->client),
- NULL,
- 10,
- NULL,
- (GAsyncReadyCallback)get_signal_strength_ready,
- ctx);
-}
-
-static void
load_signal_quality (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -1421,7 +1372,22 @@ load_signal_quality (MMIfaceModem *self,
load_signal_quality);
mm_dbg ("loading signal quality...");
- load_signal_quality_context_step (ctx);
+
+ /* Signal info introduced in NAS 1.8 */
+ if (qmi_client_check_version (ctx->client, 1, 8))
+ qmi_client_nas_get_signal_info (QMI_CLIENT_NAS (ctx->client),
+ NULL,
+ 10,
+ NULL,
+ (GAsyncReadyCallback)get_signal_info_ready,
+ ctx);
+ else
+ qmi_client_nas_get_signal_strength (QMI_CLIENT_NAS (ctx->client),
+ NULL,
+ 10,
+ NULL,
+ (GAsyncReadyCallback)get_signal_strength_ready,
+ ctx);
}
/*****************************************************************************/
@@ -1719,10 +1685,6 @@ get_technology_preference_ready (QmiClientNas *client,
output = qmi_client_nas_get_technology_preference_finish (client, res, &error);
if (!output) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_technology_preference = FALSE;
mm_dbg ("QMI operation failed: %s", error->message);
g_error_free (error);
} else if (!qmi_message_nas_get_technology_preference_output_get_result (output, &error)) {
@@ -1824,10 +1786,6 @@ allowed_modes_get_system_selection_preference_ready (QmiClientNas *client,
output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error);
if (!output) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_system_selection_preference = FALSE;
mm_dbg ("QMI operation failed: %s", error->message);
g_error_free (error);
} else if (!qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) {
@@ -1940,10 +1898,15 @@ load_allowed_modes (MMIfaceModem *self,
callback,
user_data,
load_allowed_modes);
+
+ /* System selection preference introduced in NAS 1.1
+ * TODO: Not sure when the System Selection Preference got the
+ * 'Mode Preference' TLV, so we'll need to handle the fallback. */
ctx->run_get_system_selection_preference =
- (ctx->self->priv->has_system_selection_preference &&
+ (qmi_client_check_version (client, 1, 1) &&
ctx->self->priv->has_mode_preference_in_system_selection_preference);
- ctx->run_get_technology_preference = ctx->self->priv->has_technology_preference;
+ /* Technology preference introduced in NAS 1.7 */
+ ctx->run_get_technology_preference = qmi_client_check_version (client, 1, 7);
load_allowed_modes_context_step (ctx);
}
@@ -1991,10 +1954,6 @@ set_technology_preference_ready (QmiClientNas *client,
output = qmi_client_nas_set_technology_preference_finish (client, res, &error);
if (!output) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_technology_preference = FALSE;
mm_dbg ("QMI operation failed: %s", error->message);
g_error_free (error);
} else if (!qmi_message_nas_set_technology_preference_output_get_result (output, &error)) {
@@ -2022,10 +1981,6 @@ allowed_modes_set_system_selection_preference_ready (QmiClientNas *client,
output = qmi_client_nas_set_system_selection_preference_finish (client, res, &error);
if (!output) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_system_selection_preference = FALSE;
mm_dbg ("QMI operation failed: %s", error->message);
g_error_free (error);
} else if (!qmi_message_nas_set_system_selection_preference_output_get_result (output, &error)) {
@@ -2250,10 +2205,14 @@ set_allowed_modes (MMIfaceModem *self,
set_allowed_modes);
ctx->allowed = allowed;
ctx->preferred = preferred;
+ /* System selection preference introduced in NAS 1.1
+ * TODO: Not sure when the System Selection Preference got the
+ * 'Mode Preference' TLV, so we'll need to handle the fallback. */
ctx->run_set_system_selection_preference =
- (ctx->self->priv->has_system_selection_preference &&
+ (qmi_client_check_version (client, 1, 1) &&
ctx->self->priv->has_mode_preference_in_system_selection_preference);
- ctx->run_set_technology_preference = ctx->self->priv->has_technology_preference;
+ /* Technology preference introduced in NAS 1.7 */
+ ctx->run_set_technology_preference = qmi_client_check_version (client, 1, 7);
set_allowed_modes_context_step (ctx);
}
@@ -2766,22 +2725,21 @@ modem_cdma_load_esn (MMIfaceModemCdma *_self,
}
/*****************************************************************************/
-/* Enabling/disabling unsolicited events (3GPP and CDMA interface) */
-
-typedef enum {
- ENABLE_UNSOLICITED_EVENTS_STEP_FIRST = 0,
- ENABLE_UNSOLICITED_EVENTS_STEP_CONFIG_SIGNAL_INFO,
- ENABLE_UNSOLICITED_EVENTS_STEP_RI_SIGNAL_QUALITY,
- ENABLE_UNSOLICITED_EVENTS_STEP_SER_SIGNAL_QUALITY,
- ENABLE_UNSOLICITED_EVENTS_STEP_LAST
-} EnableUnsolicitedEventsStep;
+/* Enabling/disabling unsolicited events (3GPP and CDMA interface)
+ *
+ * If NAS >= 1.8:
+ * - Config Signal Info (only when enabling)
+ * - Register Indications with Signal Info
+ *
+ * If NAS < 1.8:
+ * - Set Event Report with Signal Strength
+ */
typedef struct {
MMBroadbandModemQmi *self;
- gboolean enable;
GSimpleAsyncResult *result;
QmiClientNas *client;
- EnableUnsolicitedEventsStep step;
+ gboolean enable;
} EnableUnsolicitedEventsContext;
static void
@@ -2802,12 +2760,10 @@ common_enable_disable_unsolicited_events_finish (MMBroadbandModemQmi *self,
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
}
-static void enable_unsolicited_events_context_step (EnableUnsolicitedEventsContext *ctx);
-
static void
-ser_signal_quality_ready (QmiClientNas *client,
- GAsyncResult *res,
- EnableUnsolicitedEventsContext *ctx)
+ser_signal_strength_ready (QmiClientNas *client,
+ GAsyncResult *res,
+ EnableUnsolicitedEventsContext *ctx)
{
QmiMessageNasSetEventReportOutput *output = NULL;
GError *error = NULL;
@@ -2824,48 +2780,87 @@ ser_signal_quality_ready (QmiClientNas *client,
if (output)
qmi_message_nas_set_event_report_output_unref (output);
- /* Keep on */
- ctx->step++;
- enable_unsolicited_events_context_step (ctx);
+ /* Just ignore errors for now */
+ ctx->self->priv->unsolicited_events_enabled = ctx->enable;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_unsolicited_events_context_complete_and_free (ctx);
}
static void
-ri_signal_quality_ready (QmiClientNas *client,
- GAsyncResult *res,
- EnableUnsolicitedEventsContext *ctx)
+common_enable_disable_unsolicited_events_signal_strength (EnableUnsolicitedEventsContext *ctx)
+{
+ /* The device doesn't really like to have many threshold values, so don't
+ * grow this array without checking first */
+ static const gint8 thresholds_data[] = { -80, -40, 0, 40, 80 };
+ QmiMessageNasSetEventReportInput *input;
+ GArray *thresholds;
+
+ input = qmi_message_nas_set_event_report_input_new ();
+
+ /* Prepare thresholds, separated 20 each */
+ thresholds = g_array_sized_new (FALSE, FALSE, sizeof (gint8), G_N_ELEMENTS (thresholds_data));
+
+ /* Only set thresholds during enable */
+ if (ctx->enable)
+ g_array_append_vals (thresholds, thresholds_data, G_N_ELEMENTS (thresholds_data));
+
+ qmi_message_nas_set_event_report_input_set_signal_strength_indicator (
+ input,
+ ctx->enable,
+ thresholds,
+ NULL);
+ g_array_unref (thresholds);
+ qmi_client_nas_set_event_report (
+ ctx->client,
+ input,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)ser_signal_strength_ready,
+ ctx);
+ qmi_message_nas_set_event_report_input_unref (input);
+}
+
+static void
+ri_signal_info_ready (QmiClientNas *client,
+ GAsyncResult *res,
+ EnableUnsolicitedEventsContext *ctx)
{
QmiMessageNasRegisterIndicationsOutput *output = NULL;
GError *error = NULL;
output = qmi_client_nas_register_indications_finish (client, res, &error);
if (!output) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_register_indications = FALSE;
-
mm_dbg ("QMI operation failed: '%s'", error->message);
g_error_free (error);
} else if (!qmi_message_nas_register_indications_output_get_result (output, &error)) {
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED))
- ctx->self->priv->has_signal_info = FALSE;
-
mm_dbg ("Couldn't register indications: '%s'", error->message);
g_error_free (error);
- qmi_message_nas_register_indications_output_unref (output);
- } else {
- /* Signal quality related indications setup done, skip the deprecated step */
- qmi_message_nas_register_indications_output_unref (output);
- ctx->step = ENABLE_UNSOLICITED_EVENTS_STEP_SER_SIGNAL_QUALITY + 1;
- enable_unsolicited_events_context_step (ctx);
- return;
}
- /* Keep on */
- ctx->step++;
- enable_unsolicited_events_context_step (ctx);
+ if (output)
+ qmi_message_nas_register_indications_output_unref (output);
+
+ /* Just ignore errors for now */
+ ctx->self->priv->unsolicited_events_enabled = ctx->enable;
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ enable_unsolicited_events_context_complete_and_free (ctx);
+}
+
+static void
+common_enable_disable_unsolicited_events_signal_info (EnableUnsolicitedEventsContext *ctx)
+{
+ QmiMessageNasRegisterIndicationsInput *input;
+
+ input = qmi_message_nas_register_indications_input_new ();
+ qmi_message_nas_register_indications_input_set_signal_info (input, ctx->enable, NULL);
+ qmi_client_nas_register_indications (
+ ctx->client,
+ input,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)ri_signal_info_ready,
+ ctx);
+ qmi_message_nas_register_indications_input_unref (input);
}
static void
@@ -2878,134 +2873,54 @@ config_signal_info_ready (QmiClientNas *client,
output = qmi_client_nas_config_signal_info_finish (client, res, &error);
if (!output) {
- /* If config signal info is unsupported, completely skip trying to
- * use Register Indications */
- if (g_error_matches (error,
- QMI_CORE_ERROR,
- QMI_CORE_ERROR_UNSUPPORTED)) {
- ctx->self->priv->has_signal_info = FALSE;
- ctx->step = ENABLE_UNSOLICITED_EVENTS_STEP_SER_SIGNAL_QUALITY;
- } else
- ctx->step++;
-
mm_dbg ("QMI operation failed: '%s'", error->message);
g_error_free (error);
- enable_unsolicited_events_context_step (ctx);
- return;
- }
-
- if (!qmi_message_nas_config_signal_info_output_get_result (output, &error)) {
+ } else if (!qmi_message_nas_config_signal_info_output_get_result (output, &error)) {
mm_dbg ("Couldn't config signal info: '%s'", error->message);
g_error_free (error);
}
- qmi_message_nas_config_signal_info_output_unref (output);
+ if (output)
+ qmi_message_nas_config_signal_info_output_unref (output);
/* Keep on */
- ctx->step++;
- enable_unsolicited_events_context_step (ctx);
+ common_enable_disable_unsolicited_events_signal_info (ctx);
}
static void
-enable_unsolicited_events_context_step (EnableUnsolicitedEventsContext *ctx)
+common_enable_disable_unsolicited_events_signal_info_config (EnableUnsolicitedEventsContext *ctx)
{
- switch (ctx->step) {
- case ENABLE_UNSOLICITED_EVENTS_STEP_FIRST:
- /* Fall down */
- ctx->step++;
-
- case ENABLE_UNSOLICITED_EVENTS_STEP_CONFIG_SIGNAL_INFO:
- if (ctx->self->priv->has_signal_info &&
- ctx->enable) {
- /* RSSI values go between -105 and -60 for 3GPP technologies,
- * and from -105 to -90 in 3GPP2 technologies (approx). */
- static const gint8 thresholds_data[] = { -100, -97, -95, -92, -90, -85, -80, -75, -70, -65 };
- QmiMessageNasConfigSignalInfoInput *input;
- GArray *thresholds;
-
- input = qmi_message_nas_config_signal_info_input_new ();
-
- /* Prepare thresholds, separated 20 each */
- thresholds = g_array_sized_new (FALSE, FALSE, sizeof (gint8), G_N_ELEMENTS (thresholds_data));
- g_array_append_vals (thresholds, thresholds_data, G_N_ELEMENTS (thresholds_data));
-
- qmi_message_nas_config_signal_info_input_set_rssi_threshold (
- input,
- thresholds,
- NULL);
- g_array_unref (thresholds);
- qmi_client_nas_config_signal_info (
- ctx->client,
- input,
- 5,
- NULL,
- (GAsyncReadyCallback)config_signal_info_ready,
- ctx);
- qmi_message_nas_config_signal_info_input_unref (input);
- return;
- }
- /* Fall down */
- ctx->step++;
-
- case ENABLE_UNSOLICITED_EVENTS_STEP_RI_SIGNAL_QUALITY:
- if (ctx->self->priv->has_register_indications &&
- ctx->self->priv->has_signal_info) {
- QmiMessageNasRegisterIndicationsInput *input;
-
- input = qmi_message_nas_register_indications_input_new ();
- qmi_message_nas_register_indications_input_set_signal_strength (input, ctx->enable, NULL);
- qmi_client_nas_register_indications (
- ctx->client,
- input,
- 5,
- NULL,
- (GAsyncReadyCallback)ri_signal_quality_ready,
- ctx);
- qmi_message_nas_register_indications_input_unref (input);
- return;
- }
- /* Fall down */
- ctx->step++;
-
- case ENABLE_UNSOLICITED_EVENTS_STEP_SER_SIGNAL_QUALITY: {
- /* The device doesn't really like to have many threshold values, so don't
- * grow this array without checking first */
- static const gint8 thresholds_data[] = { -80, -40, 0, 40, 80 };
- QmiMessageNasSetEventReportInput *input;
- GArray *thresholds;
+ /* RSSI values go between -105 and -60 for 3GPP technologies,
+ * and from -105 to -90 in 3GPP2 technologies (approx). */
+ static const gint8 thresholds_data[] = { -100, -97, -95, -92, -90, -85, -80, -75, -70, -65 };
+ QmiMessageNasConfigSignalInfoInput *input;
+ GArray *thresholds;
- input = qmi_message_nas_set_event_report_input_new ();
-
- /* Prepare thresholds, separated 20 each */
- thresholds = g_array_sized_new (FALSE, FALSE, sizeof (gint8), G_N_ELEMENTS (thresholds_data));
-
- /* Only set thresholds during enable */
- if (ctx->enable)
- g_array_append_vals (thresholds, thresholds_data, G_N_ELEMENTS (thresholds_data));
-
- qmi_message_nas_set_event_report_input_set_signal_strength_indicator (
- input,
- ctx->enable,
- thresholds,
- NULL);
- g_array_unref (thresholds);
- qmi_client_nas_set_event_report (
- ctx->client,
- input,
- 5,
- NULL,
- (GAsyncReadyCallback)ser_signal_quality_ready,
- ctx);
- qmi_message_nas_set_event_report_input_unref (input);
+ /* Signal info config only to be run when enabling */
+ if (!ctx->enable) {
+ common_enable_disable_unsolicited_events_signal_info (ctx);
return;
}
- case ENABLE_UNSOLICITED_EVENTS_STEP_LAST:
- ctx->self->priv->unsolicited_events_enabled = ctx->enable;
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
- enable_unsolicited_events_context_complete_and_free (ctx);
- return;
- }
+ input = qmi_message_nas_config_signal_info_input_new ();
+
+ /* Prepare thresholds, separated 20 each */
+ thresholds = g_array_sized_new (FALSE, FALSE, sizeof (gint8), G_N_ELEMENTS (thresholds_data));
+ g_array_append_vals (thresholds, thresholds_data, G_N_ELEMENTS (thresholds_data));
+
+ qmi_message_nas_config_signal_info_input_set_rssi_threshold (
+ input,
+ thresholds,
+ NULL);
+ g_array_unref (thresholds);
+ qmi_client_nas_config_signal_info (
+ ctx->client,
+ input,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)config_signal_info_ready,
+ ctx);
+ qmi_message_nas_config_signal_info_input_unref (input);
}
static void
@@ -3042,8 +2957,12 @@ common_enable_disable_unsolicited_events (MMBroadbandModemQmi *self,
ctx->client = g_object_ref (client);
ctx->enable = enable;
ctx->result = result;
- ctx->step = ENABLE_UNSOLICITED_EVENTS_STEP_FIRST;
- enable_unsolicited_events_context_step (ctx);
+
+ /* Signal info introduced in NAS 1.8 */
+ if (qmi_client_check_version (client, 1, 8))
+ common_enable_disable_unsolicited_events_signal_info_config (ctx);
+ else
+ common_enable_disable_unsolicited_events_signal_strength (ctx);
}
/*****************************************************************************/
@@ -3243,18 +3162,21 @@ common_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self,
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;
+ /* Connect/Disconnect "Signal Info" indications.
+ * Signal info introduced in NAS 1.8 */
+ if (qmi_client_check_version (client, 1, 8)) {
+ 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);
@@ -3506,12 +3428,9 @@ mm_broadband_modem_qmi_init (MMBroadbandModemQmi *self)
MM_TYPE_BROADBAND_MODEM_QMI,
MMBroadbandModemQmiPrivate);
- /* Always try to use the newest command available first */
- self->priv->has_signal_info = TRUE;
- self->priv->has_system_selection_preference = TRUE;
+ /* Some initial defaults for when we need to gather info about
+ * supported commands/TLVs */
self->priv->has_mode_preference_in_system_selection_preference = TRUE;
- self->priv->has_technology_preference = TRUE;
- self->priv->has_register_indications = TRUE;
}
static void