This patch updates the NDISDUP check handle for Huawei modem.
For Huawei devices, which expose the standard ECM port, at command "^DHCP?" is used to query the IP and DNS
address for the connection,
At command "^NDISSTATQRY?" is used to query the connection status(connected or disconnected).
They have some different. The response of DHCP does not exactly indicate the right connection status in that
time.
So it is better to send NDISSTATQRY to check the connection status after NDISDUP connect/disconnect, but not
DHCP.
diff -urpN mm-orig/plugins/huawei/mm-broadband-bearer-huawei.c mm/plugins/huawei/mm-broadband-bearer-huawei.c
--- mm-orig/plugins/huawei/mm-broadband-bearer-huawei.c 2013-06-04 20:35:00.000000000 +0800
+++ mm/plugins/huawei/mm-broadband-bearer-huawei.c 2013-06-06 15:46:09.000000000 +0800
@@ -43,7 +43,7 @@ struct _MMBroadbandBearerHuaweiPrivate {
typedef enum {
CONNECT_3GPP_CONTEXT_STEP_FIRST = 0,
CONNECT_3GPP_CONTEXT_STEP_NDISDUP,
- CONNECT_3GPP_CONTEXT_STEP_DHCP,
+ CONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY,
CONNECT_3GPP_CONTEXT_STEP_LAST
} Connect3gppContextStep;
@@ -85,7 +85,7 @@ connect_3gpp_finish (MMBroadbandBearer *
static void connect_3gpp_context_step (Connect3gppContext *ctx);
static gboolean
-connect_retry_dhcp_check_cb (MMBroadbandBearerHuawei *self)
+connect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self)
{
Connect3gppContext *ctx;
@@ -103,44 +103,80 @@ connect_retry_dhcp_check_cb (MMBroadband
}
static void
-connect_dhcp_check_ready (MMBaseModem *modem,
+connect_ndisstatqry_check_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerHuawei *self)
{
Connect3gppContext *ctx;
- GError *error = NULL;
+ const gchar *response;
ctx = self->priv->connect_pending;
g_assert (ctx != NULL);
/* Balance refcount */
g_object_unref (self);
-
- if (!mm_base_modem_at_command_full_finish (modem, res, &error)) {
- /* Only retry the DHCP check if we get a mobile equipment error, or if
- * the command timed out. */
- if (error->domain == MM_MOBILE_EQUIPMENT_ERROR ||
- g_error_matches (error,
- MM_SERIAL_ERROR,
- MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) {
- g_error_free (error);
+
+ response = mm_base_modem_at_command_full_finish (modem, res, NULL);
+ if (!response) {
+ mm_dbg ("%s: modem doesn't support ndisstatqry command", __func__);
+ goto failed;
+ } else {
+ gchar **ndisstatqry;
+ gchar **ndisstate;
+ gchar *status;
+ guint connect_status;
+ guint index;
+
+ ndisstatqry = g_strsplit (response, "^NDISSTATQRY:", 0);
+ if (!ndisstatqry) {
+ mm_dbg ("%s: No NDISSTATQRY found\n", __func__);
+ goto failed;
+ }
+ for (index = 0; ndisstatqry[index]; index++) {
+ if (!strstr (ndisstatqry[index], ",")) {
+ continue;
+ }
+ ndisstate = g_strsplit (ndisstatqry[index], ",", 0);
+ if (!ndisstate) {
+ mm_dbg ("%s: No state found\n", __func__);
+ g_strfreev (ndisstatqry);
+ goto failed;
+ }
+ status = g_strstrip (ndisstate[0]);
+ if (!mm_get_uint_from_str (status, &connect_status)) {
+ mm_dbg ("%s: Get connect status failed\n", __func__);
+ g_strfreev (ndisstate);
+ g_strfreev (ndisstatqry);
+ goto failed;
+ }
+ g_strfreev (ndisstate);
+ if (connect_status == 1) {
+ mm_dbg ("%s: connection successfully\n", __func__);
+ break;
+ }
+ }
+ g_strfreev (ndisstatqry);
+ if (connect_status != 1) { /* Connect failed */
/* Setup timeout to retry the same step */
g_timeout_add_seconds (1,
- (GSourceFunc)connect_retry_dhcp_check_cb,
+ (GSourceFunc)connect_retry_ndisstatqry_check_cb,
g_object_ref (self));
return;
}
-
- /* Fatal error happened; e.g. modem unplugged */
- self->priv->connect_pending = NULL;
- g_simple_async_result_take_error (ctx->result, error);
- connect_3gpp_context_complete_and_free (ctx);
- return;
}
-
+
/* Success! */
ctx->step++;
connect_3gpp_context_step (ctx);
+ return;
+
+failed:
+ ctx->self->priv->connect_pending = NULL;
+ g_simple_async_result_set_error (ctx->result,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
+ "Connection attempt not supported");
+ connect_3gpp_context_complete_and_free (ctx);
}
static void
@@ -236,7 +272,6 @@ connect_3gpp_context_step (Connect3gppCo
connect_3gpp_context_complete_and_free (ctx);
return;
}
-
/* Store the context */
ctx->self->priv->connect_pending = ctx;
@@ -276,7 +311,7 @@ connect_3gpp_context_step (Connect3gppCo
return;
}
- case CONNECT_3GPP_CONTEXT_STEP_DHCP:
+ case CONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY:
/* Wait for dial up timeout, retries for 60 times
* (1s between the retries, so it means 1 minute).
* If too many retries, failed
@@ -296,12 +331,12 @@ connect_3gpp_context_step (Connect3gppCo
ctx->check_count++;
mm_base_modem_at_command_full (ctx->modem,
ctx->primary,
- "^DHCP?",
+ "^NDISSTATQRY?",
3,
FALSE,
FALSE,
NULL,
- (GAsyncReadyCallback)connect_dhcp_check_ready,
+ (GAsyncReadyCallback)connect_ndisstatqry_check_ready,
g_object_ref (ctx->self));
return;
@@ -378,7 +413,7 @@ connect_3gpp (MMBroadbandBearer *self,
typedef enum {
DISCONNECT_3GPP_CONTEXT_STEP_FIRST = 0,
DISCONNECT_3GPP_CONTEXT_STEP_NDISDUP,
- DISCONNECT_3GPP_CONTEXT_STEP_DHCP,
+ DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY,
DISCONNECT_3GPP_CONTEXT_STEP_LAST
} Disconnect3gppContextStep;
@@ -413,7 +448,7 @@ disconnect_3gpp_finish (MMBroadbandBeare
static void disconnect_3gpp_context_step (Disconnect3gppContext *ctx);
static gboolean
-disconnect_retry_dhcp_check_cb (MMBroadbandBearerHuawei *self)
+disconnect_retry_ndisstatqry_check_cb (MMBroadbandBearerHuawei *self)
{
Disconnect3gppContext *ctx;
@@ -430,11 +465,12 @@ disconnect_retry_dhcp_check_cb (MMBroadb
}
static void
-disconnect_dhcp_check_ready (MMBaseModem *modem,
+disconnect_ndisstatqry_check_ready (MMBaseModem *modem,
GAsyncResult *res,
MMBroadbandBearerHuawei *self)
{
Disconnect3gppContext *ctx;
+ const gchar *response;
ctx = self->priv->disconnect_pending;
g_assert (ctx != NULL);
@@ -442,18 +478,68 @@ disconnect_dhcp_check_ready (MMBaseModem
/* Balance refcount */
g_object_unref (self);
- /* If any response give, we're still connected */
- if (mm_base_modem_at_command_full_finish (modem, res, NULL)) {
- /* Setup timeout to retry the same step */
- g_timeout_add_seconds (1,
- (GSourceFunc)disconnect_retry_dhcp_check_cb,
- g_object_ref (self));
- return;
+ response = mm_base_modem_at_command_full_finish (modem, res, NULL);
+ if (!response) {
+ mm_dbg ("%s: modem doesn't support ndisstatqry command", __func__);
+ goto failed;
+ } else {
+ gchar **ndisstatqry;
+ gchar **ndisstate;
+ gchar *status;
+ guint connect_status;
+ guint index;
+
+ ndisstatqry = g_strsplit (response, "^NDISSTATQRY:", 0);
+ if (!ndisstatqry) {
+ mm_dbg ("%s: No NDISSTATQRY found\n", __func__);
+ goto failed;
+ }
+ for (index = 0; ndisstatqry[index]; index++) {
+ if (!strstr (ndisstatqry[index], ",")) {
+ continue;
+ }
+ ndisstate = g_strsplit (ndisstatqry[index], ",", 0);
+ if (!ndisstate) {
+ mm_dbg ("%s: No state found\n", __func__);
+ g_strfreev (ndisstatqry);
+ goto failed;
+ }
+ status = g_strstrip (ndisstate[0]);
+ if (!mm_get_uint_from_str (status, &connect_status)) {
+ mm_dbg ("%s: Get connect status failed\n", __func__);
+ g_strfreev (ndisstate);
+ g_strfreev (ndisstatqry);
+ goto failed;
+ }
+ g_strfreev (ndisstate);
+ if (connect_status == 1) {
+ mm_dbg ("%s: connection is still connected\n", __func__);
+ break;
+ }
+ }
+ g_strfreev (ndisstatqry);
+
+ if (connect_status != 0) { /* Still in connected */
+ /* Setup timeout to retry the same step */
+ g_timeout_add_seconds (1,
+ (GSourceFunc)disconnect_retry_ndisstatqry_check_cb,
+ g_object_ref (self));
+ return;
+ }
}
/* Success! */
ctx->step++;
disconnect_3gpp_context_step (ctx);
+ return;
+
+failed:
+ ctx->self->priv->disconnect_pending = NULL;
+ g_simple_async_result_set_error (ctx->result,
+ MM_MOBILE_EQUIPMENT_ERROR,
+ MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED,
+ "Disconnection attempt not supported");
+ disconnect_3gpp_context_complete_and_free (ctx);
}
static void
@@ -506,7 +592,7 @@ disconnect_3gpp_context_step (Disconnect
g_object_ref (ctx->self));
return;
- case DISCONNECT_3GPP_CONTEXT_STEP_DHCP:
+ case DISCONNECT_3GPP_CONTEXT_STEP_NDISSTATQRY:
/* If too many retries (1s of wait between the retries), failed */
if (ctx->check_count > 10) {
/* Clear context */
@@ -523,12 +609,12 @@ disconnect_3gpp_context_step (Disconnect
ctx->check_count++;
mm_base_modem_at_command_full (ctx->modem,
ctx->primary,
- "^DHCP?",
+ "^NDISSTATQRY?",
3,
FALSE,
FALSE,
NULL,
- (GAsyncReadyCallback)disconnect_dhcp_check_ready,
+ (GAsyncReadyCallback)disconnect_ndisstatqry_check_ready,
g_object_ref (ctx->self));
return;
Attachment:
change_to_ndisstatqry.patch
Description: change_to_ndisstatqry.patch