From d0f97a4c62ccab064ea305d3367ac4c020a39f78 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Thu, 26 Oct 2023 12:09:20 +0000 Subject: modem-helpers-qmi: translate QMI internal verbose call reason into MM errors Just a few key translations for now. --- src/mm-bearer-qmi.c | 53 +++------------ src/mm-modem-helpers-qmi.c | 160 ++++++++++++++++++++++++++++++++++++++------- src/mm-modem-helpers-qmi.h | 11 ++-- 3 files changed, 154 insertions(+), 70 deletions(-) diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c index 49ccba14..33b88606 100644 --- a/src/mm-bearer-qmi.c +++ b/src/mm-bearer-qmi.c @@ -1212,8 +1212,8 @@ register_for_wds_indication (ConnectContext *ctx, } static GError * -mobile_equipment_error_from_start_network_output (MMBearerQmi *self, - QmiMessageWdsStartNetworkOutput *output) +error_from_start_network_output (MMBearerQmi *self, + QmiMessageWdsStartNetworkOutput *output) { QmiWdsCallEndReason cer; QmiWdsVerboseCallEndReasonType verbose_cer_type; @@ -1224,24 +1224,7 @@ mobile_equipment_error_from_start_network_output (MMBearerQmi &verbose_cer_type, &verbose_cer_reason, NULL)) { - const gchar *verbose_cer_type_str; - const gchar *verbose_cer_reason_str; - - verbose_cer_type_str = qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type); - verbose_cer_reason_str = qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason); - mm_obj_msg (self, " verbose call end reason (%u,%d): [%s] %s", - verbose_cer_type, - verbose_cer_reason, - verbose_cer_type_str, - verbose_cer_reason_str); - - /* If we have a 3GPP verbose call end reason, we try to build an error - * with the exact error code and message */ - if (verbose_cer_type == QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP) - return mm_error_from_wds_verbose_call_end_reason_3gpp ((QmiWdsVerboseCallEndReason3gpp)verbose_cer_reason, self); - - return g_error_new (MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, - "Call failed: %s error: %s", verbose_cer_type_str, verbose_cer_reason_str); + return mm_error_from_wds_verbose_call_end_reason (verbose_cer_type, verbose_cer_reason, self); } if (qmi_message_wds_start_network_output_get_call_end_reason ( @@ -1294,7 +1277,7 @@ start_network_ready (QmiClientWds *client, mm_obj_msg (self, "couldn't start %s network: %s", ctx->running_ipv4 ? "IPv4" : "IPv6", error->message); if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_CALL_FAILED)) { g_clear_error (&error); - error = mobile_equipment_error_from_start_network_output (self, output); + error = error_from_start_network_output (self, output); } } } @@ -1391,28 +1374,12 @@ packet_service_status_indication_cb (QmiClientWds *client, &verbose_cer_type, &verbose_cer_reason, NULL)) { - const gchar *verbose_cer_type_str; - const gchar *verbose_cer_reason_str; - - verbose_cer_type_str = qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type); - verbose_cer_reason_str = qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason); - mm_obj_msg (self, "verbose call end reason (%u,%d): [%s] %s", - verbose_cer_type, - verbose_cer_reason, - verbose_cer_type_str, - verbose_cer_reason_str); - - /* If we have a 3GPP verbose call end reason, we try to build an error - * with the exact error code and message */ - if (verbose_cer_type == QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP) - connection_error = mm_error_from_wds_verbose_call_end_reason_3gpp ((QmiWdsVerboseCallEndReason3gpp)verbose_cer_reason, self); - else - connection_error = g_error_new (MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, - "Call failed: %s error: %s", verbose_cer_type_str, verbose_cer_reason_str); - } else if (qmi_indication_wds_packet_service_status_output_get_call_end_reason ( - output, - &cer, - NULL)) { + /* Create MM error based on the verbose call end reason details */ + connection_error = mm_error_from_wds_verbose_call_end_reason (verbose_cer_type, verbose_cer_reason, self); + } else if (qmi_indication_wds_packet_service_status_output_get_call_end_reason ( + output, + &cer, + NULL)) { const gchar *cer_str; cer_str = qmi_wds_call_end_reason_get_string (cer); diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c index ea0146bb..71c29e96 100644 --- a/src/mm-modem-helpers-qmi.c +++ b/src/mm-modem-helpers-qmi.c @@ -3189,6 +3189,91 @@ qmi_personalization_feature_from_mm_modem_3gpp_facility (MMModem3gppFacility /*****************************************************************************/ +typedef struct { + QmiWdsVerboseCallEndReasonInternal vcer; + gboolean is_core_error; /* TRUE if MM_CORE_ERROR, FALSE if MM_MOBILE_EQUIPMENT_ERROR */ + guint error_code; +} InternalErrorMap; + +static const InternalErrorMap internal_error_map[] = { + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_ERROR */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ENDED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_INTERNAL_CAUSE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNKNOWN_CAUSE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CLOSE_IN_PROGRESS */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NETWORK_INITIATED_TERMINATION */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APP_PREEMPTED */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDN_IPV4_CALL_DISALLOWED, FALSE, MM_MOBILE_EQUIPMENT_ERROR_IPV6_ONLY_ALLOWED }, + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDN_IPV4_CALL_THROTTLED, TRUE, MM_CORE_ERROR_THROTTLED }, + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDN_IPV6_CALL_DISALLOWED, FALSE, MM_MOBILE_EQUIPMENT_ERROR_IPV4_ONLY_ALLOWED }, + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDN_IPV6_CALL_THROTTLED, TRUE, MM_CORE_ERROR_THROTTLED }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MODEM_RESTART */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDP_PPP_NOT_SUPPORTED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_UNPREFERRED_RAT */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PHYSICAL_LINK_CLOSE_IN_PROGRESS */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_PENDING_HANDOVER */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PROFILE_BEARER_INCOMPATIBLE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MMGDSI_CARD_EVENT */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_LPM_OR_POWER_DOWN */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_DISABLED, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MPIT_EXPIRED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_IPV6_ADDRESS_TRANSFER_FAILED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_TRAT_SWAP_FAILED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_EHRPD_TO_HRPD_FALLBACK */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MANDATORY_APN_DISABLED, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MIP_CONFIG_FAILURE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_PDN_INACTIVITY_TIMER_EXPIRED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MAX_V4_CONNECTIONS */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_MAX_V6_CONNECTIONS */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_MISMATCH, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_IP_VERSION_MISMATCH */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_DUN_CALL_DISALLOWED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_INVALID_PROFILE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_EPC_NONEPC_TRANSITION */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_INVALID_PROFILE_ID */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_CALL_ALREADY_PRESENT */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_INTERFACE_IN_USE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_IP_PDP_MISMATCH */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_DISALLOWED_ON_ROAMING, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_PARAMETER_CHANGE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_INTERFACE_IN_USE_CONFIG_MATCH */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_NULL_APN_DISALLOWED, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_THERMAL_MITIGATION */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_SUBS_ID_MISMATCH */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_DATA_SETTINGS_DISABLED */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_DATA_ROAMING_SETTINGS_DISABLED */ + { QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_APN_FORMAT_INVALID, FALSE, MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN }, + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_DDS_CALL_ABORT */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_INTERNAL_VALIDATION_FAILURE */ +}; + +static GError * +error_from_wds_verbose_call_end_reason_internal (QmiWdsVerboseCallEndReasonInternal vcer_reason, + const gchar *vcer_reason_str, + gpointer log_object) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (internal_error_map); i++) { + if (internal_error_map[i].vcer == vcer_reason) { + GError *error; + + g_assert (vcer_reason_str); + if (internal_error_map[i].is_core_error) + error = g_error_new_literal (MM_CORE_ERROR, internal_error_map[i].error_code, vcer_reason_str); + else { + error = mm_mobile_equipment_error_for_code (internal_error_map[i].error_code, log_object); + g_prefix_error (&error, "%s: ", vcer_reason_str); + } + return error; + } + } + + return NULL; +} + +/*****************************************************************************/ + static const MMMobileEquipmentError qmi_vcer_3gpp_errors[] = { [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPERATOR_DETERMINED_BARRING] = MM_MOBILE_EQUIPMENT_ERROR_OPERATOR_DETERMINED_BARRING, [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INSUFFICIENT_RESOURCES] = MM_MOBILE_EQUIPMENT_ERROR_INSUFFICIENT_RESOURCES, @@ -3233,30 +3318,61 @@ static const MMMobileEquipmentError qmi_vcer_3gpp_errors[] = { /* QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_PROXY_CALL_SESSION_CONTROL_FUNCTION_ADDRESS */ }; -GError * -mm_error_from_wds_verbose_call_end_reason_3gpp (QmiWdsVerboseCallEndReason3gpp vcer_3gpp, - gpointer log_object) +static GError * +error_from_wds_verbose_call_end_reason_3gpp (QmiWdsVerboseCallEndReason3gpp vcer_reason, + const gchar *vcer_reason_str, + gpointer log_object) { MMMobileEquipmentError error_code; - const gchar *msg; - - /* convert to mobile equipment error */ - error_code = qmi_vcer_3gpp_errors[vcer_3gpp]; - if (error_code) - return mm_mobile_equipment_error_for_code (error_code, log_object); - - /* provide a nicer error message on unmapped errors */ - msg = qmi_wds_verbose_call_end_reason_3gpp_get_string (vcer_3gpp); - if (msg) - return g_error_new (MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, - "Unsupported error (%u): %s", - vcer_3gpp, msg); - - /* fallback */ - return g_error_new_literal (MM_MOBILE_EQUIPMENT_ERROR, - MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, - "Unknown error"); + GError *error; + + error_code = (vcer_reason < G_N_ELEMENTS (qmi_vcer_3gpp_errors)) ? qmi_vcer_3gpp_errors[vcer_reason] : 0; + if (!error_code) + return NULL; + + g_assert (vcer_reason_str); + error = mm_mobile_equipment_error_for_code (error_code, log_object); + g_prefix_error (&error, "%s: ", vcer_reason_str); + return error; +} + +GError * +mm_error_from_wds_verbose_call_end_reason (QmiWdsVerboseCallEndReasonType vcer_type, + guint vcer_reason, + gpointer log_object) +{ + GError *error = NULL; + const gchar *vcer_type_str; + const gchar *vcer_reason_str; + + vcer_type_str = qmi_wds_verbose_call_end_reason_type_get_string (vcer_type); + vcer_reason_str = qmi_wds_verbose_call_end_reason_get_string (vcer_type, vcer_reason); + mm_obj_msg (log_object, "verbose call end reason (%u,%d): [%s] %s", + vcer_type, vcer_reason, vcer_type_str, vcer_reason_str); + + switch (vcer_type) { + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_INTERNAL: + error = error_from_wds_verbose_call_end_reason_internal (vcer_reason, vcer_reason_str, log_object); + break; + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_3GPP: + error = error_from_wds_verbose_call_end_reason_3gpp (vcer_reason, vcer_reason_str, log_object); + break; + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_MIP: + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_CM: + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_PPP: + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_EHRPD: + case QMI_WDS_VERBOSE_CALL_END_REASON_TYPE_IPV6: + default: + break; + } + + if (error) + return error; + + return g_error_new (MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, + "Call failed: %s error: %s", + vcer_type_str ? vcer_type_str : "unknown", + vcer_reason_str ? vcer_reason_str : "unknown"); } /*****************************************************************************/ diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h index d92486ee..96b9ca85 100644 --- a/src/mm-modem-helpers-qmi.h +++ b/src/mm-modem-helpers-qmi.h @@ -255,10 +255,11 @@ gboolean qmi_personalization_feature_from_mm_modem_3gpp_facility (MMModem3gppFac /*****************************************************************************/ /* MM error translations */ -void mm_register_qmi_errors (void); -GError *mm_error_from_wds_verbose_call_end_reason_3gpp (QmiWdsVerboseCallEndReason3gpp vcer_3gpp, - gpointer log_object); -gboolean mm_error_from_qmi_loc_indication_status (QmiLocIndicationStatus status, - GError **error); +void mm_register_qmi_errors (void); +GError *mm_error_from_wds_verbose_call_end_reason (QmiWdsVerboseCallEndReasonType vcer_type, + guint vcer_reason, + gpointer log_object); +gboolean mm_error_from_qmi_loc_indication_status (QmiLocIndicationStatus status, + GError **error); #endif /* MM_MODEM_HELPERS_QMI_H */ -- cgit v1.2.3-70-g09d2