cromo: Expose DBus method to set network registration preference.

The Gobi modem attempts to register with CDMA 1x RTT first before trying
EVDO.  If CDMA 1x RTT is not available, it will hang the registration
process.  Since the call box can only emulate one technology, this
method can be used to force the modem to go directly to EVDO.

BUG=chromium-os:36951
TEST=cellular_Smoke (--technology=EVDO)

Change-Id: I62ff1e1d969961b79680250d3a41ca1902df409f
Reviewed-on: https://gerrit.chromium.org/gerrit/39274
Reviewed-by: Arman Uguray <armansito@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Ready: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
diff --git a/gobi_modem.cc b/gobi_modem.cc
index d2c7eb7..3c3b71a 100644
--- a/gobi_modem.cc
+++ b/gobi_modem.cc
@@ -1437,6 +1437,48 @@
   }
 }
 
+void GobiModem::SetNetworkPreference(const int32_t &value,
+                                     DBus::Error& error) {
+  LOG(INFO) << __func__ << ": " << value;
+
+  DBus::Error api_connect_error;
+  ScopedApiConnection connection(*this);
+  connection.ApiConnect(api_connect_error);
+
+  ULONG preference;
+  switch (value) {
+    case kNetworkPreferenceAutomatic:
+      preference = gobi::kRegistrationTechnologyAutomatic;
+      break;
+    case kNetworkPreferenceCdma1xRtt:
+      preference = gobi::kRegistrationTechnologyCdma |
+                   (gobi::kRegistrationTechnologyPreferenceCdma1xRtt << 2);
+      break;
+    case kNetworkPreferenceCdmaEvdo:
+      preference = gobi::kRegistrationTechnologyCdma |
+                   (gobi::kRegistrationTechnologyPreferenceCdmaEvdo << 2);
+      break;
+    case kNetworkPreferenceGsm:
+      preference = gobi::kRegistrationTechnologyUmts |
+                   (gobi::kRegistrationTechnologyPreferenceUmtsGsm << 2);
+      break;
+    case kNetworkPreferenceWcdma:
+      preference = gobi::kRegistrationTechnologyUmts |
+                   (gobi::kRegistrationTechnologyPreferenceUmtsWcdma << 2);
+      break;
+    default:
+      LOG(ERROR) << __func__ << ": Invalid technology " << value;
+      error.set(kSdkError, "SetNetworkPreference");
+      return;
+  }
+  ULONG rc = sdk_->SetNetworkPreference(
+                 preference, gobi::kRegistrationPreferencePersistent);
+  if (rc != 0 && rc != gobi::kOperationHasNoEffect) {
+    LOG(ERROR) << "Failed to set network registration preference: " << rc;
+    error.set(kSdkError, "SetNetworkPreference");
+  }
+}
+
 void GobiModem::ClearIdleCallbacks() {
   for (std::set<guint>::iterator it = idle_callback_ids_.begin();
        it != idle_callback_ids_.end();
@@ -1540,7 +1582,6 @@
   if (pending_enable_ != NULL) {
     FinishEnable(error);
     LOG(INFO) << "PowerModeHandler: finishing deferred call";
-
   }
 }
 
diff --git a/gobi_modem.h b/gobi_modem.h
index 9e57fe5..6293ed0 100644
--- a/gobi_modem.h
+++ b/gobi_modem.h
@@ -130,6 +130,14 @@
       public DBus::PropertiesAdaptor,
       public DBus::ObjectAdaptor {
  public:
+  enum NetworkPreference {
+    kNetworkPreferenceAutomatic = 0,
+    kNetworkPreferenceCdma1xRtt = 1,
+    kNetworkPreferenceCdmaEvdo = 2,
+    kNetworkPreferenceGsm = 3,
+    kNetworkPreferenceWcdma = 4
+  };
+
   typedef std::map<ULONG, int> StrengthMap;
 
   GobiModem(DBus::Connection& connection,
@@ -206,6 +214,8 @@
   virtual void InjectFault(const std::string& name,
                            const int32_t &value,
                            DBus::Error& error);
+  virtual void SetNetworkPreference(const int32_t &value,
+                                    DBus::Error& error);
 
   void ClearIdleCallbacks();
 
diff --git a/gobi_sdk_wrapper.h b/gobi_sdk_wrapper.h
index 18a90db..82b5205 100644
--- a/gobi_sdk_wrapper.h
+++ b/gobi_sdk_wrapper.h
@@ -305,6 +305,27 @@
   kPinStatusPermanentlyBlocked = 5
 };
 
+enum RegistrationTechnologyPreference {
+  kRegistrationTechnologyAutomatic = 0,
+  kRegistrationTechnologyCdma = 1,
+  kRegistrationTechnologyUmts = 2
+};
+
+enum RegistrationTechnologyPreferenceCdma {
+  kRegistrationTechnologyPreferenceCdma1xRtt = 2,
+  kRegistrationTechnologyPreferenceCdmaEvdo = 4
+};
+
+enum RegistrationTechnologyPreferenceUmts {
+  kRegistrationTechnologyPreferenceUmtsGsm = 1,
+  kRegistrationTechnologyPreferenceUmtsWcdma = 2
+};
+
+enum RegistrationPreferencePersistence {
+  kRegistrationPreferencePersistent = 0,
+  kRegistrationPreferencePowerCycleOnly = 1
+};
+
 typedef struct {
   ULONG radioInterface;
   ULONG activeBandClass;
diff --git a/modem_gobi.xml b/modem_gobi.xml
index e9fa452..0ac48b5 100644
--- a/modem_gobi.xml
+++ b/modem_gobi.xml
@@ -79,6 +79,22 @@
       </arg>
     </method>
 
+    <method name="SetNetworkPreference">
+      <tp:docstring>
+        Sets the network registration preference.
+      </tp:docstring>
+      <arg name="protocol" type="i" direction="in">
+        <tp:docstring>
+          Indicate which protocol to register with:
+            0: Automatic
+            1: CDMA 1xRTT
+            2: CDMA 1xEV-DO
+            3: GSM
+            4: WCDMA
+        </tp:docstring>
+      </arg>
+    </method>
+
     <signal name="DormancyStatus">
       <tp:docstring>
         Indicates that the dormancy status of the modem changed.