intel: XMM7360: Better NMEA packets parsing
XMM7360 modem NMEA trace packets are wrapped to look like AT command responses (with "<CR><LF><CR><LF>OK<CR><LF>" at the end). This wrapping causes problems if a genuine AT command was just sent and ModemManager is expecting a similarly formatted response to it. In such case the NMEA trace packet is taken as the response to the AT command, which usually causes the command to fail due to response parsing failure. Fix this by implementing a custom NMEA trace packets parser for these modems. Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
This commit is contained in:
committed by
Dan Williams
parent
6c4b90de79
commit
0787d04a39
@@ -38,20 +38,24 @@
|
||||
#include "mm-port-scheduler-rr.h"
|
||||
#include "mm-port-serial-xmmrpc-xmm7360.h"
|
||||
#include "mm-bearer-xmm7360.h"
|
||||
#include "mm-shared-xmm.h"
|
||||
#include "mm-sim-xmm7360.h"
|
||||
|
||||
static void iface_modem_init (MMIfaceModemInterface *iface);
|
||||
static void iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface);
|
||||
static void iface_shared_xmm_init (MMSharedXmmInterface *iface);
|
||||
|
||||
static MMIfaceModemInterface *iface_modem_parent;
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemXmm7360, mm_broadband_modem_xmm7360, MM_TYPE_BROADBAND_MODEM_XMM, 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_XMM, iface_shared_xmm_init)
|
||||
)
|
||||
|
||||
struct _MMBroadbandModemXmm7360Private {
|
||||
MMUnlockRetries *unlock_retries;
|
||||
GRegex *nmea_regex_full, *nmea_regex_trace;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -1158,6 +1162,56 @@ initialization_started (MMBroadbandModem *modem,
|
||||
task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nmea_received (MMPortSerialAt *port,
|
||||
GMatchInfo *info_full,
|
||||
MMBroadbandModemXmm7360 *self)
|
||||
{
|
||||
g_autofree gchar *trace_full = NULL;
|
||||
g_autoptr(GMatchInfo) info = NULL;
|
||||
|
||||
trace_full = g_match_info_fetch (info_full, 1);
|
||||
if (!trace_full) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_regex_match (self->priv->nmea_regex_trace, trace_full, 0, &info);
|
||||
while (g_match_info_matches (info)) {
|
||||
g_autofree gchar *trace = NULL;
|
||||
|
||||
trace = g_match_info_fetch (info, 1);
|
||||
if (!trace) {
|
||||
mm_obj_err (self, "fetching NMEA trace failed");
|
||||
} else {
|
||||
mm_iface_modem_location_gps_update (MM_IFACE_MODEM_LOCATION (self), trace);
|
||||
}
|
||||
|
||||
g_match_info_next (info, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nmea_parser_register (MMSharedXmm *self_shared_xmm, MMPortSerialAt *gps_port,
|
||||
gboolean is_register)
|
||||
{
|
||||
MMBroadbandModemXmm7360 *self = MM_BROADBAND_MODEM_XMM7360 (self_shared_xmm);
|
||||
|
||||
if (is_register) {
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (gps_port,
|
||||
self->priv->nmea_regex_full,
|
||||
(MMPortSerialAtUnsolicitedMsgFn)nmea_received,
|
||||
self,
|
||||
NULL);
|
||||
} else {
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (gps_port,
|
||||
self->priv->nmea_regex_full,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
MMBroadbandModemXmm7360 *
|
||||
@@ -1187,6 +1241,13 @@ mm_broadband_modem_xmm7360_init (MMBroadbandModemXmm7360 *self)
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
MM_TYPE_BROADBAND_MODEM_XMM7360,
|
||||
MMBroadbandModemXmm7360Private);
|
||||
|
||||
self->priv->nmea_regex_full = g_regex_new ("(?:\\r\\n){2}((?:\\$G.*?\\r\\n)+)(?:\\r\\n){2}OK(?:\\r\\n)",
|
||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0,
|
||||
NULL);
|
||||
self->priv->nmea_regex_trace = g_regex_new ("(\\$G.*?)\\r\\n",
|
||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1194,6 +1255,8 @@ dispose (GObject *object)
|
||||
{
|
||||
MMBroadbandModemXmm7360 *self = MM_BROADBAND_MODEM_XMM7360 (object);
|
||||
|
||||
g_clear_pointer (&self->priv->nmea_regex_trace, g_regex_unref);
|
||||
g_clear_pointer (&self->priv->nmea_regex_full, g_regex_unref);
|
||||
g_clear_object (&self->priv->unlock_retries);
|
||||
|
||||
G_OBJECT_CLASS (mm_broadband_modem_xmm7360_parent_class)->dispose (object);
|
||||
@@ -1219,6 +1282,12 @@ iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface)
|
||||
iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_shared_xmm_init (MMSharedXmmInterface *iface)
|
||||
{
|
||||
iface->nmea_parser_register = nmea_parser_register;
|
||||
}
|
||||
|
||||
static void
|
||||
mm_broadband_modem_xmm7360_class_init (MMBroadbandModemXmm7360Class *klass)
|
||||
{
|
||||
|
||||
@@ -1003,6 +1003,25 @@ nmea_received (MMPortSerialAt *port,
|
||||
g_free (trace);
|
||||
}
|
||||
|
||||
static void
|
||||
nmea_parser_register (MMSharedXmm *self, MMPortSerialAt *gps_port,
|
||||
gboolean is_register)
|
||||
{
|
||||
Private *priv = get_private (self);
|
||||
|
||||
if (is_register) {
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (gps_port,
|
||||
priv->nmea_regex,
|
||||
(MMPortSerialAtUnsolicitedMsgFn)nmea_received,
|
||||
self,
|
||||
NULL);
|
||||
} else {
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (gps_port,
|
||||
priv->nmea_regex,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* GPS engine state selection */
|
||||
|
||||
@@ -1053,11 +1072,10 @@ xlcslsr_ready (MMBaseModem *self,
|
||||
mm_obj_dbg (self, "GPS engine started");
|
||||
|
||||
g_assert (priv->gps_port);
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (priv->gps_port,
|
||||
priv->nmea_regex,
|
||||
(MMPortSerialAtUnsolicitedMsgFn)nmea_received,
|
||||
self,
|
||||
NULL);
|
||||
MM_SHARED_XMM_GET_IFACE (self)->nmea_parser_register (MM_SHARED_XMM (self),
|
||||
priv->gps_port,
|
||||
TRUE);
|
||||
|
||||
priv->gps_engine_state = ctx->state;
|
||||
|
||||
/*
|
||||
@@ -1188,10 +1206,8 @@ gps_engine_stopped (GTask *task)
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
g_assert (priv->gps_port);
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (
|
||||
priv->gps_port,
|
||||
priv->nmea_regex,
|
||||
NULL, NULL, NULL);
|
||||
MM_SHARED_XMM_GET_IFACE (self)->nmea_parser_register (self, priv->gps_port,
|
||||
FALSE);
|
||||
|
||||
if (priv->gps_port_open) {
|
||||
mm_port_serial_close (MM_PORT_SERIAL (priv->gps_port));
|
||||
@@ -1737,4 +1753,5 @@ mm_shared_xmm_setup_ports (MMBroadbandModem *self)
|
||||
static void
|
||||
mm_shared_xmm_default_init (MMSharedXmmInterface *iface)
|
||||
{
|
||||
iface->nmea_parser_register = nmea_parser_register;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ struct _MMSharedXmmInterface {
|
||||
|
||||
/* Peek location interface of the parent class of the object */
|
||||
MMIfaceModemLocationInterface * (* peek_parent_location_interface) (MMSharedXmm *self);
|
||||
|
||||
void (* nmea_parser_register) (MMSharedXmm *self, MMPortSerialAt *gps_port,
|
||||
gboolean is_register);
|
||||
};
|
||||
|
||||
/* Shared XMM device setup */
|
||||
|
||||
Reference in New Issue
Block a user