[MM][PATCH]update the NDISDUP check handle for Huawei modem



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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]