cinterion: setup/cleanup time unsolicited events
We will parse +CTZU URCs, which end up getting in the way of other commands if we don't process them. Fixes https://gitlab.freedesktop.org/mobile-broadband/ModemManager/issues/135
This commit is contained in:
@@ -46,12 +46,14 @@ static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
|
||||
static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
|
||||
static void iface_modem_location_init (MMIfaceModemLocation *iface);
|
||||
static void iface_modem_voice_init (MMIfaceModemVoice *iface);
|
||||
static void iface_modem_time_init (MMIfaceModemTime *iface);
|
||||
static void shared_cinterion_init (MMSharedCinterion *iface);
|
||||
|
||||
static MMIfaceModem *iface_modem_parent;
|
||||
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
|
||||
static MMIfaceModemLocation *iface_modem_location_parent;
|
||||
static MMIfaceModemVoice *iface_modem_voice_parent;
|
||||
static MMIfaceModemTime *iface_modem_time_parent;
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemCinterion, mm_broadband_modem_cinterion, MM_TYPE_BROADBAND_MODEM, 0,
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
|
||||
@@ -59,6 +61,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemCinterion, mm_broadband_modem_cinterion,
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init))
|
||||
|
||||
typedef enum {
|
||||
@@ -1985,11 +1988,29 @@ peek_parent_voice_interface (MMSharedCinterion *self)
|
||||
return iface_modem_voice_parent;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_modem_time_init (MMIfaceModemTime *iface)
|
||||
{
|
||||
iface_modem_time_parent = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->setup_unsolicited_events = mm_shared_cinterion_time_setup_unsolicited_events;
|
||||
iface->setup_unsolicited_events_finish = mm_shared_cinterion_time_setup_unsolicited_events_finish;
|
||||
iface->cleanup_unsolicited_events = mm_shared_cinterion_time_cleanup_unsolicited_events;
|
||||
iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_time_cleanup_unsolicited_events_finish;
|
||||
}
|
||||
|
||||
static MMIfaceModemTime *
|
||||
peek_parent_time_interface (MMSharedCinterion *self)
|
||||
{
|
||||
return iface_modem_time_parent;
|
||||
}
|
||||
|
||||
static void
|
||||
shared_cinterion_init (MMSharedCinterion *iface)
|
||||
{
|
||||
iface->peek_parent_location_interface = peek_parent_location_interface;
|
||||
iface->peek_parent_voice_interface = peek_parent_voice_interface;
|
||||
iface->peek_parent_time_interface = peek_parent_time_interface;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -31,15 +31,18 @@
|
||||
#include "mm-shared-cinterion.h"
|
||||
|
||||
static void iface_modem_location_init (MMIfaceModemLocation *iface);
|
||||
static void iface_modem_voice_init (MMIfaceModemVoice *iface);
|
||||
static void iface_modem_voice_init (MMIfaceModemVoice *iface);
|
||||
static void iface_modem_time_init (MMIfaceModemTime *iface);
|
||||
static void shared_cinterion_init (MMSharedCinterion *iface);
|
||||
|
||||
static MMIfaceModemLocation *iface_modem_location_parent;
|
||||
static MMIfaceModemVoice *iface_modem_voice_parent;
|
||||
static MMIfaceModemTime *iface_modem_time_parent;
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiCinterion, mm_broadband_modem_qmi_cinterion, MM_TYPE_BROADBAND_MODEM_QMI, 0,
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)
|
||||
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init))
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -109,11 +112,29 @@ peek_parent_voice_interface (MMSharedCinterion *self)
|
||||
return iface_modem_voice_parent;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_modem_time_init (MMIfaceModemTime *iface)
|
||||
{
|
||||
iface_modem_time_parent = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->setup_unsolicited_events = mm_shared_cinterion_time_setup_unsolicited_events;
|
||||
iface->setup_unsolicited_events_finish = mm_shared_cinterion_time_setup_unsolicited_events_finish;
|
||||
iface->cleanup_unsolicited_events = mm_shared_cinterion_time_cleanup_unsolicited_events;
|
||||
iface->cleanup_unsolicited_events_finish = mm_shared_cinterion_time_cleanup_unsolicited_events_finish;
|
||||
}
|
||||
|
||||
static MMIfaceModemTime *
|
||||
peek_parent_time_interface (MMSharedCinterion *self)
|
||||
{
|
||||
return iface_modem_time_parent;
|
||||
}
|
||||
|
||||
static void
|
||||
shared_cinterion_init (MMSharedCinterion *iface)
|
||||
{
|
||||
iface->peek_parent_location_interface = peek_parent_location_interface;
|
||||
iface->peek_parent_voice_interface = peek_parent_voice_interface;
|
||||
iface->peek_parent_time_interface = peek_parent_time_interface;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -53,11 +53,15 @@ typedef struct {
|
||||
MMIfaceModemVoice *iface_modem_voice_parent;
|
||||
FeatureSupport slcc_support;
|
||||
GRegex *slcc_regex;
|
||||
/* time */
|
||||
MMIfaceModemTime *iface_modem_time_parent;
|
||||
GRegex *ctzu_regex;
|
||||
} Private;
|
||||
|
||||
static void
|
||||
private_free (Private *ctx)
|
||||
{
|
||||
g_regex_unref (ctx->ctzu_regex);
|
||||
g_regex_unref (ctx->slcc_regex);
|
||||
g_slice_free (Private, ctx);
|
||||
}
|
||||
@@ -80,8 +84,9 @@ get_private (MMSharedCinterion *self)
|
||||
priv->sgpsc_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
priv->slcc_support = FEATURE_SUPPORT_UNKNOWN;
|
||||
priv->slcc_regex = mm_cinterion_get_slcc_regex ();
|
||||
priv->ctzu_regex = mm_cinterion_get_ctzu_regex ();
|
||||
|
||||
/* Setup parent class' MMIfaceModemLocation and MMIfaceModemVoice */
|
||||
/* Setup parent class' MMIfaceModemLocation, MMIfaceModemVoice and MMIfaceModemTime */
|
||||
|
||||
g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_location_interface);
|
||||
priv->iface_modem_location_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_location_interface (self);
|
||||
@@ -89,6 +94,9 @@ get_private (MMSharedCinterion *self)
|
||||
g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_voice_interface);
|
||||
priv->iface_modem_voice_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_voice_interface (self);
|
||||
|
||||
g_assert (MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_time_interface);
|
||||
priv->iface_modem_time_parent = MM_SHARED_CINTERION_GET_INTERFACE (self)->peek_parent_time_interface (self);
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (self), private_quark, priv, (GDestroyNotify)private_free);
|
||||
}
|
||||
|
||||
@@ -1333,6 +1341,191 @@ mm_shared_cinterion_voice_check_support (MMIfaceModemVoice *self,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Common setup/cleanup time unsolicited events */
|
||||
|
||||
static void
|
||||
ctzu_received (MMPortSerialAt *port,
|
||||
GMatchInfo *match_info,
|
||||
MMSharedCinterion *self)
|
||||
{
|
||||
gchar *iso8601 = NULL;
|
||||
MMNetworkTimezone *tz = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!mm_cinterion_parse_ctzu_urc (match_info, &iso8601, &tz, &error)) {
|
||||
mm_dbg ("Couldn't process +CTZU URC: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (iso8601);
|
||||
mm_dbg ("+CTZU URC received: %s", iso8601);
|
||||
mm_iface_modem_time_update_network_time (MM_IFACE_MODEM_TIME (self), iso8601);
|
||||
g_free (iso8601);
|
||||
|
||||
g_assert (tz);
|
||||
mm_iface_modem_time_update_network_timezone (MM_IFACE_MODEM_TIME (self), tz);
|
||||
g_object_unref (tz);
|
||||
}
|
||||
|
||||
static void
|
||||
common_time_setup_cleanup_unsolicited_events (MMSharedCinterion *self,
|
||||
gboolean enable)
|
||||
{
|
||||
Private *priv;
|
||||
MMPortSerialAt *ports[2];
|
||||
guint i;
|
||||
|
||||
priv = get_private (MM_SHARED_CINTERION (self));
|
||||
|
||||
ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
|
||||
ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
|
||||
|
||||
mm_dbg ("%s up time unsolicited events...",
|
||||
enable ? "Setting" : "Cleaning");
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (ports); i++) {
|
||||
if (!ports[i])
|
||||
continue;
|
||||
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (ports[i],
|
||||
priv->ctzu_regex,
|
||||
enable ? (MMPortSerialAtUnsolicitedMsgFn)ctzu_received : NULL,
|
||||
enable ? self : NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Cleanup unsolicited events (Time interface) */
|
||||
|
||||
gboolean
|
||||
mm_shared_cinterion_time_cleanup_unsolicited_events_finish (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
parent_time_cleanup_unsolicited_events_ready (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
Private *priv;
|
||||
|
||||
priv = get_private (MM_SHARED_CINTERION (self));
|
||||
|
||||
if (!priv->iface_modem_time_parent->cleanup_unsolicited_events_finish (self, res, &error)) {
|
||||
mm_warn ("Couldn't cleanup parent time unsolicited events: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
void
|
||||
mm_shared_cinterion_time_cleanup_unsolicited_events (MMIfaceModemTime *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
Private *priv;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
priv = get_private (MM_SHARED_CINTERION (self));
|
||||
g_assert (priv->iface_modem_time_parent);
|
||||
|
||||
/* our own cleanup first */
|
||||
common_time_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), FALSE);
|
||||
|
||||
if (priv->iface_modem_time_parent->cleanup_unsolicited_events &&
|
||||
priv->iface_modem_time_parent->cleanup_unsolicited_events_finish) {
|
||||
/* Chain up parent's cleanup */
|
||||
priv->iface_modem_time_parent->cleanup_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)parent_time_cleanup_unsolicited_events_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Setup unsolicited events (Time interface) */
|
||||
|
||||
gboolean
|
||||
mm_shared_cinterion_time_setup_unsolicited_events_finish (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
own_time_setup_unsolicited_events (GTask *task)
|
||||
{
|
||||
MMSharedCinterion *self;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
|
||||
/* our own setup next */
|
||||
common_time_setup_cleanup_unsolicited_events (MM_SHARED_CINTERION (self), TRUE);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
parent_time_setup_unsolicited_events_ready (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
GError *error = NULL;
|
||||
Private *priv;
|
||||
|
||||
priv = get_private (MM_SHARED_CINTERION (self));
|
||||
|
||||
if (!priv->iface_modem_time_parent->cleanup_unsolicited_events_finish (self, res, &error)) {
|
||||
mm_warn ("Couldn't cleanup parent time unsolicited events: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
own_time_setup_unsolicited_events (task);
|
||||
}
|
||||
|
||||
void
|
||||
mm_shared_cinterion_time_setup_unsolicited_events (MMIfaceModemTime *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
Private *priv;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
|
||||
priv = get_private (MM_SHARED_CINTERION (self));
|
||||
g_assert (priv->iface_modem_time_parent);
|
||||
|
||||
if (priv->iface_modem_time_parent->setup_unsolicited_events &&
|
||||
priv->iface_modem_time_parent->setup_unsolicited_events_finish) {
|
||||
/* chain up parent's setup first */
|
||||
priv->iface_modem_time_parent->setup_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)parent_time_setup_unsolicited_events_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
own_time_setup_unsolicited_events (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "mm-iface-modem.h"
|
||||
#include "mm-iface-modem-location.h"
|
||||
#include "mm-iface-modem-voice.h"
|
||||
#include "mm-iface-modem-time.h"
|
||||
|
||||
#define MM_TYPE_SHARED_CINTERION (mm_shared_cinterion_get_type ())
|
||||
#define MM_SHARED_CINTERION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SHARED_CINTERION, MMSharedCinterion))
|
||||
@@ -43,10 +44,16 @@ struct _MMSharedCinterion {
|
||||
|
||||
/* Peek voice interface of the parent class of the object */
|
||||
MMIfaceModemVoice * (* peek_parent_voice_interface) (MMSharedCinterion *self);
|
||||
|
||||
/* Peek time interface of the parent class of the object */
|
||||
MMIfaceModemTime * (* peek_parent_time_interface) (MMSharedCinterion *self);
|
||||
};
|
||||
|
||||
GType mm_shared_cinterion_get_type (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Location interface */
|
||||
|
||||
void mm_shared_cinterion_location_load_capabilities (MMIfaceModemLocation *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
@@ -71,7 +78,7 @@ gboolean mm_shared_cinterion_disable_location_gathering_finish (MMI
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Create call (Voice interface) */
|
||||
/* Voice interface */
|
||||
|
||||
MMBaseCall *mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
||||
MMCallDirection direction,
|
||||
@@ -112,4 +119,21 @@ gboolean mm_shared_cinterion_voice_disable_unsolicited_events_finish (MMIfaceMod
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Time interface */
|
||||
|
||||
void mm_shared_cinterion_time_setup_unsolicited_events (MMIfaceModemTime *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_shared_cinterion_time_setup_unsolicited_events_finish (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
void mm_shared_cinterion_time_cleanup_unsolicited_events (MMIfaceModemTime *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_shared_cinterion_time_cleanup_unsolicited_events_finish (MMIfaceModemTime *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_SHARED_CINTERION_H */
|
||||
|
Reference in New Issue
Block a user