aboutsummaryrefslogtreecommitdiff
path: root/src/mm-modem-helpers-mbim.c
diff options
context:
space:
mode:
authorDan Williams <dan@ioncontrol.co>2025-03-30 01:00:52 -0500
committerDan Williams <dan@ioncontrol.co>2025-04-01 10:25:43 -0500
commit19c817cfe93335aab2c579bb2a75f3336e36b1bd (patch)
tree1d4dd7d35a9e223b817ccb31074d08b8f02c855b /src/mm-modem-helpers-mbim.c
parent45313ebef8ea0a7f9e0d501227798ff2d1dc4c4a (diff)
broadband-modem-mbim: consistently handle custom data classes
Consistently interpret the modem's reported custom data class when loading current mode, supported mode, supported capabilities, setting current mode, and current access technology. Normalize the data class to include any custom data class immediately after reading it from any MBIM message. De-normalize it when sending back to the modem when setting current modes so the modem receives MBIM_DATA_CLASS_CUSTOM for the custom mode. Fixes: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/937 Signed-off-by: Dan Williams <dan@ioncontrol.co>
Diffstat (limited to 'src/mm-modem-helpers-mbim.c')
-rw-r--r--src/mm-modem-helpers-mbim.c85
1 files changed, 70 insertions, 15 deletions
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)