broadband-modem-qmi: Move to "registered" state based on DSD System Status for PS domain

"registered" state should not wholly depend on the PS/EPS/5GS domain
state reported by NAS.

It should listen to DSD system status for availabilty of data network
at modem before moving to 'registered' state".
This commit is contained in:
Akash Aggarwal
2022-04-21 19:12:02 +05:30
committed by Aleksander Morgado
parent 3893396e20
commit 6761fc0099

View File

@@ -119,6 +119,7 @@ struct _MMBroadbandModemQmiPrivate {
gboolean unsolicited_registration_events_setup;
guint serving_system_indication_id;
guint system_info_indication_id;
guint system_status_indication_id;
guint network_reject_indication_id;
/* CDMA activation helpers */
@@ -169,6 +170,11 @@ struct _MMBroadbandModemQmiPrivate {
gboolean profile_manager_unsolicited_events_enabled;
gboolean profile_manager_unsolicited_events_setup;
guint refresh_indication_id;
/* Registration helpers */
gboolean dsd_supported;
gboolean data_rat_available;
MMModem3gppRegistrationState ps_system_reg_state;
};
/*****************************************************************************/
@@ -3881,19 +3887,149 @@ common_process_system_info_3gpp (MMBroadbandModemQmi *self,
self->priv->current_operator_id = operator_id;
}
self->priv->ps_system_reg_state = ps_registration_state;
/* Report new registration states */
mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), cs_registration_state);
mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), ps_registration_state);
mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self),
has_lte_info ?
ps_registration_state : MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN);
mm_iface_modem_3gpp_update_5gs_registration_state (MM_IFACE_MODEM_3GPP (self),
has_nr5g_info ?
ps_registration_state : MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN);
/* For PS domain, move to registered state only if data rat is available */
if ((ps_registration_state != MM_MODEM_3GPP_REGISTRATION_STATE_HOME &&
ps_registration_state != MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) ||
!self->priv->dsd_supported || self->priv->data_rat_available) {
mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), ps_registration_state);
mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self),
has_lte_info ?
ps_registration_state : MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN);
mm_iface_modem_3gpp_update_5gs_registration_state (MM_IFACE_MODEM_3GPP (self),
has_nr5g_info ?
ps_registration_state : MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN);
}
mm_iface_modem_3gpp_update_access_technologies (MM_IFACE_MODEM_3GPP (self), act);
mm_iface_modem_3gpp_update_location (MM_IFACE_MODEM_3GPP (self), lac, tac, cid);
}
static void
common_process_system_status_3gpp (MMBroadbandModemQmi *self,
QmiMessageDsdGetSystemStatusOutput *response_output,
QmiIndicationDsdSystemStatusOutput *indication_output)
{
GArray *available_systems = NULL;
gboolean data_rat_available = FALSE;
gboolean is_lte = FALSE;
gboolean is_nr5g = FALSE;
if (response_output) {
qmi_message_dsd_get_system_status_output_get_available_systems (response_output, &available_systems, NULL);
if (available_systems && available_systems->len) {
QmiMessageDsdGetSystemStatusOutputAvailableSystemsSystem *system;
system = &g_array_index (available_systems, QmiMessageDsdGetSystemStatusOutputAvailableSystemsSystem, 0);
if (system->technology == QMI_DSD_DATA_SYSTEM_NETWORK_TYPE_3GPP) {
switch (system->rat) {
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_WCDMA:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_TDSCDMA:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_GERAN:
data_rat_available = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_LTE:
data_rat_available = TRUE;
is_lte = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_5G:
data_rat_available = TRUE;
is_nr5g = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_WLAN:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_1X:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_HRPD:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_EHRPD:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_WLAN:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_UNKNOWN:
default:
break;
}
}
}
} else {
qmi_indication_dsd_system_status_output_get_available_systems (indication_output, &available_systems, NULL);
if (available_systems && available_systems->len) {
QmiIndicationDsdSystemStatusOutputAvailableSystemsSystem *system;
system = &g_array_index (available_systems, QmiIndicationDsdSystemStatusOutputAvailableSystemsSystem, 0);
if (system->technology == QMI_DSD_DATA_SYSTEM_NETWORK_TYPE_3GPP) {
switch (system->rat) {
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_WCDMA:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_TDSCDMA:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_GERAN:
data_rat_available = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_LTE:
data_rat_available = TRUE;
is_lte = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_5G:
data_rat_available = TRUE;
is_nr5g = TRUE;
break;
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP_WLAN:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_1X:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_HRPD:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_EHRPD:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_3GPP2_WLAN:
case QMI_DSD_RADIO_ACCESS_TECHNOLOGY_UNKNOWN:
default:
break;
}
}
}
}
self->priv->data_rat_available = data_rat_available;
if (data_rat_available == TRUE &&
(self->priv->ps_system_reg_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
self->priv->ps_system_reg_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)) {
mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), self->priv->ps_system_reg_state);
if (is_lte)
mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self), self->priv->ps_system_reg_state);
if (is_nr5g)
mm_iface_modem_3gpp_update_5gs_registration_state (MM_IFACE_MODEM_3GPP (self), self->priv->ps_system_reg_state);
}
}
static void
get_system_status_3gpp_ready (QmiClientDsd *client,
GAsyncResult *res,
GTask *task)
{
MMBroadbandModemQmi *self;
QmiMessageDsdGetSystemStatusOutput *output;
GError *error = NULL;
self = g_task_get_source_object (task);
output = qmi_client_dsd_get_system_status_finish (client, res, &error);
if (!output || !qmi_message_dsd_get_system_status_output_get_result (output, &error)) {
/* If this command fails, flag that dsd is not unsupported */
self->priv->dsd_supported = FALSE;
g_error_free (error);
}
if (output) {
common_process_system_status_3gpp (self, output, NULL);
qmi_message_dsd_get_system_status_output_unref (output);
}
/* Just ignore errors for now */
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
get_system_info_ready (QmiClientNas *client,
GAsyncResult *res,
@@ -3902,6 +4038,7 @@ get_system_info_ready (QmiClientNas *client,
MMBroadbandModemQmi *self;
QmiMessageNasGetSystemInfoOutput *output;
GError *error = NULL;
QmiClient *client_dsd;
self = g_task_get_source_object (task);
@@ -3945,10 +4082,30 @@ get_system_info_ready (QmiClientNas *client,
}
common_process_system_info_3gpp (self, output, NULL);
qmi_message_nas_get_system_info_output_unref (output);
if (self->priv->dsd_supported) {
client_dsd = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
QMI_SERVICE_DSD,
MM_PORT_QMI_FLAG_DEFAULT,
&error);
if (!client_dsd) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
qmi_client_dsd_get_system_status (QMI_CLIENT_DSD (client_dsd),
NULL,
10,
NULL,
(GAsyncReadyCallback)get_system_status_3gpp_ready,
task);
return;
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
qmi_message_nas_get_system_info_output_unref (output);
}
static void
@@ -4025,6 +4182,9 @@ modem_3gpp_enable_disable_unsolicited_registration_events_finish (MMIfaceModem3g
static void
common_enable_disable_unsolicited_registration_events_serving_system (GTask *task);
static void
common_enable_disable_unsolicited_registration_events_system_status (GTask *task);
static void
ri_serving_system_or_system_info_ready (QmiClientNas *client,
GAsyncResult *res,
@@ -4053,8 +4213,42 @@ ri_serving_system_or_system_info_ready (QmiClientNas *client,
mm_obj_dbg (self, "couldn't register serving system indications: '%s', assuming always enabled", error->message);
}
if (!ctx->system_info_checked)
if (!ctx->system_info_checked) {
ctx->system_info_checked = TRUE;
/* registered system info indications. now try to register for system status indications */
if (self->priv->dsd_supported) {
common_enable_disable_unsolicited_registration_events_system_status (task);
return;
}
}
/* Just ignore errors for now */
self->priv->unsolicited_registration_events_enabled = ctx->enable;
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
ri_system_status_ready (QmiClientDsd *client,
GAsyncResult *res,
GTask *task)
{
MMBroadbandModemQmi *self;
UnsolicitedRegistrationEventsContext *ctx;
g_autoptr(QmiMessageDsdSystemStatusChangeOutput) output = NULL;
g_autoptr(GError) error = NULL;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
output = qmi_client_dsd_system_status_change_finish (client, res, &error);
if (!output || !qmi_message_dsd_system_status_change_output_get_result (output, &error)) {
/* If this command fails, flag that dsd is not unsupported */
self->priv->dsd_supported = FALSE;
if (ctx->enable)
mm_obj_dbg (self, "couldn't register system status indications: '%s', assuming always enabled", error->message);
g_clear_error (&error);
}
/* Just ignore errors for now */
self->priv->unsolicited_registration_events_enabled = ctx->enable;
@@ -4081,6 +4275,40 @@ common_enable_disable_unsolicited_registration_events_serving_system (GTask *tas
task);
}
static void
common_enable_disable_unsolicited_registration_events_system_status (GTask *task)
{
MMBroadbandModemQmi *self;
QmiClient *client;
UnsolicitedRegistrationEventsContext *ctx;
g_autoptr(QmiMessageDsdSystemStatusChangeInput) input = NULL;
GError *error = NULL;
self = g_task_get_source_object (task);
client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
QMI_SERVICE_DSD,
MM_PORT_QMI_FLAG_DEFAULT,
&error);
if (!client) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
ctx = g_task_get_task_data (task);
input = qmi_message_dsd_system_status_change_input_new ();
qmi_message_dsd_system_status_change_input_set_register_indication (input, ctx->enable, NULL);
qmi_client_dsd_system_status_change (
QMI_CLIENT_DSD (client),
input,
5,
NULL,
(GAsyncReadyCallback)ri_system_status_ready,
task);
}
static void
common_enable_disable_unsolicited_registration_events_system_info (GTask *task)
{
@@ -5116,6 +5344,16 @@ system_info_indication_cb (QmiClientNas *client,
common_process_system_info_3gpp (self, NULL, output);
}
static void
system_status_indication_cb (QmiClientDsd *client,
QmiIndicationDsdSystemStatusOutput *output,
MMBroadbandModemQmi *self)
{
if (mm_iface_modem_is_3gpp (MM_IFACE_MODEM (self)))
common_process_system_status_3gpp (self, NULL, output);
}
static void
serving_system_indication_cb (QmiClientNas *client,
QmiIndicationNasServingSystemOutput *output,
@@ -5162,13 +5400,19 @@ common_setup_cleanup_unsolicited_registration_events (MMBroadbandModemQmi *self,
gpointer user_data)
{
GTask *task;
QmiClient *client = NULL;
QmiClient *client_nas = NULL;
QmiClient *client_dsd = NULL;
if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
QMI_SERVICE_NAS, &client,
QMI_SERVICE_NAS, &client_nas,
callback, user_data))
return;
client_dsd = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
QMI_SERVICE_DSD,
MM_PORT_QMI_FLAG_DEFAULT,
NULL);
task = g_task_new (self, NULL, callback, user_data);
if (enable == self->priv->unsolicited_registration_events_setup) {
@@ -5186,26 +5430,26 @@ common_setup_cleanup_unsolicited_registration_events (MMBroadbandModemQmi *self,
if (enable) {
g_assert (self->priv->system_info_indication_id == 0);
self->priv->system_info_indication_id =
g_signal_connect (client,
g_signal_connect (client_nas,
"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);
g_signal_handler_disconnect (client_nas, self->priv->system_info_indication_id);
self->priv->system_info_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,
g_signal_connect (client_nas,
"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);
g_signal_handler_disconnect (client_nas, self->priv->serving_system_indication_id);
self->priv->serving_system_indication_id = 0;
}
@@ -5213,16 +5457,33 @@ common_setup_cleanup_unsolicited_registration_events (MMBroadbandModemQmi *self,
if (enable) {
g_assert (self->priv->network_reject_indication_id == 0);
self->priv->network_reject_indication_id =
g_signal_connect (client,
g_signal_connect (client_nas,
"network-reject",
G_CALLBACK (network_reject_indication_cb),
self);
} else {
g_assert (self->priv->network_reject_indication_id != 0);
g_signal_handler_disconnect (client, self->priv->network_reject_indication_id);
g_signal_handler_disconnect (client_nas, self->priv->network_reject_indication_id);
self->priv->network_reject_indication_id = 0;
}
/* Connect/Disconnect "System Status" indications */
if (client_dsd) {
self->priv->dsd_supported = TRUE;
if (enable) {
g_assert (self->priv->system_status_indication_id == 0);
self->priv->system_status_indication_id =
g_signal_connect (client_dsd,
"system-status",
G_CALLBACK (system_status_indication_cb),
self);
} else {
g_assert (self->priv->system_status_indication_id != 0);
g_signal_handler_disconnect (client_dsd, self->priv->system_status_indication_id);
self->priv->system_status_indication_id = 0;
}
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
@@ -12344,6 +12605,7 @@ static const QmiService qmi_services[] = {
QMI_SERVICE_LOC,
QMI_SERVICE_PDC,
QMI_SERVICE_VOICE,
QMI_SERVICE_DSD,
};
typedef struct {
@@ -12679,6 +12941,8 @@ mm_broadband_modem_qmi_init (MMBroadbandModemQmi *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
MM_TYPE_BROADBAND_MODEM_QMI,
MMBroadbandModemQmiPrivate);
self->priv->ps_system_reg_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
self->priv->data_rat_available = FALSE;
}
static void