Merge request !1323 from 'mbim-data-class-unknown'
broadband-modem-mbim: consistently handle custom data classes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1323
This commit is contained in:
@@ -166,6 +166,7 @@ print_signal_info (void)
|
||||
gchar *lte_rsrq = NULL;
|
||||
gchar *lte_snr = NULL;
|
||||
gchar *lte_error_rate = NULL;
|
||||
gchar *nr5g_rssi = NULL;
|
||||
gchar *nr5g_rsrp = NULL;
|
||||
gchar *nr5g_rsrq = NULL;
|
||||
gchar *nr5g_snr = NULL;
|
||||
@@ -235,6 +236,8 @@ print_signal_info (void)
|
||||
|
||||
signal = mm_modem_signal_peek_nr5g (ctx->modem_signal);
|
||||
if (signal) {
|
||||
if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN)
|
||||
nr5g_rssi = g_strdup_printf ("%.2lf", value);
|
||||
if ((value = mm_signal_get_rsrq (signal)) != MM_SIGNAL_UNKNOWN)
|
||||
nr5g_rsrq = g_strdup_printf ("%.2lf", value);
|
||||
if ((value = mm_signal_get_rsrp (signal)) != MM_SIGNAL_UNKNOWN)
|
||||
@@ -267,6 +270,7 @@ print_signal_info (void)
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_LTE_RSRP, lte_rsrp, "dBm");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_LTE_SNR, lte_snr, "dB");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_LTE_ERROR_RATE, lte_error_rate, "%%");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_5G_RSSI, nr5g_rssi, "dBm");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_5G_RSRQ, nr5g_rsrq, "dB");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_5G_RSRP, nr5g_rsrp, "dBm");
|
||||
mmcli_output_string_take_typed (MMC_F_SIGNAL_5G_SNR, nr5g_snr, "dB");
|
||||
|
||||
@@ -202,6 +202,7 @@ static FieldInfo field_infos[] = {
|
||||
[MMC_F_SIGNAL_LTE_RSRP] = { "modem.signal.lte.rsrp", "rsrp", MMC_S_MODEM_SIGNAL_LTE, },
|
||||
[MMC_F_SIGNAL_LTE_SNR] = { "modem.signal.lte.snr", "s/n", MMC_S_MODEM_SIGNAL_LTE, },
|
||||
[MMC_F_SIGNAL_LTE_ERROR_RATE] = { "modem.signal.lte.error-rate", "error rate", MMC_S_MODEM_SIGNAL_LTE, },
|
||||
[MMC_F_SIGNAL_5G_RSSI] = { "modem.signal.5g.rssi", "rssi", MMC_S_MODEM_SIGNAL_5G, },
|
||||
[MMC_F_SIGNAL_5G_RSRQ] = { "modem.signal.5g.rsrq", "rsrq", MMC_S_MODEM_SIGNAL_5G, },
|
||||
[MMC_F_SIGNAL_5G_RSRP] = { "modem.signal.5g.rsrp", "rsrp", MMC_S_MODEM_SIGNAL_5G, },
|
||||
[MMC_F_SIGNAL_5G_SNR] = { "modem.signal.5g.snr", "s/n", MMC_S_MODEM_SIGNAL_5G, },
|
||||
|
||||
@@ -214,6 +214,7 @@ typedef enum {
|
||||
MMC_F_SIGNAL_LTE_RSRP,
|
||||
MMC_F_SIGNAL_LTE_SNR,
|
||||
MMC_F_SIGNAL_LTE_ERROR_RATE,
|
||||
MMC_F_SIGNAL_5G_RSSI,
|
||||
MMC_F_SIGNAL_5G_RSRQ,
|
||||
MMC_F_SIGNAL_5G_RSRP,
|
||||
MMC_F_SIGNAL_5G_SNR,
|
||||
|
||||
@@ -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);
|
||||
|
||||
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));
|
||||
normalized_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
|
||||
@@ -2183,6 +2211,18 @@ modem_power_down (MMIfaceModem *self,
|
||||
/*****************************************************************************/
|
||||
/* Signal quality loading (Modem interface) */
|
||||
|
||||
static MbimDataClass
|
||||
enabled_cache_best_available_data_class (MMBroadbandModemMbim *self)
|
||||
{
|
||||
MbimDataClass data_class;
|
||||
|
||||
/* Best guess of current data class */
|
||||
data_class = self->priv->enabled_cache.highest_available_data_class;
|
||||
if (data_class == 0)
|
||||
data_class = self->priv->enabled_cache.available_data_classes;
|
||||
return data_class;
|
||||
}
|
||||
|
||||
static guint
|
||||
modem_load_signal_quality_finish (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
@@ -2255,10 +2295,7 @@ signal_state_query_ready (MbimDevice *device,
|
||||
if (error)
|
||||
g_task_return_error (task, error);
|
||||
else {
|
||||
/* Best guess of current data class */
|
||||
data_class = self->priv->enabled_cache.highest_available_data_class;
|
||||
if (data_class == 0)
|
||||
data_class = self->priv->enabled_cache.available_data_classes;
|
||||
data_class = enabled_cache_best_available_data_class (self);
|
||||
if (mm_signal_from_mbim_signal_state (data_class, rssi, error_rate, rsrp_snr, rsrp_snr_count,
|
||||
self, &cdma, &evdo, &gsm, &umts, <e, &nr5g))
|
||||
mm_iface_modem_signal_update (MM_IFACE_MODEM_SIGNAL (self), cdma, evdo, gsm, umts, lte, nr5g);
|
||||
@@ -4914,11 +4951,7 @@ basic_connect_notification_signal_state (MMBroadbandModemMbim *self,
|
||||
quality = mm_signal_quality_from_mbim_signal_state (coded_rssi, rsrp_snr, rsrp_snr_count, self);
|
||||
mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), quality);
|
||||
|
||||
/* Best guess of current data class */
|
||||
data_class = self->priv->enabled_cache.highest_available_data_class;
|
||||
if (data_class == 0)
|
||||
data_class = self->priv->enabled_cache.available_data_classes;
|
||||
|
||||
data_class = enabled_cache_best_available_data_class (self);
|
||||
if (mm_signal_from_mbim_signal_state (data_class, coded_rssi, coded_error_rate, rsrp_snr, rsrp_snr_count,
|
||||
self, &cdma, &evdo, &gsm, &umts, <e, &nr5g))
|
||||
mm_iface_modem_signal_update (MM_IFACE_MODEM_SIGNAL (self), cdma, evdo, gsm, umts, lte, nr5g);
|
||||
@@ -4981,11 +5014,10 @@ static void
|
||||
update_access_technologies (MMBroadbandModemMbim *self)
|
||||
{
|
||||
MMModemAccessTechnology act;
|
||||
MbimDataClass data_class;
|
||||
|
||||
act = mm_modem_access_technology_from_mbim_data_class (self->priv->enabled_cache.highest_available_data_class);
|
||||
if (act == MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)
|
||||
act = mm_modem_access_technology_from_mbim_data_class (self->priv->enabled_cache.available_data_classes);
|
||||
|
||||
data_class = enabled_cache_best_available_data_class (self);
|
||||
act = mm_modem_access_technology_from_mbim_data_class (data_class);
|
||||
mm_iface_modem_3gpp_update_access_technologies (MM_IFACE_MODEM_3GPP (self), act);
|
||||
}
|
||||
|
||||
@@ -5271,6 +5303,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 +5792,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;
|
||||
}
|
||||
@@ -7532,10 +7574,7 @@ mbimexv2_signal_state_query_ready (MbimDevice *device,
|
||||
|
||||
result = g_slice_new0 (SignalLoadValuesResult);
|
||||
|
||||
/* Best guess of current data class */
|
||||
data_class = self->priv->enabled_cache.highest_available_data_class;
|
||||
if (data_class == 0)
|
||||
data_class = self->priv->enabled_cache.available_data_classes;
|
||||
data_class = enabled_cache_best_available_data_class (self);
|
||||
if (!mm_signal_from_mbim_signal_state (
|
||||
data_class, rssi, error_rate, rsrp_snr, rsrp_snr_count, self,
|
||||
NULL, NULL, &result->gsm, &result->umts, &result->lte, &result->nr5g)) {
|
||||
@@ -10393,7 +10432,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);
|
||||
|
||||
+70
-15
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -25,6 +25,10 @@ if enable_qmi
|
||||
test_units += {'modem-helpers-qmi': libkerneldevice_dep}
|
||||
endif
|
||||
|
||||
if enable_mbim
|
||||
test_units += {'modem-helpers-mbim': libkerneldevice_dep}
|
||||
endif
|
||||
|
||||
foreach test_unit, test_deps: test_units
|
||||
test_name = 'test-' + test_unit
|
||||
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details:
|
||||
*
|
||||
* Copyright (c) 2025 Dan Williams <dan@ioncontrol.co>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <ModemManager.h>
|
||||
#define _LIBMM_INSIDE_MM
|
||||
#include <libmm-glib.h>
|
||||
|
||||
#include "mm-enums-types.h"
|
||||
#include "mm-flags-types.h"
|
||||
#include "mm-modem-helpers-mbim.h"
|
||||
#include "mm-log-test.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const MbimDataClass data_class;
|
||||
const gdouble rssi;
|
||||
const gdouble rscp;
|
||||
const gdouble ecio;
|
||||
const gdouble sinr;
|
||||
const gdouble io;
|
||||
const gdouble rsrq;
|
||||
const gdouble rsrp;
|
||||
const gdouble snr;
|
||||
const gdouble error_rate;
|
||||
} ExpectedSignal;
|
||||
|
||||
typedef struct {
|
||||
const gchar *detail;
|
||||
const gboolean expect_success;
|
||||
|
||||
const MbimDataClass data_class;
|
||||
const guint coded_rssi;
|
||||
const guint coded_error_rate;
|
||||
const MbimRsrpSnrInfo rsrp_snr[2];
|
||||
|
||||
const ExpectedSignal expected[2];
|
||||
} SignalStateTestcase;
|
||||
|
||||
const SignalStateTestcase signal_tests[] = {
|
||||
{ "5g-no-rsrp-snr",
|
||||
TRUE,
|
||||
MBIM_DATA_CLASS_5G_SA,
|
||||
16, 99,
|
||||
{ { .system_type = MBIM_DATA_CLASS_NONE }, { .system_type = MBIM_DATA_CLASS_NONE } },
|
||||
{ { MBIM_DATA_CLASS_5G_SA,
|
||||
-97,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
MM_SIGNAL_UNKNOWN,
|
||||
},
|
||||
{ MBIM_DATA_CLASS_NONE }
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
guint32 rsrp;
|
||||
guint32 snr;
|
||||
guint32 rsrp_threshold;
|
||||
guint32 snr_threshold;
|
||||
guint32 system_type;
|
||||
} MbimRsrpSnrInfo;
|
||||
#endif
|
||||
|
||||
static MMSignal *
|
||||
select_signal_for_data_class (MbimDataClass data_class,
|
||||
MMSignal **cdma,
|
||||
MMSignal **evdo,
|
||||
MMSignal **gsm,
|
||||
MMSignal **umts,
|
||||
MMSignal **lte,
|
||||
MMSignal **nr5g)
|
||||
{
|
||||
if (data_class & (MBIM_DATA_CLASS_5G_NSA |
|
||||
MBIM_DATA_CLASS_5G_SA))
|
||||
return *nr5g;
|
||||
if (data_class & (MBIM_DATA_CLASS_LTE))
|
||||
return *lte;
|
||||
if (data_class & (MBIM_DATA_CLASS_UMTS |
|
||||
MBIM_DATA_CLASS_HSDPA |
|
||||
MBIM_DATA_CLASS_HSUPA))
|
||||
return *umts;
|
||||
if (data_class & (MBIM_DATA_CLASS_GPRS |
|
||||
MBIM_DATA_CLASS_EDGE))
|
||||
return *gsm;
|
||||
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))
|
||||
return *evdo;
|
||||
if (data_class & MBIM_DATA_CLASS_1XRTT)
|
||||
return *cdma;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_signal_state_case (gconstpointer user_data)
|
||||
{
|
||||
const SignalStateTestcase *tc = user_data;
|
||||
gboolean success;
|
||||
guint count;
|
||||
g_autoptr(MMSignal) cdma;
|
||||
g_autoptr(MMSignal) evdo;
|
||||
g_autoptr(MMSignal) gsm;
|
||||
g_autoptr(MMSignal) umts;
|
||||
g_autoptr(MMSignal) lte;
|
||||
g_autoptr(MMSignal) nr5g;
|
||||
MMSignal *tmp;
|
||||
|
||||
for (count = 0;
|
||||
count < G_N_ELEMENTS (tc->rsrp_snr) && tc->rsrp_snr[count].system_type;
|
||||
count++);
|
||||
|
||||
success = mm_signal_from_mbim_signal_state (tc->data_class,
|
||||
tc->coded_rssi,
|
||||
tc->coded_error_rate,
|
||||
(MbimRsrpSnrInfo **) &tc->rsrp_snr,
|
||||
count,
|
||||
NULL,
|
||||
&cdma,
|
||||
&evdo,
|
||||
&gsm,
|
||||
&umts,
|
||||
<e,
|
||||
&nr5g);
|
||||
g_assert_cmpint (success, ==, tc->expect_success);
|
||||
|
||||
for (count = 0;
|
||||
count < G_N_ELEMENTS (tc->expected) && (tc->expected[count].data_class != MBIM_DATA_CLASS_NONE);
|
||||
count++) {
|
||||
tmp = select_signal_for_data_class (tc->expected[count].data_class,
|
||||
&cdma, &evdo, &gsm, &umts, <e, &nr5g);
|
||||
g_assert (tmp);
|
||||
g_assert_cmpfloat (mm_signal_get_rssi (tmp), ==, tc->expected[count].rssi);
|
||||
g_assert_cmpfloat (mm_signal_get_rscp (tmp), ==, tc->expected[count].rscp);
|
||||
g_assert_cmpfloat (mm_signal_get_ecio (tmp), ==, tc->expected[count].ecio);
|
||||
g_assert_cmpfloat (mm_signal_get_sinr (tmp), ==, tc->expected[count].sinr);
|
||||
g_assert_cmpfloat (mm_signal_get_io (tmp), ==, tc->expected[count].io);
|
||||
g_assert_cmpfloat (mm_signal_get_rsrq (tmp), ==, tc->expected[count].rsrq);
|
||||
g_assert_cmpfloat (mm_signal_get_rsrp (tmp), ==, tc->expected[count].rsrp);
|
||||
g_assert_cmpfloat (mm_signal_get_snr (tmp), ==, tc->expected[count].snr);
|
||||
g_assert_cmpfloat (mm_signal_get_error_rate (tmp), ==, tc->expected[count].error_rate);
|
||||
}
|
||||
if (count == 0 ) {
|
||||
g_assert (!cdma);
|
||||
g_assert (!evdo);
|
||||
g_assert (!gsm);
|
||||
g_assert (!umts);
|
||||
g_assert (!lte);
|
||||
g_assert (!nr5g);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
guint i;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (signal_tests); i++) {
|
||||
g_autofree gchar *detail;
|
||||
|
||||
detail = g_strdup_printf ("/MM/mbim/signal-state/%s", signal_tests[i].detail);
|
||||
g_test_add_data_func (detail, &signal_tests[i], test_signal_state_case);
|
||||
}
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
Reference in New Issue
Block a user