// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gobi-cromo-plugin/gobi_cdma_modem.h"

extern "C" {
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
}

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/stringprintf.h>
#include <cromo/carrier.h>
#include <mm/mm-modem.h>

#include "gobi-cromo-plugin/gobi_modem_handler.h"

using base::FilePath;
using base::StringPrintf;
using std::string;
using utilities::DBusPropertyMap;

// static
static const char kExecPostActivationStepsCookieCrumbFormat[] =
    "/tmp/cromo-modem-exec-post-activation-steps-%s";

//======================================================================
// Construct and destruct

GobiCdmaModem::GobiCdmaModem(DBus::Connection& connection,
                             const DBus::Path& path,
                             const gobi::DeviceElement& device,
                             gobi::Sdk* sdk,
                             GobiModemHelper *modem_helper)
    : GobiModem(connection, path, device, sdk, modem_helper),
      activation_time_(METRIC_BASE_NAME "Activation", 0, 150000, 20),
      activation_in_progress_(false),
      force_activated_status_(false) {
}

GobiCdmaModem::~GobiCdmaModem() {
}

void GobiCdmaModem::Init() {
  GobiModem::Init();

  DBus::Error error;
  ScopedApiConnection connection(*this);
  connection.ApiConnect(error);
  if (error.is_set()) {
    LOG(ERROR) << "Failed to connect to Gobi modem, "
               << "skipping post activation steps";
    return;
  }
  int activation_state = GobiCdmaModem::GetMmActivationState();
  if (activation_state == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED &&
      ShouldExecPostActivationSteps()) {
    LOG(INFO) << "Executing post activation steps";
    PerformPostActivationSteps();
  }
}

void GobiCdmaModem::GetCdmaRegistrationState(ULONG* cdma_1x_state,
                                             ULONG* cdma_evdo_state,
                                             ULONG* roaming_state,
                                             DBus::Error& error) {
  ULONG reg_state;
  ULONG l1;
  WORD w1, w2;
  BYTE radio_interfaces[10];
  BYTE num_radio_interfaces = sizeof(radio_interfaces)/sizeof(BYTE);
  CHAR netname[32];

  ULONG rc = sdk_->GetServingNetwork(&reg_state, &l1, &num_radio_interfaces,
                                     radio_interfaces, roaming_state,
                                     &w1, &w2, sizeof(netname), netname);
  if (rc != 0) {
    // All errors are treated as if the modem is not yet registered.
    *cdma_1x_state = gobi::kUnregistered;
    *cdma_evdo_state = gobi::kUnregistered;
    *roaming_state = gobi::kRoaming;  // Should not matter
    return;
  }

  // There is no guarantee that both interfaces will be included in
  // the array, so assume not registered.
  *cdma_1x_state = gobi::kUnregistered;
  *cdma_evdo_state = gobi::kUnregistered;
  for (int i = 0; i < num_radio_interfaces; i++) {
    if (radio_interfaces[i] == gobi::kRfiCdma1xRtt)
      *cdma_1x_state = reg_state;
    else if (radio_interfaces[i] == gobi::kRfiCdmaEvdo)
      *cdma_evdo_state = reg_state;
  }
}

