altair-lte: add SIMREFRESH support
Register for SIMREFRESH event and reload own numbers and reregister modem with network when this happens.
This commit is contained in:

committed by
Aleksander Morgado

parent
5e7fee1d11
commit
c21709b32e
@@ -53,6 +53,12 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemAltairLte, mm_broadband_modem_altair_lte
|
|||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init));
|
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init));
|
||||||
|
|
||||||
struct _MMBroadbandModemAltairLtePrivate {
|
struct _MMBroadbandModemAltairLtePrivate {
|
||||||
|
/* Regex for SIM refresh notifications */
|
||||||
|
GRegex *sim_refresh_regex;
|
||||||
|
/* Timer that goes off 10s after the last SIM refresh notification.
|
||||||
|
* This indicates that there are no more SIM refreshes and we should
|
||||||
|
* reregister the device.*/
|
||||||
|
guint sim_refresh_timer_id;
|
||||||
/* Regex for bearer related notifications */
|
/* Regex for bearer related notifications */
|
||||||
GRegex *statcm_regex;
|
GRegex *statcm_regex;
|
||||||
};
|
};
|
||||||
@@ -634,7 +640,101 @@ modem_3gpp_register_in_network_finish (MMIfaceModem3gpp *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Setup/Cleanup unsolicited events (3GPP interface) */
|
/* SIMREFRESH unsolicited event handler */
|
||||||
|
|
||||||
|
static void
|
||||||
|
altair_reregister_ready (MMBaseModem *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (!mm_base_modem_at_command_finish (self, res, NULL)) {
|
||||||
|
mm_dbg ("Failed to reregister modem");
|
||||||
|
} else {
|
||||||
|
mm_dbg ("Modem reregistered successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
altair_deregister_ready (MMBaseModem *self,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (!mm_base_modem_at_command_finish (self, res, NULL)) {
|
||||||
|
mm_dbg ("Deregister modem failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm_dbg ("Deregistered modem, now reregistering");
|
||||||
|
|
||||||
|
/* Register */
|
||||||
|
mm_base_modem_at_command (
|
||||||
|
MM_BASE_MODEM (self),
|
||||||
|
"%CMATT=1",
|
||||||
|
10,
|
||||||
|
FALSE, /* allow_cached */
|
||||||
|
(GAsyncReadyCallback)altair_reregister_ready,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
altair_load_own_numbers_ready (MMIfaceModem *iface_modem,
|
||||||
|
GAsyncResult *res,
|
||||||
|
MMBroadbandModemAltairLte *self)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GStrv str_list;
|
||||||
|
|
||||||
|
str_list = MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers_finish (MM_IFACE_MODEM (self), res, &error);
|
||||||
|
if (error) {
|
||||||
|
mm_warn ("Couldn't reload Own Numbers: '%s'", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
if (str_list) {
|
||||||
|
mm_iface_modem_update_own_numbers (iface_modem, str_list);
|
||||||
|
g_strfreev (str_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deregister */
|
||||||
|
mm_dbg ("Reregistering modem");
|
||||||
|
mm_base_modem_at_command (
|
||||||
|
MM_BASE_MODEM (self),
|
||||||
|
"%CMATT=0",
|
||||||
|
10,
|
||||||
|
FALSE, /* allow_cached */
|
||||||
|
(GAsyncReadyCallback)altair_deregister_ready,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
altair_sim_refresh_timer_expired (MMBroadbandModemAltairLte *self)
|
||||||
|
{
|
||||||
|
mm_dbg ("No more SIM refreshes, reloading Own Numbers and reregistering modem");
|
||||||
|
|
||||||
|
g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers);
|
||||||
|
g_assert (MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers_finish);
|
||||||
|
MM_IFACE_MODEM_GET_INTERFACE (self)->load_own_numbers (
|
||||||
|
MM_IFACE_MODEM (self),
|
||||||
|
(GAsyncReadyCallback)altair_load_own_numbers_ready,
|
||||||
|
self);
|
||||||
|
|
||||||
|
self->priv->sim_refresh_timer_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
altair_sim_refresh_changed (MMAtSerialPort *port,
|
||||||
|
GMatchInfo *match_info,
|
||||||
|
MMBroadbandModemAltairLte *self)
|
||||||
|
{
|
||||||
|
mm_dbg ("Received SIM refresh notification");
|
||||||
|
if (self->priv->sim_refresh_timer_id) {
|
||||||
|
g_source_remove (self->priv->sim_refresh_timer_id);
|
||||||
|
}
|
||||||
|
self->priv->sim_refresh_timer_id =
|
||||||
|
g_timeout_add_seconds(10,
|
||||||
|
(GSourceFunc)altair_sim_refresh_timer_expired,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MM_STATCM_ALTAIR_LTE_DEREGISTERED = 0,
|
MM_STATCM_ALTAIR_LTE_DEREGISTERED = 0,
|
||||||
@@ -651,6 +751,9 @@ bearer_list_report_disconnect_status_foreach (MMBearer *bearer,
|
|||||||
MM_BEARER_CONNECTION_STATUS_DISCONNECTED);
|
MM_BEARER_CONNECTION_STATUS_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* STATCM unsolicited event handler */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
altair_statcm_changed (MMAtSerialPort *port,
|
altair_statcm_changed (MMAtSerialPort *port,
|
||||||
GMatchInfo *match_info,
|
GMatchInfo *match_info,
|
||||||
@@ -682,6 +785,9 @@ altair_statcm_changed (MMAtSerialPort *port,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Setup/Cleanup unsolicited events (3GPP interface) */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
|
set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
|
||||||
gboolean enable)
|
gboolean enable)
|
||||||
@@ -697,6 +803,14 @@ set_3gpp_unsolicited_events_handlers (MMBroadbandModemAltairLte *self,
|
|||||||
if (!ports[i])
|
if (!ports[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* SIM refresh handler */
|
||||||
|
mm_at_serial_port_add_unsolicited_msg_handler (
|
||||||
|
ports[i],
|
||||||
|
self->priv->sim_refresh_regex,
|
||||||
|
enable ? (MMAtSerialUnsolicitedMsgFn)altair_sim_refresh_changed : NULL,
|
||||||
|
enable ? self : NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* bearer mode related */
|
/* bearer mode related */
|
||||||
mm_at_serial_port_add_unsolicited_msg_handler (
|
mm_at_serial_port_add_unsolicited_msg_handler (
|
||||||
ports[i],
|
ports[i],
|
||||||
@@ -793,6 +907,31 @@ modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self,
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Enabling unsolicited events (3GPP interface) */
|
/* Enabling unsolicited events (3GPP interface) */
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
response_processor_no_result_stop_on_error (MMBaseModem *self,
|
||||||
|
gpointer none,
|
||||||
|
const gchar *command,
|
||||||
|
const gchar *response,
|
||||||
|
gboolean last_command,
|
||||||
|
const GError *error,
|
||||||
|
GVariant **result,
|
||||||
|
GError **result_error)
|
||||||
|
{
|
||||||
|
if (error) {
|
||||||
|
*result_error = g_error_copy (error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MMBaseModemAtCommand unsolicited_events_enable_sequence[] = {
|
||||||
|
{ "%STATCM=1", 10, FALSE, response_processor_no_result_stop_on_error },
|
||||||
|
{ "%NOTIFYEV=\"SIMREFRESH\",1", 10, FALSE, NULL },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self,
|
modem_3gpp_enable_unsolicited_events_finish (MMIfaceModem3gpp *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -808,7 +947,7 @@ own_enable_unsolicited_events_ready (MMBaseModem *self,
|
|||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
mm_base_modem_at_command_full_finish (self, res, &error);
|
mm_base_modem_at_sequence_finish (self, res, NULL, &error);
|
||||||
if (error)
|
if (error)
|
||||||
g_simple_async_result_take_error (simple, error);
|
g_simple_async_result_take_error (simple, error);
|
||||||
else
|
else
|
||||||
@@ -832,14 +971,11 @@ parent_enable_unsolicited_events_ready (MMIfaceModem3gpp *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Our own enable now */
|
/* Our own enable now */
|
||||||
mm_base_modem_at_command_full (
|
mm_base_modem_at_sequence (
|
||||||
MM_BASE_MODEM (self),
|
MM_BASE_MODEM (self),
|
||||||
mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
|
unsolicited_events_enable_sequence,
|
||||||
"%STATCM=1",
|
NULL, /* response_processor_context */
|
||||||
10,
|
NULL, /* response_processor_context_free */
|
||||||
FALSE, /* allow_cached */
|
|
||||||
FALSE, /* raw */
|
|
||||||
NULL, /* cancellable */
|
|
||||||
(GAsyncReadyCallback)own_enable_unsolicited_events_ready,
|
(GAsyncReadyCallback)own_enable_unsolicited_events_ready,
|
||||||
simple);
|
simple);
|
||||||
}
|
}
|
||||||
@@ -866,6 +1002,12 @@ modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *self,
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Disabling unsolicited events (3GPP interface) */
|
/* Disabling unsolicited events (3GPP interface) */
|
||||||
|
|
||||||
|
static const MMBaseModemAtCommand unsolicited_events_disable_sequence[] = {
|
||||||
|
{ "%STATCM=0", 10, FALSE, NULL },
|
||||||
|
{ "%NOTIFYEV=\"SIMREFRESH\",0", 10, FALSE, NULL },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self,
|
modem_3gpp_disable_unsolicited_events_finish (MMIfaceModem3gpp *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -896,7 +1038,7 @@ own_disable_unsolicited_events_ready (MMBaseModem *self,
|
|||||||
{
|
{
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
mm_base_modem_at_command_full_finish (self, res, &error);
|
mm_base_modem_at_sequence_finish (self, res, NULL, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
g_simple_async_result_take_error (simple, error);
|
g_simple_async_result_take_error (simple, error);
|
||||||
g_simple_async_result_complete (simple);
|
g_simple_async_result_complete (simple);
|
||||||
@@ -924,14 +1066,11 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *self,
|
|||||||
modem_3gpp_disable_unsolicited_events);
|
modem_3gpp_disable_unsolicited_events);
|
||||||
|
|
||||||
/* Our own disable first */
|
/* Our own disable first */
|
||||||
mm_base_modem_at_command_full (
|
mm_base_modem_at_sequence (
|
||||||
MM_BASE_MODEM (self),
|
MM_BASE_MODEM (self),
|
||||||
mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)),
|
unsolicited_events_disable_sequence,
|
||||||
"%STATCM=0",
|
NULL, /* response_processor_context */
|
||||||
10,
|
NULL, /* response_processor_context_free */
|
||||||
FALSE, /* allow_cached */
|
|
||||||
FALSE, /* raw */
|
|
||||||
NULL, /* cancellable */
|
|
||||||
(GAsyncReadyCallback)own_disable_unsolicited_events_ready,
|
(GAsyncReadyCallback)own_disable_unsolicited_events_ready,
|
||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
@@ -1086,10 +1225,25 @@ mm_broadband_modem_altair_lte_init (MMBroadbandModemAltairLte *self)
|
|||||||
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE,
|
MM_TYPE_BROADBAND_MODEM_ALTAIR_LTE,
|
||||||
MMBroadbandModemAltairLtePrivate);
|
MMBroadbandModemAltairLtePrivate);
|
||||||
|
|
||||||
|
self->priv->sim_refresh_regex = g_regex_new ("\\r\\n\\%NOTIFYEV:\\s*SIMREFRESH,?(\\d*)\\r+\\n",
|
||||||
|
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||||
|
self->priv->sim_refresh_timer_id = 0;
|
||||||
self->priv->statcm_regex = g_regex_new ("\\r\\n\\%STATCM:\\s*(\\d*),?(\\d*)\\r+\\n",
|
self->priv->statcm_regex = g_regex_new ("\\r\\n\\%STATCM:\\s*(\\d*),?(\\d*)\\r+\\n",
|
||||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finalize (GObject *object)
|
||||||
|
{
|
||||||
|
MMBroadbandModemAltairLte *self = MM_BROADBAND_MODEM_ALTAIR_LTE (object);
|
||||||
|
|
||||||
|
if (self->priv->sim_refresh_timer_id)
|
||||||
|
g_source_remove (self->priv->sim_refresh_timer_id);
|
||||||
|
g_regex_unref (self->priv->sim_refresh_regex);
|
||||||
|
g_regex_unref (self->priv->statcm_regex);
|
||||||
|
G_OBJECT_CLASS (mm_broadband_modem_altair_lte_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iface_modem_init (MMIfaceModem *iface)
|
iface_modem_init (MMIfaceModem *iface)
|
||||||
{
|
{
|
||||||
@@ -1174,6 +1328,7 @@ mm_broadband_modem_altair_lte_class_init (MMBroadbandModemAltairLteClass *klass)
|
|||||||
|
|
||||||
g_type_class_add_private (object_class, sizeof (MMBroadbandModemAltairLtePrivate));
|
g_type_class_add_private (object_class, sizeof (MMBroadbandModemAltairLtePrivate));
|
||||||
|
|
||||||
|
object_class->finalize = finalize;
|
||||||
broadband_modem_class->setup_ports = setup_ports;
|
broadband_modem_class->setup_ports = setup_ports;
|
||||||
|
|
||||||
/* The Altair LTE modem reboots itself upon receiving an ATZ command. We
|
/* The Altair LTE modem reboots itself upon receiving an ATZ command. We
|
||||||
|
@@ -3965,6 +3965,21 @@ sim_reinit_ready (MMSim *sim,
|
|||||||
interface_initialization_step (ctx);
|
interface_initialization_step (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mm_iface_modem_update_own_numbers (MMIfaceModem *self,
|
||||||
|
const GStrv own_numbers)
|
||||||
|
{
|
||||||
|
MmGdbusModem *skeleton = NULL;
|
||||||
|
|
||||||
|
g_object_get (self,
|
||||||
|
MM_IFACE_MODEM_DBUS_SKELETON, &skeleton,
|
||||||
|
NULL);
|
||||||
|
if (skeleton) {
|
||||||
|
mm_gdbus_modem_set_own_numbers (skeleton, (const gchar * const *)own_numbers);
|
||||||
|
g_object_unref (skeleton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_own_numbers_ready (MMIfaceModem *self,
|
load_own_numbers_ready (MMIfaceModem *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
|
@@ -419,6 +419,10 @@ void mm_iface_modem_update_state (MMIfaceModem *self,
|
|||||||
void mm_iface_modem_update_failed_state (MMIfaceModem *self,
|
void mm_iface_modem_update_failed_state (MMIfaceModem *self,
|
||||||
MMModemStateFailedReason failed_reason);
|
MMModemStateFailedReason failed_reason);
|
||||||
|
|
||||||
|
/* Allow update own numbers */
|
||||||
|
void mm_iface_modem_update_own_numbers (MMIfaceModem *self,
|
||||||
|
const GStrv own_numbers);
|
||||||
|
|
||||||
/* Allow reporting new access tech */
|
/* Allow reporting new access tech */
|
||||||
void mm_iface_modem_update_access_technologies (MMIfaceModem *self,
|
void mm_iface_modem_update_access_technologies (MMIfaceModem *self,
|
||||||
MMModemAccessTechnology access_tech,
|
MMModemAccessTechnology access_tech,
|
||||||
|
Reference in New Issue
Block a user