diff options
author | Jack Song <jinjian.song@fibocom.com> | 2022-02-09 11:23:22 +0800 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2022-02-16 13:04:45 +0000 |
commit | d902ddfee5b4477232a1bd25028475700e4a1995 (patch) | |
tree | f1fac2c83296e4a5a3e0ba3e1b438c1a7e660c62 | |
parent | 45102fcd60b24770f41466b2f88d0ec7e487a09e (diff) |
fibocom: toggle modem power after attach APN
When the attach APN settings are changed, the device will go through a
radio on -> radio off -> radio on cycle so that the new changes are
taken into consideration.
This change is done in a Fibocom-specific MBIM modem implementation
because it's working around a firmware bug that would prevent for the
attach settings to be considered automatically.
-rw-r--r-- | plugins/Makefile.am | 6 | ||||
-rwxr-xr-x | plugins/fibocom/77-mm-fibocom-port-types.rules | 3 | ||||
-rwxr-xr-x | plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c | 177 | ||||
-rwxr-xr-x | plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h | 47 | ||||
-rw-r--r-- | plugins/fibocom/mm-plugin-fibocom.c | 26 | ||||
-rw-r--r-- | plugins/meson.build | 4 |
6 files changed, 262 insertions, 1 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index b12b559d..93a9ce26 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -697,6 +697,12 @@ libmm_plugin_fibocom_la_SOURCES = \ fibocom/mm-plugin-fibocom.c \ fibocom/mm-plugin-fibocom.h \ $(NULL) +if WITH_MBIM +libmm_plugin_fibocom_la_SOURCES += \ + fibocom/mm-broadband-modem-mbim-xmm-fibocom.c \ + fibocom/mm-broadband-modem-mbim-xmm-fibocom.h \ + $(NULL) +endif libmm_plugin_fibocom_la_CPPFLAGS = \ $(PLUGIN_COMMON_COMPILER_FLAGS) \ $(XMM_COMMON_COMPILER_FLAGS) \ diff --git a/plugins/fibocom/77-mm-fibocom-port-types.rules b/plugins/fibocom/77-mm-fibocom-port-types.rules index b97ba3b4..544dc256 100755 --- a/plugins/fibocom/77-mm-fibocom-port-types.rules +++ b/plugins/fibocom/77-mm-fibocom-port-types.rules @@ -8,6 +8,9 @@ LABEL="mm_fibocom_port_types" SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" +# Fibocom L850-GL attach APN with toggle modem power +ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1" + # Fibocom L850-GL # ttyACM0 (if #2): AT port # ttyACM1 (if #4): debug port (ignore) diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c new file mode 100755 index 00000000..d1f2e069 --- /dev/null +++ b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.c @@ -0,0 +1,177 @@ +/* -*- 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) 2022 Fibocom Wireless Inc. + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "ModemManager.h" +#include "mm-log-object.h" +#include "mm-iface-modem.h" +#include "mm-iface-modem-3gpp.h" +#include "mm-broadband-modem-mbim-xmm-fibocom.h" + +static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); + +static MMIfaceModem3gpp *iface_modem_3gpp_parent; + +G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmmFibocom, mm_broadband_modem_mbim_xmm_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM_XMM, 0, + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)) + +/*****************************************************************************/ + +static gboolean +modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +after_attach_apn_modem_power_up_ready (MMIfaceModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_iface_modem_set_power_state_finish (self, res, &error)) { + mm_obj_warn (self, "failed to power up modem after attach APN settings update: %s", error->message); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mm_obj_dbg (self, "success toggling modem power up after attach APN"); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +parent_set_initial_eps_bearer_settings_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish (self, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mm_obj_dbg (self, "toggle modem power up after attach APN"); + mm_iface_modem_set_power_state (MM_IFACE_MODEM (self), + MM_MODEM_POWER_STATE_ON, + (GAsyncReadyCallback) after_attach_apn_modem_power_up_ready, + task); +} + +static void +before_attach_apn_modem_power_down_ready (MMIfaceModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + MMBearerProperties *config; + + config = g_task_get_task_data (task); + + if (!mm_iface_modem_set_power_state_finish (self, res, &error)) { + mm_obj_warn (self, "failed to power down modem before attach APN settings update: %s", error->message); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + mm_obj_dbg (self, "success toggling modem power down before attach APN"); + if (iface_modem_3gpp_parent->set_initial_eps_bearer_settings && + iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish) { + iface_modem_3gpp_parent->set_initial_eps_bearer_settings (MM_IFACE_MODEM_3GPP (self), + config, + (GAsyncReadyCallback)parent_set_initial_eps_bearer_settings_ready, + task); + return; + } +} + +static void +modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self, + MMBearerProperties *config, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, g_object_ref (config), g_object_unref); + + mm_obj_dbg (self, "toggle modem power down before attach APN"); + mm_iface_modem_set_power_state (MM_IFACE_MODEM (self), + MM_MODEM_POWER_STATE_LOW, + (GAsyncReadyCallback) before_attach_apn_modem_power_down_ready, + task); +} + +/******************************************************************************/ + +MMBroadbandModemMbimXmmFibocom * +mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device, + const gchar **drivers, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id) +{ + return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, + MM_BASE_MODEM_DEVICE, device, + MM_BASE_MODEM_DRIVERS, drivers, + MM_BASE_MODEM_PLUGIN, plugin, + MM_BASE_MODEM_VENDOR_ID, vendor_id, + MM_BASE_MODEM_PRODUCT_ID, product_id, + /* MBIM bearer supports NET only */ + MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, + MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, + MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, + MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED, FALSE, + MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + MM_BROADBAND_MODEM_MBIM_QMI_UNSUPPORTED, TRUE, +#endif + NULL); +} + +static void +mm_broadband_modem_mbim_xmm_fibocom_init (MMBroadbandModemMbimXmmFibocom *self) +{ +} + +static void +iface_modem_3gpp_init (MMIfaceModem3gpp *iface) +{ + iface_modem_3gpp_parent = g_type_interface_peek_parent (iface); + + iface->set_initial_eps_bearer_settings = modem_3gpp_set_initial_eps_bearer_settings; + iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish; +} + +static void +mm_broadband_modem_mbim_xmm_fibocom_class_init (MMBroadbandModemMbimXmmFibocomClass *klass) +{ +} diff --git a/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h new file mode 100755 index 00000000..db51cfc8 --- /dev/null +++ b/plugins/fibocom/mm-broadband-modem-mbim-xmm-fibocom.h @@ -0,0 +1,47 @@ +/* -*- 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) 2022 Fibocom Wireless Inc. + */ + +#ifndef MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H +#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H + +#include "mm-broadband-modem-mbim-xmm.h" + +#define MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM (mm_broadband_modem_mbim_xmm_fibocom_get_type ()) +#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocom)) +#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass)) +#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM)) +#define MM_IS_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM)) +#define MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_XMM_FIBOCOM, MMBroadbandModemMbimXmmFibocomClass)) + +typedef struct _MMBroadbandModemMbimXmmFibocom MMBroadbandModemMbimXmmFibocom; +typedef struct _MMBroadbandModemMbimXmmFibocomClass MMBroadbandModemMbimXmmFibocomClass; + +struct _MMBroadbandModemMbimXmmFibocom { + MMBroadbandModemMbimXmm parent; +}; + +struct _MMBroadbandModemMbimXmmFibocomClass{ + MMBroadbandModemMbimXmmClass parent; +}; + +GType mm_broadband_modem_mbim_xmm_fibocom_get_type (void); + +MMBroadbandModemMbimXmmFibocom *mm_broadband_modem_mbim_xmm_fibocom_new (const gchar *device, + const gchar **drivers, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id); + +#endif /* MM_BROADBAND_MODEM_MBIM_XMM_FIBOCOM_H */ diff --git a/plugins/fibocom/mm-plugin-fibocom.c b/plugins/fibocom/mm-plugin-fibocom.c index 74f25c55..a8370848 100644 --- a/plugins/fibocom/mm-plugin-fibocom.c +++ b/plugins/fibocom/mm-plugin-fibocom.c @@ -28,6 +28,7 @@ #if defined WITH_MBIM #include "mm-broadband-modem-mbim.h" #include "mm-broadband-modem-mbim-xmm.h" +#include "mm-broadband-modem-mbim-xmm-fibocom.h" #endif #if defined WITH_QMI @@ -41,6 +42,22 @@ MM_PLUGIN_DEFINE_MINOR_VERSION /*****************************************************************************/ +#if defined WITH_MBIM +static gboolean +mm_port_probe_list_has_initial_eps_off_on_tag (GList *probes) +{ + GList *l; + + for (l = probes; l; l = g_list_next (l)) { + if (mm_kernel_device_get_global_property_as_boolean (mm_port_probe_peek_port (MM_PORT_PROBE (l->data)), + "ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON")) + return TRUE; + } + + return FALSE; +} +#endif + static MMBaseModem * create_modem (MMPlugin *self, const gchar *uid, @@ -54,6 +71,15 @@ create_modem (MMPlugin *self, if (mm_port_probe_list_has_mbim_port (probes)) { if (mm_port_probe_list_is_xmm (probes)) { mm_obj_dbg (self, "MBIM-powered XMM-based Fibocom modem found..."); + if (mm_port_probe_list_has_initial_eps_off_on_tag (probes)) { + mm_obj_dbg (self, "initial eps need to toggle modem power"); + return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_fibocom_new (uid, + drivers, + mm_plugin_get_name (self), + vendor, + product)); + } + return MM_BASE_MODEM (mm_broadband_modem_mbim_xmm_new (uid, drivers, mm_plugin_get_name (self), diff --git a/plugins/meson.build b/plugins/meson.build index 27df5ead..6bcb3649 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -342,7 +342,9 @@ if plugins_options['fibocom'] 'fibocom/mm-broadband-modem-fibocom.c', 'fibocom/mm-plugin-fibocom.c', ) - + if enable_mbim + sources += files('fibocom/mm-broadband-modem-mbim-xmm-fibocom.c') + endif plugins += {'plugin-fibocom': { 'plugin': true, 'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc], 'c_args': c_args}, |