aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUjjwal Pande <ujjwalpande@google.com>2024-05-30 00:04:24 +0000
committerAleksander Morgado <aleksander@aleksander.es>2024-06-12 09:39:12 +0000
commit2904510e760fa1fdf491d1ef4574c29d05307b3b (patch)
tree999160f261639f947303ef96589e7d1a0bf497b0
parentdf8287bf6c2febd068d06f0f45194bc622118bd4 (diff)
api: new NetworkRejection property
When a modem is not able to register to the network, MBIM and QMI indications related to registration reports network rejection cause codes if request is rejected by the network. This information is currently logged in the ModemManager but not exposed outside of ModemManager. These are the changes to define interface to expose network reject cause codes over d-bus to the above layers which could be used by above layers to present this information in a user friendly way.
-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,