fibocom: setup several +SIM URCs as hotplug event indications

Treat the following URCs as indications of possible SIM hot swap
events:
  +SIM: Inserted
  +SIM: Removed
  +SIM DROP

Any time any of these is received, a SIM hot swap event is reported,
and the logic can then determine what to do. These should lead to
doing nothing if they happen as part of a controlled SIM slot switch.

Signed-off-by: Aleksander Morgado <aleksandermj@google.com>
This commit is contained in:
Aleksander Morgado
2025-06-18 22:10:54 +00:00
parent 7d4784ed28
commit a24b60e52e
6 changed files with 152 additions and 6 deletions
@@ -27,6 +27,7 @@ static void iface_modem_init (MMIfaceModemInterface *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface);
static void shared_fibocom_init (MMSharedFibocomInterface *iface);
static MMIfaceModemInterface *iface_modem_parent;
static MMIfaceModemFirmwareInterface *iface_modem_firmware_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemFibocom, mm_broadband_modem_fibocom, MM_TYPE_BROADBAND_MODEM, 0,
@@ -254,6 +255,10 @@ mm_broadband_modem_fibocom_init (MMBroadbandModemFibocom *self)
static void
iface_modem_init (MMIfaceModemInterface *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
iface->setup_sim_hot_swap = mm_shared_fibocom_setup_sim_hot_swap;
iface->setup_sim_hot_swap_finish = mm_shared_fibocom_setup_sim_hot_swap_finish;
iface->create_bearer = modem_create_bearer;
iface->create_bearer_finish = modem_create_bearer_finish;
iface->reset = modem_reset;
@@ -273,6 +278,12 @@ iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface)
iface->load_update_settings_finish = mm_shared_fibocom_firmware_load_update_settings_finish;
}
static MMIfaceModemInterface *
peek_parent_modem_interface (MMSharedFibocom *self)
{
return iface_modem_parent;
}
static MMIfaceModemFirmwareInterface *
peek_parent_firmware_interface (MMSharedFibocom *self)
{
@@ -288,8 +299,9 @@ peek_parent_class (MMSharedFibocom *self)
static void
shared_fibocom_init (MMSharedFibocomInterface *iface)
{
iface->peek_parent_class = peek_parent_class;
iface->peek_parent_modem_interface = peek_parent_modem_interface;
iface->peek_parent_firmware_interface = peek_parent_firmware_interface;
iface->peek_parent_class = peek_parent_class;
}
static void
@@ -27,12 +27,15 @@
#include "mm-broadband-modem-mbim-fibocom.h"
#include "mm-shared-fibocom.h"
static void shared_fibocom_init (MMSharedFibocomInterface *iface);
static void iface_modem_init (MMIfaceModemInterface *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface);
static void shared_fibocom_init (MMSharedFibocomInterface *iface);
static MMIfaceModemInterface *iface_modem_parent;
static MMIfaceModemFirmwareInterface *iface_modem_firmware_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimFibocom, mm_broadband_modem_mbim_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM, 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_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init))
@@ -66,6 +69,15 @@ mm_broadband_modem_mbim_fibocom_init (MMBroadbandModemMbimFibocom *self)
{
}
static void
iface_modem_init (MMIfaceModemInterface *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
iface->setup_sim_hot_swap = mm_shared_fibocom_setup_sim_hot_swap;
iface->setup_sim_hot_swap_finish = mm_shared_fibocom_setup_sim_hot_swap_finish;
}
static void
iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface)
{
@@ -75,6 +87,12 @@ iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface)
iface->load_update_settings_finish = mm_shared_fibocom_firmware_load_update_settings_finish;
}
static MMIfaceModemInterface *
peek_parent_modem_interface (MMSharedFibocom *self)
{
return iface_modem_parent;
}
static MMIfaceModemFirmwareInterface *
peek_parent_firmware_interface (MMSharedFibocom *self)
{
@@ -90,8 +108,9 @@ peek_parent_class (MMSharedFibocom *self)
static void
shared_fibocom_init (MMSharedFibocomInterface *iface)
{
iface->peek_parent_class = peek_parent_class;
iface->peek_parent_modem_interface = peek_parent_modem_interface;
iface->peek_parent_firmware_interface = peek_parent_firmware_interface;
iface->peek_parent_class = peek_parent_class;
}
static void
@@ -31,7 +31,7 @@ static void iface_modem_init (MMIfaceModemInterface *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface);
static void shared_fibocom_init (MMSharedFibocomInterface *iface);
static MMIfaceModemInterface *iface_modem_parent;
static MMIfaceModemInterface *iface_modem_parent;
static MMIfaceModemFirmwareInterface *iface_modem_firmware_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimXmmFibocom, mm_broadband_modem_mbim_xmm_fibocom, MM_TYPE_BROADBAND_MODEM_MBIM_XMM, 0,
@@ -212,6 +212,7 @@ static void
iface_modem_init (MMIfaceModemInterface *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
iface->load_revision = load_revision;
iface->load_revision_finish = load_revision_finish;
}
@@ -225,6 +226,12 @@ iface_modem_firmware_init (MMIfaceModemFirmwareInterface *iface)
iface->load_update_settings_finish = mm_shared_fibocom_firmware_load_update_settings_finish;
}
static MMIfaceModemInterface *
peek_parent_modem_interface (MMSharedFibocom *self)
{
return iface_modem_parent;
}
static MMIfaceModemFirmwareInterface *
peek_parent_firmware_interface (MMSharedFibocom *self)
{
@@ -240,8 +247,9 @@ peek_parent_class (MMSharedFibocom *self)
static void
shared_fibocom_init (MMSharedFibocomInterface *iface)
{
iface->peek_parent_class = peek_parent_class;
iface->peek_parent_modem_interface = peek_parent_modem_interface;
iface->peek_parent_firmware_interface = peek_parent_firmware_interface;
iface->peek_parent_class = peek_parent_class;
}
static void
+96
View File
@@ -42,6 +42,8 @@ static GQuark private_quark;
typedef struct {
/* Parent class */
MMBaseModemClass *class_parent;
/* Modem interface of parent class */
MMIfaceModemInterface *iface_modem_parent;
/* Firmware interface of parent class */
MMIfaceModemFirmwareInterface *iface_modem_firmware_parent;
/* URCs to ignore */
@@ -74,6 +76,10 @@ get_private (MMSharedFibocom *self)
g_assert (MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_class);
priv->class_parent = MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_class (self);
/* Setup modem interface of parent class */
if (MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_modem_interface)
priv->iface_modem_parent = MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_modem_interface (self);
/* Setup firmware interface of parent class */
if (MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_firmware_interface)
priv->iface_modem_firmware_parent = MM_SHARED_FIBOCOM_GET_IFACE (self)->peek_parent_firmware_interface (self);
@@ -86,6 +92,96 @@ get_private (MMSharedFibocom *self)
/*****************************************************************************/
static void
sim_hotswap_unsolicited_handler (MMPortSerialAt *port,
GMatchInfo *match_info,
MMIfaceModem *self)
{
mm_obj_dbg (self, "processing +SIM URC reporting a SIM hotswap event");
mm_iface_modem_process_sim_event (MM_IFACE_MODEM (self));
}
/*****************************************************************************/
/* Setup SIM hot swap context (Modem interface) */
gboolean
mm_shared_fibocom_setup_sim_hot_swap_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
parent_setup_sim_hot_swap_ready (MMIfaceModem *self,
GAsyncResult *res,
GTask *task)
{
Private *priv;
g_autoptr(GError) error = NULL;
priv = get_private (MM_SHARED_FIBOCOM (self));
if (!priv->iface_modem_parent->setup_sim_hot_swap_finish (self, res, &error))
mm_obj_dbg (self, "additional SIM hot swap detection setup failed: %s", error->message);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
void
mm_shared_fibocom_setup_sim_hot_swap (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
Private *priv;
MMPortSerialAt *ports[2];
GTask *task;
guint i;
g_autoptr(GRegex) pattern = NULL;
g_autoptr(GError) error = NULL;
priv = get_private (MM_SHARED_FIBOCOM (self));
task = g_task_new (self, NULL, callback, user_data);
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
pattern = g_regex_new ("(\\+SIM: Inserted)|(\\+SIM: Removed)|(\\+SIM DROP)\\r\\n", G_REGEX_RAW, 0, NULL);
g_assert (pattern);
for (i = 0; i < G_N_ELEMENTS (ports); i++) {
if (ports[i])
mm_port_serial_at_add_unsolicited_msg_handler (
ports[i],
pattern,
(MMPortSerialAtUnsolicitedMsgFn)sim_hotswap_unsolicited_handler,
self,
NULL);
}
mm_obj_dbg (self, "+SIM based hotswap detection set up");
if (!mm_broadband_modem_sim_hot_swap_ports_context_init (MM_BROADBAND_MODEM (self), &error))
mm_obj_warn (self, "failed to initialize SIM hot swap ports context: %s", error->message);
/* Now, if available, setup parent logic */
if (priv->iface_modem_parent->setup_sim_hot_swap &&
priv->iface_modem_parent->setup_sim_hot_swap_finish) {
priv->iface_modem_parent->setup_sim_hot_swap (self,
(GAsyncReadyCallback) parent_setup_sim_hot_swap_ready,
task);
return;
}
/* Otherwise, we're done */
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
/*****************************************************************************/
#if defined WITH_MBIM
MMPort *
+10
View File
@@ -37,6 +37,9 @@ struct _MMSharedFibocomInterface {
/* Peek parent class of the object */
MMBaseModemClass * (* peek_parent_class) (MMSharedFibocom *self);
/* Peek modem interface of the parent class of the object */
MMIfaceModemInterface * (* peek_parent_modem_interface) (MMSharedFibocom *self);
/* Peek firmware interface of the parent class of the object */
MMIfaceModemFirmwareInterface * (* peek_parent_firmware_interface) (MMSharedFibocom *self);
};
@@ -61,4 +64,11 @@ MMFirmwareUpdateSettings *mm_shared_fibocom_firmware_load_update_settings_finish
GAsyncResult *res,
GError **error);
void mm_shared_fibocom_setup_sim_hot_swap (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean mm_shared_fibocom_setup_sim_hot_swap_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error);
#endif /* MM_SHARED_FIBOCOM_H */
@@ -426,7 +426,6 @@ iface_modem_init (MMIfaceModemInterface *iface)
iface->create_bearer_list = create_bearer_list;
iface->load_unlock_retries = mm_shared_mtk_load_unlock_retries;
iface->load_unlock_retries_finish = mm_shared_mtk_load_unlock_retries_finish;
}
static void
@@ -444,6 +443,8 @@ peek_parent_class (MMSharedFibocom *self)
return MM_BASE_MODEM_CLASS (mm_broadband_modem_mbim_mtk_fibocom_parent_class);
}
/* Note: shared fibocom is only used to create usbmisc/wwan ports, so there is no need
* to initialize the parent modem/firmware interface objects. */
static void
shared_fibocom_init (MMSharedFibocomInterface *iface)
{