diff options
author | Bolan Wang <bolan.wang@fibocom.com> | 2024-08-26 20:06:57 +0800 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2024-11-20 10:38:23 +0000 |
commit | 1d43bb0dacb9019a7681ae80cd02a7f2959b11f0 (patch) | |
tree | b750838815d07a5b13f51afa59c0faae7bf9f6a8 /src | |
parent | 87e1e8b2d45172e3a3f338d0b14777e143b28586 (diff) |
plugin,mtk: workaround for invalid rssi threshold on FM350.
FM350 modems report an invalid rssi threshold (always 0) in the signal-state response message.
It results in signal quality not being updated. We can use this patch to workaround this bug.
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c | 166 |
1 files changed, 159 insertions, 7 deletions
diff --git a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c index a2c90899..ce8bc6a3 100644 --- a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c +++ b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c @@ -24,21 +24,25 @@ #include "ModemManager.h" #include "mm-log-object.h" #include "mm-iface-modem.h" +#include "mm-iface-modem-signal.h" #include "mm-bearer-mbim-mtk-fibocom.h" #include "mm-broadband-modem-mbim-mtk-fibocom.h" #include "mm-shared-fibocom.h" #include "mm-shared-mtk.h" -static void iface_modem_init (MMIfaceModemInterface *iface); -static void shared_fibocom_init (MMSharedFibocomInterface *iface); -static void shared_mtk_init (MMSharedMtkInterface *iface); +static void iface_modem_init (MMIfaceModemInterface *iface); +static void iface_modem_signal_init (MMIfaceModemSignalInterface *iface); +static void shared_fibocom_init (MMSharedFibocomInterface *iface); +static void shared_mtk_init (MMSharedMtkInterface *iface); -static MMIfaceModemInterface *iface_modem_parent; +static MMIfaceModemInterface *iface_modem_parent; +static MMIfaceModemSignalInterface *iface_modem_signal_parent; G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimMtkFibocom, mm_broadband_modem_mbim_mtk_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM_MTK, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_MTK, shared_mtk_init)) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_MTK, shared_mtk_init)) struct _MMBroadbandModemMbimMtkFibocomPrivate { /* Custom MTK/Fibocom bearer behavior */ @@ -65,6 +69,9 @@ struct _MMBroadbandModemMbimMtkFibocomPrivate { /* NW error normalization required in old firmware versions. */ #define NORMALIZE_NW_ERROR_UNNEEDED 29, 22, 13 +/* Default rssi threshold in the module. */ +#define DEFAULT_RSSI_THRESHOLD 6 + static inline gboolean fm350_check_version (guint A1, guint A2, guint A3, guint B1, guint B2, guint B3) @@ -230,6 +237,142 @@ normalize_nw_error (MMBroadbandModemMbim *self, return nw_error; } +/*****************************************************************************/ +/* Load extended signal information (Signal interface) */ + +static gboolean +signal_setup_thresholds_finish (MMIfaceModemSignal *self, + GAsyncResult *res, + GError **error) +{ + return iface_modem_signal_parent->setup_thresholds_finish (self, res, error); +} + +static void +setup_default_thresholds_ready (MMIfaceModemSignal *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!iface_modem_signal_parent->setup_thresholds_finish (self, res, &error)) { + mm_obj_dbg (self, "setup rssi thresholds failed: %s", error->message); + g_task_return_error (task, error); + } else { + g_task_return_boolean (task, TRUE); + } + + g_object_unref (task); +} + +static void +signal_state_query_ready (MbimDevice *device, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemMbimMtkFibocom *self; + GError *error = NULL; + g_autoptr(MbimMessage) response = NULL; + guint32 rssi_threshold; + guint32 error_rate_threshold; + + 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)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + if (!mbim_device_check_ms_mbimex_version (device, 2, 0)) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Failed MBIMEx v2.0 signal state response support check"); + g_object_unref (task); + return; + } + + if (!mbim_message_ms_basic_connect_v2_signal_state_response_parse ( + response, + NULL, /* rssi */ + NULL, /* error_rate */ + NULL, /* signal_strength_interval */ + &rssi_threshold, + &error_rate_threshold, + NULL, /* rsrp_snr_count */ + NULL, /* rsrp_snr */ + &error)) { + g_prefix_error (&error, "Failed processing MBIMEx v2.0 signal state response: "); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* If the device doesn't have a default rssi threshold, to set one. */ + if (rssi_threshold == 0) { + iface_modem_signal_parent->setup_thresholds ( + MM_IFACE_MODEM_SIGNAL (self), + DEFAULT_RSSI_THRESHOLD, + error_rate_threshold, + (GAsyncReadyCallback)setup_default_thresholds_ready, + task); + return; + } + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +parent_setup_thresholds_ready (MMIfaceModemSignal *self, + GAsyncResult *res, + GTask *task) +{ + MMPortMbim *port; + MbimDevice *device; + g_autoptr(MbimMessage) message = NULL; + + port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)); + if (!port) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't peek MBIM port"); + g_object_unref (task); + return; + } + + device = mm_port_mbim_peek_device (port); + + message = mbim_message_signal_state_query_new (NULL); + mbim_device_command (device, + message, + 5, + NULL, + (GAsyncReadyCallback)signal_state_query_ready, + task); +} + +static void +signal_setup_thresholds (MMIfaceModemSignal *self, + guint rssi_threshold, + gboolean error_rate_threshold, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + + /* First call the parent setup_thresholds method to set the rssi threshold (0) for the module, + * making the module to set this value to its internal default according to the specification. + * Then use the signal state MBIM request to check the default rssi threshold for module responses. + * If there is no valid rssi threshold, to set a default value. */ + iface_modem_signal_parent->setup_thresholds ( + self, + rssi_threshold, + error_rate_threshold, + (GAsyncReadyCallback)parent_setup_thresholds_ready, + task); +} + /******************************************************************************/ MMBroadbandModemMbimMtkFibocom * @@ -286,6 +429,15 @@ iface_modem_init (MMIfaceModemInterface *iface) } +static void +iface_modem_signal_init (MMIfaceModemSignalInterface *iface) +{ + iface_modem_signal_parent = g_type_interface_peek_parent (iface); + + iface->setup_thresholds = signal_setup_thresholds; + iface->setup_thresholds_finish = signal_setup_thresholds_finish; +} + static MMBaseModemClass * peek_parent_class (MMSharedFibocom *self) { |