aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mm-broadband-modem-qmi.c394
1 files changed, 270 insertions, 124 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 12a9708c..5f3a2d87 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -63,6 +63,7 @@ struct _MMBroadbandModemQmiPrivate {
gboolean unsolicited_registration_events_enabled;
gboolean unsolicited_registration_events_setup;
guint serving_system_indication_id;
+ guint system_info_indication_id;
};
/*****************************************************************************/
@@ -3022,7 +3023,8 @@ process_common_info (QmiNasServiceStatus service_status,
}
static gboolean
-process_gsm_info (QmiMessageNasGetSystemInfoOutput *output,
+process_gsm_info (QmiMessageNasGetSystemInfoOutput *response_output,
+ QmiIndicationNasSystemInfoOutput *indication_output,
MMModemAccessTechnology *mm_access_technologies,
MMModem3gppRegistrationState *mm_cs_registration_state,
MMModem3gppRegistrationState *mm_ps_registration_state,
@@ -3047,6 +3049,9 @@ process_gsm_info (QmiMessageNasGetSystemInfoOutput *output,
gboolean egprs_support_valid;
gboolean egprs_support;
+ g_assert ((response_output != NULL && indication_output == NULL) ||
+ (response_output == NULL && indication_output != NULL));
+
*mm_ps_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_cs_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_lac = 0;
@@ -3054,28 +3059,54 @@ process_gsm_info (QmiMessageNasGetSystemInfoOutput *output,
g_free (*mm_operator_id);
*mm_operator_id = NULL;
- if (!qmi_message_nas_get_system_info_output_get_gsm_service_status (
- output,
- &service_status,
- NULL, /* true_service_status */
- NULL, /* preferred_data_path */
- NULL) ||
- !qmi_message_nas_get_system_info_output_get_gsm_system_info (
- output,
- &domain_valid, &domain,
- NULL, NULL, /* service_capability */
- &roaming_status_valid, &roaming_status,
- &forbidden_valid, &forbidden,
- &lac_valid, &lac,
- &cid_valid, &cid,
- NULL, NULL, NULL, /* registration_reject_info */
- &network_id_valid, &mcc, &mnc,
- &egprs_support_valid, &egprs_support,
- NULL, NULL, /* dtm_support */
- NULL)) {
- mm_dbg ("No GSM service reported");
- /* No GSM service */
- return FALSE;
+ if (response_output) {
+ if (!qmi_message_nas_get_system_info_output_get_gsm_service_status (
+ response_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_message_nas_get_system_info_output_get_gsm_system_info (
+ response_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ &egprs_support_valid, &egprs_support,
+ NULL, NULL, /* dtm_support */
+ NULL)) {
+ mm_dbg ("No GSM service reported");
+ /* No GSM service */
+ return FALSE;
+ }
+ } else {
+ if (!qmi_indication_nas_system_info_output_get_gsm_service_status (
+ indication_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_indication_nas_system_info_output_get_gsm_system_info (
+ indication_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ &egprs_support_valid, &egprs_support,
+ NULL, NULL, /* dtm_support */
+ NULL)) {
+ mm_dbg ("No GSM service reported");
+ /* No GSM service */
+ return FALSE;
+ }
}
if (!process_common_info (service_status,
@@ -3102,7 +3133,8 @@ process_gsm_info (QmiMessageNasGetSystemInfoOutput *output,
}
static gboolean
-process_wcdma_info (QmiMessageNasGetSystemInfoOutput *output,
+process_wcdma_info (QmiMessageNasGetSystemInfoOutput *response_output,
+ QmiIndicationNasSystemInfoOutput *indication_output,
MMModemAccessTechnology *mm_access_technologies,
MMModem3gppRegistrationState *mm_cs_registration_state,
MMModem3gppRegistrationState *mm_ps_registration_state,
@@ -3127,6 +3159,9 @@ process_wcdma_info (QmiMessageNasGetSystemInfoOutput *output,
gboolean hs_service_valid;
QmiNasWcdmaHsService hs_service;
+ g_assert ((response_output != NULL && indication_output == NULL) ||
+ (response_output == NULL && indication_output != NULL));
+
*mm_ps_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_cs_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_lac = 0;
@@ -3134,29 +3169,56 @@ process_wcdma_info (QmiMessageNasGetSystemInfoOutput *output,
g_free (*mm_operator_id);
*mm_operator_id = NULL;
- if (!qmi_message_nas_get_system_info_output_get_wcdma_service_status (
- output,
- &service_status,
- NULL, /* true_service_status */
- NULL, /* preferred_data_path */
- NULL) ||
- !qmi_message_nas_get_system_info_output_get_wcdma_system_info (
- output,
- &domain_valid, &domain,
- NULL, NULL, /* service_capability */
- &roaming_status_valid, &roaming_status,
- &forbidden_valid, &forbidden,
- &lac_valid, &lac,
- &cid_valid, &cid,
- NULL, NULL, NULL, /* registration_reject_info */
- &network_id_valid, &mcc, &mnc,
- NULL, NULL, /* hs_call_status */
- &hs_service_valid, &hs_service,
- NULL, NULL, /* primary_scrambling_code */
- NULL)) {
- mm_dbg ("No WCDMA service reported");
- /* No GSM service */
- return FALSE;
+ if (response_output) {
+ if (!qmi_message_nas_get_system_info_output_get_wcdma_service_status (
+ response_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_message_nas_get_system_info_output_get_wcdma_system_info (
+ response_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ NULL, NULL, /* hs_call_status */
+ &hs_service_valid, &hs_service,
+ NULL, NULL, /* primary_scrambling_code */
+ NULL)) {
+ mm_dbg ("No WCDMA service reported");
+ /* No GSM service */
+ return FALSE;
+ }
+ } else {
+ if (!qmi_indication_nas_system_info_output_get_wcdma_service_status (
+ indication_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_indication_nas_system_info_output_get_wcdma_system_info (
+ indication_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ NULL, NULL, /* hs_call_status */
+ &hs_service_valid, &hs_service,
+ NULL, NULL, /* primary_scrambling_code */
+ NULL)) {
+ mm_dbg ("No WCDMA service reported");
+ /* No GSM service */
+ return FALSE;
+ }
}
if (!process_common_info (service_status,
@@ -3202,7 +3264,8 @@ process_wcdma_info (QmiMessageNasGetSystemInfoOutput *output,
}
static gboolean
-process_lte_info (QmiMessageNasGetSystemInfoOutput *output,
+process_lte_info (QmiMessageNasGetSystemInfoOutput *response_output,
+ QmiIndicationNasSystemInfoOutput *indication_output,
MMModemAccessTechnology *mm_access_technologies,
MMModem3gppRegistrationState *mm_cs_registration_state,
MMModem3gppRegistrationState *mm_ps_registration_state,
@@ -3225,6 +3288,9 @@ process_lte_info (QmiMessageNasGetSystemInfoOutput *output,
const gchar *mcc;
const gchar *mnc;
+ g_assert ((response_output != NULL && indication_output == NULL) ||
+ (response_output == NULL && indication_output != NULL));
+
*mm_ps_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_cs_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
*mm_lac = 0;
@@ -3232,27 +3298,52 @@ process_lte_info (QmiMessageNasGetSystemInfoOutput *output,
g_free (*mm_operator_id);
*mm_operator_id = NULL;
- if (!qmi_message_nas_get_system_info_output_get_lte_service_status (
- output,
- &service_status,
- NULL, /* true_service_status */
- NULL, /* preferred_data_path */
- NULL) ||
- !qmi_message_nas_get_system_info_output_get_lte_system_info (
- output,
- &domain_valid, &domain,
- NULL, NULL, /* service_capability */
- &roaming_status_valid, &roaming_status,
- &forbidden_valid, &forbidden,
- &lac_valid, &lac,
- &cid_valid, &cid,
- NULL, NULL, NULL, /* registration_reject_info */
- &network_id_valid, &mcc, &mnc,
- NULL, NULL, /* tac */
- NULL)) {
- mm_dbg ("No LTE service reported");
- /* No GSM service */
- return FALSE;
+ if (response_output) {
+ if (!qmi_message_nas_get_system_info_output_get_lte_service_status (
+ response_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_message_nas_get_system_info_output_get_lte_system_info (
+ response_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ NULL, NULL, /* tac */
+ NULL)) {
+ mm_dbg ("No LTE service reported");
+ /* No GSM service */
+ return FALSE;
+ }
+ } else {
+ if (!qmi_indication_nas_system_info_output_get_lte_service_status (
+ indication_output,
+ &service_status,
+ NULL, /* true_service_status */
+ NULL, /* preferred_data_path */
+ NULL) ||
+ !qmi_indication_nas_system_info_output_get_lte_system_info (
+ indication_output,
+ &domain_valid, &domain,
+ NULL, NULL, /* service_capability */
+ &roaming_status_valid, &roaming_status,
+ &forbidden_valid, &forbidden,
+ &lac_valid, &lac,
+ &cid_valid, &cid,
+ NULL, NULL, NULL, /* registration_reject_info */
+ &network_id_valid, &mcc, &mnc,
+ NULL, NULL, /* tac */
+ NULL)) {
+ mm_dbg ("No LTE service reported");
+ /* No GSM service */
+ return FALSE;
+ }
}
if (!process_common_info (service_status,
@@ -3276,12 +3367,10 @@ process_lte_info (QmiMessageNasGetSystemInfoOutput *output,
}
static void
-get_system_info_ready (QmiClientNas *client,
- GAsyncResult *res,
- RunRegistrationChecksContext *ctx)
+common_process_system_info (MMBroadbandModemQmi *self,
+ QmiMessageNasGetSystemInfoOutput *response_output,
+ QmiIndicationNasSystemInfoOutput *indication_output)
{
- QmiMessageNasGetSystemInfoOutput *output;
- GError *error = NULL;
MMModemAccessTechnology access_technologies;
MMModem3gppRegistrationState cs_registration_state;
MMModem3gppRegistrationState ps_registration_state;
@@ -3289,22 +3378,6 @@ get_system_info_ready (QmiClientNas *client,
guint32 cid;
gchar *operator_id;
- output = qmi_client_nas_get_system_info_finish (client, res, &error);
- if (!output) {
- g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (ctx->result, error);
- run_registration_checks_context_complete_and_free (ctx);
- return;
- }
-
- if (!qmi_message_nas_get_system_info_output_get_result (output, &error)) {
- g_prefix_error (&error, "Couldn't get system info: ");
- g_simple_async_result_take_error (ctx->result, error);
- qmi_message_nas_get_system_info_output_unref (output);
- run_registration_checks_context_complete_and_free (ctx);
- return;
- }
-
access_technologies = 0;
ps_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
cs_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
@@ -3316,21 +3389,21 @@ get_system_info_ready (QmiClientNas *client,
* LTE > WCDMA > GSM
* The first one giving results will be the one reported.
*/
- if (!process_lte_info (output,
+ if (!process_lte_info (response_output, indication_output,
&access_technologies,
&cs_registration_state,
&ps_registration_state,
&lac,
&cid,
&operator_id) &&
- !process_wcdma_info (output,
+ !process_wcdma_info (response_output, indication_output,
&access_technologies,
&cs_registration_state,
&ps_registration_state,
&lac,
&cid,
&operator_id) &&
- !process_gsm_info (output,
+ !process_gsm_info (response_output, indication_output,
&access_technologies,
&cs_registration_state,
&ps_registration_state,
@@ -3342,26 +3415,51 @@ get_system_info_ready (QmiClientNas *client,
/* Cache current operator ID */
if (operator_id) {
- g_free (ctx->self->priv->current_operator_id);
- ctx->self->priv->current_operator_id = operator_id;
+ g_free (self->priv->current_operator_id);
+ self->priv->current_operator_id = operator_id;
}
/* Report new registration states */
- if (ctx->cs_supported)
- mm_iface_modem_3gpp_update_cs_registration_state (
- MM_IFACE_MODEM_3GPP (ctx->self),
- cs_registration_state,
- access_technologies,
- lac,
- cid);
+ mm_iface_modem_3gpp_update_cs_registration_state (
+ MM_IFACE_MODEM_3GPP (self),
+ cs_registration_state,
+ access_technologies,
+ lac,
+ cid);
- if (ctx->ps_supported)
- mm_iface_modem_3gpp_update_ps_registration_state (
- MM_IFACE_MODEM_3GPP (ctx->self),
- ps_registration_state,
- access_technologies,
- lac,
- cid);
+ mm_iface_modem_3gpp_update_ps_registration_state (
+ MM_IFACE_MODEM_3GPP (self),
+ ps_registration_state,
+ access_technologies,
+ lac,
+ cid);
+}
+
+static void
+get_system_info_ready (QmiClientNas *client,
+ GAsyncResult *res,
+ RunRegistrationChecksContext *ctx)
+{
+ QmiMessageNasGetSystemInfoOutput *output;
+ GError *error = NULL;
+
+ output = qmi_client_nas_get_system_info_finish (client, res, &error);
+ if (!output) {
+ g_prefix_error (&error, "QMI operation failed: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ run_registration_checks_context_complete_and_free (ctx);
+ return;
+ }
+
+ if (!qmi_message_nas_get_system_info_output_get_result (output, &error)) {
+ g_prefix_error (&error, "Couldn't get system info: ");
+ g_simple_async_result_take_error (ctx->result, error);
+ qmi_message_nas_get_system_info_output_unref (output);
+ run_registration_checks_context_complete_and_free (ctx);
+ return;
+ }
+
+ common_process_system_info (ctx->self, output, NULL);
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
qmi_message_nas_get_system_info_output_unref (output);
@@ -3459,9 +3557,9 @@ modem_3gpp_enable_disable_unsolicited_registration_events_finish (MMIfaceModem3g
}
static void
-ri_serving_system_ready (QmiClientNas *client,
- GAsyncResult *res,
- UnsolicitedRegistrationEventsContext *ctx)
+ri_serving_system_or_system_info_ready (QmiClientNas *client,
+ GAsyncResult *res,
+ UnsolicitedRegistrationEventsContext *ctx)
{
QmiMessageNasRegisterIndicationsOutput *output = NULL;
GError *error = NULL;
@@ -3496,7 +3594,24 @@ common_enable_disable_unsolicited_registration_events_serving_system (Unsolicite
input,
5,
NULL,
- (GAsyncReadyCallback)ri_serving_system_ready,
+ (GAsyncReadyCallback)ri_serving_system_or_system_info_ready,
+ ctx);
+ qmi_message_nas_register_indications_input_unref (input);
+}
+
+static void
+common_enable_disable_unsolicited_registration_events_system_info (UnsolicitedRegistrationEventsContext *ctx)
+{
+ QmiMessageNasRegisterIndicationsInput *input;
+
+ input = qmi_message_nas_register_indications_input_new ();
+ qmi_message_nas_register_indications_input_set_system_info (input, ctx->enable, NULL);
+ qmi_client_nas_register_indications (
+ ctx->client,
+ input,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)ri_serving_system_or_system_info_ready,
ctx);
qmi_message_nas_register_indications_input_unref (input);
}
@@ -3522,6 +3637,12 @@ modem_3gpp_disable_unsolicited_registration_events (MMIfaceModem3gpp *self,
callback,
user_data);
+ /* System Info was added in NAS 1.8 */
+ if (qmi_client_check_version (client, 1, 8)) {
+ common_enable_disable_unsolicited_registration_events_system_info (ctx);
+ return;
+ }
+
/* Ability to explicitly enable/disable serving system indications was
* added in NAS 1.2 */
if (qmi_client_check_version (client, 1, 2)) {
@@ -3586,6 +3707,14 @@ common_setup_cleanup_unsolicited_registration_events_finish (MMBroadbandModemQmi
}
static void
+system_info_indication_cb (QmiClientNas *client,
+ MMBroadbandModemQmi *self,
+ QmiIndicationNasSystemInfoOutput *output)
+{
+ common_process_system_info (self, NULL, output);
+}
+
+static void
serving_system_indication_cb (QmiClientNas *client,
MMBroadbandModemQmi *self,
QmiIndicationNasServingSystemOutput *output)
@@ -3734,18 +3863,35 @@ common_setup_cleanup_unsolicited_registration_events (MMBroadbandModemQmi *self,
/* Store new state */
self->priv->unsolicited_registration_events_setup = enable;
- /* Connect/Disconnect "Serving System" indications */
- if (enable) {
- g_assert (self->priv->serving_system_indication_id == 0);
- self->priv->serving_system_indication_id =
- g_signal_connect (client,
- "serving-system",
- G_CALLBACK (serving_system_indication_cb),
- self);
+ /* Signal info introduced in NAS 1.8 */
+ if (qmi_client_check_version (client, 1, 8)) {
+ /* Connect/Disconnect "System Info" indications */
+ if (enable) {
+ g_assert (self->priv->system_info_indication_id == 0);
+ self->priv->system_info_indication_id =
+ g_signal_connect (client,
+ "system-info",
+ G_CALLBACK (system_info_indication_cb),
+ self);
+ } else {
+ g_assert (self->priv->system_info_indication_id != 0);
+ g_signal_handler_disconnect (client, self->priv->system_info_indication_id);
+ self->priv->system_info_indication_id = 0;
+ }
} else {
- g_assert (self->priv->serving_system_indication_id != 0);
- g_signal_handler_disconnect (client, self->priv->serving_system_indication_id);
- self->priv->serving_system_indication_id = 0;
+ /* Connect/Disconnect "Serving System" indications */
+ if (enable) {
+ g_assert (self->priv->serving_system_indication_id == 0);
+ self->priv->serving_system_indication_id =
+ g_signal_connect (client,
+ "serving-system",
+ G_CALLBACK (serving_system_indication_cb),
+ self);
+ } else {
+ g_assert (self->priv->serving_system_indication_id != 0);
+ g_signal_handler_disconnect (client, self->priv->serving_system_indication_id);
+ self->priv->serving_system_indication_id = 0;
+ }
}
g_simple_async_result_set_op_res_gboolean (result, TRUE);