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

_______________________________________________
networkmanager-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/networkmanager-list

Reply via email to