mtk: expect async SLAAC only in FM350 >= 29.23.06

Async SLAAC implementation in the FM350 is only available since
29.23.06, so only wait for the IP configuration indications reporting
the SLAAC result in newer versions.
This commit is contained in:
Aleksander Morgado
2024-02-15 21:01:52 +00:00
parent f31f42dda1
commit 1373ca7e51
5 changed files with 262 additions and 1 deletions
+1
View File
@@ -652,6 +652,7 @@ if plugins_options['mtk']
if enable_mbim
incs += [fibocom_inc]
sources += files(
'mtk/mm-bearer-mbim-mtk-fibocom.c',
'mtk/mm-broadband-modem-mbim-mtk.c',
'mtk/mm-broadband-modem-mbim-mtk-fibocom.c'
)
@@ -0,0 +1,58 @@
/* -*- 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) 2024 Google, Inc.
*/
#include <config.h>
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-bearer-mbim-mtk-fibocom.h"
G_DEFINE_TYPE (MMBearerMbimMtkFibocom, mm_bearer_mbim_mtk_fibocom, MM_TYPE_BEARER_MBIM)
/*****************************************************************************/
MMBaseBearer *
mm_bearer_mbim_mtk_fibocom_new (MMBroadbandModemMbim *modem,
gboolean is_async_slaac_supported,
MMBearerProperties *config)
{
MMBaseBearer *bearer;
/* 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);
/* Only export valid bearers */
mm_base_bearer_export (bearer);
return bearer;
}
static void
mm_bearer_mbim_mtk_fibocom_init (MMBearerMbimMtkFibocom *self)
{
}
static void
mm_bearer_mbim_mtk_fibocom_class_init (MMBearerMbimMtkFibocomClass *klass)
{
}
@@ -0,0 +1,53 @@
/* -*- 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) 2024 Google, Inc.
*/
#ifndef MM_BEARER_MBIM_MTK_FIBOCOM_H
#define MM_BEARER_MBIM_MTK_FIBOCOM_H
#include <glib.h>
#include <glib-object.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-bearer-mbim.h"
#define MM_TYPE_BEARER_MBIM_MTK_FIBOCOM (mm_bearer_mbim_mtk_fibocom_get_type ())
#define MM_BEARER_MBIM_MTK_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BEARER_MBIM_MTK_FIBOCOM, MMBearerMbimMtkFibocom))
#define MM_BEARER_MBIM_MTK_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BEARER_MBIM_MTK_FIBOCOM, MMBearerMbimMtkFibocomClass))
#define MM_IS_BEARER_MBIM_MTK_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BEARER_MBIM_MTK_FIBOCOM))
#define MM_IS_BEARER_MBIM_MTK_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BEARER_MBIM_MTK_FIBOCOM))
#define MM_BEARER_MBIM_MTK_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BEARER_MBIM_MTK_FIBOCOM, MMBearerMbimMtkFibocomClass))
typedef struct _MMBearerMbimMtkFibocom MMBearerMbimMtkFibocom;
typedef struct _MMBearerMbimMtkFibocomClass MMBearerMbimMtkFibocomClass;
struct _MMBearerMbimMtkFibocom {
MMBearerMbim parent;
};
struct _MMBearerMbimMtkFibocomClass {
MMBearerMbimClass parent;
};
GType mm_bearer_mbim_mtk_fibocom_get_type (void);
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,
MMBearerProperties *config);
#endif /* MM_BEARER_MBIM_MTK_FIBOCOM_H */
@@ -25,16 +25,146 @@
#include "mm-log-object.h"
#include "mm-iface-modem.h"
#include "mm-iface-modem-3gpp.h"
#include "mm-bearer-mbim-mtk-fibocom.h"
#include "mm-broadband-modem-mbim-mtk-fibocom.h"
#include "mm-shared-fibocom.h"
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
static void shared_fibocom_init (MMSharedFibocom *iface);
static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_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_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init))
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init))
struct _MMBroadbandModemMbimMtkFibocomPrivate {
/* Supported features */
gboolean is_async_slaac_supported;
};
/*****************************************************************************/
/* Asynchronous indications of IP configuration updates during the initial
* modem-SLAAC operation with the network are not supported in old firmware
* versions. */
#define ASYNC_SLAAC_SUPPORTED_VERSION 29, 23, 6
static inline gboolean
fm350_check_version (guint A1, guint A2, guint A3,
guint B1, guint B2, guint B3)
{
return ((A1 > B1) || ((A1 == B1) && ((A2 > B2) || ((A2 == B2) && (A3 >= B3)))));
}
static void
process_fm350_version_features (MMBroadbandModemMbimMtkFibocom *self,
const gchar *revision)
{
g_auto(GStrv) split = NULL;
guint major;
guint minor;
guint micro;
/* Expected revision string is a multi-line value like this:
* 81600.0000.00.MM.mm.uu_GC
* F09
* For version comparison we care only about the "MM.mm.uu" part.
*/
split = g_strsplit_set (revision, "._", -1);
if (!split || g_strv_length (split) < 6) {
mm_obj_warn (self, "failed to process FM350 firmware version string");
return;
}
if (!mm_get_uint_from_str (split[3], &major) ||
!mm_get_uint_from_str (split[4], &minor) ||
!mm_get_uint_from_str (split[5], &micro)) {
mm_obj_warn (self, "failed to process FM350 firmware version string: %s.%s.%s",
split[3], split[4], split[5]);
return;
}
/* Check if async SLAAC is supported */
self->priv->is_async_slaac_supported = fm350_check_version (major, minor, micro, ASYNC_SLAAC_SUPPORTED_VERSION);
mm_obj_info (self, "FM350 async SLAAC result indications are %ssupported",
self->priv->is_async_slaac_supported ? "" : "not ");
}
/*****************************************************************************/
/* Revision loading (Modem interface) */
static gchar *
load_revision_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static void
parent_load_revision_ready (MMIfaceModem *self,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
gchar *revision;
revision = iface_modem_parent->load_revision_finish (self, res, &error);
if (!revision) {
g_task_return_error (task, error);
} else {
process_fm350_version_features (MM_BROADBAND_MODEM_MBIM_MTK_FIBOCOM (self), revision);
g_task_return_pointer (task, revision, g_free);
}
g_object_unref (task);
}
static void
load_revision (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_assert (iface_modem_parent->load_revision);
g_assert (iface_modem_parent->load_revision_finish);
iface_modem_parent->load_revision (self,
(GAsyncReadyCallback)parent_load_revision_ready,
g_task_new (self, NULL, callback, user_data));
}
/*****************************************************************************/
/* Create Bearer (Modem interface) */
static MMBaseBearer *
create_bearer_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static void
create_bearer (MMIfaceModem *_self,
MMBearerProperties *properties,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMBroadbandModemMbimMtkFibocom *self = MM_BROADBAND_MODEM_MBIM_MTK_FIBOCOM (_self);
MMBaseBearer *bearer;
GTask *task;
task = g_task_new (self, NULL, callback, user_data);
mm_obj_dbg (self, "creating MTK Fibocom MBIM bearer (async SLAAC %s)",
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,
properties);
g_task_return_pointer (task, bearer, g_object_unref);
g_object_unref (task);
}
/******************************************************************************/
@@ -67,6 +197,20 @@ mm_broadband_modem_mbim_mtk_fibocom_new (const gchar *device,
static void
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);
}
static void
iface_modem_init (MMIfaceModem *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
iface->load_revision = load_revision;
iface->load_revision_finish = load_revision_finish;
iface->create_bearer = create_bearer;
iface->create_bearer_finish = create_bearer_finish;
}
static void
@@ -93,4 +237,7 @@ shared_fibocom_init (MMSharedFibocom *iface)
static void
mm_broadband_modem_mbim_mtk_fibocom_class_init (MMBroadbandModemMbimMtkFibocomClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (object_class, sizeof (MMBroadbandModemMbimMtkFibocomPrivate));
}
@@ -27,9 +27,11 @@
typedef struct _MMBroadbandModemMbimMtkFibocom MMBroadbandModemMbimMtkFibocom;
typedef struct _MMBroadbandModemMbimMtkFibocomClass MMBroadbandModemMbimMtkFibocomClass;
typedef struct _MMBroadbandModemMbimMtkFibocomPrivate MMBroadbandModemMbimMtkFibocomPrivate;
struct _MMBroadbandModemMbimMtkFibocom {
MMBroadbandModemMbimMtk parent;
MMBroadbandModemMbimMtkFibocomPrivate *priv;
};
struct _MMBroadbandModemMbimMtkFibocomClass{