aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/mmcli-modem.c54
-rw-r--r--cli/mmcli-output.c4
-rw-r--r--cli/mmcli-output.h4
-rw-r--r--include/ModemManager-enums.h155
-rw-r--r--introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml47
-rw-r--r--libmm-glib/libmm-glib.h1
-rw-r--r--libmm-glib/meson.build2
-rw-r--r--libmm-glib/mm-modem-3gpp.c49
-rw-r--r--libmm-glib/mm-modem-3gpp.h4
-rw-r--r--libmm-glib/mm-network-rejection.c321
-rw-r--r--libmm-glib/mm-network-rejection.h97
-rw-r--r--src/mm-iface-modem-3gpp.c58
-rw-r--r--src/mm-iface-modem-3gpp.h6
13 files changed, 788 insertions, 14 deletions
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index 1375c7b4..2c17f5b4 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -412,6 +412,11 @@ print_modem_info (void)
const gchar *initial_eps_bearer_password = NULL;
const gchar *nr5g_registration_settings_mico_mode_str = NULL;
const gchar *nr5g_registration_settings_drx_cycle_str = NULL;
+ MMNetworkRejection *network_rejection = NULL;
+ const gchar *nw_rejection_operator_id = NULL;
+ const gchar *nw_rejection_operator_name = NULL;
+ g_autofree gchar *nw_rejection_access_technology = NULL;
+ g_autofree gchar *nw_rejection_error_str = NULL;
if (ctx->modem_3gpp) {
imei = mm_modem_3gpp_get_imei (ctx->modem_3gpp);
@@ -445,22 +450,43 @@ print_modem_info (void)
nr5g_registration_settings_drx_cycle_str = mm_modem_3gpp_drx_cycle_get_string (mm_nr5g_registration_settings_get_drx_cycle (nr5g_registration_settings));
}
}
+
+ network_rejection = mm_modem_3gpp_peek_network_rejection (ctx->modem_3gpp);
+ if (network_rejection) {
+ MMNetworkError nw_rejection_error_n;
+ MMModemAccessTechnology nw_rejection_access_technology_n;
+ const gchar *nw_rejection_error = NULL;
+
+ nw_rejection_error_n = mm_network_rejection_get_error (network_rejection);
+ nw_rejection_error = mm_network_error_get_string (nw_rejection_error_n);
+ nw_rejection_error_str = nw_rejection_error ? g_strdup_printf ("%s", nw_rejection_error) :
+ g_strdup_printf ("unknown network rejection error: %u", nw_rejection_error_n);
+ nw_rejection_operator_id = mm_network_rejection_get_operator_id (network_rejection);
+ nw_rejection_operator_name = mm_network_rejection_get_operator_name (network_rejection);
+ nw_rejection_access_technology_n = mm_network_rejection_get_access_technology (network_rejection);
+ nw_rejection_access_technology = mm_modem_access_technology_build_string_from_mask (nw_rejection_access_technology_n);
+
+ }
}
- mmcli_output_string (MMC_F_3GPP_IMEI, imei);
- mmcli_output_string_list (MMC_F_3GPP_ENABLED_LOCKS, facility_locks);
- mmcli_output_string (MMC_F_3GPP_OPERATOR_ID, operator_code);
- mmcli_output_string (MMC_F_3GPP_OPERATOR_NAME, operator_name);
- mmcli_output_string (MMC_F_3GPP_REGISTRATION, registration);
- mmcli_output_string (MMC_F_3GPP_PACKET_SERVICE_STATE, packet_service_state);
- mmcli_output_string (MMC_F_3GPP_EPS_UE_MODE, eps_ue_mode);
- mmcli_output_string (MMC_F_3GPP_EPS_INITIAL_BEARER_PATH, g_strcmp0 (initial_eps_bearer_path, "/") != 0 ? initial_eps_bearer_path : NULL);
- mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_APN, initial_eps_bearer_apn);
- mmcli_output_string_take (MMC_F_3GPP_EPS_BEARER_SETTINGS_IP_TYPE, initial_eps_bearer_ip_family_str);
- mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_USER, initial_eps_bearer_user);
- mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_PASSWORD, initial_eps_bearer_password);
- mmcli_output_string (MMC_F_3GPP_5GNR_REGISTRATION_MICO_MODE, nr5g_registration_settings_mico_mode_str);
- mmcli_output_string (MMC_F_3GPP_5GNR_REGISTRATION_DRX_CYCLE, nr5g_registration_settings_drx_cycle_str);
+ mmcli_output_string (MMC_F_3GPP_IMEI, imei);
+ mmcli_output_string_list (MMC_F_3GPP_ENABLED_LOCKS, facility_locks);
+ mmcli_output_string (MMC_F_3GPP_OPERATOR_ID, operator_code);
+ mmcli_output_string (MMC_F_3GPP_OPERATOR_NAME, operator_name);
+ mmcli_output_string (MMC_F_3GPP_REGISTRATION, registration);
+ mmcli_output_string_take (MMC_F_3GPP_NETWORK_REJECTION_ERROR, g_steal_pointer (&nw_rejection_error_str));
+ mmcli_output_string (MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_ID, nw_rejection_operator_id);
+ mmcli_output_string (MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_NAME, nw_rejection_operator_name);
+ mmcli_output_string_take (MMC_F_3GPP_NETWORK_REJECTION_ACCESS_TECHNOLOGY, g_steal_pointer (&nw_rejection_access_technology));
+ mmcli_output_string (MMC_F_3GPP_PACKET_SERVICE_STATE, packet_service_state);
+ mmcli_output_string (MMC_F_3GPP_EPS_UE_MODE, eps_ue_mode);
+ mmcli_output_string (MMC_F_3GPP_EPS_INITIAL_BEARER_PATH, g_strcmp0 (initial_eps_bearer_path, "/") != 0 ? initial_eps_bearer_path : NULL);
+ mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_APN, initial_eps_bearer_apn);
+ mmcli_output_string_take (MMC_F_3GPP_EPS_BEARER_SETTINGS_IP_TYPE, initial_eps_bearer_ip_family_str);
+ mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_USER, initial_eps_bearer_user);
+ mmcli_output_string (MMC_F_3GPP_EPS_BEARER_SETTINGS_PASSWORD, initial_eps_bearer_password);
+ mmcli_output_string (MMC_F_3GPP_5GNR_REGISTRATION_MICO_MODE, nr5g_registration_settings_mico_mode_str);
+ mmcli_output_string (MMC_F_3GPP_5GNR_REGISTRATION_DRX_CYCLE, nr5g_registration_settings_drx_cycle_str);
mmcli_output_pco_list (pco_list);
g_free (facility_locks);
diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c
index 151778ef..c1c064da 100644
--- a/cli/mmcli-output.c
+++ b/cli/mmcli-output.c
@@ -136,6 +136,10 @@ static FieldInfo field_infos[] = {
[MMC_F_3GPP_OPERATOR_ID] = { "modem.3gpp.operator-code", "operator id", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_OPERATOR_NAME] = { "modem.3gpp.operator-name", "operator name", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_REGISTRATION] = { "modem.3gpp.registration-state", "registration", MMC_S_MODEM_3GPP, },
+ [MMC_F_3GPP_NETWORK_REJECTION_ERROR] = { "modem.3gpp.network-rejection-error", "network rejection error", MMC_S_MODEM_3GPP, },
+ [MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_ID] = { "modem.3gpp.network-rejection-operator-id", "network rejection operator id", MMC_S_MODEM_3GPP, },
+ [MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_NAME] = { "modem.3gpp.network-rejection-operator-name", "network rejection operator name", MMC_S_MODEM_3GPP, },
+ [MMC_F_3GPP_NETWORK_REJECTION_ACCESS_TECHNOLOGY] = { "modem.3gpp.network-rejection-access-technology", "network rejection access technology", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_PACKET_SERVICE_STATE] = { "modem.3gpp.packet-service-state", "packet service state", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_PCO] = { "modem.3gpp.pco", "pco", MMC_S_MODEM_3GPP, },
[MMC_F_3GPP_EPS_UE_MODE] = { "modem.3gpp.eps.ue-mode-operation", "ue mode of operation", MMC_S_MODEM_3GPP_EPS, },
diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h
index 5e2a3071..f942f16b 100644
--- a/cli/mmcli-output.h
+++ b/cli/mmcli-output.h
@@ -138,6 +138,10 @@ typedef enum {
MMC_F_3GPP_OPERATOR_NAME,
MMC_F_3GPP_REGISTRATION,
MMC_F_3GPP_PACKET_SERVICE_STATE,
+ MMC_F_3GPP_NETWORK_REJECTION_ERROR,
+ MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_ID,
+ MMC_F_3GPP_NETWORK_REJECTION_OPERATOR_NAME,
+ MMC_F_3GPP_NETWORK_REJECTION_ACCESS_TECHNOLOGY,
MMC_F_3GPP_PCO,
/* 3GPP EPS section */
MMC_F_3GPP_EPS_UE_MODE,
diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h
index 178c15f2..1217e581 100644
--- a/include/ModemManager-enums.h
+++ b/include/ModemManager-enums.h
@@ -1954,4 +1954,159 @@ typedef enum { /*< underscore_name=mm_serving_cell_type >*/
MM_SERVING_CELL_TYPE_INVALID = 0xFFFFFFFF
} MMServingCellType;
+/**
+ * MMNetworkError:
+ * @MM_NETWORK_ERROR_NONE: No error.
+ * @MM_NETWORK_ERROR_IMSI_UNKNOWN_IN_HLR: IMSI unknown in the HLR.
+ * @MM_NETWORK_ERROR_ILLEGAL_MS: Illegal MS.
+ * @MM_NETWORK_ERROR_IMSI_UNKNOWN_IN_VLR: IMSI unknown in the VLR.
+ * @MM_NETWORK_ERROR_IMEI_NOT_ACCEPTED: IMEI not accepted.
+ * @MM_NETWORK_ERROR_ILLEGAL_ME: Illegal ME.
+ * @MM_NETWORK_ERROR_GPRS_NOT_ALLOWED: GPRS not allowed.
+ * @MM_NETWORK_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED: GPRS and non-GPRS not allowed.
+ * @MM_NETWORK_ERROR_MS_IDENTITY_NOT_DERIVED_BY_NETWORK: MS identity cannot be derived by the network.
+ * @MM_NETWORK_ERROR_IMPLICITLY_DETACHED: Implicitly detached.
+ * @MM_NETWORK_ERROR_PLMN_NOT_ALLOWED: PLMN not allowed.
+ * @MM_NETWORK_ERROR_LOCATION_AREA_NOT_ALLOWED: Location area not allowed.
+ * @MM_NETWORK_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA: Roaming not allowed in the location area.
+ * @MM_NETWORK_ERROR_GPRS_NOT_ALLOWED_IN_PLMN: GPRS not allowed in PLMN.
+ * @MM_NETWORK_ERROR_NO_CELLS_IN_LOCATION_AREA: No cells in location area.
+ * @MM_NETWORK_ERROR_MSC_TEMPORARILY_NOT_REACHABLE: MSC temporarily not reachable.
+ * @MM_NETWORK_ERROR_NETWORK_FAILURE: Network failure.
+ * @MM_NETWORK_ERROR_MAC_FAILURE: MAC failure.
+ * @MM_NETWORK_ERROR_SYNCH_FAILURE: Synch failure.
+ * @MM_NETWORK_ERROR_CONGESTION: Congestion.
+ * @MM_NETWORK_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE: GSM authentication unacceptable.
+ * @MM_NETWORK_ERROR_NOT_AUTHORIZED_FOR_CSG: Not authorized for this CSG.
+ * @MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES: Insufficient resources.
+ * @MM_NETWORK_ERROR_MISSING_OR_UNKNOWN_APN: Missing or unknown access point name.
+ * @MM_NETWORK_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE: Unknown PDP address or PDP type.
+ * @MM_NETWORK_ERROR_USER_AUTHENTICATION_FAILED: User authentication failed.
+ * @MM_NETWORK_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW: Activation rejected by GGSN, Serving GW or PDN GW.
+ * @MM_NETWORK_ERROR_ACTIVATION_REJECTED_UNSPECIFIED: Activation rejected, unspecified.
+ * @MM_NETWORK_ERROR_SERVICE_OPTION_NOT_SUPPORTED: Service option not supported.
+ * @MM_NETWORK_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED: Requested service option not subscribed.
+ * @MM_NETWORK_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER: Service option temporarily out of order.
+ * @MM_NETWORK_ERROR_NO_PDP_CONTEXT_ACTIVATED: No PDP context activated.
+ * @MM_NETWORK_ERROR_SEMANTIC_ERROR_IN_THE_TFT_OPERATION: Semantic error in the TFT operation.
+ * @MM_NETWORK_ERROR_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION: Syntactical error in the TFT operation.
+ * @MM_NETWORK_ERROR_UNKNOWN_PDP_CONTEXT: Unknown PDP context.
+ * @MM_NETWORK_ERROR_SEMANTIC_ERRORS_IN_PACKET_FILTER: Semantic errors in packet filter.
+ * @MM_NETWORK_ERROR_SYNTACTICAL_ERRORS_IN_PACKET_FILTER: Syntactical errors in packet filter.
+ * @MM_NETWORK_ERROR_PDP_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED: PDP context without TFT already activated.
+ * @MM_NETWORK_ERROR_REQUEST_REJECTED_OR_BEARER_CONTROL_MODE_VIOLATION: Request rejected, Bearer Control Mode violation.
+ * @MM_NETWORK_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED: Last PDN disconnection not allowed.
+ * @MM_NETWORK_ERROR_PDP_TYPE_IPV4_ONLY_ALLOWED: PDP type IPv4 only allowed.
+ * @MM_NETWORK_ERROR_PDP_TYPE_IPV6_ONLY_ALLOWED: PDP type IPv6 only allowed.
+ * @MM_NETWORK_ERROR_NO_NETWORK_SLICES_AVAILABLE: No network slices available.
+ * @MM_NETWORK_ERROR_MAXIMUM_NUMBER_OF_PDP_CONTEXTS_REACHED: Maximum number of PDP contexts reached.
+ * @MM_NETWORK_ERROR_REQUESTED_APN_NOT_SUPPORTED_IN_CURRENT_RAT_AND_PLMN: Requested APN not supported in current RAT and PLMN combination.
+ * @MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN: Insufficient resources for specific slice and DNN.
+ * @MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE: Insufficient resources for specific slice.
+ * @MM_NETWORK_ERROR_NGKSI_ALREADY_IN_USE: NgKSI already in use.
+ * @MM_NETWORK_ERROR_NON_3GPP_ACCESS_TO_5GCN_NOT_ALLOWED: Non-3GPP access to 5GCN not allowed.
+ * @MM_NETWORK_ERROR_SERVING_NETWORK_NOT_AUTHORIZED: Serving network not authorized.
+ * @MM_NETWORK_ERROR_TEMPORARILY_NOT_AUTHORIZED_FOR_THIS_SNPN: Temporarily not authorized for this SNPN.
+ * @MM_NETWORK_ERROR_PERMANENTLY_NOT_AUTHORIZED_FOR_THIS_SNPN: Permanently not authorized for this SNPN.
+ * @MM_NETWORK_ERROR_NOT_AUTHORIZED_FOR_THIS_CAG_OR_AUTHORIZED_FOR_CAG_CELLS_ONLY: Not authorized for this CAG or authorized for CAG cells.
+ * @MM_NETWORK_ERROR_WIRELINE_ACCESS_AREA_NOT_ALLOWED: Wireline access area not allowed.
+ * @MM_NETWORK_ERROR_PAYLOAD_WAS_NOT_FORWARDED: Payload was not forwarded.
+ * @MM_NETWORK_ERROR_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE: DNN not supported or not subscribed in the slice.
+ * @MM_NETWORK_ERROR_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION: Insufficient user-plane resources for the PDU session.
+ * @MM_NETWORK_ERROR_SEMANTICALLY_INCORRECT_MESSAGE: Semantically incorrect message.
+ * @MM_NETWORK_ERROR_INVALID_MANDATORY_INFORMATION: Invalid mandatory information.
+ * @MM_NETWORK_ERROR_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED: Message type non-existent or not implemented.
+ * @MM_NETWORK_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: Message type not compatible with protocol state.
+ * @MM_NETWORK_ERROR_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED: Information element non-existent or not implemented.
+ * @MM_NETWORK_ERROR_CONDITIONAL_IE_ERROR: Conditional IE error.
+ * @MM_NETWORK_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE: Message not compatible with protocol state.
+ * @MM_NETWORK_ERROR_PROTOCOL_ERROR_UNSPECIFIED: Protocol error, unspecified.
+ * @MM_NETWORK_ERROR_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXT: APN restriction value incompatible with active PDP context.
+ * @MM_NETWORK_ERROR_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED: Multiple accesses to a PDN connection not allowed.
+ *
+ * Network errors reported by the network when registration is rejected.
+ * Even though some error names make reference to legacy technologies (e.g. GPRS), errors are not
+ * technology specific and the same type of errors are reported even for newer
+ * technologies like LTE and 5G.
+ * Network errors are defined in 3GPP TS 24.008 in sections 10.5.3.6 and
+ * 10.5.5.14 (detailed in annex G) and in 3GPP TS 24.301 in section 9.9.3.9.
+ *
+ * Since: 1.24
+ */
+typedef enum { /*< underscore_name=mm_network_error >*/
+ MM_NETWORK_ERROR_NONE = 0,
+ MM_NETWORK_ERROR_IMSI_UNKNOWN_IN_HLR = 2,
+ MM_NETWORK_ERROR_ILLEGAL_MS = 3,
+ MM_NETWORK_ERROR_IMSI_UNKNOWN_IN_VLR = 4,
+ MM_NETWORK_ERROR_IMEI_NOT_ACCEPTED = 5,
+ MM_NETWORK_ERROR_ILLEGAL_ME = 6,
+ MM_NETWORK_ERROR_GPRS_NOT_ALLOWED = 7,
+ MM_NETWORK_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED = 8,
+ MM_NETWORK_ERROR_MS_IDENTITY_NOT_DERIVED_BY_NETWORK = 9,
+ MM_NETWORK_ERROR_IMPLICITLY_DETACHED = 10,
+ MM_NETWORK_ERROR_PLMN_NOT_ALLOWED = 11,
+ MM_NETWORK_ERROR_LOCATION_AREA_NOT_ALLOWED = 12,
+ MM_NETWORK_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA = 13,
+ MM_NETWORK_ERROR_GPRS_NOT_ALLOWED_IN_PLMN = 14,
+ MM_NETWORK_ERROR_NO_CELLS_IN_LOCATION_AREA = 15,
+ MM_NETWORK_ERROR_MSC_TEMPORARILY_NOT_REACHABLE = 16,
+ MM_NETWORK_ERROR_NETWORK_FAILURE = 17,
+ MM_NETWORK_ERROR_CS_DOMAIN_NOT_AVAILABLE = 18,
+ MM_NETWORK_ERROR_ESM_FAILURE = 19,
+ MM_NETWORK_ERROR_MAC_FAILURE = 20,
+ MM_NETWORK_ERROR_SYNCH_FAILURE = 21,
+ MM_NETWORK_ERROR_CONGESTION = 22,
+ MM_NETWORK_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE = 23,
+ MM_NETWORK_ERROR_NOT_AUTHORIZED_FOR_CSG = 25,
+ MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES = 26,
+ MM_NETWORK_ERROR_MISSING_OR_UNKNOWN_APN = 27,
+ MM_NETWORK_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE = 28,
+ MM_NETWORK_ERROR_USER_AUTHENTICATION_FAILED = 29,
+ MM_NETWORK_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW = 30,
+ MM_NETWORK_ERROR_REDIRECTION_TO_5GCN_REQUIRED = 31,
+ MM_NETWORK_ERROR_SERVICE_OPTION_NOT_SUPPORTED = 32,
+ MM_NETWORK_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED = 33,
+ MM_NETWORK_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER = 34,
+ MM_NETWORK_ERROR_REQUESTED_SERVICE_OPTION_NOT_AUTHORIZED = 35,
+ MM_NETWORK_ERROR_CALL_CANNOT_BE_IDENTIFIED = 38,
+ MM_NETWORK_ERROR_CS_SERVICE_TEMPORARILY_NOT_AVAILABLE = 39,
+ MM_NETWORK_ERROR_NO_PDP_CONTEXT_ACTIVATED = 40,
+ MM_NETWORK_ERROR_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 41,
+ MM_NETWORK_ERROR_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 42,
+ MM_NETWORK_ERROR_UNKNOWN_PDP_CONTEXT = 43,
+ MM_NETWORK_ERROR_SEMANTIC_ERRORS_IN_PACKET_FILTER = 44,
+ MM_NETWORK_ERROR_SYNTACTICAL_ERRORS_IN_PACKET_FILTER = 45,
+ MM_NETWORK_ERROR_PDP_CONTEXT_WITHOUT_TFT_ALREADY_ACTIVATED = 46,
+ MM_NETWORK_ERROR_REQUEST_REJECTED_OR_BEARER_CONTROL_MODE_VIOLATION = 48,
+ MM_NETWORK_ERROR_LAST_PDN_DISCONNECTION_NOT_ALLOWED = 49,
+ MM_NETWORK_ERROR_PDP_TYPE_IPV4_ONLY_ALLOWED = 50,
+ MM_NETWORK_ERROR_PDP_TYPE_IPV6_ONLY_ALLOWED = 51,
+ MM_NETWORK_ERROR_NO_NETWORK_SLICES_AVAILABLE = 62,
+ MM_NETWORK_ERROR_MAXIMUM_NUMBER_OF_PDP_CONTEXTS_REACHED = 65,
+ MM_NETWORK_ERROR_REQUESTED_APN_NOT_SUPPORTED_IN_CURRENT_RAT_AND_PLMN = 66,
+ MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE_AND_DNN = 67,
+ MM_NETWORK_ERROR_INSUFFICIENT_RESOURCES_FOR_SPECIFIC_SLICE = 69,
+ MM_NETWORK_ERROR_NGKSI_ALREADY_IN_USE = 71,
+ MM_NETWORK_ERROR_NON_3GPP_ACCESS_TO_5GCN_NOT_ALLOWED = 72,
+ MM_NETWORK_ERROR_SERVING_NETWORK_NOT_AUTHORIZED = 73,
+ MM_NETWORK_ERROR_TEMPORARILY_NOT_AUTHORIZED_FOR_THIS_SNPN = 74,
+ MM_NETWORK_ERROR_PERMANENTLY_NOT_AUTHORIZED_FOR_THIS_SNPN = 75,
+ MM_NETWORK_ERROR_NOT_AUTHORIZED_FOR_THIS_CAG_OR_AUTHORIZED_FOR_CAG_CELLS_ONLY = 76,
+ MM_NETWORK_ERROR_WIRELINE_ACCESS_AREA_NOT_ALLOWED = 77,
+ MM_NETWORK_ERROR_PAYLOAD_WAS_NOT_FORWARDED = 90,
+ MM_NETWORK_ERROR_DNN_NOT_SUPPORTED_OR_NOT_SUBSCRIBED_IN_THE_SLICE = 91,
+ MM_NETWORK_ERROR_INSUFFICIENT_USER_PLANE_RESOURCES_FOR_THE_PDU_SESSION = 92,
+ MM_NETWORK_ERROR_SEMANTICALLY_INCORRECT_MESSAGE = 95,
+ MM_NETWORK_ERROR_INVALID_MANDATORY_INFORMATION = 96,
+ MM_NETWORK_ERROR_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED = 97,
+ MM_NETWORK_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+ MM_NETWORK_ERROR_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED = 99,
+ MM_NETWORK_ERROR_CONDITIONAL_IE_ERROR = 100,
+ MM_NETWORK_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+ MM_NETWORK_ERROR_PROTOCOL_ERROR_UNSPECIFIED = 111,
+ MM_NETWORK_ERROR_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXT = 112,
+ MM_NETWORK_ERROR_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED = 113,
+ MM_NETWORK_ERROR_UNKNOWN = 114,
+} MMNetworkError;
+
#endif /* _MODEMMANAGER_ENUMS_H_ */
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
index f7719676..04cabb8b 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -161,6 +161,53 @@
<property name="RegistrationState" type="u" access="read" />
<!--
+ NetworkRejection:
+
+ This property holds the latest network rejection information received from the
+ network during registration failure, and it will be cleared whenever the modem
+ successfully registers.
+ Network errors are defined in 3GPP TS 24.008 in sections 10.5.3.6 and
+ 10.5.5.14 (detailed in annex G) and in 3GPP TS 24.301 in section 9.9.3.9.
+
+ Mandatory items include:
+ <variablelist>
+ <varlistentry><term><literal>"error"</literal></term>
+ <listitem>
+ A <link linkend="MMNetworkError">MMNetworkError</link>,
+ specifying the reason why a request from the mobile station
+ is rejected by the network, given as an unsigned integer value
+ (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ Optionally following items could be included if reported by modem along
+ with network error.
+ <variablelist>
+ <varlistentry><term><literal>"operator-id"</literal></term>
+ <listitem>
+ Operator id reported along with network error, given as a string value (signature <literal>"s"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"operator-name"</literal></term>
+ <listitem>
+ Operator name reported along with network error, given as a string value (signature <literal>"s"</literal>).
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"access-technology"</literal></term>
+ <listitem>
+ A <link linkend="MMModemAccessTechnology">MMModemAccessTechnology</link>,
+ specifying the available data class reported along with network error,
+ given as an unsigned integer value (signature <literal>"u"</literal>).
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ Since: 1.24
+ -->
+ <property name="NetworkRejection" type="a{sv}" access="read" />
+
+ <!--
OperatorCode:
Code of the operator to which the mobile is currently registered.
diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h
index 8c282562..c0fde6e0 100644
--- a/libmm-glib/libmm-glib.h
+++ b/libmm-glib/libmm-glib.h
@@ -93,6 +93,7 @@
#include <mm-cell-info-tdscdma.h>
#include <mm-cell-info-lte.h>
#include <mm-cell-info-nr5g.h>
+#include <mm-network-rejection.h>
#include <mm-compat.h>
/* generated */
diff --git a/libmm-glib/meson.build b/libmm-glib/meson.build
index de668dab..0871778c 100644
--- a/libmm-glib/meson.build
+++ b/libmm-glib/meson.build
@@ -61,6 +61,7 @@ headers = files(
'mm-sms.h',
'mm-sms-properties.h',
'mm-unlock-retries.h',
+ 'mm-network-rejection.h',
)
install_headers(
@@ -123,6 +124,7 @@ sources = files(
'mm-sms.c',
'mm-sms-properties.c',
'mm-unlock-retries.c',
+ 'mm-network-rejection.c',
)
deps = [include_dep]
diff --git a/libmm-glib/mm-modem-3gpp.c b/libmm-glib/mm-modem-3gpp.c
index cb228108..e86360d3 100644
--- a/libmm-glib/mm-modem-3gpp.c
+++ b/libmm-glib/mm-modem-3gpp.c
@@ -52,6 +52,7 @@ struct _MMModem3gppPrivate {
PROPERTY_OBJECT_DECLARE (initial_eps_bearer_settings, MMBearerProperties)
PROPERTY_OBJECT_DECLARE (nr5g_registration_settings, MMNr5gRegistrationSettings)
+ PROPERTY_OBJECT_DECLARE (network_rejection, MMNetworkRejection)
};
/*****************************************************************************/
@@ -696,6 +697,52 @@ PROPERTY_OBJECT_DEFINE_FAILABLE (initial_eps_bearer_settings,
MMBearerProperties,
mm_bearer_properties_new_from_dictionary)
+/**
+ * mm_modem_3gpp_get_network_rejection:
+ * @self: A #MMModem3gpp.
+ *
+ * Gets a #MMNetworkRejection object specifying the network rejection
+ * information received during registration failure.
+ *
+ * <warning>The values reported by @self are not updated when the values in the
+ * interface change. Instead, the client is expected to call
+ * mm_modem_3gpp_get_network_rejection() again to get a new
+ * #MMNetworkRejection with the new values.</warning>
+ *
+ * Returns: (transfer full): A #MMNetworkRejection that must be freed with
+ * g_object_unref() or %NULL if unknown.
+ *
+ * Since: 1.24
+ */
+
+/**
+ * mm_modem_3gpp_peek_network_rejection:
+ * @self: A #MMModem3gpp.
+ *
+ * Gets a #MMNetworkRejection object specifying the network rejection
+ * information received during registration failure.
+ *
+ * <warning>The returned value is only valid until the property changes so
+ * it is only safe to use this function on the thread where
+ * @self was constructed. Use mm_modem_3gpp_get_network_rejection()
+ * if on another thread.</warning>
+ *
+ * Returns: (transfer none): A #MMNetworkRejection. Do not free the returned
+ * value, it belongs to @self.
+ *
+ * Since: 1.24
+ */
+
+/* helpers to match the property substring name with the one in our API */
+#define mm_gdbus_modem_3gpp_dup_network_rejection mm_gdbus_modem3gpp_dup_network_rejection
+
+PROPERTY_OBJECT_DEFINE_FAILABLE (network_rejection,
+ Modem3gpp, modem_3gpp, MODEM_3GPP,
+ MMNetworkRejection,
+ mm_network_rejection_new_from_dictionary)
+
+/*****************************************************************************/
+
/*****************************************************************************/
static GList *
@@ -1613,6 +1660,7 @@ mm_modem_3gpp_init (MMModem3gpp *self)
PROPERTY_INITIALIZE (initial_eps_bearer_settings, "initial-eps-bearer-settings")
PROPERTY_INITIALIZE (nr5g_registration_settings, "nr5g-registration-settings")
+ PROPERTY_INITIALIZE (network_rejection, "network-rejection")
}
static void
@@ -1624,6 +1672,7 @@ finalize (GObject *object)
PROPERTY_OBJECT_FINALIZE (initial_eps_bearer_settings);
PROPERTY_OBJECT_FINALIZE (nr5g_registration_settings);
+ PROPERTY_OBJECT_FINALIZE (network_rejection);
G_OBJECT_CLASS (mm_modem_3gpp_parent_class)->finalize (object);
}
diff --git a/libmm-glib/mm-modem-3gpp.h b/libmm-glib/mm-modem-3gpp.h
index 8f137676..6a9ae8e9 100644
--- a/libmm-glib/mm-modem-3gpp.h
+++ b/libmm-glib/mm-modem-3gpp.h
@@ -32,6 +32,7 @@
#include "mm-bearer.h"
#include "mm-nr5g-registration-settings.h"
+#include "mm-network-rejection.h"
#include "mm-gdbus-modem.h"
G_BEGIN_DECLS
@@ -98,6 +99,9 @@ MMModem3gppPacketServiceState mm_modem_3gpp_get_packet_service_state (MMModem3gp
MMNr5gRegistrationSettings *mm_modem_3gpp_get_nr5g_registration_settings (MMModem3gpp *self);
MMNr5gRegistrationSettings *mm_modem_3gpp_peek_nr5g_registration_settings (MMModem3gpp *self);
+MMNetworkRejection *mm_modem_3gpp_get_network_rejection (MMModem3gpp *self);
+MMNetworkRejection *mm_modem_3gpp_peek_network_rejection (MMModem3gpp *self);
+
void mm_modem_3gpp_register (MMModem3gpp *self,
const gchar *network_id,
GCancellable *cancellable,
diff --git a/libmm-glib/mm-network-rejection.c b/libmm-glib/mm-network-rejection.c
new file mode 100644
index 00000000..7bea1475
--- /dev/null
+++ b/libmm-glib/mm-network-rejection.c
@@ -0,0 +1,321 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2024 Google, Inc.
+ */
+
+#include <string.h>
+
+#include "mm-errors-types.h"
+#include "mm-network-rejection.h"
+
+/**
+ * SECTION: mm-network-rejection
+ * @title: MMNetworkRejection
+ * @short_description: Helper object to handle network rejection.
+ *
+ * The #MMNetworkRejection is an object handling the network rejection
+ * related information.
+ *
+ * This object is retrieved with either mm_modem_3gpp_get_network_rejection(),
+ * or mm_modem_3gpp_peek_network_rejection().
+ */
+
+G_DEFINE_TYPE (MMNetworkRejection, mm_network_rejection, G_TYPE_OBJECT)
+
+#define PROPERTY_ERROR "error"
+#define PROPERTY_OPERATOR_ID "operator-id"
+#define PROPERTY_OPERATOR_NAME "operator-name"
+#define PROPERTY_ACCESS_TECHNOLOGY "access-technology"
+
+struct _MMNetworkRejectionPrivate {
+ gchar *operator_id;
+ gchar *operator_name;
+ MMModemAccessTechnology access_technology;
+ MMNetworkError error;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_get_operator_id:
+ * @self: a #MMNetworkRejection.
+ *
+ * Gets the operator id reported with network reject.
+ *
+ * Returns: a string with the operator id, or #NULL if unknown. Do not free the
+ * returned value, it is owned by @self.
+ *
+ * Since: 1.24
+ */
+const gchar *
+mm_network_rejection_get_operator_id (MMNetworkRejection *self)
+{
+ g_return_val_if_fail (MM_IS_NETWORK_REJECTION (self), NULL);
+
+ return self->priv->operator_id;
+}
+
+/**
+ * mm_network_rejection_set_operator_id: (skip)
+ */
+void
+mm_network_rejection_set_operator_id (MMNetworkRejection *self,
+ const gchar *operator_id)
+{
+ g_return_if_fail (MM_IS_NETWORK_REJECTION (self));
+
+ g_free (self->priv->operator_id);
+ self->priv->operator_id = g_strdup (operator_id);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_get_operator_name:
+ * @self: a #MMNetworkRejection.
+ *
+ * Gets the operator name reported with network reject.
+ *
+ * Returns: a string with the operator name, or #NULL if unknown. Do not free the
+ * returned value, it is owned by @self.
+ *
+ * Since: 1.24
+ */
+const gchar *
+mm_network_rejection_get_operator_name (MMNetworkRejection *self)
+{
+ g_return_val_if_fail (MM_IS_NETWORK_REJECTION (self), NULL);
+
+ return self->priv->operator_name;
+}
+
+/**
+ * mm_network_rejection_set_operator_name: (skip)
+ */
+void
+mm_network_rejection_set_operator_name (MMNetworkRejection *self,
+ const gchar *operator_name)
+{
+ g_return_if_fail (MM_IS_NETWORK_REJECTION (self));
+
+ g_free (self->priv->operator_name);
+ self->priv->operator_name = g_strdup (operator_name);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_get_error:
+ * @self: a #MMNetworkRejection.
+ *
+ * Gets the network error reported with network reject.
+ *
+ * Returns: the network error.
+ *
+ * Since: 1.24
+ */
+MMNetworkError
+mm_network_rejection_get_error (MMNetworkRejection *self)
+{
+ g_return_val_if_fail (MM_IS_NETWORK_REJECTION (self), 0);
+
+ return self->priv->error;
+}
+
+/**
+ * mm_network_rejection_set_error: (skip)
+ */
+void
+mm_network_rejection_set_error (MMNetworkRejection *self,
+ MMNetworkError error)
+{
+ g_return_if_fail (MM_IS_NETWORK_REJECTION (self));
+
+ self->priv->error = error;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_get_access_technology:
+ * @self: a #MMNetworkRejection.
+ *
+ * Gets the available class reported with network reject.
+ *
+ * Returns: the available class.
+ *
+ * Since: 1.24
+ */
+MMModemAccessTechnology
+mm_network_rejection_get_access_technology (MMNetworkRejection *self)
+{
+ g_return_val_if_fail (MM_IS_NETWORK_REJECTION (self), 0);
+
+ return self->priv->access_technology;
+}
+
+/**
+ * mm_network_rejection_set_access_technology: (skip)
+ */
+void
+mm_network_rejection_set_access_technology (MMNetworkRejection *self,
+ MMModemAccessTechnology access_technology)
+{
+ g_return_if_fail (MM_IS_NETWORK_REJECTION (self));
+
+ self->priv->access_technology = access_technology;
+}
+
+/*****************************************************************************/
+
+
+/**
+ * mm_network_rejection_get_dictionary: (skip)
+ */
+GVariant *
+mm_network_rejection_get_dictionary (MMNetworkRejection *self)
+{
+ GVariantBuilder builder;
+
+ if (!self)
+ return NULL;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_ERROR,
+ g_variant_new_uint32 (self->priv->error));
+
+ if (self->priv->operator_id)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_OPERATOR_ID,
+ g_variant_new_string (self->priv->operator_id));
+
+ if (self->priv->operator_name)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_OPERATOR_NAME,
+ g_variant_new_string (self->priv->operator_name));
+
+ if (self->priv->access_technology)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_ACCESS_TECHNOLOGY,
+ g_variant_new_uint32 (self->priv->access_technology));
+
+ return g_variant_ref_sink (g_variant_builder_end (&builder));
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_new_from_dictionary: (skip)
+ */
+MMNetworkRejection *
+mm_network_rejection_new_from_dictionary (GVariant *dictionary,
+ GError **error)
+{
+ GVariantIter iter;
+ gchar *key;
+ GVariant *value;
+ MMNetworkRejection *self;
+
+ self = mm_network_rejection_new ();
+ if (!dictionary)
+ return self;
+
+ if (!g_variant_is_of_type (dictionary, G_VARIANT_TYPE ("a{sv}"))) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot create network rejection from dictionary: "
+ "invalid variant type received");
+ g_object_unref (self);
+ return NULL;
+ }
+
+ g_variant_iter_init (&iter, dictionary);
+ while (g_variant_iter_next (&iter, "{sv}", &key, &value)) {
+ if (g_str_equal (key, PROPERTY_ERROR)) {
+ mm_network_rejection_set_error (
+ self,
+ g_variant_get_uint32 (value));
+ } else if (g_str_equal (key, PROPERTY_OPERATOR_ID)) {
+ mm_network_rejection_set_operator_id (
+ self,
+ g_variant_get_string (value, NULL));
+ } else if (g_str_equal (key, PROPERTY_OPERATOR_NAME)) {
+ mm_network_rejection_set_operator_name (
+ self,
+ g_variant_get_string (value, NULL));
+ } else if (g_str_equal (key, PROPERTY_ACCESS_TECHNOLOGY)) {
+ mm_network_rejection_set_access_technology (
+ self,
+ g_variant_get_uint32 (value));
+ }
+
+ g_free (key);
+ g_variant_unref (value);
+ }
+
+ return self;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_network_rejection_new: (skip)
+ */
+MMNetworkRejection *
+mm_network_rejection_new (void)
+{
+ return (MM_NETWORK_REJECTION (
+ g_object_new (MM_TYPE_NETWORK_REJECTION, NULL)));
+}
+
+static void
+mm_network_rejection_init (MMNetworkRejection *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ MM_TYPE_NETWORK_REJECTION,
+ MMNetworkRejectionPrivate);
+}
+
+static void
+finalize (GObject *object)
+{
+ MMNetworkRejection *self = MM_NETWORK_REJECTION (object);
+
+ g_free (self->priv->operator_id);
+ g_free (self->priv->operator_name);
+
+ G_OBJECT_CLASS (mm_network_rejection_parent_class)->finalize (object);
+}
+
+static void
+mm_network_rejection_class_init (MMNetworkRejectionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMNetworkRejectionPrivate));
+
+ object_class->finalize = finalize;
+}
diff --git a/libmm-glib/mm-network-rejection.h b/libmm-glib/mm-network-rejection.h
new file mode 100644
index 00000000..2142454a
--- /dev/null
+++ b/libmm-glib/mm-network-rejection.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm-glib -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2024 Google, Inc.
+ */
+
+#ifndef MM_NETWORK_REJECTION_H
+#define MM_NETWORK_REJECTION_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_NETWORK_REJECTION (mm_network_rejection_get_type ())
+#define MM_NETWORK_REJECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_NETWORK_REJECTION, MMNetworkRejection))
+#define MM_NETWORK_REJECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_NETWORK_REJECTION, MMNetworkRejectionClass))
+#define MM_IS_NETWORK_REJECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_NETWORK_REJECTION))
+#define MM_IS_NETWORK_REJECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_NETWORK_REJECTION))
+#define MM_NETWORK_REJECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_NETWORK_REJECTION, MMNetworkRejectionClass))
+
+typedef struct _MMNetworkRejection MMNetworkRejection;
+typedef struct _MMNetworkRejectionClass MMNetworkRejectionClass;
+typedef struct _MMNetworkRejectionPrivate MMNetworkRejectionPrivate;
+
+/**
+ * MMNetworkRejection:
+ *
+ * The #MMNetworkRejection structure contains private data and should
+ * only be accessed using the provided API.
+ */
+struct _MMNetworkRejection {
+ /*< private >*/
+ GObject parent;
+ MMNetworkRejectionPrivate *priv;
+};
+
+struct _MMNetworkRejectionClass {
+ /*< private >*/
+ GObjectClass parent;
+};
+
+GType mm_network_rejection_get_type (void);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMNetworkRejection, g_object_unref)
+
+MMNetworkError mm_network_rejection_get_error (MMNetworkRejection *self);
+MMModemAccessTechnology mm_network_rejection_get_access_technology (MMNetworkRejection *self);
+const gchar *mm_network_rejection_get_operator_id (MMNetworkRejection *self);
+const gchar *mm_network_rejection_get_operator_name (MMNetworkRejection *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+MMNetworkRejection *mm_network_rejection_new (void);
+MMNetworkRejection *mm_network_rejection_new_from_dictionary (GVariant *dictionary,
+ GError **error);
+
+void mm_network_rejection_set_error (MMNetworkRejection *self,
+ MMNetworkError error);
+void mm_network_rejection_set_operator_id (MMNetworkRejection *self,
+ const gchar *operator_id);
+void mm_network_rejection_set_operator_name (MMNetworkRejection *self,
+ const gchar *operator_name);
+void mm_network_rejection_set_access_technology (MMNetworkRejection *self,
+ MMModemAccessTechnology access_technology);
+
+GVariant *mm_network_rejection_get_dictionary (MMNetworkRejection *self);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_NETWORK_REJECTION_H */
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 77599a8b..6560b475 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -2363,6 +2363,13 @@ update_registration_state (MMIfaceModem3gpp *self,
if (mm_modem_3gpp_registration_state_is_registered (new_state)) {
MMModemState modem_state;
+ /* When moving to registered state, clear network rejection */
+ mm_iface_modem_3gpp_update_network_rejection (self,
+ MM_NETWORK_ERROR_NONE,
+ NULL,
+ NULL,
+ MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
+
/* If already reloading registration info, skip it */
if (priv->reloading_registration_info)
return;
@@ -2597,6 +2604,57 @@ mm_iface_modem_3gpp_update_pco_list (MMIfaceModem3gpp *self,
/*****************************************************************************/
void
+mm_iface_modem_3gpp_update_network_rejection (MMIfaceModem3gpp *self,
+ MMNetworkError error,
+ const gchar *operator_id,
+ const gchar *operator_name,
+ MMModemAccessTechnology access_technology)
+{
+ MmGdbusModem3gpp *skeleton = NULL;
+ Private *priv;
+ g_autoptr(MMNetworkRejection) new_code = NULL;
+ g_autoptr(GVariant) dictionary = NULL;
+ g_autofree gchar *access_tech_str = NULL;
+ const gchar *nw_rejection_error = NULL;
+
+ priv = get_private (self);
+ if (!priv->iface_enabled)
+ return;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton,
+ NULL);
+ if (!skeleton)
+ return;
+
+ if (!error) {
+ mm_gdbus_modem3gpp_set_network_rejection (skeleton, NULL);
+ return;
+ }
+
+ access_tech_str = mm_modem_access_technology_build_string_from_mask (access_technology);
+ nw_rejection_error = mm_network_error_get_string (error);
+
+ mm_obj_warn (self, "Network rejection received: reason '%s' (%u), "
+ "operator id '%s', operator name '%s', access technology '%s'",
+ nw_rejection_error ? nw_rejection_error : "unknown", error,
+ operator_id ? operator_id : "none",
+ operator_name ? operator_name : "none",
+ access_tech_str);
+
+ new_code = mm_network_rejection_new ();
+ mm_network_rejection_set_error (new_code, error);
+ mm_network_rejection_set_operator_id (new_code, operator_id);
+ mm_network_rejection_set_operator_name (new_code, operator_name);
+ mm_network_rejection_set_access_technology (new_code, access_technology);
+
+ dictionary = mm_network_rejection_get_dictionary (new_code);
+ mm_gdbus_modem3gpp_set_network_rejection (skeleton, dictionary);
+}
+
+/*****************************************************************************/
+
+void
mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self,
MMBearerProperties *properties)
{
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index af726ef0..b0f74403 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -363,6 +363,12 @@ void mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self,
MMBearerProperties *properties);
void mm_iface_modem_3gpp_reload_initial_eps_bearer (MMIfaceModem3gpp *self);
+void mm_iface_modem_3gpp_update_network_rejection (MMIfaceModem3gpp *self,
+ MMNetworkError error,
+ const gchar *operator_code,
+ const gchar *operator_name,
+ MMModemAccessTechnology access_technology);
+
/* Run all registration checks */
void mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,