int GobiCdmaModem::GetMmActivationState() {
  ULONG device_activation_state;
  ULONG rc;
  rc = sdk_->GetActivationState(&device_activation_state);
  if (rc != 0) {
    LOG(ERROR) << "GetActivationState: " << rc;
    return -1;
  }
  LOG(INFO) << "Device activation state: " << device_activation_state;
  if (activation_in_progress_ && !force_activated_status_) {
    LOG(INFO) << "Device activation still in progress";
    return MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
  }
  if (device_activation_state == 1) {
    return MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
  }

  if (force_activated_status_) {
    // |force_activated_status_| is set to true for testing purposes via
    // org.chromium.ModemManager.Modem.Gobi.ForceModemActivatedStatus.
    LOG(INFO) << __func__ << "Forcing modem activation status to activated";
    return MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
  }

  ULONG firmware_id;
  ULONG technology_id;
  ULONG carrier_id;
  ULONG region;
  ULONG gps_capability;
  const Carrier *carrier = nullptr;
  rc = sdk_->GetFirmwareInfo(&firmware_id,
                             &technology_id,
                             &carrier_id,
                             &region,
                             &gps_capability);
  if (rc == 0) {
    carrier = handler_->server().FindCarrierByCarrierId(carrier_id);
    if (!carrier)
      LOG(WARNING) << "Carrier lookup failed for ID " << carrier_id;
  } else {
    LOG(WARNING) << "GetFirmwareInfo failed: " << rc;
  }
  if (!carrier)
    return MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;

  // Is the modem de-activated, or is there an activation in flight?
  switch (carrier->activation_method()) {
    case Carrier::kOmadm: {
        ULONG session_state;
        ULONG session_type;
        ULONG failure_reason;
        BYTE retry_count;
        WORD session_pause;
        WORD time_remaining;  // For session pause
        rc = sdk_->OMADMGetSessionInfo(
            &session_state, &session_type, &failure_reason, &retry_count,
            &session_pause, & time_remaining);
        if (rc != 0) {
          // kNoTrackingSessionHasBeenStarted -> modem has never tried
          // to run OMADM; this is not an error condition.
          if (rc != gobi::kNoTrackingSessionHasBeenStarted) {
            LOG(ERROR) << "Could not get omadm state: " << rc;
          }
          return MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED;
        }
        return (session_state <= gobi::kOmadmMaxFinal) ?
            MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED :
            MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
      }
      break;
    case Carrier::kOtasp:
      return (device_activation_state == gobi::kNotActivated) ?
          MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED :
          MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
      break;
    default:  // This is a UMTS carrier; we count it as activated
      return MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
  }
}

//======================================================================
// Callbacks and callback utilities

static GobiCdmaModem* LookupCdmaModem(GobiModemHandler *handler,
                                       const DBus::Path &path) {
  return static_cast<GobiCdmaModem *>(handler->LookupByDbusPath(path));
}

static BYTE* GetFileContents(const char* filename, ULONG* num_bytes) {
  int bytes_read;
  int fd;
  struct stat st;

  fd = open(filename, O_RDONLY);
  if (fd == -1) {
    LOG(WARNING) << "Can't open '" << filename << "': " << strerror(errno);
    return nullptr;
  }

  if (fstat(fd, &st) == -1) {
    LOG(WARNING) << "Can't fstat '" << filename << "': " << strerror(errno);
    close(fd);
    return nullptr;
  }

  *num_bytes = st.st_size;
  BYTE* buffer = new BYTE[*num_bytes];
  bytes_read = read(fd, reinterpret_cast<char*>(buffer), *num_bytes);

  if (bytes_read < 0) {
    LOG(WARNING) << "Cannot read contents of PRL file \"" << filename
                 << "\": " << strerror(errno);
    delete [] buffer;
    close(fd);
    return nullptr;
  }

  LOG(INFO) << "Read " << bytes_read << " bytes from file \""
            << filename << "\"";
  *num_bytes = bytes_read;
  close(fd);
  return buffer;
}

gboolean GobiCdmaModem::ActivationStatusCallback(gpointer data) {
  ActivationStatusArgs* args = static_cast<ActivationStatusArgs*>(data);
  LOG(INFO) << "OTASP status callback: " << args->device_activation_state;
  GobiCdmaModem* modem = LookupCdmaModem(handler_, *args->path);

  if (modem) {
    if (args->device_activation_state == gobi::kActivated ||
        args->device_activation_state == gobi::kNotActivated) {
      modem->ActivationFinished();
    }
    if (args->device_activation_state == gobi::kActivated) {
      DBus::Error error;
      // Reset modem as per SDK documentation. This has the side-effect of
      // causing the modem to disappear from the DBus bus, which will cause the
      // connection manager to lose track of its state, but when we come back,
      // we'll be in the right state.

      // Do not send the ActivationStateChanged signal here as it will
      // only serve to encourage flimflam to start issuing new
      // commands and the modem is about to disappear anyway.
      modem->ResetModem(error);
    } else if (args->device_activation_state == gobi::kNotActivated) {
      modem->SendActivationStateChanged(
          MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED);
    }
  }
  return FALSE;
}

static void OMADMAlertCallback(ULONG type, USHORT id) {
  LOG(INFO) << "OMDADMAlertCallback type " << type << " id " << id;
}

