aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c184
-rw-r--r--src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h3
-rw-r--r--src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c15
3 files changed, 193 insertions, 9 deletions
diff --git a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
index 1effc603..71957a07 100644
--- a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
+++ b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.c
@@ -19,40 +19,208 @@
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
+#include "mm-log-object.h"
#include "mm-bearer-mbim-mtk-fibocom.h"
G_DEFINE_TYPE (MMBearerMbimMtkFibocom, mm_bearer_mbim_mtk_fibocom, MM_TYPE_BEARER_MBIM)
+struct _MMBearerMbimMtkFibocomPrivate {
+ /* Whether IP packet filters need to be removed */
+ gboolean remove_ip_packet_filters;
+ gboolean reload_stats_unsupported;
+};
+
+/*****************************************************************************/
+/* Stats */
+
+typedef struct {
+ guint64 rx_bytes;
+ guint64 tx_bytes;
+} ReloadStatsResult;
+
+static gboolean
+reload_stats_finish (MMBaseBearer *_self,
+ guint64 *rx_bytes,
+ guint64 *tx_bytes,
+ GAsyncResult *res,
+ GError **error)
+{
+ MMBearerMbimMtkFibocom *self = MM_BEARER_MBIM_MTK_FIBOCOM (_self);
+ g_autofree ReloadStatsResult *stats = NULL;
+ g_autoptr(GError) inner_error = NULL;
+
+ stats = g_task_propagate_pointer (G_TASK (res), &inner_error);
+ if (!stats) {
+ /* If filters need to be removed on every stats query, we must never
+ * return an error, otherwise the upper layers will stop the stats reloading
+ * logic. Only return an error when filters are not being removed. */
+ if (!self->priv->remove_ip_packet_filters) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ /* Flag as stats reloading being unsupported, we will avoid querying. */
+ self->priv->reload_stats_unsupported = TRUE;
+ }
+
+ if (rx_bytes)
+ *rx_bytes = stats ? stats->rx_bytes : 0;
+ if (tx_bytes)
+ *tx_bytes = stats ? stats->tx_bytes : 0;
+ return TRUE;
+}
+
+static void
+parent_reload_stats_ready (MMBaseBearer *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ g_autofree ReloadStatsResult *stats = NULL;
+ GError *error = NULL;
+
+ stats = g_new0 (ReloadStatsResult, 1);
+
+ if (!MM_BASE_BEARER_CLASS (mm_bearer_mbim_mtk_fibocom_parent_class)->reload_stats_finish (
+ self,
+ &stats->rx_bytes,
+ &stats->tx_bytes,
+ res,
+ &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, g_steal_pointer (&stats), g_free);
+ g_object_unref (task);
+}
+
+static void
+packet_statistics_query (GTask *task)
+{
+ MMBearerMbimMtkFibocom *self;
+
+ self = g_task_get_source_object (task);
+ if (self->priv->reload_stats_unsupported) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Skipping stats reloading");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Chain up parent's stats query */
+ MM_BASE_BEARER_CLASS (mm_bearer_mbim_mtk_fibocom_parent_class)->reload_stats (
+ MM_BASE_BEARER (self),
+ (GAsyncReadyCallback) parent_reload_stats_ready,
+ task);
+}
+
+static void
+packet_filters_set_ready (MbimDevice *device,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBearerMbim *self;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(MbimMessage) response = NULL;
+
+ 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))
+ mm_obj_dbg (self, "Couldn't reset IP packet filters: %s", error->message);
+
+ packet_statistics_query (task);
+}
+
+static void
+ensure_removed_filters (GTask *task)
+{
+ MMBearerMbimMtkFibocom *self;
+ MMPortMbim *port;
+ g_autoptr(MbimMessage) message = NULL;
+ g_autoptr(MMBaseModem) modem = NULL;
+ guint32 session_id;
+
+ self = g_task_get_source_object (task);
+
+ g_object_get (self,
+ MM_BASE_BEARER_MODEM, &modem,
+ NULL);
+ port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (modem));
+ 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;
+ }
+
+ mm_obj_dbg (self, "Resetting IP packet filters...");
+
+ session_id = mm_bearer_mbim_get_session_id (MM_BEARER_MBIM (self));
+ message = mbim_message_ip_packet_filters_set_new (session_id, 0, NULL, NULL);
+ mbim_device_command (mm_port_mbim_peek_device (port),
+ message,
+ 5,
+ NULL,
+ (GAsyncReadyCallback)packet_filters_set_ready,
+ task);
+}
+
+static void
+reload_stats (MMBaseBearer *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBearerMbimMtkFibocom *self = MM_BEARER_MBIM_MTK_FIBOCOM (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ if (self->priv->remove_ip_packet_filters)
+ ensure_removed_filters (task);
+ else
+ packet_statistics_query (task);
+}
+
/*****************************************************************************/
MMBaseBearer *
mm_bearer_mbim_mtk_fibocom_new (MMBroadbandModemMbim *modem,
gboolean is_async_slaac_supported,
+ gboolean remove_ip_packet_filters,
MMBearerProperties *config)
{
- MMBaseBearer *bearer;
+ MMBearerMbimMtkFibocom *self;
/* The Mbim bearer inherits from MMBaseBearer (so it's not a MMBroadbandBearer)
* and that means that the object is not async-initable, so we just use
* g_object_new() here */
- bearer = g_object_new (MM_TYPE_BEARER_MBIM_MTK_FIBOCOM,
- MM_BASE_BEARER_MODEM, modem,
- MM_BASE_BEARER_CONFIG, config,
- MM_BEARER_MBIM_ASYNC_SLAAC, is_async_slaac_supported,
- NULL);
+ self = g_object_new (MM_TYPE_BEARER_MBIM_MTK_FIBOCOM,
+ MM_BASE_BEARER_MODEM, modem,
+ MM_BASE_BEARER_CONFIG, config,
+ MM_BEARER_MBIM_ASYNC_SLAAC, is_async_slaac_supported,
+ NULL);
+
+ self->priv->remove_ip_packet_filters = remove_ip_packet_filters;
/* Only export valid bearers */
- mm_base_bearer_export (bearer);
+ mm_base_bearer_export (MM_BASE_BEARER (self));
- return bearer;
+ return MM_BASE_BEARER (self);
}
static void
mm_bearer_mbim_mtk_fibocom_init (MMBearerMbimMtkFibocom *self)
{
+ /* Initialize private data */
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_BEARER_MBIM_MTK_FIBOCOM, MMBearerMbimMtkFibocomPrivate);
}
static void
mm_bearer_mbim_mtk_fibocom_class_init (MMBearerMbimMtkFibocomClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMBearerMbimMtkFibocomPrivate));
+
+ base_bearer_class->reload_stats = reload_stats;
+ base_bearer_class->reload_stats_finish = reload_stats_finish;
}
diff --git a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
index 736d3fc9..7e093a52 100644
--- a/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
+++ b/src/plugins/mtk/mm-bearer-mbim-mtk-fibocom.h
@@ -33,9 +33,11 @@
typedef struct _MMBearerMbimMtkFibocom MMBearerMbimMtkFibocom;
typedef struct _MMBearerMbimMtkFibocomClass MMBearerMbimMtkFibocomClass;
+typedef struct _MMBearerMbimMtkFibocomPrivate MMBearerMbimMtkFibocomPrivate;
struct _MMBearerMbimMtkFibocom {
MMBearerMbim parent;
+ MMBearerMbimMtkFibocomPrivate *priv;
};
struct _MMBearerMbimMtkFibocomClass {
@@ -48,6 +50,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMBearerMbimMtkFibocom, g_object_unref)
/* MBIM bearer creation implementation */
MMBaseBearer *mm_bearer_mbim_mtk_fibocom_new (MMBroadbandModemMbim *modem,
gboolean is_async_slaac_supported,
+ gboolean remove_ip_packet_filters,
MMBearerProperties *config);
#endif /* MM_BEARER_MBIM_MTK_FIBOCOM_H */
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 cfcd3616..7ef97b64 100644
--- a/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
+++ b/src/plugins/mtk/mm-broadband-modem-mbim-mtk-fibocom.c
@@ -42,9 +42,10 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimMtkFibocom, mm_broadband_modem_mbim_
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init))
struct _MMBroadbandModemMbimMtkFibocomPrivate {
- /* Supported features */
+ /* Custom MTK/Fibocom bearer behavior */
gboolean is_multiplex_supported;
gboolean is_async_slaac_supported;
+ gboolean remove_ip_packet_filters;
};
/*****************************************************************************/
@@ -58,6 +59,9 @@ struct _MMBroadbandModemMbimMtkFibocomPrivate {
* versions. */
#define MULTIPLEX_SUPPORTED_VERSION 29, 23, 6
+/* Explicit IP packet filter removal required in old firmware versions. */
+#define IP_PACKET_FILTER_REMOVAL_UNNEEDED_VERSION 29, 23, 6
+
static inline gboolean
fm350_check_version (guint A1, guint A2, guint A3,
guint B1, guint B2, guint B3)
@@ -102,6 +106,11 @@ process_fm350_version_features (MMBroadbandModemMbimMtkFibocom *self,
self->priv->is_multiplex_supported = fm350_check_version (major, minor, micro, MULTIPLEX_SUPPORTED_VERSION);
mm_obj_info (self, "FM350 multiplexing is %ssupported",
self->priv->is_multiplex_supported ? "" : "not ");
+
+ /* Check if we need to remove IP packet filters */
+ self->priv->remove_ip_packet_filters = !fm350_check_version (major, minor, micro, IP_PACKET_FILTER_REMOVAL_UNNEEDED_VERSION);
+ mm_obj_info (self, "FM350 %s IP packet filter removal",
+ self->priv->remove_ip_packet_filters ? "requires" : "does not require");
}
/*****************************************************************************/
@@ -171,6 +180,7 @@ create_bearer (MMIfaceModem *_self,
self->priv->is_async_slaac_supported ? "supported" : "unsupported");
bearer = mm_bearer_mbim_mtk_fibocom_new (MM_BROADBAND_MODEM_MBIM (self),
self->priv->is_async_slaac_supported,
+ self->priv->remove_ip_packet_filters,
properties);
g_task_return_pointer (task, bearer, g_object_unref);
g_object_unref (task);
@@ -230,6 +240,9 @@ mm_broadband_modem_mbim_mtk_fibocom_init (MMBroadbandModemMbimMtkFibocom *self)
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
MM_TYPE_BROADBAND_MODEM_MBIM_MTK_FIBOCOM,
MMBroadbandModemMbimMtkFibocomPrivate);
+
+ /* By default remove, unless we have a new enough version */
+ self->priv->remove_ip_packet_filters = TRUE;
}
static void