novatel: Poll for whether the connection still exists.

Novatel E362 firmware doesn't notify us by unsolicited message if the
connection goes away, so set up a polling loop to check.

While here, inline a method that's only used in one place so that the
containing function is single-exit and single-cleanup.

Change-Id: If72f7c6ef06de3fb22530d42f62a8dddc6fecfda
This commit is contained in:
Nathan Williams
2012-05-02 21:05:06 +02:00
committed by Aleksander Morgado
parent 83bc51edcb
commit 1c1a6a16ec
+79 -33
View File
@@ -32,6 +32,8 @@
#include "mm-modem-helpers.h"
#include "mm-utils.h"
#define CONNECTION_CHECK_TIMEOUT_SEC 5
G_DEFINE_TYPE (MMBroadbandBearerNovatel, mm_broadband_bearer_novatel, MM_TYPE_BROADBAND_BEARER);
enum {
@@ -48,6 +50,8 @@ static GParamSpec *properties[PROP_LAST];
struct _MMBroadbandBearerNovatelPrivate {
/* timeout id for checking whether we're still connected */
guint connection_poller;
/* Username for authenticating to APN */
gchar *user;
/* Password for authenticating to APN */
@@ -105,19 +109,6 @@ detailed_connect_context_complete_and_free (DetailedConnectContext *ctx)
g_free (ctx);
}
static void
detailed_connect_context_complete_and_free_successful (DetailedConnectContext *ctx)
{
MMBearerIpConfig *config;
config = mm_bearer_ip_config_new ();
mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP);
g_simple_async_result_set_op_res_gpointer (ctx->result,
config,
(GDestroyNotify)g_object_unref);
detailed_connect_context_complete_and_free (ctx);
}
static gboolean
connect_3gpp_finish (MMBroadbandBearer *self,
GAsyncResult *res,
@@ -140,6 +131,46 @@ connect_3gpp_finish (MMBroadbandBearer *self,
static gboolean connect_3gpp_qmistatus (DetailedConnectContext *ctx);
static void
poll_connection_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerNovatel *bearer)
{
const gchar *result;
GError *error = NULL;
result = mm_base_modem_at_command_finish (modem, res, &error);
if (!result) {
mm_warn ("QMI connection status failed: %s", error->message);
g_error_free (error);
} else {
result = mm_strip_tag (result, "$NWQMISTATUS:");
if (g_strrstr(result, "QMI State: DISCONNECTED")) {
mm_bearer_report_disconnection (MM_BEARER (bearer));
g_source_remove (bearer->priv->connection_poller);
bearer->priv->connection_poller = 0;
}
}
}
static gboolean
poll_connection (MMBroadbandBearerNovatel *bearer)
{
MMBaseModem *modem = NULL;
g_object_get (MM_BEARER (bearer),
MM_BEARER_MODEM, &modem,
NULL);
mm_base_modem_at_command (
modem,
"$NWQMISTATUS",
3,
FALSE,
(GAsyncReadyCallback)poll_connection_ready,
bearer);
g_object_unref (modem);
return TRUE;
}
static void
connect_3gpp_qmistatus_ready (MMBaseModem *modem,
GAsyncResult *res,
@@ -154,28 +185,34 @@ connect_3gpp_qmistatus_ready (MMBaseModem *modem,
if (!result) {
mm_warn ("QMI connection status failed: %s", error->message);
g_simple_async_result_take_error (ctx->result, error);
detailed_connect_context_complete_and_free (ctx);
return;
}
result = mm_strip_tag (result, "$NWQMISTATUS:");
if (g_strrstr(result, "QMI State: CONNECTED")) {
mm_dbg("Connected");
detailed_connect_context_complete_and_free_successful (ctx);
return;
} else {
mm_dbg("Error: '%s'", result);
if (ctx->retries > 0) {
ctx->retries--;
mm_dbg("Retrying status check in a second. %d retries left.",
ctx->retries);
g_timeout_add_seconds(1, (GSourceFunc)connect_3gpp_qmistatus, ctx);
return;
result = mm_strip_tag (result, "$NWQMISTATUS:");
if (g_strrstr(result, "QMI State: CONNECTED")) {
MMBearerIpConfig *config;
MMBroadbandBearerNovatel *bearer = MM_BROADBAND_BEARER_NOVATEL (ctx->self);
mm_dbg("Connected");
bearer->priv->connection_poller = g_timeout_add_seconds (CONNECTION_CHECK_TIMEOUT_SEC,
(GSourceFunc)poll_connection,
bearer);
config = mm_bearer_ip_config_new ();
mm_bearer_ip_config_set_method (config, MM_BEARER_IP_METHOD_DHCP);
g_simple_async_result_set_op_res_gpointer (ctx->result,
config,
(GDestroyNotify)g_object_unref);
} else {
mm_dbg("Error: '%s'", result);
if (ctx->retries > 0) {
ctx->retries--;
mm_dbg("Retrying status check in a second. %d retries left.",
ctx->retries);
g_timeout_add_seconds(1, (GSourceFunc)connect_3gpp_qmistatus, ctx);
return;
}
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"%s", result);
}
g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"%s", result);
}
detailed_connect_context_complete_and_free (ctx);
}
@@ -379,6 +416,12 @@ disconnect_3gpp (MMBroadbandBearer *self,
gpointer user_data)
{
DetailedDisconnectContext *ctx;
MMBroadbandBearerNovatel *bearer = MM_BROADBAND_BEARER_NOVATEL (self);
if (bearer->priv->connection_poller) {
g_source_remove (bearer->priv->connection_poller);
bearer->priv->connection_poller = 0;
}
ctx = detailed_disconnect_context_new (self, modem, primary, secondary,
data, callback, user_data);
@@ -400,6 +443,8 @@ finalize (GObject *object)
g_free (self->priv->user);
g_free (self->priv->password);
if (self->priv->connection_poller)
g_source_remove (self->priv->connection_poller);
G_OBJECT_CLASS (mm_broadband_bearer_novatel_parent_class)->finalize (object);
}
@@ -493,6 +538,7 @@ mm_broadband_bearer_novatel_init (MMBroadbandBearerNovatel *self)
self->priv->user = NULL;
self->priv->password = NULL;
self->priv->connection_poller = 0;
}
static void