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:
@@ -4,5 +4,6 @@
|
||||
tags
|
||||
/.vscode
|
||||
/cscope.out
|
||||
/.cache
|
||||
subprojects/libmbim
|
||||
subprojects/libqmi
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user