// 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) {
    PLOG(WARNING) << "Can't open '" << filename << "'";
    return nullptr;
  }

  if (fstat(fd, &st) == -1) {
    PLOG(WARNING) << "Can't fstat '" << filename << "'";
    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) {
    PLOG(WARNING) << "Cannot read contents of PRL file \"" << filename << "\"";
    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;
}
