aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem-mbim.c87
-rw-r--r--src/mm-modem-helpers-mbim.c85
-rw-r--r--src/mm-modem-helpers-mbim.h17
3 files changed, 144 insertions, 45 deletions
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 7185a059..4f49a53e 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -130,7 +130,7 @@ struct _MMBroadbandModemMbimPrivate {
/* Queried and cached capabilities */
MbimCellularClass caps_cellular_class;
MbimDataClass caps_data_class;
- gchar *caps_custom_data_class;
+ MbimDataClass caps_custom_data_class;
MbimSmsCaps caps_sms;
guint caps_max_sessions;
gchar *caps_device_id;
@@ -518,6 +518,8 @@ device_caps_query_ready (MbimDevice *device,
MMBroadbandModemMbim *self;
GError *error = NULL;
LoadCurrentCapabilitiesContext *ctx;
+ MbimDataClass caps_data_class = MBIM_DATA_CLASS_NONE;
+ g_autofree gchar *caps_custom_data_class_str;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
@@ -550,7 +552,7 @@ device_caps_query_ready (MbimDevice *device,
NULL, /* lte_band_class_array */
NULL, /* nr_band_class_array_size */
NULL, /* nr_band_class_array */
- &self->priv->caps_custom_data_class,
+ &caps_custom_data_class_str,
&self->priv->caps_device_id,
&self->priv->caps_firmware_info,
&self->priv->caps_hardware_info,
@@ -560,7 +562,7 @@ device_caps_query_ready (MbimDevice *device,
return;
}
/* Translate data class v3 to standard data class to simplify further usage of the field */
- self->priv->caps_data_class = mm_mbim_data_class_from_mbim_data_class_v3_and_subclass (data_class_v3, data_subclass);
+ caps_data_class = mm_mbim_data_class_from_mbim_data_class_v3_and_subclass (data_class_v3, data_subclass);
} else if (mbim_device_check_ms_mbimex_version (device, 2, 0)) {
if (!mbim_message_ms_basic_connect_extensions_device_caps_response_parse (
response,
@@ -568,11 +570,11 @@ device_caps_query_ready (MbimDevice *device,
&self->priv->caps_cellular_class,
NULL, /* voice_class */
NULL, /* sim_class */
- &self->priv->caps_data_class,
+ &caps_data_class,
&self->priv->caps_sms,
NULL, /* ctrl_caps */
&self->priv->caps_max_sessions,
- &self->priv->caps_custom_data_class,
+ &caps_custom_data_class_str,
&self->priv->caps_device_id,
&self->priv->caps_firmware_info,
&self->priv->caps_hardware_info,
@@ -589,11 +591,11 @@ device_caps_query_ready (MbimDevice *device,
&self->priv->caps_cellular_class,
NULL, /* voice_class */
NULL, /* sim_class */
- &self->priv->caps_data_class,
+ &caps_data_class,
&self->priv->caps_sms,
NULL, /* ctrl_caps */
&self->priv->caps_max_sessions,
- &self->priv->caps_custom_data_class,
+ &caps_custom_data_class_str,
&self->priv->caps_device_id,
&self->priv->caps_firmware_info,
&self->priv->caps_hardware_info,
@@ -604,9 +606,14 @@ device_caps_query_ready (MbimDevice *device,
}
}
+ /* Normalize data class capabilities to include any custom data class */
+ self->priv->caps_custom_data_class = mm_mbim_data_class_from_custom_caps (caps_data_class,
+ caps_custom_data_class_str);
+ self->priv->caps_data_class = mm_modem_mbim_normalize_data_class_mask (caps_data_class,
+ self->priv->caps_custom_data_class);
+
ctx->current_mbim = mm_modem_capability_from_mbim_device_caps (self->priv->caps_cellular_class,
- self->priv->caps_data_class,
- self->priv->caps_custom_data_class);
+ self->priv->caps_data_class);
complete_current_capabilities (task);
}
@@ -708,8 +715,7 @@ load_supported_capabilities_mbim (GTask *task)
/* Current capabilities should have been cached already, just assume them */
current = mm_modem_capability_from_mbim_device_caps (self->priv->caps_cellular_class,
- self->priv->caps_data_class,
- self->priv->caps_custom_data_class);
+ self->priv->caps_data_class);
if (current != 0) {
supported = g_array_sized_new (FALSE, FALSE, sizeof (MMModemCapability), 1);
g_array_append_val (supported, current);
@@ -1067,7 +1073,7 @@ load_supported_modes_mbim (GTask *task,
}
/* Build all */
- mask_all = mm_modem_mode_from_mbim_data_class (self->priv->caps_data_class, self->priv->caps_custom_data_class);
+ mask_all = mm_modem_mode_from_mbim_data_class (self->priv->caps_data_class);
mode.allowed = mask_all;
mode.preferred = MM_MODEM_MODE_NONE;
all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
@@ -1188,11 +1194,14 @@ register_state_current_modes_query_ready (MbimDevice *device,
GAsyncResult *res,
GTask *task)
{
+ MMBroadbandModemMbim *self;
g_autoptr(MbimMessage) response = NULL;
MMModemModeCombination *mode = NULL;
GError *error = NULL;
MbimDataClass preferred_data_classes;
+ self = g_task_get_source_object (task);
+
response = mbim_device_command_finish (device, res, &error);
if (!response ||
!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
@@ -1214,8 +1223,12 @@ register_state_current_modes_query_ready (MbimDevice *device,
return;
}
+ /* Normalize preferred data class to include any custom data class */
+ preferred_data_classes = mm_modem_mbim_normalize_data_class_mask (preferred_data_classes,
+ self->priv->caps_custom_data_class);
+
mode = g_new0 (MMModemModeCombination, 1);
- mode->allowed = mm_modem_mode_from_mbim_data_class (preferred_data_classes, NULL);
+ mode->allowed = mm_modem_mode_from_mbim_data_class (preferred_data_classes);
mode->preferred = MM_MODEM_MODE_NONE;
g_task_return_pointer (task, mode, (GDestroyNotify)g_free);
g_object_unref (task);
@@ -1301,9 +1314,17 @@ complete_pending_allowed_modes_action (MMBroadbandModemMbim *self,
if (!self->priv->pending_allowed_modes_action)
return;
+ /* requested_data_classes is de-normalized (since we just sent it to the modem) */
requested_data_classes = (MbimDataClass) GPOINTER_TO_UINT (g_task_get_task_data (self->priv->pending_allowed_modes_action));
- requested_modes = mm_modem_mode_from_mbim_data_class (requested_data_classes, NULL);
- preferred_modes = mm_modem_mode_from_mbim_data_class (preferred_data_classes, NULL);
+ requested_modes = mm_modem_mode_from_mbim_data_class (requested_data_classes);
+
+ /* But preferred_data_classes is normalized (since we just pulled it out of
+ * an MBIM message). De-normalize preferred_data_classes so we can compare
+ * it to requested_data_classes.
+ */
+ preferred_data_classes = mm_modem_mbim_normalize_data_class_mask (preferred_data_classes,
+ self->priv->caps_custom_data_class);
+ preferred_modes = mm_modem_mode_from_mbim_data_class (preferred_data_classes);
/* only early complete on success, as we don't know if they're going to be
* intermediate indications emitted before the preference change is valid */
@@ -1367,8 +1388,8 @@ register_state_current_modes_set_ready (MbimDevice *device,
return;
}
- requested_modes = mm_modem_mode_from_mbim_data_class (requested_data_classes, NULL);
- preferred_modes = mm_modem_mode_from_mbim_data_class (preferred_data_classes, NULL);
+ requested_modes = mm_modem_mode_from_mbim_data_class (requested_data_classes);
+ preferred_modes = mm_modem_mode_from_mbim_data_class (preferred_data_classes);
if (requested_modes != preferred_modes) {
g_autofree gchar *requested_modes_str = NULL;
@@ -1422,6 +1443,7 @@ modem_set_current_modes (MMIfaceModem *_self,
GTask *task;
MbimDevice *device;
g_autoptr(GCancellable) cancellable = NULL;
+ MbimDataClass normalized_class;
if (!peek_device (self, &device, callback, user_data))
return;
@@ -1445,11 +1467,17 @@ modem_set_current_modes (MMIfaceModem *_self,
/* Limit ANY to the currently supported modes */
if (allowed == MM_MODEM_MODE_ANY)
- allowed = mm_modem_mode_from_mbim_data_class (self->priv->caps_data_class, self->priv->caps_custom_data_class);
+ allowed = mm_modem_mode_from_mbim_data_class (self->priv->caps_data_class);
+
+ normalized_class = mm_mbim_data_class_from_modem_mode (allowed,
+ mm_iface_modem_is_3gpp (_self),
+ mm_iface_modem_is_cdma (_self));
- self->priv->requested_data_class = mm_mbim_data_class_from_modem_mode (allowed,
- mm_iface_modem_is_3gpp (_self),
- mm_iface_modem_is_cdma (_self));
+ /* Replace any normalized data class with MBIM_DATA_CLASS_CUSTOM
+ * before sending back to the modem.
+ */
+ self->priv->requested_data_class = mm_modem_mbim_denormalize_data_class_mask (normalized_class,
+ self->priv->caps_custom_data_class);
/* Store the ongoing allowed modes action, so that we can finish the
* operation early via indications, instead of waiting for the modem
@@ -5271,6 +5299,13 @@ common_process_register_state (MMBroadbandModemMbim *self,
}
}
+ /* Normalize preferred and available data classes to include any custom data class */
+ preferred_data_classes = mm_modem_mbim_normalize_data_class_mask (preferred_data_classes,
+ self->priv->caps_custom_data_class);
+ available_data_classes = mm_modem_mbim_normalize_data_class_mask (available_data_classes,
+ self->priv->caps_custom_data_class);
+
+
nw_error = mm_broadband_modem_mbim_normalize_nw_error (self, nw_error);
nw_error_str = mbim_nw_error_get_string (nw_error);
available_data_classes_str = mbim_data_class_build_string_from_mask (available_data_classes);
@@ -5753,9 +5788,12 @@ common_process_packet_service (MMBroadbandModemMbim *self,
if (packet_service_state == MBIM_PACKET_SERVICE_STATE_ATTACHED) {
if (data_class_v3)
- self->priv->enabled_cache.highest_available_data_class = mm_mbim_data_class_from_mbim_data_class_v3_and_subclass (data_class_v3, data_subclass);
- else
- self->priv->enabled_cache.highest_available_data_class = data_class;
+ data_class = mm_mbim_data_class_from_mbim_data_class_v3_and_subclass (data_class_v3, data_subclass);
+
+ /* Normalize data class to include any custom data class */
+ data_class = mm_modem_mbim_normalize_data_class_mask (data_class,
+ self->priv->caps_custom_data_class);
+ self->priv->enabled_cache.highest_available_data_class = data_class;
} else if (packet_service_state == MBIM_PACKET_SERVICE_STATE_DETACHED) {
self->priv->enabled_cache.highest_available_data_class = 0;
}
@@ -10393,7 +10431,6 @@ finalize (GObject *object)
{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (object);
- g_free (self->priv->caps_custom_data_class);
g_free (self->priv->caps_device_id);
g_free (self->priv->caps_firmware_info);
g_free (self->priv->caps_hardware_info);
diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c
index 49d38531..aef31866 100644
--- a/src/mm-modem-helpers-mbim.c
+++ b/src/mm-modem-helpers-mbim.c
@@ -25,10 +25,77 @@
/*****************************************************************************/
+typedef struct {
+ const gchar *custom_class;
+ const MbimDataClass primary_data_class;
+ const MbimDataClass secondary_data_class;
+} CustomDataClass;
+
+static const CustomDataClass custom_data_classes[] = {
+ /* "5GSA/TDS": Quectel RM502Q */
+ { "5GSA", MBIM_DATA_CLASS_5G_SA, MBIM_DATA_CLASS_NONE },
+ /* "5G/TDS": Telit FN990, Quectel RM502Q, Gosuncn GM800
+ * "5G": Dell Snapdragon X55/Foxconn T99W175
+ */
+ { "5G", MBIM_DATA_CLASS_5G_NSA, MBIM_DATA_CLASS_5G_SA },
+ /* "HSPA+": Dell DW5821e/Foxconn T77W968, Huawei EM820W */
+ { "HSPA+", MBIM_DATA_CLASS_HSDPA | MBIM_DATA_CLASS_HSUPA, MBIM_DATA_CLASS_NONE },
+};
+
+MbimDataClass
+mm_mbim_data_class_from_custom_caps (MbimDataClass orig_data_class,
+ const gchar *custom_data_class)
+{
+ guint i;
+
+ if (orig_data_class & MBIM_DATA_CLASS_CUSTOM) {
+ for (i = 0; i < G_N_ELEMENTS (custom_data_classes); i++) {
+ if (strstr (custom_data_class, custom_data_classes[i].custom_class)) {
+ /* If the original data class already includes the primary custom
+ * class add the secondary instead. Devices sometimes report a variant
+ * of the custom class depending on MBIMex version.
+ *
+ * For example, Foxconn X55 supports SA but reports "...,lte,custom"
+ * with MBIMex1 and "...,lte,5g-nsa,custom" with MBIMex2. Fix that
+ * up with the highest level we can be sure the device supports.
+ */
+ if (orig_data_class & custom_data_classes[i].primary_data_class)
+ return custom_data_classes[i].secondary_data_class;
+ else
+ return custom_data_classes[i].primary_data_class;
+ }
+ }
+ }
+ return MBIM_DATA_CLASS_NONE;
+}
+
+MbimDataClass
+mm_modem_mbim_normalize_data_class_mask (MbimDataClass orig_data_class,
+ MbimDataClass custom_data_class)
+{
+ if (orig_data_class & MBIM_DATA_CLASS_CUSTOM) {
+ orig_data_class |= custom_data_class;
+ orig_data_class &= ~MBIM_DATA_CLASS_CUSTOM;
+ }
+ return orig_data_class;
+}
+
+MbimDataClass
+mm_modem_mbim_denormalize_data_class_mask (MbimDataClass orig_data_class,
+ MbimDataClass custom_data_class)
+{
+ if (orig_data_class & custom_data_class) {
+ orig_data_class &= ~custom_data_class;
+ orig_data_class |= MBIM_DATA_CLASS_CUSTOM;
+ }
+ return orig_data_class;
+}
+
+/*****************************************************************************/
+
MMModemCapability
mm_modem_capability_from_mbim_device_caps (MbimCellularClass caps_cellular_class,
- MbimDataClass caps_data_class,
- const gchar *caps_custom_data_class)
+ MbimDataClass caps_data_class)
{
MMModemCapability mask = 0;
@@ -43,12 +110,6 @@ mm_modem_capability_from_mbim_device_caps (MbimCellularClass caps_cellular_clas
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;
@@ -148,8 +209,7 @@ mm_modem_3gpp_packet_service_state_from_mbim_packet_service_state (MbimPacketSer
/*****************************************************************************/
MMModemMode
-mm_modem_mode_from_mbim_data_class (MbimDataClass data_class,
- const gchar *caps_custom_data_class)
+mm_modem_mode_from_mbim_data_class (MbimDataClass data_class)
{
MMModemMode mask = MM_MODEM_MODE_NONE;
@@ -166,11 +226,6 @@ mm_modem_mode_from_mbim_data_class (MbimDataClass data_class,
if (data_class & (MBIM_DATA_CLASS_5G_NSA |
MBIM_DATA_CLASS_5G_SA))
mask |= MM_MODEM_MODE_5G;
- /* Some modems (e.g. Telit FN990) reports MBIM custom data class "5G/TDS" */
- if ((data_class & MBIM_DATA_CLASS_CUSTOM) && caps_custom_data_class) {
- if (strstr (caps_custom_data_class, "5G"))
- mask |= MM_MODEM_MODE_5G;
- }
/* 3GPP2... */
if (data_class & MBIM_DATA_CLASS_1XRTT)
diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h
index ba664bbb..6a058937 100644
--- a/src/mm-modem-helpers-mbim.h
+++ b/src/mm-modem-helpers-mbim.h
@@ -27,9 +27,17 @@
/*****************************************************************************/
/* MBIM/BasicConnect to MM translations */
-MMModemCapability mm_modem_capability_from_mbim_device_caps (MbimCellularClass caps_cellular_class,
- MbimDataClass caps_data_class,
- const gchar *caps_custom_data_class);
+MbimDataClass mm_mbim_data_class_from_custom_caps (MbimDataClass orig_data_class,
+ const gchar *custom_data_class);
+
+MbimDataClass mm_modem_mbim_normalize_data_class_mask (MbimDataClass orig_data_class,
+ MbimDataClass custom_data_class);
+
+MbimDataClass mm_modem_mbim_denormalize_data_class_mask (MbimDataClass orig_data_class,
+ MbimDataClass custom_data_class);
+
+MMModemCapability mm_modem_capability_from_mbim_device_caps (MbimCellularClass caps_cellular_class,
+ MbimDataClass caps_data_class);
MMModemLock mm_modem_lock_from_mbim_pin_type (MbimPinType pin_type);
@@ -40,8 +48,7 @@ MMModem3gppPacketServiceState mm_modem_3gpp_packet_service_state_from_mbim_packe
MbimDataClass mm_mbim_data_class_from_mbim_data_class_v3_and_subclass (MbimDataClassV3 data_class_v3,
MbimDataSubclass data_subclass);
-MMModemMode mm_modem_mode_from_mbim_data_class (MbimDataClass data_class,
- const gchar *caps_custom_data_class);
+MMModemMode mm_modem_mode_from_mbim_data_class (MbimDataClass data_class);
MbimDataClass mm_mbim_data_class_from_modem_mode (MMModemMode modem_mode,
gboolean is_3gpp,