Bug 887485 - Wifi code needs to issue fwreload to netd as part of initialization. r=mrbkap
authorVincent Chang <vchang@mozilla.com>
Tue, 30 Jul 2013 16:07:13 +0800
changeset 153632 d144ffab454362f834974dc1a1c843dee85212c2
parent 153631 eb3e049e7558f21c93c771bd66a6d7bec21161ee
child 153633 54434a926c5f2f8ff7506499a400ebb56d7ee2a6
child 154315 4f36a65d85e7c86d9be9f4a141d72f7700ff6cf4
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs887485
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 887485 - Wifi code needs to issue fwreload to netd as part of initialization. r=mrbkap
dom/system/gonk/NetworkManager.js
dom/system/gonk/net_worker.js
dom/system/gonk/nsINetworkManager.idl
dom/wifi/WifiWorker.js
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -429,16 +429,37 @@ NetworkManager.prototype = {
     this.controlMessage(params, function(result) {
       let success = result.resultCode >= NETD_COMMAND_OKAY &&
                     result.resultCode < NETD_COMMAND_ERROR;
       callback.networkStatsAvailable(success, result.rxBytes,
                                      result.txBytes, result.date);
     });
   },
 
+  setWifiOperationMode: function setWifiOperationMode(interfaceName, mode, callback) {
+    debug("setWifiOperationMode on " + interfaceName + " to " + mode);
+
+    let params = {
+      cmd: "setWifiOperationMode",
+      ifname: interfaceName,
+      mode: mode
+    };
+
+    params.report = true;
+    params.isAsync = true;
+
+    this.controlMessage(params, function(result) {
+      if (isError(result.resultCode)) {
+        callback.wifiOperationModeResult("netd command error");
+      } else {
+        callback.wifiOperationModeResult(null);
+      }
+    });
+  },
+
   // Helpers
 
   controlMessage: function controlMessage(params, callback) {
     if (callback) {
       let id = callback.name;
       params.id = id;
       this.controlCallbacks[id] = callback;
     }
--- a/dom/system/gonk/net_worker.js
+++ b/dom/system/gonk/net_worker.js
@@ -161,16 +161,28 @@ function updateUpStreamSuccess(params) {
 }
 
 function updateUpStreamFail(params) {
   // Notify the main thread.
   postMessage(params);
   return true;
 }
 
+function wifiOperationModeFail(params) {
+  // Notify the main thread.
+  postMessage(params);
+  return true;
+}
+
+function wifiOperationModeSuccess(params) {
+  // Notify the main thread.
+  postMessage(params);
+  return true;
+}
+
 /**
  * Get network interface properties from the system property table.
  *
  * @param ifname
  *        Name of the network interface.
  */
 function getIFProperties(ifname) {
   return {
@@ -796,16 +808,28 @@ function getNetworkInterfaceStats(params
   params.rxBytes = -1;
   params.txBytes = -1;
   params.date = new Date();
 
   chain(params, gNetworkInterfaceStatsChain, networkInterfaceStatsFail);
   return true;
 }
 
+let gWifiOperationModeChain = [wifiFirmwareReload,
+                               wifiOperationModeSuccess];
+
+/**
+ * handling main thread's reload Wifi firmware request
+ */
+function setWifiOperationMode(params) {
+  debug("setWifiOperationMode: " + params.ifname + " " + params.mode);
+  chain(params, gWifiOperationModeChain, wifiOperationModeFail);
+  return true;
+}
+
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("Network Worker: " + s + "\n");
   };
 } else {
   debug = function (s) {};
 }
--- a/dom/system/gonk/nsINetworkManager.idl
+++ b/dom/system/gonk/nsINetworkManager.idl
@@ -103,20 +103,33 @@ interface nsIWifiTetheringCallback : nsI
 interface nsINetworkStatsCallback : nsISupports
 {
   void networkStatsAvailable(in boolean success,
                              in unsigned long rxBytes,
                              in unsigned long txBytes,
                              in jsval date);
 };
 
+[scriptable, function, uuid(9ede8720-f8bc-11e2-b778-0800200c9a66)]
+interface nsIWifiOperationModeCallback : nsISupports
+{
+  /**
+   * Callback function used to report result to WifiManager.
+   *
+   * @param error
+   *        An error message if the operation wasn't successful,
+   *        or `null` if it was.
+   */
+  void wifiOperationModeResult(in jsval error);
+};
+
 /**
  * Manage network interfaces.
  */
-[scriptable, uuid(f39a0fb6-2752-47d2-943e-a0cdd3e43494)]
+[scriptable, uuid(5b22c620-f8b9-11e2-b778-0800200c9a66)]
 interface nsINetworkManager : nsISupports
 {
   /**
    * Register the given network interface with the network manager.
    *
    * Consumers will be notified with the 'network-interface-registered'
    * observer notification.
    *
@@ -203,9 +216,24 @@ interface nsINetworkManager : nsISupport
    *        Select the Network interface to request estats.
    *
    * @param callback
    *        Callback to notify result and provide stats, connectionType
    *        and the date when stats are retrieved
    */
   void getNetworkInterfaceStats(in DOMString networkName, in nsINetworkStatsCallback callback);
 
+  /**
+   * Reload Wifi firmware to specific operation mode.
+   *
+   * @param interfaceName
+   *        Wifi Network interface name.
+   *
+   * @param mode
+   *        AP  - Access pointer mode.
+   *        P2P - Peer to peer connection mode.
+   *        STA - Station mode.
+   *
+   * @param callback
+   *        Callback to notify Wifi firmware reload result.
+   */
+  void setWifiOperationMode(in DOMString interfaceName, in DOMString mode, in nsIWifiOperationModeCallback callback);
 };
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1219,46 +1219,56 @@ var WifiManager = (function() {
         WifiNetworkInterface.gateway = null;
         WifiNetworkInterface.dns1 = null;
         WifiNetworkInterface.dns2 = null;
         Services.obs.notifyObservers(WifiNetworkInterface,
                                      kNetworkInterfaceStateChangedTopic,
                                      null);
 
         prepareForStartup(function() {
-          loadDriver(function (status) {
-            if (status < 0) {
+          gNetworkManager.setWifiOperationMode(ifname,
+                                               WIFI_FIRMWARE_STATION,
+                                               function (status) {
+            if (status) {
               callback(status);
               manager.state = "UNINITIALIZED";
               return;
             }
 
-            function doStartSupplicant() {
-              cancelWaitForDriverReadyTimer();
-              startSupplicant(function (status) {
-                if (status < 0) {
-                  unloadDriver(function() {
-                    callback(status);
+            loadDriver(function (status) {
+              if (status < 0) {
+                callback(status);
+                manager.state = "UNINITIALIZED";
+                return;
+              }
+
+              function doStartSupplicant() {
+                cancelWaitForDriverReadyTimer();
+                startSupplicant(function (status) {
+                  if (status < 0) {
+                    unloadDriver(function() {
+                      callback(status);
+                    });
+                    manager.state = "UNINITIALIZED";
+                    return;
+                  }
+
+                  manager.supplicantStarted = true;
+                  enableInterface(ifname, function (ok) {
+                    callback(ok ? 0 : -1);
                   });
-                  manager.state = "UNINITIALIZED";
-                  return;
-                }
-
-                manager.supplicantStarted = true;
-                enableInterface(ifname, function (ok) {
-                  callback(ok ? 0 : -1);
                 });
-              });
-            }
-
-            // Driver startup on certain platforms takes longer than it takes for us
-            // to return from loadDriver, so wait 2 seconds before starting
-            // the supplicant to give it a chance to start.
-            createWaitForDriverReadyTimer(doStartSupplicant);
-         });
+              }
+
+              // Driver startup on certain platforms takes longer than it takes for us
+              // to return from loadDriver, so wait 2 seconds before starting
+              // the supplicant to give it a chance to start.
+              createWaitForDriverReadyTimer(doStartSupplicant);
+           });
+          });
         });
       });
     } else {
       // Note these following calls ignore errors. If we fail to kill the
       // supplicant gracefully, then we need to continue telling it to die
       // until it does.
       terminateSupplicant(function (ok) {
         manager.connectionDropped(function () {