summaryrefslogtreecommitdiff
path: root/src/mm-modem-helpers-mbim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-modem-helpers-mbim.c')
-rw-r--r--src/mm-modem-helpers-mbim.c775
1 files changed, 689 insertions, 86 deletions
diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c
index 36d55023..c31310ae 100644
--- a/src/mm-modem-helpers-mbim.c
+++ b/src/mm-modem-helpers-mbim.c
@@ -10,14 +10,50 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ * Copyright (C) 2013-2021 Aleksander Morgado <aleksander@aleksander.es>
*/
#include "mm-modem-helpers-mbim.h"
#include "mm-modem-helpers.h"
#include "mm-enums-types.h"
#include "mm-errors-types.h"
-#include "mm-log.h"
+#include "mm-error-helpers.h"
+#include "mm-log-object.h"
+
+#include <string.h>
+
+/*****************************************************************************/
+
+MMModemCapability
+mm_modem_capability_from_mbim_device_caps (MbimCellularClass caps_cellular_class,
+ MbimDataClass caps_data_class,
+ const gchar *caps_custom_data_class)
+{
+ MMModemCapability mask = 0;
+
+ if (caps_cellular_class & MBIM_CELLULAR_CLASS_GSM)
+ mask |= MM_MODEM_CAPABILITY_GSM_UMTS;
+
+#if 0 /* Disable until we add MBIM CDMA support */
+ if (caps_cellular_class & MBIM_CELLULAR_CLASS_CDMA)
+ mask |= MM_MODEM_CAPABILITY_CDMA_EVDO;
+#endif
+
+ if (caps_data_class & MBIM_DATA_CLASS_LTE)
+ mask |= MM_MODEM_CAPABILITY_LTE;
+
+ /* e.g. Gosuncn GM800 reports MBIM custom data class "5G/TDS" */
+ if ((caps_data_class & MBIM_DATA_CLASS_CUSTOM) && caps_custom_data_class) {
+ if (strstr (caps_custom_data_class, "5G"))
+ mask |= MM_MODEM_CAPABILITY_5GNR;
+ }
+
+ /* Support for devices with Microsoft extensions */
+ if (caps_data_class & (MBIM_DATA_CLASS_5G_NSA | MBIM_DATA_CLASS_5G_SA))
+ mask |= MM_MODEM_CAPABILITY_5GNR;
+
+ return mask;
+}
/*****************************************************************************/
@@ -25,9 +61,6 @@ MMModemLock
mm_modem_lock_from_mbim_pin_type (MbimPinType pin_type)
{
switch (pin_type) {
- case MBIM_PIN_TYPE_UNKNOWN:
- case MBIM_PIN_TYPE_CUSTOM:
- break;
case MBIM_PIN_TYPE_PIN1:
return MM_MODEM_LOCK_SIM_PIN;
case MBIM_PIN_TYPE_PIN2:
@@ -60,6 +93,10 @@ mm_modem_lock_from_mbim_pin_type (MbimPinType pin_type)
return MM_MODEM_LOCK_PH_SP_PIN;
case MBIM_PIN_TYPE_CORPORATE_PUK:
return MM_MODEM_LOCK_PH_CORP_PUK;
+ case MBIM_PIN_TYPE_UNKNOWN:
+ case MBIM_PIN_TYPE_CUSTOM:
+ default:
+ break;
}
return MM_MODEM_LOCK_UNKNOWN;
@@ -90,6 +127,80 @@ mm_modem_3gpp_registration_state_from_mbim_register_state (MbimRegisterState sta
/*****************************************************************************/
+MMModemMode
+mm_modem_mode_from_mbim_data_class (MbimDataClass data_class)
+{
+ MMModemMode mask = MM_MODEM_MODE_NONE;
+
+ /* 3GPP... */
+ if (data_class & (MBIM_DATA_CLASS_GPRS |
+ MBIM_DATA_CLASS_EDGE))
+ mask |= MM_MODEM_MODE_2G;
+ if (data_class & (MBIM_DATA_CLASS_UMTS |
+ MBIM_DATA_CLASS_HSDPA |
+ MBIM_DATA_CLASS_HSUPA))
+ mask |= MM_MODEM_MODE_3G;
+ if (data_class & MBIM_DATA_CLASS_LTE)
+ mask |= MM_MODEM_MODE_4G;
+ if (data_class & (MBIM_DATA_CLASS_5G_NSA |
+ MBIM_DATA_CLASS_5G_SA))
+ mask |= MM_MODEM_MODE_5G;
+
+ /* 3GPP2... */
+ if (data_class & MBIM_DATA_CLASS_1XRTT)
+ mask |= MM_MODEM_MODE_2G;
+ if (data_class & (MBIM_DATA_CLASS_1XEVDO |
+ MBIM_DATA_CLASS_1XEVDO_REVA |
+ MBIM_DATA_CLASS_1XEVDV |
+ MBIM_DATA_CLASS_3XRTT |
+ MBIM_DATA_CLASS_1XEVDO_REVB))
+ mask |= MM_MODEM_MODE_3G;
+ if (data_class & MBIM_DATA_CLASS_UMB)
+ mask |= MM_MODEM_MODE_4G;
+
+ return mask;
+}
+
+MbimDataClass
+mm_mbim_data_class_from_modem_mode (MMModemMode modem_mode,
+ gboolean is_3gpp,
+ gboolean is_cdma)
+{
+ MbimDataClass mask = 0;
+
+ /* 3GPP... */
+ if (is_3gpp) {
+ if (modem_mode & MM_MODEM_MODE_2G)
+ mask |= (MBIM_DATA_CLASS_GPRS |
+ MBIM_DATA_CLASS_EDGE);
+ if (modem_mode & MM_MODEM_MODE_3G)
+ mask |= (MBIM_DATA_CLASS_UMTS |
+ MBIM_DATA_CLASS_HSDPA |
+ MBIM_DATA_CLASS_HSUPA);
+ if (modem_mode & MM_MODEM_MODE_4G)
+ mask |= MBIM_DATA_CLASS_LTE;
+ if (modem_mode & MM_MODEM_MODE_5G)
+ mask |= (MBIM_DATA_CLASS_5G_NSA |
+ MBIM_DATA_CLASS_5G_SA);
+ }
+
+ /* 3GPP2... */
+ if (is_cdma) {
+ if (modem_mode & MM_MODEM_MODE_2G)
+ mask |= MBIM_DATA_CLASS_1XRTT;
+ if (modem_mode & MM_MODEM_MODE_3G)
+ mask |= (MBIM_DATA_CLASS_1XEVDO |
+ MBIM_DATA_CLASS_1XEVDO_REVA |
+ MBIM_DATA_CLASS_1XEVDV |
+ MBIM_DATA_CLASS_3XRTT |
+ MBIM_DATA_CLASS_1XEVDO_REVB);
+ if (modem_mode & MM_MODEM_MODE_4G)
+ mask |= MBIM_DATA_CLASS_UMB;
+ }
+
+ return mask;
+}
+
MMModemAccessTechnology
mm_modem_access_technology_from_mbim_data_class (MbimDataClass data_class)
{
@@ -107,6 +218,11 @@ mm_modem_access_technology_from_mbim_data_class (MbimDataClass data_class)
mask |= MM_MODEM_ACCESS_TECHNOLOGY_HSUPA;
if (data_class & MBIM_DATA_CLASS_LTE)
mask |= MM_MODEM_ACCESS_TECHNOLOGY_LTE;
+ if (data_class & MBIM_DATA_CLASS_5G_NSA)
+ mask |= (MM_MODEM_ACCESS_TECHNOLOGY_LTE | MM_MODEM_ACCESS_TECHNOLOGY_5GNR);
+ if (data_class & MBIM_DATA_CLASS_5G_SA)
+ mask |= MM_MODEM_ACCESS_TECHNOLOGY_5GNR;
+
if (data_class & MBIM_DATA_CLASS_1XRTT)
mask |= MM_MODEM_ACCESS_TECHNOLOGY_1XRTT;
if (data_class & MBIM_DATA_CLASS_1XEVDO)
@@ -175,92 +291,380 @@ mm_3gpp_network_info_list_from_mbim_providers (const MbimProvider *const *provid
/*****************************************************************************/
+MbimPinType
+mbim_pin_type_from_mm_modem_3gpp_facility (MMModem3gppFacility facility)
+{
+ switch (facility) {
+ case MM_MODEM_3GPP_FACILITY_NET_PERS:
+ return MBIM_PIN_TYPE_NETWORK_PIN;
+ case MM_MODEM_3GPP_FACILITY_NET_SUB_PERS:
+ return MBIM_PIN_TYPE_NETWORK_SUBSET_PIN;
+ case MM_MODEM_3GPP_FACILITY_PROVIDER_PERS:
+ return MBIM_PIN_TYPE_SERVICE_PROVIDER_PIN;
+ case MM_MODEM_3GPP_FACILITY_CORP_PERS:
+ return MBIM_PIN_TYPE_CORPORATE_PIN;
+ case MM_MODEM_3GPP_FACILITY_SIM:
+ return MBIM_PIN_TYPE_PIN1;
+ case MM_MODEM_3GPP_FACILITY_FIXED_DIALING:
+ return MBIM_PIN_TYPE_PIN2;
+ case MM_MODEM_3GPP_FACILITY_PH_SIM:
+ return MBIM_PIN_TYPE_DEVICE_SIM_PIN;
+ case MM_MODEM_3GPP_FACILITY_PH_FSIM:
+ return MBIM_PIN_TYPE_DEVICE_FIRST_SIM_PIN;
+ case MM_MODEM_3GPP_FACILITY_NONE:
+ default:
+ return MBIM_PIN_TYPE_UNKNOWN;
+ }
+}
+
+/*****************************************************************************/
+
+static const MMMobileEquipmentError mbim_nw_errors[] = {
+ [MBIM_NW_ERROR_IMSI_UNKNOWN_IN_HLR] = MM_MOBILE_EQUIPMENT_ERROR_IMSI_UNKNOWN_IN_HSS,
+ [MBIM_NW_ERROR_ILLEGAL_MS] = MM_MOBILE_EQUIPMENT_ERROR_ILLEGAL_UE,
+ [MBIM_NW_ERROR_IMSI_UNKNOWN_IN_VLR] = MM_MOBILE_EQUIPMENT_ERROR_IMSI_UNKNOWN_IN_VLR,
+ [MBIM_NW_ERROR_ILLEGAL_ME] = MM_MOBILE_EQUIPMENT_ERROR_ILLEGAL_ME,
+ [MBIM_NW_ERROR_GPRS_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_PS_SERVICES_NOT_ALLOWED,
+ [MBIM_NW_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_PS_AND_NON_PS_SERVICES_NOT_ALLOWED,
+ [MBIM_NW_ERROR_PLMN_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_PLMN_NOT_ALLOWED,
+ [MBIM_NW_ERROR_LOCATION_AREA_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_AREA_NOT_ALLOWED,
+ [MBIM_NW_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA] = MM_MOBILE_EQUIPMENT_ERROR_ROAMING_NOT_ALLOWED_IN_AREA,
+ [MBIM_NW_ERROR_GPRS_NOT_ALLOWED_IN_PLMN] = MM_MOBILE_EQUIPMENT_ERROR_PS_SERVICES_NOT_ALLOWED_IN_PLMN,
+ [MBIM_NW_ERROR_NO_CELLS_IN_LOCATION_AREA] = MM_MOBILE_EQUIPMENT_ERROR_NO_CELLS_IN_AREA,
+ [MBIM_NW_ERROR_NETWORK_FAILURE] = MM_MOBILE_EQUIPMENT_ERROR_NETWORK_FAILURE_ATTACH,
+ [MBIM_NW_ERROR_CONGESTION] = MM_MOBILE_EQUIPMENT_ERROR_CONGESTION,
+ [MBIM_NW_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE] = MM_MOBILE_EQUIPMENT_ERROR_USER_AUTHENTICATION_FAILED,
+ [MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_CSG] = MM_MOBILE_EQUIPMENT_ERROR_NOT_AUTHORIZED_FOR_CSG,
+ [MBIM_NW_ERROR_INSUFFICIENT_RESOURCES] = MM_MOBILE_EQUIPMENT_ERROR_INSUFFICIENT_RESOURCES,
+ [MBIM_NW_ERROR_MISSING_OR_UNKNOWN_APN] = MM_MOBILE_EQUIPMENT_ERROR_MISSING_OR_UNKNOWN_APN,
+ [MBIM_NW_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE] = MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN_PDP_ADDRESS_OR_TYPE,
+ [MBIM_NW_ERROR_USER_AUTHENTICATION_FAILED] = MM_MOBILE_EQUIPMENT_ERROR_USER_AUTHENTICATION_FAILED,
+ [MBIM_NW_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW] = MM_MOBILE_EQUIPMENT_ERROR_ACTIVATION_REJECTED_BY_GGSN_OR_GW,
+ [MBIM_NW_ERROR_ACTIVATION_REJECTED_UNSPECIFIED] = MM_MOBILE_EQUIPMENT_ERROR_ACTIVATION_REJECTED_UNSPECIFIED,
+ [MBIM_NW_ERROR_SERVICE_OPTION_NOT_SUPPORTED] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_NOT_SUPPORTED,
+ [MBIM_NW_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_NOT_SUBSCRIBED,
+ [MBIM_NW_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER] = MM_MOBILE_EQUIPMENT_ERROR_SERVICE_OPTION_OUT_OF_ORDER,
+ [MBIM_NW_ERROR_MAXIMUM_NUMBER_OF_PDP_CONTEXTS_REACHED] = MM_MOBILE_EQUIPMENT_ERROR_MAXIMUM_NUMBER_OF_BEARERS_REACHED,
+ [MBIM_NW_ERROR_REQUESTED_APN_NOT_SUPPORTED_IN_CURRENT_RAT_AND_PLMN] = MM_MOBILE_EQUIPMENT_ERROR_REQUESTED_APN_NOT_SUPPORTED,
+ [MBIM_NW_ERROR_SEMANTICALLY_INCORRECT_MESSAGE] = MM_MOBILE_EQUIPMENT_ERROR_SEMANTICALLY_INCORRECT_MESSAGE,
+ [MBIM_NW_ERROR_PROTOCOL_ERROR_UNSPECIFIED] = MM_MOBILE_EQUIPMENT_ERROR_UNSPECIFIED_PROTOCOL_ERROR,
+ [MBIM_NW_ERROR_IMEI_NOT_ACCEPTED] = MM_MOBILE_EQUIPMENT_ERROR_IMEI_NOT_ACCEPTED,
+ [MBIM_NW_ERROR_MS_IDENTITY_NOT_DERIVED_BY_NETWORK] = MM_MOBILE_EQUIPMENT_ERROR_UE_IDENTITY_NOT_DERIVED_FROM_NETWORK,
+ [MBIM_NW_ERROR_IMPLICITLY_DETACHED] = MM_MOBILE_EQUIPMENT_ERROR_IMPLICITLY_DETACHED,
+ [MBIM_NW_ERROR_MSC_TEMPORARILY_NOT_REACHABLE] = MM_MOBILE_EQUIPMENT_ERROR_MSC_TEMPORARILY_NOT_REACHABLE,
+ [MBIM_NW_ERROR_NO_PDP_CONTEXT_ACTIVATED] = MM_MOBILE_EQUIPMENT_ERROR_NO_BEARER_ACTIVATED,
+ [MBIM_NW_ERROR_PDP_TYPE_IPV4_ONLY_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_IPV4_ONLY_ALLOWED,
+ [MBIM_NW_ERROR_PDP_TYPE_IPV6_ONLY_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_IPV6_ONLY_ALLOWED,
+ [MBIM_NW_ERROR_INVALID_MANDATORY_INFORMATION] = MM_MOBILE_EQUIPMENT_ERROR_INVALID_MANDATORY_INFORMATION,
+ [MBIM_NW_ERROR_MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_TYPE_NOT_IMPLEMENTED,
+ [MBIM_NW_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE,
+ [MBIM_NW_ERROR_INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED] = MM_MOBILE_EQUIPMENT_ERROR_IE_NOT_IMPLEMENTED,
+ [MBIM_NW_ERROR_CONDITIONAL_IE_ERROR] = MM_MOBILE_EQUIPMENT_ERROR_CONDITIONAL_IE_ERROR,
+ [MBIM_NW_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE] = MM_MOBILE_EQUIPMENT_ERROR_MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE,
+ [MBIM_NW_ERROR_APN_RESTRICTION_VALUE_INCOMPATIBLE_WITH_ACTIVE_PDP_CONTEXT] = MM_MOBILE_EQUIPMENT_ERROR_APN_RESTRICTION_INCOMPATIBLE,
+ [MBIM_NW_ERROR_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED] = MM_MOBILE_EQUIPMENT_ERROR_MULTIPLE_ACCESS_TO_PDN_CONNECTION_NOT_ALLOWED,
+ [MBIM_NW_ERROR_NONE] = MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN,
+ /* known unmapped errors */
+ /* MBIM_NW_ERROR_MAC_FAILURE */
+ /* MBIM_NW_ERROR_SYNCH_FAILURE */
+};
+
GError *
-mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error)
+mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error,
+ gpointer log_object)
{
- switch (nw_error) {
- case MBIM_NW_ERROR_IMSI_UNKNOWN_IN_HLR:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_IMSI_UNKNOWN_IN_HLR,
- "IMSI unknown in HLR");
- case MBIM_NW_ERROR_ILLEGAL_MS:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_MS,
- "Illegal MS");
- case MBIM_NW_ERROR_IMSI_UNKNOWN_IN_VLR:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_IMSI_UNKNOWN_IN_VLR,
- "IMSI unknown in VLR");
- case MBIM_NW_ERROR_ILLEGAL_ME:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_ME,
- "Illegal ME");
- case MBIM_NW_ERROR_GPRS_NOT_ALLOWED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED,
- "GPRS not allowed");
- case MBIM_NW_ERROR_GPRS_AND_NON_GPRS_NOT_ALLOWED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED,
- "GPRS and non-GPRS not allowed");
- case MBIM_NW_ERROR_PLMN_NOT_ALLOWED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_PLMN_NOT_ALLOWED,
- "PLMN not allowed");
- case MBIM_NW_ERROR_LOCATION_AREA_NOT_ALLOWED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_LOCATION_NOT_ALLOWED,
- "Location area not allowed");
- case MBIM_NW_ERROR_ROAMING_NOT_ALLOWED_IN_LOCATION_AREA:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_ROAMING_NOT_ALLOWED,
- "Roaming not allowed in location area");
- case MBIM_NW_ERROR_GPRS_NOT_ALLOWED_IN_PLMN:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED,
- "GPRS not allowed in PLMN");
- case MBIM_NW_ERROR_NO_CELLS_IN_LOCATION_AREA:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_NO_CELLS_IN_LOCATION_AREA,
- "No cells in location area");
- case MBIM_NW_ERROR_NETWORK_FAILURE:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_NETWORK_FAILURE,
- "Network failure");
- case MBIM_NW_ERROR_CONGESTION:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_CONGESTION,
- "Congestion");
- case MBIM_NW_ERROR_GSM_AUTHENTICATION_UNACCEPTABLE:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_USER_AUTHENTICATION_FAILED,
- "GSM authentication unacceptable");
- case MBIM_NW_ERROR_NOT_AUTHORIZED_FOR_CSG:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_USER_AUTHENTICATION_FAILED,
- "Not authorized for this CSG");
- case MBIM_NW_ERROR_MISSING_OR_UNKNOWN_APN:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_MISSING_OR_UNKNOWN_APN,
- "Missing or unknown APN");
- case MBIM_NW_ERROR_SERVICE_OPTION_NOT_SUPPORTED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUPPORTED,
- "Service option not supported");
- case MBIM_NW_ERROR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUBSCRIBED,
- "Requested service option not subscribed");
- case MBIM_NW_ERROR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER:
+ MMMobileEquipmentError error_code;
+ const gchar *msg;
+
+ /* convert to mobile equipment error */
+ error_code = mbim_nw_errors[nw_error];
+ if (error_code)
+ return mm_mobile_equipment_error_for_code (error_code, log_object);
+
+ /* provide a nicer error message on unmapped errors */
+ msg = mbim_nw_error_get_string (nw_error);
+ if (msg)
return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_OUT_OF_ORDER,
- "Service option temporarily out of order");
+ MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN,
+ "Unsupported error (%u): %s",
+ nw_error, msg);
+
+ /* fallback */
+ return g_error_new_literal (MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN,
+ "Unknown error");
+}
+
+/*****************************************************************************/
+
+MMBearerAllowedAuth
+mm_bearer_allowed_auth_from_mbim_auth_protocol (MbimAuthProtocol auth_protocol)
+{
+ switch (auth_protocol) {
+ case MBIM_AUTH_PROTOCOL_NONE:
+ return MM_BEARER_ALLOWED_AUTH_NONE;
+ case MBIM_AUTH_PROTOCOL_PAP:
+ return MM_BEARER_ALLOWED_AUTH_PAP;
+ case MBIM_AUTH_PROTOCOL_CHAP:
+ return MM_BEARER_ALLOWED_AUTH_CHAP;
+ case MBIM_AUTH_PROTOCOL_MSCHAPV2:
+ return MM_BEARER_ALLOWED_AUTH_MSCHAPV2;
default:
- return g_error_new (MM_MOBILE_EQUIPMENT_ERROR,
- MM_MOBILE_EQUIPMENT_ERROR_GPRS_UNKNOWN,
- "Unknown error (%u)",
- nw_error);
+ return MM_BEARER_ALLOWED_AUTH_UNKNOWN;
+ }
+}
+
+MbimAuthProtocol
+mm_bearer_allowed_auth_to_mbim_auth_protocol (MMBearerAllowedAuth bearer_auth,
+ gpointer log_object,
+ GError **error)
+{
+ gchar *str;
+
+ /* NOTE: the input is a BITMASK, so we try to find a "best match" */
+
+ if (bearer_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN) {
+ mm_obj_dbg (log_object, "using default (CHAP) authentication method");
+ return MBIM_AUTH_PROTOCOL_CHAP;
+ }
+ if (bearer_auth & MM_BEARER_ALLOWED_AUTH_CHAP)
+ return MBIM_AUTH_PROTOCOL_CHAP;
+ if (bearer_auth & MM_BEARER_ALLOWED_AUTH_PAP)
+ return MBIM_AUTH_PROTOCOL_PAP;
+ if (bearer_auth & MM_BEARER_ALLOWED_AUTH_MSCHAPV2)
+ return MBIM_AUTH_PROTOCOL_MSCHAPV2;
+ if (bearer_auth & MM_BEARER_ALLOWED_AUTH_NONE)
+ return MBIM_AUTH_PROTOCOL_NONE;
+
+ str = mm_bearer_allowed_auth_build_string_from_mask (bearer_auth);
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Unsupported authentication methods (%s)",
+ str);
+ g_free (str);
+ return MBIM_AUTH_PROTOCOL_NONE;
+}
+
+/*****************************************************************************/
+
+MMBearerApnType
+mm_bearer_apn_type_from_mbim_context_type (MbimContextType context_type)
+{
+ switch (context_type) {
+ case MBIM_CONTEXT_TYPE_INTERNET:
+ return MM_BEARER_APN_TYPE_DEFAULT;
+ case MBIM_CONTEXT_TYPE_VPN:
+ return MM_BEARER_APN_TYPE_PRIVATE;
+ case MBIM_CONTEXT_TYPE_VOICE:
+ return MM_BEARER_APN_TYPE_VOICE;
+ case MBIM_CONTEXT_TYPE_VIDEO_SHARE:
+ return MM_BEARER_APN_TYPE_VIDEO_SHARE;
+ case MBIM_CONTEXT_TYPE_PURCHASE:
+ return MM_BEARER_APN_TYPE_PURCHASE;
+ case MBIM_CONTEXT_TYPE_IMS:
+ return MM_BEARER_APN_TYPE_IMS;
+ case MBIM_CONTEXT_TYPE_MMS:
+ return MM_BEARER_APN_TYPE_MMS;
+ case MBIM_CONTEXT_TYPE_LOCAL:
+ return MM_BEARER_APN_TYPE_LOCAL;
+ case MBIM_CONTEXT_TYPE_ADMIN:
+ return MM_BEARER_APN_TYPE_MANAGEMENT;
+ case MBIM_CONTEXT_TYPE_APP:
+ return MM_BEARER_APN_TYPE_APP;
+ case MBIM_CONTEXT_TYPE_XCAP:
+ return MM_BEARER_APN_TYPE_XCAP;
+ case MBIM_CONTEXT_TYPE_TETHERING:
+ return MM_BEARER_APN_TYPE_TETHERING;
+ case MBIM_CONTEXT_TYPE_EMERGENCY_CALLING:
+ return MM_BEARER_APN_TYPE_EMERGENCY;
+ /* some types unused right now */
+ case MBIM_CONTEXT_TYPE_INVALID:
+ case MBIM_CONTEXT_TYPE_NONE:
+ default:
+ return MM_BEARER_APN_TYPE_NONE;
+ }
+}
+
+MbimContextType
+mm_bearer_apn_type_to_mbim_context_type (MMBearerApnType apn_type,
+ gpointer log_object,
+ GError **error)
+{
+ g_autofree gchar *str = NULL;
+
+ /* NOTE: the input is a BITMASK, so we try to find a "best match" */
+
+ if (apn_type == MM_BEARER_APN_TYPE_NONE) {
+ mm_obj_dbg (log_object, "using default (internet) APN type");
+ return MBIM_CONTEXT_TYPE_INTERNET;
+ }
+
+ if (apn_type & MM_BEARER_APN_TYPE_DEFAULT)
+ return MBIM_CONTEXT_TYPE_INTERNET;
+ if (apn_type & MM_BEARER_APN_TYPE_IMS)
+ return MBIM_CONTEXT_TYPE_IMS;
+ if (apn_type & MM_BEARER_APN_TYPE_MMS)
+ return MBIM_CONTEXT_TYPE_MMS;
+ if (apn_type &MM_BEARER_APN_TYPE_MANAGEMENT)
+ return MBIM_CONTEXT_TYPE_ADMIN;
+ if (apn_type & MM_BEARER_APN_TYPE_VOICE)
+ return MBIM_CONTEXT_TYPE_VOICE;
+ if (apn_type & MM_BEARER_APN_TYPE_PRIVATE)
+ return MBIM_CONTEXT_TYPE_VPN;
+ if (apn_type & MM_BEARER_APN_TYPE_PURCHASE)
+ return MBIM_CONTEXT_TYPE_PURCHASE;
+ if (apn_type & MM_BEARER_APN_TYPE_VIDEO_SHARE)
+ return MBIM_CONTEXT_TYPE_VIDEO_SHARE;
+ if (apn_type & MM_BEARER_APN_TYPE_LOCAL)
+ return MBIM_CONTEXT_TYPE_LOCAL;
+ if (apn_type & MM_BEARER_APN_TYPE_APP)
+ return MBIM_CONTEXT_TYPE_APP;
+ if (apn_type & MM_BEARER_APN_TYPE_XCAP)
+ return MBIM_CONTEXT_TYPE_XCAP;
+ if (apn_type & MM_BEARER_APN_TYPE_TETHERING)
+ return MBIM_CONTEXT_TYPE_TETHERING;
+
+ str = mm_bearer_apn_type_build_string_from_mask (apn_type);
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Unsupported APN types (%s)",
+ str);
+ return MBIM_CONTEXT_TYPE_NONE;
+}
+
+/*****************************************************************************/
+
+MMBearerIpFamily
+mm_bearer_ip_family_from_mbim_context_ip_type (MbimContextIpType ip_type)
+{
+ switch (ip_type) {
+ case MBIM_CONTEXT_IP_TYPE_IPV4:
+ return MM_BEARER_IP_FAMILY_IPV4;
+ case MBIM_CONTEXT_IP_TYPE_IPV6:
+ return MM_BEARER_IP_FAMILY_IPV6;
+ case MBIM_CONTEXT_IP_TYPE_IPV4V6:
+ return MM_BEARER_IP_FAMILY_IPV4V6;
+ case MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6:
+ return MM_BEARER_IP_FAMILY_IPV4 | MM_BEARER_IP_FAMILY_IPV6;
+ case MBIM_CONTEXT_IP_TYPE_DEFAULT:
+ default:
+ return MM_BEARER_IP_FAMILY_NONE;
+ }
+}
+
+MbimContextIpType
+mm_bearer_ip_family_to_mbim_context_ip_type (MMBearerIpFamily ip_family,
+ GError **error)
+{
+ gchar *str;
+
+ /* NOTE: the input is a BITMASK, so we try to find a "best match" */
+
+ switch ((guint)ip_family) {
+ case MM_BEARER_IP_FAMILY_IPV4:
+ return MBIM_CONTEXT_IP_TYPE_IPV4;
+ case MM_BEARER_IP_FAMILY_IPV6:
+ return MBIM_CONTEXT_IP_TYPE_IPV6;
+ case MM_BEARER_IP_FAMILY_IPV4V6:
+ return MBIM_CONTEXT_IP_TYPE_IPV4V6;
+ case (MM_BEARER_IP_FAMILY_IPV4 | MM_BEARER_IP_FAMILY_IPV6):
+ return MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6;
+ case MM_BEARER_IP_FAMILY_NONE:
+ case MM_BEARER_IP_FAMILY_ANY:
+ /* A valid default IP family should have been specified */
+ g_assert_not_reached ();
+ default:
+ break;
+ }
+
+ str = mm_bearer_ip_family_build_string_from_mask (ip_family);
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Unsupported IP type configuration: '%s'",
+ str);
+ g_free (str);
+ return MBIM_CONTEXT_IP_TYPE_DEFAULT;
+}
+
+/*****************************************************************************/
+
+/* index in the array is the code point (8 possible values), and the actual
+ * value is the lower limit of the error rate range. */
+static const gdouble bit_error_rate_ranges[] = { 0.00, 0.20, 0.40, 0.80, 1.60, 3.20, 6.40, 12.80 };
+static const gdouble frame_error_rate_ranges[] = { 0.00, 0.01, 0.10, 0.50, 1.00, 2.00, 4.00, 8.00 };
+
+gboolean
+mm_signal_error_rate_percentage_from_coded_value (guint coded_value,
+ gdouble *out_percentage,
+ gboolean is_gsm,
+ GError **error)
+{
+ if ((is_gsm && (coded_value >= G_N_ELEMENTS (bit_error_rate_ranges))) ||
+ (!is_gsm && (coded_value >= G_N_ELEMENTS (frame_error_rate_ranges)))) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "error rate coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_percentage = (is_gsm ? bit_error_rate_ranges[coded_value] : frame_error_rate_ranges[coded_value]);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_rssi_from_coded_value (guint coded_value,
+ gdouble *out_rssi,
+ GError **error)
+{
+ /* expected values between 0 and 31 */
+ if (coded_value > 31) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "rssi coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_rssi = (gdouble)coded_value - 113;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_rsrp_from_coded_value (guint coded_value,
+ gdouble *out_rsrp,
+ GError **error)
+{
+ /* expected values between 0 and 126 */
+ if (coded_value > 126) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "rsrp coded value out of range: %u", coded_value);
+ return FALSE;
+ }
+
+ *out_rsrp = (gdouble)coded_value - 156;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_signal_snr_from_coded_value (guint coded_value,
+ gdouble *out_snr,
+ GError **error)
+{
+ /* expected values between 0 and 126 */
+ if (coded_value > 127) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "snr coded value out of range: %u", coded_value);
+ return FALSE;
}
+
+ *out_snr = ((gdouble)coded_value)/2 - 23;
+ return TRUE;
}
/*****************************************************************************/
@@ -277,7 +681,206 @@ mm_sms_state_from_mbim_message_status (MbimSmsStatus status)
return MM_SMS_STATE_STORED;
case MBIM_SMS_STATUS_SENT:
return MM_SMS_STATE_SENT;
+ default:
+ break;
}
return MM_SMS_STATE_UNKNOWN;
}
+
+/*****************************************************************************/
+
+guint
+mm_signal_quality_from_mbim_signal_state (guint rssi,
+ MbimRsrpSnrInfoArray *rsrp_snr,
+ guint32 rsrp_snr_count,
+ gpointer log_object)
+{
+ guint quality;
+
+ /* When MBIMEx is enabled we may get RSSI unset, but per access technology
+ * RSRP available. When more than one access technology in use (e.g. 4G+5G in
+ * 5G NSA), take the highest RSRP value reported. */
+ if (rssi == 99 && rsrp_snr && rsrp_snr_count) {
+ guint i;
+ gint max_rsrp = G_MININT;
+
+ for (i = 0; i < rsrp_snr_count; i++) {
+ MbimRsrpSnrInfo *info;
+
+ info = rsrp_snr[i];
+ /* scale the value to dBm */
+ if (info->rsrp < 127) {
+ gint rsrp;
+
+ rsrp = -157 + info->rsrp;
+ if (rsrp > max_rsrp)
+ max_rsrp = rsrp;
+ }
+ }
+ quality = MM_RSRP_TO_QUALITY (max_rsrp);
+ mm_obj_dbg (log_object, "signal state update: %ddBm --> %u%%", max_rsrp, quality);
+ } else {
+ /* Normalize the quality. 99 means unknown, we default it to 0 */
+ quality = MM_CLAMP_HIGH (rssi == 99 ? 0 : rssi, 31) * 100 / 31;
+ mm_obj_dbg (log_object, "signal state update: %u --> %u%%", rssi, quality);
+ }
+
+ return quality;
+}
+
+static MMSignal **
+select_mbim_signal_with_data_class (MbimDataClass data_class,
+ MMSignal **cdma,
+ MMSignal **evdo,
+ MMSignal **gsm,
+ MMSignal **umts,
+ MMSignal **lte,
+ MMSignal **nr5g)
+{
+ switch (data_class) {
+ case MBIM_DATA_CLASS_5G_NSA:
+ case MBIM_DATA_CLASS_5G_SA:
+ return nr5g;
+ case MBIM_DATA_CLASS_LTE:
+ return lte;
+ case MBIM_DATA_CLASS_UMTS:
+ case MBIM_DATA_CLASS_HSDPA:
+ case MBIM_DATA_CLASS_HSUPA:
+ return umts;
+ case MBIM_DATA_CLASS_GPRS:
+ case MBIM_DATA_CLASS_EDGE:
+ return gsm;
+ case MBIM_DATA_CLASS_1XEVDO:
+ case MBIM_DATA_CLASS_1XEVDO_REVA:
+ case MBIM_DATA_CLASS_1XEVDV:
+ case MBIM_DATA_CLASS_3XRTT:
+ case MBIM_DATA_CLASS_1XEVDO_REVB:
+ return evdo;
+ case MBIM_DATA_CLASS_1XRTT:
+ return cdma;
+ case MBIM_DATA_CLASS_UMB:
+ case MBIM_DATA_CLASS_CUSTOM:
+ default:
+ return NULL;
+ }
+}
+
+gboolean
+mm_signal_from_mbim_signal_state (MbimDataClass data_class,
+ guint coded_rssi,
+ guint coded_error_rate,
+ MbimRsrpSnrInfoArray *rsrp_snr,
+ guint32 rsrp_snr_count,
+ gpointer log_object,
+ MMSignal **out_cdma,
+ MMSignal **out_evdo,
+ MMSignal **out_gsm,
+ MMSignal **out_umts,
+ MMSignal **out_lte,
+ MMSignal **out_nr5g)
+{
+ MMSignal **tmp;
+ MMSignal **last_updated = NULL;
+ guint n_out_updated = 0;
+
+ *out_cdma = NULL;
+ *out_evdo = NULL;
+ *out_gsm = NULL;
+ *out_umts = NULL;
+ *out_lte = NULL;
+ *out_nr5g = NULL;
+
+ /* When MBIMEx v2.0 is available, we get LTE+5GNR information reported
+ * in the RSRP/SNR list of items. */
+ if (rsrp_snr && rsrp_snr_count) {
+ guint i;
+
+ for (i = 0; i < rsrp_snr_count; i++) {
+ MbimRsrpSnrInfo *info;
+
+ info = rsrp_snr[i];
+
+ tmp = select_mbim_signal_with_data_class (info->system_type,
+ out_cdma, out_evdo,
+ out_gsm, out_umts, out_lte, out_nr5g);
+ if (!tmp || ((info->rsrp == 0xFFFFFFFF) && (info->snr == 0xFFFFFFFF)))
+ continue;
+
+ last_updated = tmp;
+ n_out_updated++;
+
+ *tmp = mm_signal_new ();
+
+ mm_signal_set_rsrp (*tmp, MM_SIGNAL_UNKNOWN);
+ if (info->rsrp != 0xFFFFFFFF) {
+ g_autoptr(GError) error = NULL;
+ gdouble rsrp;
+
+ if (!mm_signal_rsrp_from_coded_value (info->rsrp, &rsrp, &error))
+ mm_obj_dbg (log_object, "couldn't convert RSRP coded value '%u': %s", info->rsrp, error->message);
+ else
+ mm_signal_set_rsrp (*tmp, rsrp);
+ }
+
+ mm_signal_set_snr (*tmp, MM_SIGNAL_UNKNOWN);
+ if (info->snr != 0xFFFFFFFF) {
+ g_autoptr(GError) error = NULL;
+ gdouble snr;
+
+ if (!mm_signal_snr_from_coded_value (info->snr, &snr, &error))
+ mm_obj_dbg (log_object, "couldn't convert SNR coded value '%u': %s", info->snr, error->message);
+ else
+ mm_signal_set_snr (*tmp, snr);
+ }
+ }
+ }
+
+ /* The MBIM v1.0 details (RSSI, error rate) will only be set if
+ * the target access technology is known without any doubt.
+ * E.g. if we are in 5GNSA (4G+5G), we will only set the fields
+ * if one of them has valid values. If both have valid values,
+ * we'll skip updating RSSI and error rate, as we wouldn't know
+ * to which of them applies. */
+ if (n_out_updated > 1)
+ return TRUE;
+
+ if (n_out_updated == 0) {
+ tmp = select_mbim_signal_with_data_class (data_class,
+ out_cdma, out_evdo,
+ out_gsm, out_umts, out_lte, out_nr5g);
+ if (!tmp)
+ return FALSE;
+ *tmp = mm_signal_new ();
+ } else {
+ tmp = last_updated;
+ g_assert (tmp && *tmp);
+ }
+
+ mm_signal_set_error_rate (*tmp, MM_SIGNAL_UNKNOWN);
+ if (coded_error_rate != 99) {
+ g_autoptr(GError) error = NULL;
+ gdouble error_rate;
+
+ if (!mm_signal_error_rate_percentage_from_coded_value (coded_error_rate,
+ &error_rate,
+ data_class == (MBIM_DATA_CLASS_GPRS | MBIM_DATA_CLASS_EDGE),
+ &error))
+ mm_obj_dbg (log_object, "couldn't convert error rate coded value '%u': %s", coded_error_rate, error->message);
+ else
+ mm_signal_set_error_rate (*tmp, error_rate);
+ }
+
+ mm_signal_set_rssi (*tmp, MM_SIGNAL_UNKNOWN);
+ if (coded_rssi != 99) {
+ g_autoptr(GError) error = NULL;
+ gdouble rssi;
+
+ if (!mm_signal_rssi_from_coded_value (coded_rssi, &rssi, &error))
+ mm_obj_dbg (log_object, "couldn't convert RSSI coded value '%u': %s", coded_rssi, error->message);
+ else
+ mm_signal_set_rssi (*tmp, rssi);
+ }
+
+ return TRUE;
+}