diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-bearer-qmi.c | 86 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.c | 73 | ||||
-rw-r--r-- | src/mm-modem-helpers-qmi.h | 3 |
3 files changed, 131 insertions, 31 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c index 8926918c..02059831 100644 --- a/src/mm-bearer-qmi.c +++ b/src/mm-bearer-qmi.c @@ -894,6 +894,55 @@ get_current_settings (GTask *task, QmiClientWds *client) qmi_message_wds_get_current_settings_input_unref (input); } +static GError * +mobile_equipment_error_from_start_network_output (MMBearerQmi *self, + QmiMessageWdsStartNetworkOutput *output) +{ + QmiWdsCallEndReason cer; + QmiWdsVerboseCallEndReasonType verbose_cer_type; + gint16 verbose_cer_reason; + + if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( + output, + &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_info (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 qmi_mobile_equipment_error_from_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); + } + + if (qmi_message_wds_start_network_output_get_call_end_reason ( + output, + &cer, + NULL)) { + const gchar *cer_str; + + cer_str = qmi_wds_call_end_reason_get_string (cer); + mm_obj_info (self, "call end reason (%u): %s", cer, cer_str); + + return g_error_new (MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, + "Call failed: %s", cer_str); + } + + return g_error_new_literal (MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, "Call failed"); +} + static void start_network_ready (QmiClientWds *client, GAsyncResult *res, @@ -911,49 +960,24 @@ start_network_ready (QmiClientWds *client, g_assert (!(ctx->running_ipv4 && ctx->running_ipv6)); output = qmi_client_wds_start_network_finish (client, res, &error); - if (output && - !qmi_message_wds_start_network_output_get_result (output, &error)) { + if (output && !qmi_message_wds_start_network_output_get_result (output, &error)) { /* No-effect errors should be ignored. The modem will keep the * connection active as long as there is a WDS client which requested * to start the network. If ModemManager crashed while a connection was * active, we would be leaving an unreleased WDS client around and the * modem would just keep connected. */ - if (g_error_matches (error, - QMI_PROTOCOL_ERROR, - QMI_PROTOCOL_ERROR_NO_EFFECT)) { - g_error_free (error); - error = NULL; + if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NO_EFFECT)) { + g_clear_error (&error); if (ctx->running_ipv4) ctx->packet_data_handle_ipv4 = GLOBAL_PACKET_DATA_HANDLE; else ctx->packet_data_handle_ipv6 = GLOBAL_PACKET_DATA_HANDLE; - /* Fall down to a successful connection */ } else { mm_obj_info (self, "couldn't start network: %s", error->message); - if (g_error_matches (error, - QMI_PROTOCOL_ERROR, - QMI_PROTOCOL_ERROR_CALL_FAILED)) { - QmiWdsCallEndReason cer; - QmiWdsVerboseCallEndReasonType verbose_cer_type; - gint16 verbose_cer_reason; - - if (qmi_message_wds_start_network_output_get_call_end_reason ( - output, - &cer, - NULL)) - mm_obj_info (self, "call end reason (%u): %s", cer, qmi_wds_call_end_reason_get_string (cer)); - - if (qmi_message_wds_start_network_output_get_verbose_call_end_reason ( - output, - &verbose_cer_type, - &verbose_cer_reason, - NULL)) - mm_obj_info (self, "verbose call end reason (%u,%d): [%s] %s", - verbose_cer_type, - verbose_cer_reason, - qmi_wds_verbose_call_end_reason_type_get_string (verbose_cer_type), - qmi_wds_verbose_call_end_reason_get_string (verbose_cer_type, verbose_cer_reason)); + 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); } } } diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c index 13e60810..c95aa9eb 100644 --- a/src/mm-modem-helpers-qmi.c +++ b/src/mm-modem-helpers-qmi.c @@ -21,6 +21,7 @@ #include "mm-modem-helpers-qmi.h" #include "mm-modem-helpers.h" +#include "mm-error-helpers.h" #include "mm-enums-types.h" #include "mm-log-object.h" @@ -1617,6 +1618,78 @@ mm_bearer_apn_type_from_qmi_apn_type (QmiWdsApnTypeMask apn_type) } /*****************************************************************************/ + +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, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_APN] = MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP] = MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_AUTHENTICATION_FAILED] = MM_MOBILE_EQUIPMENT_ERROR_USER_AUTHENTICATION_FAILED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_GGSN_REJECT] = MM_MOBILE_EQUIPMENT_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ACTIVATION_REJECT] = MM_MOBILE_EQUIPMENT_ERROR_ACTIVATION_REJECTED_UNSPECIFIED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_NOT_SUPPORTED] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_NOT_SUPPORTED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_UNSUBSCRIBED] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_OPTION_TEMPORARILY_OUT_OF_ORDER] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_OUT_OF_ORDER, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NSAPI_ALREADY_USED] = MM_MOBILE_EQUIPMENT_ERROR_NSAPI_OR_PTI_ALREADY_IN_USE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REGULAR_DEACTIVATION] = MM_MOBILE_EQUIPMENT_ERROR_REGULAR_DEACTIVATION, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_QOS_NOT_ACCEPTED] = MM_MOBILE_EQUIPMENT_ERROR_QOS_NOT_ACCEPTED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_NETWORK_FAILURE] = MM_MOBILE_EQUIPMENT_ERROR_NETWORK_FAILURE_ATTACH, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_REATTACH_REQUIRED] = MM_MOBILE_EQUIPMENT_ERROR_NETWORK_FAILURE_ATTACH, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FEATURE_NOT_SUPPORTED] = MM_MOBILE_EQUIPMENT_ERROR_FEATURE_NOT_SUPPORTED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SEMANTIC_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_SEMANTIC_ERROR_IN_TFT_OPERATION, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_TFT_SYNTAX_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_SYNTACTICAL_ERROR_IN_TFT_OPERATION, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_PDP_CONTEXT] = MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN_PDP_CONTEXT, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SEMANTIC_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_SEMANTIC_ERRORS_IN_PACKET_FILTER, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_FILTER_SYNTAX_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_SYNTACTICAL_ERROR_IN_PACKET_FILTER, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDP_WITHOUT_ACTIVE_TFT] = MM_MOBILE_EQUIPMENT_ERROR_PDP_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV4_ONLY_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_IPV4_ONLY_ALLOWED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_IPV6_ONLY_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_IPV6_ONLY_ALLOWED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_SINGLE_ADDRESS_BEARER_ONLY] = MM_MOBILE_EQUIPMENT_ERROR_SINGLE_ADDRESS_BEARERS_ONLY_ALLOWED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_ESM_INFO_NOT_RECEIVED] = MM_MOBILE_EQUIPMENT_ERROR_ESM_INFORMATION_NOT_RECEIVED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PDN_CONNECTION_DOES_NOT_EXIST] = MM_MOBILE_EQUIPMENT_ERROR_PDN_CONNECTION_NONEXISTENT, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MULTIPLE_CONNECTION_TO_SAME_PDN_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_MULTIPLE_PDN_CONNECTION_SAME_APN_NOT_ALLOWED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_TRANSACTION_ID] = MM_MOBILE_EQUIPMENT_ERROR_INVALID_TRANSACTION_ID_VALUE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_INCORRECT_SEMANTIC] = MM_MOBILE_EQUIPMENT_ERROR_SEMANTICALLY_INCORRECT_MESSAGE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_MANDATORY_INFO] = MM_MOBILE_EQUIPMENT_ERROR_INVALID_MANDATORY_INFORMATION, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_UNSUPPORTED] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_TYPE_NONCOMPATIBLE_STATE] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_UNKNOWN_INFO_ELEMENT] = MM_MOBILE_EQUIPMENT_ERROR_IE_NOT_IMPLEMENTED, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_CONDITIONAL_IE_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_CONDITIONAL_IE_ERROR, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_MESSAGE_AND_PROTOCOL_STATE_UNCOMPATIBLE] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, + [QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_PROTOCOL_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_UNSPECIFIED_PROTOCOL_ERROR, + /* unmapped errors */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_LLC_SNDCP_FAILURE */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_APN_TYPE_CONFLICT */ + /* QMI_WDS_VERBOSE_CALL_END_REASON_3GPP_INVALID_PROXY_CALL_SESSION_CONTROL_FUNCTION_ADDRESS */ +}; + +GError * +qmi_mobile_equipment_error_from_verbose_call_end_reason_3gpp (QmiWdsVerboseCallEndReason3gpp vcer_3gpp, + 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"); +} + +/*****************************************************************************/ /* QMI/WDA to MM translations */ QmiDataEndpointType diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h index 29d014d3..04e5934c 100644 --- a/src/mm-modem-helpers-qmi.h +++ b/src/mm-modem-helpers-qmi.h @@ -126,6 +126,9 @@ QmiWdsApnTypeMask mm_bearer_apn_type_to_qmi_apn_type (MMBearerApn gpointer log_object); MMBearerApnType mm_bearer_apn_type_from_qmi_apn_type (QmiWdsApnTypeMask apn_type); +GError *qmi_mobile_equipment_error_from_verbose_call_end_reason_3gpp (QmiWdsVerboseCallEndReason3gpp vcer_3gpp, + gpointer log_object); + /*****************************************************************************/ /* QMI/WDA to MM translations */ |