Merge request !1280 from 'intel-rpc-xmm7360'

intel: XMM7360: unlocking/enabling RPC timeout fix and location support

https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1280
This commit is contained in:
Dan Williams
2025-06-14 16:09:43 -05:00
12 changed files with 416 additions and 48 deletions
+1
View File
@@ -4,5 +4,6 @@
tags
/.vscode
/cscope.out
/.cache
subprojects/libmbim
subprojects/libqmi
+43
View File
@@ -1865,6 +1865,49 @@ mm_port_serial_flash (MMPortSerial *self,
ctx->flash_id = g_timeout_add (flash_time, (GSourceFunc)flash_do, self);
}
/*****************************************************************************/
/* Flush */
gboolean mm_port_serial_flush (MMPortSerial *self,
MMPortSerialFlushType type,
GError **error)
{
int tcflush_type;
g_return_val_if_fail (MM_IS_PORT_SERIAL (self), FALSE);
if (!mm_port_serial_is_open (self)) {
g_set_error_literal (error,
MM_SERIAL_ERROR,
MM_SERIAL_ERROR_NOT_OPEN,
"The serial port is not open.");
return FALSE;
}
if (type == MM_PORT_SERIAL_FLUSH_RX) {
tcflush_type = TCIFLUSH;
} else if (type == MM_PORT_SERIAL_FLUSH_TX) {
tcflush_type = TCOFLUSH;
} else if (type == MM_PORT_SERIAL_FLUSH_BOTH) {
tcflush_type = TCIOFLUSH;
} else {
g_assert_not_reached ();
return FALSE;
}
g_assert (self->priv->fd >= 0);
if (tcflush (self->priv->fd, tcflush_type) != 0) {
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to flush (%d) serial port, errno %d",
tcflush_type, errno);
return FALSE;
}
return TRUE;
}
/*****************************************************************************/
gboolean
+10
View File
@@ -48,6 +48,12 @@ typedef enum {
MM_PORT_SERIAL_RESPONSE_ERROR,
} MMPortSerialResponseType;
typedef enum {
MM_PORT_SERIAL_FLUSH_RX,
MM_PORT_SERIAL_FLUSH_TX,
MM_PORT_SERIAL_FLUSH_BOTH,
} MMPortSerialFlushType;
typedef struct _MMPortSerial MMPortSerial;
typedef struct _MMPortSerialClass MMPortSerialClass;
typedef struct _MMPortSerialPrivate MMPortSerialPrivate;
@@ -141,6 +147,10 @@ gboolean mm_port_serial_flash_finish (MMPortSerial *self,
GError **error);
void mm_port_serial_flash_cancel (MMPortSerial *self);
gboolean mm_port_serial_flush (MMPortSerial *self,
MMPortSerialFlushType type,
GError **error);
void mm_port_serial_command (MMPortSerial *self,
GByteArray *command,
guint32 timeout_seconds,
+4
View File
@@ -26,6 +26,7 @@
#include "mm-broadband-modem-xmm7360.h"
#include "mm-broadband-modem-xmm7360-rpc.h"
#include "mm-port-serial-xmmrpc-xmm7360.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMBearerXmm7360, mm_bearer_xmm7360, MM_TYPE_BASE_BEARER)
@@ -673,6 +674,7 @@ static const MMBroadbandModemXmm7360RpcCommand disconnect_sequence[] = {
},
3,
FALSE,
FALSE,
mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success
/* response will be: L(0x0) L(0x0) L(0x5dffffff) L(0x0) (meaning unknown) */
},
@@ -686,6 +688,7 @@ static const MMBroadbandModemXmm7360RpcCommand disconnect_sequence[] = {
},
3,
FALSE,
FALSE,
mm_broadband_modem_xmm7360_rpc_response_processor_final
/* response will be: L(0x0) (meaning unknown) */
},
@@ -731,6 +734,7 @@ mm_bearer_xmm7360_new (MMBroadbandModemXmm7360 *modem,
* g_object_new here */
bearer = g_object_new (MM_TYPE_BEARER_XMM7360,
MM_BASE_BEARER_MODEM, modem,
MM_BIND_TO, modem,
MM_BASE_BEARER_CONFIG, config,
NULL);
@@ -84,6 +84,7 @@ typedef struct {
gulong cancelled_id;
GCancellable *parent_cancellable;
const MMBroadbandModemXmm7360RpcCommand *current;
gboolean current_retry;
const MMBroadbandModemXmm7360RpcCommand *sequence;
guint next_command_wait_id;
} RpcSequenceContext;
@@ -152,6 +153,7 @@ rpc_sequence_parse_response (MMPortSerialXmmrpcXmm7360 *port,
RpcSequenceContext *ctx;
Xmm7360RpcResponse *response = NULL;
g_autoptr(GError) command_error = NULL;
gboolean command_retry = FALSE;
response = mm_port_serial_xmmrpc_xmm7360_command_finish (port, res, &command_error);
@@ -173,6 +175,20 @@ rpc_sequence_parse_response (MMPortSerialXmmrpcXmm7360 *port,
next->callid ? FALSE : TRUE, /* Last command in sequence? */
command_error,
&result_error);
if (processor_result == MM_BROADBAND_MODEM_XMM7360_RPC_RESPONSE_PROCESSOR_RESULT_FAILURE
&& ctx->current->allow_retry_once && !ctx->current_retry) {
mm_obj_warn (port, "Command failed (%s), retrying once",
result_error ? result_error->message : "UNKNOWN");
if (response)
xmm7360_rpc_response_free (response);
g_clear_error (&result_error);
command_retry = TRUE;
goto skip_result;
}
switch (processor_result) {
case MM_BROADBAND_MODEM_XMM7360_RPC_RESPONSE_PROCESSOR_RESULT_CONTINUE:
g_assert (!result_error);
@@ -195,8 +211,14 @@ rpc_sequence_parse_response (MMPortSerialXmmrpcXmm7360 *port,
}
}
if (processor_result == MM_BROADBAND_MODEM_XMM7360_RPC_RESPONSE_PROCESSOR_RESULT_CONTINUE) {
ctx->current++;
skip_result:
if (processor_result == MM_BROADBAND_MODEM_XMM7360_RPC_RESPONSE_PROCESSOR_RESULT_CONTINUE ||
command_retry) {
if (!command_retry) {
ctx->current++;
}
ctx->current_retry = command_retry;
if (ctx->current->callid) {
g_assert (!ctx->next_command_wait_id);
ctx->next_command_wait_id = g_timeout_add_seconds (ctx->current->wait_seconds,
@@ -204,6 +226,7 @@ rpc_sequence_parse_response (MMPortSerialXmmrpcXmm7360 *port,
task);
return;
}
g_assert (!command_retry);
/* On last command, end. */
}
@@ -61,6 +61,7 @@ typedef struct {
guint timeout;
/* Flag to allow cached replies */
gboolean allow_cached;
gboolean allow_retry_once;
/* The response processor */
MMBroadbandModemXmm7360RpcResponseProcessor response_processor;
/* Time to wait before sending this command (in seconds) */
+91 -17
View File
@@ -31,29 +31,31 @@
#include "mm-log-object.h"
#include "mm-iface-modem.h"
#include "mm-iface-modem-3gpp.h"
#include "mm-iface-modem-location.h"
#include "mm-broadband-modem-xmm.h"
#include "mm-broadband-modem-xmm7360.h"
#include "mm-broadband-modem-xmm7360-rpc.h"
#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_modem_location_init (MMIfaceModemLocationInterface *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_IFACE_MODEM_LOCATION, iface_modem_location_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, iface_shared_xmm_init)
)
struct _MMBroadbandModemXmm7360Private {
MMUnlockRetries *unlock_retries;
GRegex *nmea_regex_full, *nmea_regex_trace;
};
/*****************************************************************************/
@@ -1088,14 +1090,14 @@ static const Xmm7360RpcMsgArg set_radio_signal_reporting_args[] = {
};
static const MMBroadbandModemXmm7360RpcCommand init_sequence[] = {
{ XMM7360_RPC_CALL_UTA_MS_SMS_INIT, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_CBS_INIT, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_NET_OPEN, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_NET_SET_RADIO_SIGNAL_REPORTING, FALSE, set_radio_signal_reporting_args, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success},
{ XMM7360_RPC_CALL_UTA_MS_CALL_CS_INIT, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_CALL_PS_INITIALIZE, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_SS_INIT, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_SIM_OPEN_REQ, FALSE, NULL, 3, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_final },
{ XMM7360_RPC_CALL_UTA_MS_SMS_INIT, FALSE, NULL, 3, FALSE, TRUE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_CBS_INIT, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_NET_OPEN, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_NET_SET_RADIO_SIGNAL_REPORTING, FALSE, set_radio_signal_reporting_args, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success},
{ XMM7360_RPC_CALL_UTA_MS_CALL_CS_INIT, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_CALL_PS_INITIALIZE, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_SS_INIT, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_continue_on_success },
{ XMM7360_RPC_CALL_UTA_MS_SIM_OPEN_REQ, FALSE, NULL, 3, FALSE, FALSE, mm_broadband_modem_xmm7360_rpc_response_processor_final },
{ 0 }
};
@@ -1108,6 +1110,8 @@ initialization_started (MMBroadbandModem *modem,
MMBroadbandModemXmm7360 *self = MM_BROADBAND_MODEM_XMM7360 (modem);
InitializationStartedContext *ctx;
GTask *task;
MMPortSerialAt *at_port;
g_autoptr(MMPortScheduler) sched = NULL;
task = g_task_new (self,
NULL,
@@ -1120,6 +1124,14 @@ initialization_started (MMBroadbandModem *modem,
ctx->timeout_id = 0;
g_task_set_task_data (task, ctx, (GDestroyNotify)initialization_started_context_free);
at_port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
if (!at_port) {
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
"no primary AT port");
g_object_unref (task);
return;
}
/* Open XMMRPC port for initialization */
if (!mm_port_serial_open (MM_PORT_SERIAL (ctx->port), &error)) {
g_prefix_error (&error, "Couldn't open XMMRPC port during initialization: ");
@@ -1134,6 +1146,13 @@ initialization_started (MMBroadbandModem *modem,
task,
NULL);
g_object_get (G_OBJECT (ctx->port), MM_PORT_SERIAL_SCHEDULER, &sched, NULL);
g_object_set (sched,
MM_PORT_SCHEDULER_RR_INTER_PORT_DELAY,
300,
NULL);
g_object_set (G_OBJECT (at_port), MM_PORT_SERIAL_SCHEDULER, sched, NULL);
mm_obj_dbg (self, "running init sequence...");
mm_broadband_modem_xmm7360_rpc_sequence_full (MM_BROADBAND_MODEM_XMM7360 (self),
ctx->port,
@@ -1143,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 *
@@ -1172,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
@@ -1179,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);
@@ -1205,13 +1283,9 @@ iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface)
}
static void
iface_modem_location_init (MMIfaceModemLocationInterface *iface)
iface_shared_xmm_init (MMSharedXmmInterface *iface)
{
/* asking for location capabilities can destabilize the device */
iface->load_capabilities = NULL;
iface->load_capabilities_finish = NULL;
iface->enable_location_gathering = NULL;
iface->enable_location_gathering_finish = NULL;
iface->nmea_parser_register = nmea_parser_register;
}
static void
@@ -535,6 +535,12 @@ serial_command_ready (MMPortSerial *port,
g_byte_array_remove_range (response_buffer, 0, response_buffer->len);
g_byte_array_unref (response_buffer);
if (response &&
response->type == XMM7360_RPC_RESPONSE_TYPE_RESPONSE) {
xmm7360_byte_array_log (port, "", response->body);
xmm7360_rpc_msg_args_log (port, "", response->content);
}
g_task_return_pointer (task, response, (GDestroyNotify) xmm7360_rpc_response_free);
g_object_unref (task);
}
@@ -569,10 +575,9 @@ mm_port_serial_xmmrpc_xmm7360_command (MMPortSerialXmmrpcXmm7360 *self,
task = g_task_new (self, NULL, callback, user_data);
/* Body logged in debug_log() */
mm_obj_dbg (self, "--> %s%s", is_async ? "(async) " : "", xmm_7360_rpc_call_id_get_string (callid));
xmm7360_byte_array_log (self, "", buf);
mm_port_serial_command (MM_PORT_SERIAL (self),
buf,
timeout_seconds,
@@ -656,8 +661,7 @@ parse_unsolicited (MMPortSerial *port, GByteArray *response_buffer)
if (response->type == XMM7360_RPC_RESPONSE_TYPE_RESPONSE) {
mm_obj_dbg (port, "<-- (response)");
xmm7360_byte_array_log (port, "", response->body);
xmm7360_rpc_msg_args_log (port, "", response->content);
/* Body logged in serial_command_ready() */
return;
}
@@ -692,6 +696,37 @@ parse_unsolicited (MMPortSerial *port, GByteArray *response_buffer)
g_byte_array_remove_range (response_buffer, 0, response_buffer->len);
}
static void
debug_log (MMPortSerial *self,
const gchar *prefix,
const gchar *buf,
gsize len)
{
static GString *debug = NULL;
const char *s;
if (g_strcmp0 (prefix, "<--") == 0) {
/* Incoming data is already logged in parse functions */
return;
}
if (!debug)
debug = g_string_sized_new (256);
g_string_append (debug, prefix);
g_string_append (debug, " raw [");
s = buf;
while (len--) {
g_string_append_printf (debug, "%02x", (guint8)*s);
s++;
}
g_string_append_c (debug, ']');
mm_obj_dbg (self, "%s", debug->str);
g_string_truncate (debug, 0);
}
/*****************************************************************************/
MMPortSerialXmmrpcXmm7360 *
@@ -747,4 +782,5 @@ mm_port_serial_xmmrpc_xmm7360_class_init (MMPortSerialXmmrpcXmm7360Class *klass)
serial_class->parse_response = parse_response;
serial_class->parse_unsolicited = parse_unsolicited;
serial_class->debug_log = debug_log;
}
+3
View File
@@ -17,6 +17,7 @@
#include "mm-broadband-modem-xmm7360-rpc.h"
#include "mm-log-object.h"
#include "mm-sim-xmm7360.h"
#include "mm-bind.h"
G_DEFINE_TYPE (MMSimXmm7360, mm_sim_xmm7360, MM_TYPE_BASE_SIM)
@@ -392,6 +393,7 @@ mm_sim_xmm7360_new (MMBaseModem *modem,
callback,
user_data,
MM_BASE_SIM_MODEM, modem,
MM_BIND_TO, modem,
"active", TRUE, /* by default always active */
NULL);
}
@@ -413,6 +415,7 @@ mm_sim_xmm7360_new_initialized (MMBaseModem *modem,
sim = MM_BASE_SIM (g_object_new (MM_TYPE_SIM_XMM7360,
MM_BASE_SIM_MODEM, modem,
MM_BIND_TO, modem,
MM_BASE_SIM_SLOT_NUMBER, slot_number,
"active", active,
"sim-type", sim_type,
+4
View File
@@ -149,4 +149,8 @@ mm_broadband_modem_xmm_class_init (MMBroadbandModemXmmClass *klass)
MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports;
broadband_modem_class->initialization_started =
mm_shared_xmm_initialization_started;
broadband_modem_class->initialization_started_finish =
mm_shared_xmm_initialization_started_finish;
}
+185 -25
View File
@@ -44,6 +44,7 @@ typedef enum {
GPS_ENGINE_STATE_STANDALONE,
GPS_ENGINE_STATE_AGPS_MSA,
GPS_ENGINE_STATE_AGPS_MSB,
GPS_ENGINE_STATE_UNKNOWN,
} GpsEngineState;
typedef struct {
@@ -64,6 +65,7 @@ typedef struct {
MMModemLocationSource enabled_sources;
GpsEngineState gps_engine_state;
MMPortSerialAt *gps_port;
gboolean gps_port_open;
GRegex *xlsrstop_regex;
GRegex *nmea_regex;
@@ -75,6 +77,13 @@ static void
private_free (Private *priv)
{
g_assert (!priv->pending_gps_engine_stop_task);
if (priv->gps_port_open) {
g_assert (priv->gps_port);
mm_port_serial_close (MM_PORT_SERIAL (priv->gps_port));
priv->gps_port_open = FALSE;
}
g_clear_object (&priv->gps_port);
if (priv->supported_modes)
g_array_unref (priv->supported_modes);
@@ -97,7 +106,7 @@ get_private (MMSharedXmm *self)
priv = g_object_get_qdata (G_OBJECT (self), private_quark);
if (!priv) {
priv = g_slice_new0 (Private);
priv->gps_engine_state = GPS_ENGINE_STATE_OFF;
priv->gps_engine_state = GPS_ENGINE_STATE_UNKNOWN;
/* Setup regex for URCs */
priv->xbipi_regex = g_regex_new ("\\r\\n\\+XBIPI:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
@@ -995,6 +1004,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 */
@@ -1029,6 +1057,7 @@ xlcslsr_ready (MMBaseModem *self,
const gchar *response;
GError *error = NULL;
Private *priv;
g_autoptr(GError) reopen_error = NULL;
priv = get_private (MM_SHARED_XMM (self));
ctx = g_task_get_task_data (task);
@@ -1044,13 +1073,24 @@ 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;
/*
* Keep GPS port open if would not be kept open otherwise
* (like with a locked/non-enabled modem).
*/
g_assert (!priv->gps_port_open);
if (!mm_port_serial_open (MM_PORT_SERIAL (priv->gps_port), &reopen_error)) {
mm_obj_warn (self, "unexpected GPS port reopen error: %s",
reopen_error->message);
} else {
priv->gps_port_open = TRUE;
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
@@ -1092,6 +1132,7 @@ gps_engine_start (GTask *task)
pos_mode = 2;
break;
case GPS_ENGINE_STATE_OFF:
case GPS_ENGINE_STATE_UNKNOWN:
default:
g_assert_not_reached ();
break;
@@ -1167,10 +1208,14 @@ 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));
priv->gps_port_open = FALSE;
}
g_clear_object (&priv->gps_port);
priv->gps_engine_state = GPS_ENGINE_STATE_OFF;
@@ -1314,6 +1359,8 @@ gps_engine_state_select (MMSharedXmm *self,
GTask *task;
Private *priv;
g_assert (state != GPS_ENGINE_STATE_UNKNOWN);
priv = get_private (self);
task = g_task_new (self, NULL, callback, user_data);
@@ -1663,7 +1710,6 @@ mm_shared_xmm_setup_ports (MMBroadbandModem *self)
{
Private *priv;
MMPortSerialAt *ports[2];
g_autoptr(MMPortSerialAt) gps_port = NULL;
guint i;
mm_obj_dbg (self, "setting up ports in XMM modem...");
@@ -1686,23 +1732,136 @@ mm_shared_xmm_setup_ports (MMBroadbandModem *self)
priv->xbipi_regex,
NULL, NULL, NULL);
}
}
/* Setup the GPS port */
gps_port = shared_xmm_get_gps_control_port (MM_SHARED_XMM (self), NULL);
if (gps_port) {
/* After running AT+XLSRSTOP we may get an unsolicited response
* reporting its status, we just ignore it. */
mm_port_serial_at_add_unsolicited_msg_handler (
gps_port,
priv->xlsrstop_regex,
NULL, NULL, NULL);
gpointer
mm_shared_xmm_initialization_started_finish (MMBroadbandModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
/* make sure GPS is stopped in case it was left enabled */
mm_base_modem_at_command_full (MM_BASE_MODEM (self),
MM_IFACE_PORT_AT (gps_port),
"+XLSRSTOP",
3, FALSE, FALSE, NULL, NULL, NULL);
static void
initialization_started_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
MMBroadbandModem *self = MM_BROADBAND_MODEM (source_object);
g_autoptr(GTask) task = user_data;
Private *priv = get_private (MM_SHARED_XMM (self));
g_autoptr(GError) error = NULL;
gpointer ret;
g_assert (priv->broadband_modem_class_parent);
g_assert (priv->broadband_modem_class_parent->initialization_started_finish);
ret = priv->broadband_modem_class_parent->initialization_started_finish (self,
res,
&error);
if (!ret) {
g_task_return_error (task, g_steal_pointer (&error));
return;
}
g_task_return_pointer (task, ret, NULL);
}
static void
gps_init_stop_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
MMSharedXmm *self_xmm = MM_SHARED_XMM (source_object);
Private *priv = get_private (self_xmm);
MMBroadbandModem *self = MM_BROADBAND_MODEM (source_object);
g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
if (!gps_engine_state_select_finish (self_xmm, res, &error)) {
mm_obj_dbg (self, "GPS stop at init failed: %s",
error ? error->message : "(unknown");
/* assume GPS simply wasn't on in the modem in the first place */
if (priv->gps_port) {
MM_SHARED_XMM_GET_IFACE (self)->nmea_parser_register (self_xmm,
priv->gps_port,
FALSE);
if (priv->gps_port_open) {
mm_port_serial_close (MM_PORT_SERIAL (priv->gps_port));
priv->gps_port_open = FALSE;
}
g_clear_object (&priv->gps_port);
}
priv->gps_engine_state = GPS_ENGINE_STATE_OFF;
}
g_assert (priv->broadband_modem_class_parent);
g_assert (priv->broadband_modem_class_parent->initialization_started);
priv->broadband_modem_class_parent->initialization_started (self,
initialization_started_done,
g_steal_pointer (&task));
}
void
mm_shared_xmm_initialization_started (MMBroadbandModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
MMSharedXmm *self_xmm = MM_SHARED_XMM (self);
Private *priv = get_private (self_xmm);
g_autoptr(GTask) task = NULL;
g_autoptr(MMPortSerialAt) gps_port = NULL;
task = g_task_new (self, NULL, callback, user_data);
/* Setup the GPS port and stop GPS if it is not supposed to be running */
gps_port = shared_xmm_get_gps_control_port (self_xmm, NULL);
if (gps_port && priv->gps_engine_state == GPS_ENGINE_STATE_UNKNOWN) {
g_autoptr(GError) gps_port_open_error = NULL;
g_autoptr(GError) gps_port_flush_error = NULL;
g_assert (!priv->gps_port);
priv->gps_port = g_steal_pointer (&gps_port);
MM_SHARED_XMM_GET_IFACE (self)->nmea_parser_register (self_xmm,
priv->gps_port,
TRUE);
g_assert (!priv->gps_port_open);
if (!mm_port_serial_open (MM_PORT_SERIAL (priv->gps_port),
&gps_port_open_error)) {
mm_obj_warn (self, "unexpected init GPS port open error: %s",
gps_port_open_error->message);
} else {
priv->gps_port_open = TRUE;
}
mm_obj_dbg (self,
"flushing pending data in GPS port");
if (!mm_port_serial_flush (MM_PORT_SERIAL (priv->gps_port),
MM_PORT_SERIAL_FLUSH_RX,
&gps_port_flush_error)) {
mm_obj_warn (self, "unexpected init GPS port flush error: %s",
gps_port_flush_error->message);
}
gps_engine_state_select (self_xmm, GPS_ENGINE_STATE_OFF,
gps_init_stop_done, g_steal_pointer (&task));
return;
}
g_assert (priv->broadband_modem_class_parent);
g_assert (priv->broadband_modem_class_parent->initialization_started);
priv->broadband_modem_class_parent->initialization_started (self,
initialization_started_done,
g_steal_pointer (&task));
}
/*****************************************************************************/
@@ -1710,4 +1869,5 @@ mm_shared_xmm_setup_ports (MMBroadbandModem *self)
static void
mm_shared_xmm_default_init (MMSharedXmmInterface *iface)
{
iface->nmea_parser_register = nmea_parser_register;
}
+9
View File
@@ -38,11 +38,20 @@ 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 */
void mm_shared_xmm_setup_ports (MMBroadbandModem *self);
void mm_shared_xmm_initialization_started (MMBroadbandModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
gpointer mm_shared_xmm_initialization_started_finish (MMBroadbandModem *self,
GAsyncResult *res,
GError **error);
/* Shared XMM device management support */