gboolean GobiCdmaModem::OmadmStateDeviceConfigureCallback(gpointer data) {
  OmadmStateArgs* args = static_cast<OmadmStateArgs*>(data);
  LOG(INFO) << "OMA-DM State Device Configure Callback: "
            << args->session_state;
  GobiCdmaModem* modem = LookupCdmaModem(handler_, *args->path);
  bool activation_done = true;
  if (modem) {
    switch (args->session_state) {
      case gobi::kOmadmComplete:
        modem->SendActivationStateChanged(
            MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
        // Activation completed successfully, the modem will reset.  Mark the
        // modem to execute post activation steps when it's next seen.
        modem->MarkForExecPostActivationStepsAfterReset();
        break;
      case gobi::kOmadmFailed:
        LOG(INFO) << "OMA-DM device configuration failure reason: "
                  << args->failure_reason;
        // fall through
      case gobi::kOmadmUpdateInformationUnavailable:
        modem->SendActivationStateChanged(
            MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED);
        break;
      default:
        activation_done = false;
    }
  }

  if (activation_done) {
    modem->sdk_->SetOMADMStateCallback(nullptr);
    modem->ActivationFinished();
  }

  return FALSE;
}

gboolean GobiCdmaModem::OmadmStateClientPrlUpdateCallback(gpointer data) {
  OmadmStateArgs* args = static_cast<OmadmStateArgs*>(data);
  LOG(INFO) << "OMA-DM State Client PRL Update Callback: "
            << args->session_state;
  GobiCdmaModem* modem = LookupCdmaModem(handler_, *args->path);
  bool done = true;
  switch (args->session_state) {
    case gobi::kOmadmComplete:
      LOG(INFO) << "OMA-DM client initiated PRL completed, "
                << "information updated.";
      break;
    case gobi::kOmadmUpdateInformationUnavailable:
      LOG(INFO) << "OMA-DM client initiated PRL completed, "
                << "update information unavailable (PRL up-to-date).";
      break;
    case gobi::kOmadmFailed:
      LOG(INFO) << "OMA-DM client initiated PRL update failure reason: "
                << args->failure_reason;
      break;
    case gobi::kOmadmPrlDownloaded:
      LOG(INFO) << "OMA-DM client initiated PRL completed, PRL downloaded.";
      break;
    default:
      done = false;
      break;
  }
  if (done) {
    modem->sdk_->SetOMADMStateCallback(nullptr);
    modem->activation_in_progress_ = false;
  }
  return FALSE;
}

void GobiCdmaModem::SignalStrengthHandler(INT8 signal_strength,
                                          ULONG radio_interface) {
  unsigned long ss_percent = MapDbmToPercent(signal_strength);

  ULONG cdma_evdo_state;
  ULONG cdma_1x_state;
  ULONG roaming_state;
  DBus::Error error;
  GetCdmaRegistrationState(&cdma_1x_state, &cdma_evdo_state,
                           &roaming_state, error);
  if ((radio_interface == gobi::kRfiCdma1xRtt &&
       cdma_1x_state == gobi::kRegistered) ||
      (radio_interface == gobi::kRfiCdmaEvdo &&
       cdma_evdo_state == gobi::kRegistered)) {
    SignalQuality(ss_percent);  // NB:  org.freedesktop...Modem.Cdma
  }
}


void GobiCdmaModem::RegisterCallbacks() {
  GobiModem::RegisterCallbacks();
  sdk_->SetOMADMAlertCallback(OMADMAlertCallback);
  sdk_->SetActivationStatusCallback(ActivationStatusCallbackTrampoline);
  sdk_->SetOMADMStateCallback(nullptr);
}

//======================================================================
// DBUS Methods: overridden Modem.Simple
void GobiCdmaModem::Connect(const DBusPropertyMap& properties,
                            DBus::Error& error) {
  if (activation_in_progress_) {
    LOG(WARNING) << "Connect while modem is activating";
    error.set(kConnectError, "Modem is activating");
    return;
  }
  GobiModem::Connect(properties, error);
}

void GobiCdmaModem::GetTechnologySpecificStatus(DBusPropertyMap* properties) {
  WORD prl_version;
  ULONG rc = sdk_->GetPRLVersion(&prl_version);
  if (rc == 0) {
    (*properties)["prl_version"].writer().append_uint16(prl_version);
  }

  int activation_state = GetMmActivationState();
  if (activation_state >= 0) {
    (*properties)["activation_state"].writer().append_uint32(activation_state);
  }
}

//======================================================================
// DBUS Methods: ModemGobi
void GobiCdmaModem::ForceModemActivatedStatus(DBus::Error& error) {
  force_activated_status_ = true;
}

//======================================================================
// DBUS Methods: ModemCDMA

// NB: This function only uses the DBus::Error field to return
// kOperationInitiatedError.  Other errors are returned as uint32_t
// values from MM_MODEM_CDMA_ACTIVATION_ERROR
uint32_t GobiCdmaModem::Activate(const std::string& carrier_name,
                             DBus::Error& activation_started_error) {
  LOG(INFO) << "Activate(" << carrier_name << ")";

  // Check current firmware to see whether it's for the requested carrier
  ULONG firmware_id;
  ULONG technology;
  ULONG carrier_id;
  ULONG region;
  ULONG gps_capability;

  ULONG rc = sdk_->GetFirmwareInfo(&firmware_id,
                                   &technology,
                                   &carrier_id,
                                   &region,
                                   &gps_capability);

  if (0 != rc) {
    LOG(ERROR) << "GetFirmwareInfo: " << rc;
    return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
  }
  const Carrier *carrier;
  if (carrier_name.empty()) {
    carrier = handler_->server().FindCarrierByCarrierId(carrier_id);
    if (!carrier) {
      LOG(ERROR) << "Unknown carrier id: " << carrier_id;
      return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
    }
  } else {
    carrier = handler_->server().FindCarrierByName(carrier_name);
    if (!carrier) {
      LOG(WARNING) << "Unknown carrier: " << carrier_name;
      return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
    }
    if (carrier_id != carrier->carrier_id()) {
      LOG(WARNING) << "Current device firmware does not match the requested"
          "carrier.";
      LOG(WARNING) << "SetCarrier operation must be done before activating.";
      return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
    }
  }

  DBus::Error internal_error;
  DBusPropertyMap status = GetStatus(internal_error);
  if (internal_error.is_set()) {
    LOG(ERROR) << internal_error;
    return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
  }

  DBusPropertyMap::const_iterator p;
  p = status.find("no_signal");
  if (p != status.end()) {
    LOG(ERROR) << "no_signal";
    return MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL;
  }

  p = status.find("activation_state");
  if (p != status.end()) {
    try {  // Style guide violation forced by dbus-c++
      LOG(INFO) << "Current activation state: "
                << p->second.reader().get_uint32();
    } catch (const DBus::Error &e) {
      LOG(ERROR) << e;
      return MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
    }
  }

  uint32_t ret;
  activation_time_.Start();
  switch (carrier->activation_method()) {
    case Carrier::kOmadm:
      ret = ActivateOmadm();
      break;

    case Carrier::kOtasp:
      if (carrier->CdmaCarrierSpecificActivate(status, this, &ret)) {
        // ret is set in call above
        break;
      }
      if (carrier->activation_code() == nullptr) {
        LOG(ERROR) << "Number was not supplied for OTASP activation";
        ret = MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
        break;
      }
      ret = ActivateOtasp(carrier->activation_code());
      break;

    default:
      LOG(ERROR) << "Unknown activation method: "
                   << carrier->activation_method();
      ret = MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN;
      break;
  }
  if (ret == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR)
    // Record that activation is in progress
    activation_in_progress_ = true;

  return ret;
}

void GobiCdmaModem::ActivateManual(const DBusPropertyMap& const_properties,
                               DBus::Error &error) {
  using utilities::ExtractString;
  DBusPropertyMap properties(const_properties);

  // TODO(rochberg): Does it make sense to set defaults from the
  // modem's current state?
  const char* spc = nullptr;
  const char* prl_file = nullptr;
  uint16_t system_id = 65535;
  const char* mdn = nullptr;
  const char* min = nullptr;
  const char* mnha = nullptr;
  const char* mnaaa = nullptr;

  DBusPropertyMap::const_iterator p;
  // try/catch required to cope with dbus-c++'s handling of type
  // mismatches
  try {  // Style guide violation forced by dbus-c++
    spc = ExtractString(properties, "spc", "000000", error);
    prl_file = ExtractString(properties, "prlfile", nullptr, error);
    p = properties.find("system_id");
    if (p != properties.end()) {
      system_id = p->second.reader().get_uint16();
    }
    mdn = ExtractString(properties, "mdn", "",  error);
    min = ExtractString(properties, "min", "", error);
    mnha = ExtractString(properties, "mnha", nullptr, error);
    mnaaa = ExtractString(properties, "mnaaa", nullptr, error);
  } catch (DBus::Error e) {
    error = e;
    return;
  }
  BYTE* prl = nullptr;
  ULONG prl_size = 0;
  if (prl_file) {
    prl = GetFileContents(prl_file, &prl_size);
    if (!prl) {
      error.set(kActivationError, "PRL file cannot be read");
      return;
    }
  }
  ULONG rc = sdk_->ActivateManual(spc,
                                  system_id,
                                  mdn,
                                  min,
                                  prl_size,
                                  prl,
                                  mnha,
                                  mnaaa);
  delete [] prl;
  ENSURE_SDK_SUCCESS(ActivateManual, rc, kActivationError);
}

void GobiCdmaModem::ActivateManualDebug(
    const std::map<std::string, std::string>& properties,
    DBus::Error &error) {
  DBusPropertyMap output;

  for (std::map<std::string, std::string>::const_iterator i =
           properties.begin();
       i != properties.end();
       ++i) {
    if (i->first != "system_id") {
      output[i->first].writer().append_string(i->second.c_str());
    } else {
      const std::string& value = i->second;
      char *end;
      errno = 0;
      uint16_t system_id = static_cast<uint16_t>(
          strtoul(value.c_str(), &end, 10));
      if (errno != 0 || *end != '\0') {
        LOG(ERROR) << "Bad system_id: " << value;
        error.set(kSdkError, "Bad system_id");
        return;
      }
      output[i->first].writer().append_uint16(system_id);
    }
  }
  ActivateManual(output, error);
}

uint32_t GobiCdmaModem::ActivateOmadm() {
  ULONG rc;
  LOG(INFO) << "Activating OMA-DM device configure";

  rc = sdk_->OMADMSetPRLUpdateFeature(TRUE);
  if (rc != 0) {
    LOG(ERROR) << "OMA-DM device configure activation failed to enable PRL "
               << "update: " << rc;
    return MM_MODEM_CDMA_ACTIVATION_ERROR_START_FAILED;
  }
  sdk_->SetOMADMStateCallback(OmadmStateDeviceConfigureCallbackTrampoline);
  rc = sdk_->OMADMStartSession(gobi::kConfigure);
  if (rc != 0) {
    LOG(ERROR) << "OMA-DM device configure activation failed: " << rc;
    return MM_MODEM_CDMA_ACTIVATION_ERROR_START_FAILED;
  }
  return MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR;
}

uint32_t GobiCdmaModem::ActivateOtasp(const std::string& number) {
  ULONG rc;
  LOG(INFO) << "Activating OTASP";

  rc = sdk_->ActivateAutomatic(number.c_str());
  if (rc != 0) {
    LOG(ERROR) << "OTASP activation failed: " << rc;
    return MM_MODEM_CDMA_ACTIVATION_ERROR_START_FAILED;
  }
  return MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR;
}

void GobiCdmaModem::ActivationFinished(void) {
  activation_time_.StopIfStarted();
  activation_in_progress_ = false;
}

void GobiCdmaModem::PerformPostActivationSteps() {
  activation_in_progress_ = true;
  StartClientInitiatedPrlUpdate();
}

void GobiCdmaModem::StartClientInitiatedPrlUpdate() {
  LOG(INFO) << "Activating OMA-DM client initiated PRL update";
  sdk_->SetOMADMStateCallback(OmadmStateClientPrlUpdateCallbackTrampoline);
  ULONG rc = sdk_->OMADMSetPRLUpdateFeature(TRUE);
  if (rc != 0) {
    LOG(ERROR) << "OMA-DM client initiated PRL update failed to enable PRL "
               << "update: " << rc;
    sdk_->SetOMADMStateCallback(nullptr);
    return;
  }
  rc = sdk_->OMADMStartSession(gobi::kPrlUpdate);
  if (rc != 0) {
    LOG(ERROR) << "OMA-DM client initiated PRL update failed to start: "
               << rc;
    sdk_->SetOMADMStateCallback(nullptr);
  }
}

std::string GobiCdmaModem::GetEsn(DBus::Error& error) {
  LOG(INFO) << "GetEsn";

  SerialNumbers serials;
  GetSerialNumbers(&serials, error);
  return serials.esn;
}

void GobiCdmaModem::GetRegistrationState(uint32_t& cdma_1x_state,
                                         uint32_t& cdma_evdo_state,
                                         DBus::Error& error) {
  cdma_1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
  cdma_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
  // Ignore current registration state if the modem state itself hasn't
  // transitioned to the registered state else a caller may think the modem is
  // in the registered when we have not marked it as such so other operations
  // may fail.
  if (mm_state() < MM_MODEM_STATE_REGISTERED)
    return;

  GetRegistrationStateInternal(cdma_1x_state, cdma_evdo_state, error);
}

void GobiCdmaModem::GetRegistrationStateInternal(uint32_t& cdma_1x_state,
                                                 uint32_t& cdma_evdo_state,
                                                 DBus::Error& error) {
  ULONG reg_state_evdo;
  ULONG reg_state_1x;
  ULONG roaming_state;

  cdma_1x_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
  cdma_evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;

  GetCdmaRegistrationState(&reg_state_1x, &reg_state_evdo,
                           &roaming_state, error);
  if (error.is_set())
    return;

  uint32_t mm_reg_state;

  if (roaming_state == gobi::kHome)
    mm_reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_HOME;
  else
    mm_reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING;

  if (reg_state_1x == gobi::kRegistered)
    cdma_1x_state = mm_reg_state;
  if (reg_state_evdo == gobi::kRegistered)
    cdma_evdo_state = mm_reg_state;
}

// returns <band class, band, system id>
DBus::Struct<uint32_t, std::string, uint32_t> GobiCdmaModem::GetServingSystem(
    DBus::Error& error) {
  DBus::Struct<uint32_t, std::string, uint32_t> result;
  WORD mcc, mnc, sid, nid;
  CHAR netname[32];
  ULONG reg_state;
  ULONG roaming_state;
  ULONG l1;
  BYTE radio_interfaces[10];
  BYTE num_radio_interfaces = sizeof(radio_interfaces)/sizeof(BYTE);
  LOG(INFO) << "GetServingSystem";

  ULONG rc = sdk_->GetServingNetwork(&reg_state, &l1, &num_radio_interfaces,
                                     radio_interfaces, &roaming_state,
                                     &mcc, &mnc, sizeof(netname), netname);
  ENSURE_SDK_SUCCESS_WITH_RESULT(GetServingNetwork, rc, kSdkError, result);
  LOG(INFO) << "Serving MCC/MNC: " << mcc << "/" << mnc;
  if (reg_state != gobi::kRegistered) {
    error.set(kErrorNoNetwork, "No network service is available");
    return result;
  }

  rc = sdk_->GetHomeNetwork(&mcc, &mnc,
                            sizeof(netname), netname, &sid, &nid);
  ENSURE_SDK_SUCCESS_WITH_RESULT(GetHomeNetwork, rc, kSdkError, result);

  LOG(INFO) << "Home MCC/MNC: " << mcc << "/" << mnc << " SID/NID: " << sid
            << "/" << nid << " name: " << netname;
  gobi::RfInfoInstance rf_info[10];
  BYTE rf_info_size = sizeof(rf_info) / sizeof(rf_info[0]);

  rc = sdk_->GetRFInfo(
      &rf_info_size, static_cast<BYTE*>(reinterpret_cast<void*>(&rf_info[0])));
  if (rc == gobi::kInformationElementUnavailable) {
    error.set(kErrorNoNetwork, "No network service is available");
    return result;
  } else if (rc != 0) {
    error.set(kSdkError, "GetRFInfo");
    return result;
  }

  if (rf_info_size != 0) {
    LOG(INFO) << "RF info for " << rf_info[0].radioInterface
              << " band class " << rf_info[0].activeBandClass
              << " channel "    << rf_info[0].activeChannel;
    switch (rf_info[0].activeBandClass) {
      case 0:
      case 85:          // WCDMA 800
        result._1 = 1;  // 800 Mhz band class
        break;
      case 1:
      case 81:          // WCDMA PCS 1900
        result._1 = 2;  // 1900 Mhz band class
        break;
      default:
        result._1 = 0;  // unknown band class
        break;
    }
    result._2 = "F";    // XXX bogus
  }
  result._3 = sid;

  return result;
}

uint32_t GobiCdmaModem::GetSignalQuality(DBus::Error& error) {
  return GobiModem::CommonGetSignalQuality(error);
}

void GobiCdmaModem::RegistrationStateHandler() {
  uint32_t cdma_1x_state;
  uint32_t evdo_state;
  DBus::Error error;
  bool registered = false;

  GetRegistrationStateInternal(cdma_1x_state, evdo_state, error);
  if (error.is_set())
    return;
  if (cdma_1x_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN ||
      evdo_state != MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
    registered = true;
    registration_time_.StopIfStarted();
  }
  RegistrationStateChanged(cdma_1x_state, evdo_state);
  if (registered && mm_state() <= MM_MODEM_STATE_SEARCHING)
    SetMmState(MM_MODEM_STATE_REGISTERED,
               MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);

  // TODO(ers) check data bearer technology and notify if appropriate.

  LOG(INFO) << "  => 1xRTT: " << cdma_1x_state << " EVDO: " << evdo_state;
}

void GobiCdmaModem::DataCapabilitiesHandler(BYTE num_data_caps,
                                            ULONG* data_caps) {
  // TODO(ers) explore whether we should be doing anything
  // with this event.
}

void GobiCdmaModem::SetTechnologySpecificProperties() {
  SerialNumbers serials;
  DBus::Error error;
  GetSerialNumbers(&serials, error);
  if (!error.is_set())
    Meid = serials.meid;
}

bool GobiCdmaModem::CheckEnableOk(DBus::Error &error) {
  return !activation_in_progress_;
}

void GobiCdmaModem::SendActivationStateFailed() {
  DBusPropertyMap empty;
  ActivationStateChanged(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED,
                         MM_MODEM_CDMA_ACTIVATION_ERROR_UNKNOWN,
                         empty);
}

void GobiCdmaModem::SendActivationStateChanged(uint32_t mm_activation_error) {
  DBusPropertyMap status;
  DBusPropertyMap to_send;
  DBus::Error internal_error;
  status = GetStatus(internal_error);
  if (internal_error.is_set()) {
    // GetStatus should never fail;  we are punting here.
    SendActivationStateFailed();
    return;
  }

  DBusPropertyMap::const_iterator p;
  uint32_t mm_activation_state;

  if ((p = status.find("activation_state")) == status.end()) {
    LOG(ERROR);
    SendActivationStateFailed();
    return;
  }
  try {  // Style guide violation forced by dbus-c++
    mm_activation_state = p->second.reader().get_uint32();
  } catch (const DBus::Error &e) {
    LOG(ERROR);
    SendActivationStateFailed();
    return;
  }

  if (mm_activation_error == MM_MODEM_CDMA_ACTIVATION_ERROR_TIMED_OUT &&
      mm_activation_state == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED) {
    mm_activation_error = MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR;
  }

  // TODO(rochberg):  Table drive
  if ((p = status.find("mdn")) != status.end()) {
    to_send["mdn"] = p->second;
  }
  if ((p = status.find("min")) != status.end()) {
    to_send["min"] = p->second;
  }
  if ((p = status.find("payment_url")) != status.end()) {
    to_send["payment_url"] = p->second;
  }
  if ((p = status.find("payment_url_method")) != status.end()) {
    to_send["payment_url_method"] = p->second;
  }
  if ((p = status.find("payment_url_postdata")) != status.end()) {
    to_send["payment_url_postdata"] = p->second;
  }

  ActivationStateChanged(mm_activation_state,
                         mm_activation_error,
                         to_send);
}

FilePath GobiCdmaModem::GetExecPostActivationStepsCookieCrumbPath() const {
  string path =
      StringPrintf(kExecPostActivationStepsCookieCrumbFormat,
                   device_.deviceKey);
  return FilePath::FromUTF8Unsafe(path);
}

void GobiCdmaModem::MarkForExecPostActivationStepsAfterReset() {
  // This is a best effort attempt to write out the cookie crumb so don't
  // need to check for write failures.
  base::WriteFile(GetExecPostActivationStepsCookieCrumbPath(), "", 0);
}

bool GobiCdmaModem::ShouldExecPostActivationSteps() const {
  FilePath cookie_crumb_path = GetExecPostActivationStepsCookieCrumbPath();
  if (base::PathExists(cookie_crumb_path)) {
    base::DeleteFile(cookie_crumb_path, false);
    return true;
  }
  return false;
}
