// Copyright (c) 2012 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_modem.h"
#include "gobi_modem_handler.h"
#include <sstream>

#include <dbus/dbus.h>

#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/wait.h>

extern "C" {
#include <libudev.h>
#include <time.h>
};

#include <base/logging.h>
#include <base/stringprintf.h>
#include <cromo/carrier.h>
#include <cromo/cromo_server.h>
#include <cromo/utilities.h>


// This ought to be in a header file somewhere, but if it is, I can't find it.
#ifndef NDEBUG
static const int DEBUG = 1;
#else
static const int DEBUG = 0;
#endif

#define DEFINE_ERROR(name) \
  const char* k##name##Error = "org.chromium.ModemManager.Error." #name;
#define DEFINE_MM_ERROR(name, str) \
  const char* kError##name = \
    "org.freedesktop.ModemManager.Modem.Gsm." str;

#include "gobi_modem_errors.h"
#undef DEFINE_ERROR
#undef DEFINE_MM_ERROR

static const char k2kNetworkDriver[] = "QCUSBNet2k";
static const char k3kNetworkDriver[] = "GobiNet";
static const char kUnifiedNetworkDriver[] = "gobi";

using utilities::DBusPropertyMap;

// The following constants define the granularity with which signal
// strength is reported, i.e., the number of bars.
//
// The values given here are used to compute an array of thresholds
// consisting of the values [-113, -98, -83, -68, -53], which results
// in the following mapping of signal strength as reported in dBm to
// bars displayed:
//
// <  -113             0 bars
// >= -113 and < -98   1 bar
// >=  -98 and < -83   2 bars
// >=  -83 and < -68   3 bars
// >=  -68 and < -53   4 bars
// >=  -53             5 bars

// Any reported signal strength larger than or equal to kMaxSignalStrengthDbm
// is considered full strength.
static const int kMaxSignalStrengthDbm = -53;
// Any reported signal strength smaller than kMinSignalStrengthDbm is
// considered zero strength.
static const int kMinSignalStrengthDbm = -113;
// The number of signal strength levels we want to report, ranging from
// 0 bars to kSignalStrengthNumLevels-1 bars.
static const int kSignalStrengthNumLevels = 6;

// static
// Number of times to retry StartDataSession() when it fails due to lack of
// service.
const int GobiModem::kNumStartDataSessionRetries = 10;
// Error message returned by SetCarrier() when an unknown carrier is specified.
const char GobiModemHelper::kErrorUnknownCarrier[] = "Unknown carrier name";

// Encapsulates a separate thread that calls sdk->StartDataSession.
// We need to run this on a separate thread so that we can continue to
// process DBus messages (including requests to cancel the call to
// StartDataSession).  The main thread creates an anonynmous
// SessionStarter, then deletes it when the session starter passes a
// pointer to itself as an argument to SessionStarterDoneCallback.
class SessionStarter {
 public:
  SessionStarter(gobi::Sdk *sdk,
                 GobiModem *modem,
                 const char *apn,
                 const char *username,
                 const char *password)
      : sdk_(sdk),
        modem_dbus_path_(modem->path()),
        apn_(apn),
        username_(username),
        password_(password),
        return_value_(ULONG_MAX),
        failure_reason_(ULONG_MAX),
        connect_time_(METRIC_BASE_NAME "Connect", 0, 150000, 20),
        fault_inject_sleep_time_ms_(static_cast <useconds_t> (
            modem->injected_faults_["AsyncConnectSleepMs"])) {
    // Do not save modem; it might be deleted from under us
  }

  static void *StarterThreadTrampoline(void *data) {
    SessionStarter *s = static_cast<SessionStarter *>(data);
    return s->Run();
  }

  void *Run(void) {
    connect_time_.Start();
    // A warning: there is a race here, if the modem handler is
    // deallocated while this is in flight, we'll lose sdk_.  If this
    // is a problem, we'll need to refcount sdk_.
    LOG(INFO) << "Starter thread running";
    for (int count = 0; count < GobiModem::kNumStartDataSessionRetries;
         ++count) {
      return_value_ = sdk_->StartDataSession(
          NULL,
          apn_.get(),
          NULL,  // Authentication
          username_.get(),
          password_.get(),
          &session_id_,  // OUT: session ID
          &failure_reason_);  // OUT: failure reason
      if (return_value_ != gobi::kCallFailed &&
          failure_reason_ != gobi::kReasonNoService)
        break;
      gobi::RegistrationState reg_state =
        GobiModem::GetRegistrationState(sdk_);
      if (reg_state == gobi::kRegistrationDenied)
        break;
      sleep(1);
    }
    if (return_value_ == gobi::kOperationHasNoEffect) {
      return_value_ = 0;
      failure_reason_ = 0;
    }
    if (return_value_)
      LOG(ERROR) << "StartDataSession failed with "
                 << "(" << return_value_ << ", " << failure_reason_ << ")";
    connect_time_.Stop();
    if (fault_inject_sleep_time_ms_ > 0) {
      LOG(WARNING) << "Fault injection:  connect sleeping for "
                   << fault_inject_sleep_time_ms_ << "ms";
      usleep(1000 * fault_inject_sleep_time_ms_);
    }
    LOG(INFO) << "Starter completing";
    g_idle_add(CompletionCallback, this);
    return NULL;
  }

  static gboolean CompletionCallback(void *data) {
    // Runs on main thread;
    scoped_ptr<SessionStarter> s(static_cast<SessionStarter *>(data));

    int join_rc = pthread_join(s->thread_, NULL);
    if (join_rc != 0) {
      errno = join_rc;
      PLOG(ERROR) << "Join failed";
    }

    // GobiModem::handler_ is a static
    GobiModem *modem = GobiModem::handler_->LookupByDbusPath(
        s->modem_dbus_path_);
    if (modem == NULL) {
      // The DBUs call is never completed; the object was unregistered
      // from the bus.
      LOG(ERROR) << "SessionStarter complete with no modem";
      return false;
    }
    modem->SessionStarterDoneCallback(s.get());
    return false;
  }

  void StartDataSession(DBus::Error& error) {
    // Runs on main thread
    int rc = pthread_create(
        &thread_, NULL /* attributes */, StarterThreadTrampoline, this);
    if (rc != 0) {
      errno = rc;
      PLOG(ERROR) << "Thread creation failed: " << rc;
      error.set(kConnectError, "Could not start thread");
    }
  }

  static ULONG CancelDataSession(gobi::Sdk *sdk) {
    // Runs on main thread
    LOG(WARNING) << "Cancelling in-flight data session start";

    // Horrendous hack alert; If we issue CancelStartDataSession
    // before the StartDataSession request has made much progress,
    // then the StartDataSession call ends up hanging for the entire 5
    // minute timeout.  Empirically, 100ms seems to be a long enough
    // pause, so we go for 3x that.  This solution is totally
    // unacceptable, but debugging the Gobi API isn't an option right
    // now.
    usleep(300000);

    ULONG rc;
    rc = sdk->CancelStartDataSession();
    if (rc != 0) {
      LOG(ERROR) << "CancelStartDataSession failed: " << rc;
    }
    return rc;
  }

 protected:
  gobi::Sdk *sdk_;
  DBus::Path modem_dbus_path_;

  // CharStarCopier preserves NULL-ness
  gobi::CharStarCopier apn_;
  gobi::CharStarCopier username_;
  gobi::CharStarCopier password_;

  ULONG session_id_;
  ULONG return_value_;
  ULONG failure_reason_;

  MetricsStopwatch connect_time_;
  int fault_inject_sleep_time_ms_;
  pthread_t thread_;
  DBus::Tag continuation_tag_;
 private:
  DISALLOW_COPY_AND_ASSIGN(SessionStarter);

  friend class GobiModem;
};

// Tracks a call to Enable (enable or disable) because the Enable
// operation waits for the PowerCallback, or because we cannot respond
// immmediately (because a long-running connect is already in
// progress)
class PendingEnable {
 public:
  PendingEnable(bool enable) : enable_(enable) {}
  DBus::Tag tag_;
  // NB: contrary to our style guide, this throws an exception that
  // dbus catches
  void RecordEnableAndReturnLater(GobiModem *modem) {
    modem->return_later(&tag_);
  }
  virtual ~PendingEnable() {}
  const bool enable_;
 private:
  DISALLOW_COPY_AND_ASSIGN(PendingEnable);
};

unsigned long GobiModem::MapDbmToPercent(INT8 signal_strength_dbm) {
  unsigned long signal_strength_percent;

  if (signal_strength_dbm < kMinSignalStrengthDbm)
    signal_strength_percent = 0;
  else if (signal_strength_dbm >= kMaxSignalStrengthDbm)
    signal_strength_percent = 100;
  else
    signal_strength_percent =
        ((signal_strength_dbm - kMinSignalStrengthDbm) * 100 /
         (kMaxSignalStrengthDbm - kMinSignalStrengthDbm));
  return signal_strength_percent;
}

ULONG GobiModem::MapDataBearerToRfi(ULONG data_bearer_technology) {
  switch (data_bearer_technology) {
    case gobi::kDataBearerCdma1xRtt:
      return gobi::kRfiCdma1xRtt;
    case gobi::kDataBearerCdmaEvdo:
    case gobi::kDataBearerCdmaEvdoRevA:
      return gobi::kRfiCdmaEvdo;
    case gobi::kDataBearerGprs:
      return gobi::kRfiGsm;
    case gobi::kDataBearerWcdma:
    case gobi::kDataBearerEdge:
    case gobi::kDataBearerHsdpaDlWcdmaUl:
    case gobi::kDataBearerWcdmaDlUsupaUl:
    case gobi::kDataBearerHsdpaDlHsupaUl:
      return gobi::kRfiUmts;
    default:
      return gobi::kRfiCdmaEvdo;
  }
}

static struct udev_enumerate *enumerate_net_devices(struct udev *udev)
{
  int rc;
  struct udev_enumerate *udev_enumerate = udev_enumerate_new(udev);

  if (udev_enumerate == NULL) {
    return NULL;
  }

  rc = udev_enumerate_add_match_subsystem(udev_enumerate, "net");
  if (rc != 0) {
    udev_enumerate_unref(udev_enumerate);
    return NULL;
  }

  rc = udev_enumerate_scan_devices(udev_enumerate);
  if (rc != 0) {
    udev_enumerate_unref(udev_enumerate);
    return NULL;
  }
  return udev_enumerate;
}

GobiModem* GobiModem::connected_modem_(NULL);
GobiModemHandler* GobiModem::handler_;
GobiModem::mutex_wrapper_ GobiModem::modem_mutex_;

bool StartExitTrampoline(void *arg) {
  GobiModem *modem = static_cast<GobiModem*>(arg);
  return modem->StartExit();
}

bool ExitOkTrampoline(void *arg) {
  GobiModem *modem = static_cast<GobiModem*>(arg);
  return !modem->is_connecting_or_connected();
}

GobiModem::GobiModem(DBus::Connection& connection,
                     const DBus::Path& path,
                     const gobi::DeviceElement& device,
                     gobi::Sdk* sdk,
                     GobiModemHelper *modem_helper)
    : DBus::ObjectAdaptor(connection, path),
      sdk_(sdk),
      modem_helper_(modem_helper),
      last_seen_(-1),
      mm_state_(MM_MODEM_STATE_UNKNOWN),
      session_id_(0),
      signal_available_(false),
      exiting_(false),
      device_resetting_(false),
      getting_deallocated_(false),
      session_starter_in_flight_(false),
      disconnect_time_(METRIC_BASE_NAME "Disconnect", 0, 150000, 20),
      registration_time_(METRIC_BASE_NAME "Registration", 0, 150000, 20) {
  memcpy(&device_, &device, sizeof(device_));
}

void GobiModem::Init() {
  sdk_->set_current_modem_path(path());
  metrics_lib_.reset(new MetricsLibrary());
  metrics_lib_->Init();

  // Initialize DBus object properties
  IpMethod = MM_MODEM_IP_METHOD_DHCP;
  UnlockRequired = "";
  UnlockRetries = 999;
  SetDeviceProperties();
  SetModemProperties();

  for (int i = 0; i < GOBI_EVENT_MAX; i++) {
    event_enabled[i] = false;
  }

  char name[64];
  void *thisp = static_cast<void*>(this);
  snprintf(name, sizeof(name), "gobi-%p", thisp);
  hooks_name_ = name;

  handler_->server().start_exit_hooks().Add(hooks_name_, StartExitTrampoline,
                                            this);
  handler_->server().exit_ok_hooks().Add(hooks_name_, ExitOkTrampoline, this);
}

GobiModem::~GobiModem() {
  pthread_mutex_lock(&modem_mutex_.mutex_);
  getting_deallocated_ = true;
  pthread_mutex_unlock(&modem_mutex_.mutex_);

  if (pending_enable_ != NULL) {
    // Despite the imminent destruction of the modem, pretend that the
    // pending_enable succeeded.  It is a race anyway.
    FinishEnable(DBus::Error());
  }
  handler_->server().start_exit_hooks().Del(hooks_name_);
  handler_->server().exit_ok_hooks().Del(hooks_name_);

  ApiDisconnect();
}

enum {
  METRIC_INDEX_NONE = 0,
  METRIC_INDEX_QMI_HARDWARE_RESTRICTED,
  METRIC_INDEX_MAX
};

static unsigned int QCErrorToMetricIndex(unsigned int error) {
  if (error == gobi::kQMIHardwareRestricted)
    return METRIC_INDEX_QMI_HARDWARE_RESTRICTED;
  return METRIC_INDEX_NONE;
}


void GobiModem::RescheduleDisable(void) {
  static const int kRetryDisableTimeoutSec = 1;

  retry_disable_callback_source_.TimeoutAddFull(
      G_PRIORITY_DEFAULT,
      kRetryDisableTimeoutSec,
      RetryDisableCallback,
      new CallbackArgs(new DBus::Path(path())),
      CleanupRetryDisableCallback);
}

void GobiModem::CleanupRetryDisableCallback(gpointer data) {
  delete static_cast<CallbackArgs*>(data);
}

gboolean GobiModem::RetryDisableCallback(gpointer data) {
  CallbackArgs *args = static_cast<CallbackArgs*>(data);

  // GobiModem::handler_ is a static
  GobiModem *modem = GobiModem::handler_->LookupByDbusPath(*args->path);
  if (modem == NULL) {
    LOG(ERROR) << "DisableRetryCallback with no modem";
    return FALSE;
  }
  modem->PerformDeferredDisable();
  return FALSE;
}


// EnableHelper
//
// Enable or Disable (poweroff) the modem based on the enable flag.
// Calling the GOBI SetPower API does not immediately change the power
// level of the modem, it merely starts the process.  Once the power
// level has changed, the PowerModeHandler is invoked, and
// PowerModeHandler finishes updating the state of the modem and
// disconnecting from the Qualcomm API when the modem is disabled.
//
// There are several failure modes which include failing to
// communicate with the gobi API and failing to communicate with the
// module.
//
// If the user_initiated argument is false, force the modem to be disabled even
// if an error is returned when trying stop the current data session.
//
// Returns:
//   true -  to indicate either that SetPower operation has started and
//           PowerModeHandler will be called later, or that
//           CancelDataSession has been called and
//           SessionStarterDoneCallback will be called later.
//   false - the dbus error has been set because the operation could
//           not be completed, or the operation would have no effect.
//
bool GobiModem::EnableHelper(const bool& enable, DBus::Error& error,
                             const bool &user_initiated)
{
  if (enable && Enabled()) {
    ScopedApiConnection connection(*this);
    connection.ApiConnect(error);
    CheckEnableOk(error);
  } else if (enable && !Enabled()) {
    ApiConnect(error);
    if (error.is_set())
      return false;
    if (!CheckEnableOk(error)) {
      ApiDisconnect();
      return false;
    }
    LogGobiInformation();

    /* Check the Enabled state again after API connect.  The cached
     * value may be stale.  This can happen if the RF Enable pin was
     * pulled low and a SetPower call was made, but failed with 1083.
     * When the pin voltage changes the modem will be enabled, but
     * because this plugin does not maintain a connection to the GOBI
     * API, there will be no callback to inform it of the change in
     * power state.
     */
    GetPowerState();
    if (Enabled()) {
      return false;
    }

    ULONG rc = sdk_->SetPower(gobi::kOnline);
    metrics_lib_->SendEnumToUMA(METRIC_BASE_NAME "SetPower",
                                QCErrorToMetricIndex(rc),
                                METRIC_INDEX_MAX);
    if (rc != 0) {
      error.set(kSdkError, "SetPower");
      LOG(WARNING) << "SetPower failed : " << rc;
      ApiDisconnect();
      return false;
    }
    SetMmState(MM_MODEM_STATE_ENABLING, MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
    return true;
  } else if (!enable && Enabled()) {
    if (is_connecting_or_connected()) {
      LOG(INFO) << "Disable while connected or connect in flight";

      int fault_inject_sleep_time_ms = static_cast <useconds_t> (
          injected_faults_["DisableSleepMs"]);
      if (fault_inject_sleep_time_ms) {
        LOG(WARNING) << "Fault injection:  disable sleeping for "
                     << fault_inject_sleep_time_ms << "ms";
        usleep(1000 * fault_inject_sleep_time_ms);
      }

      if (ForceDisconnect() == 0)
        return true;
      if (user_initiated) {
        // The error on force disconnect is probably a race.  If this
        // was a user initiated request, allow
        // SessionStarterDoneCallback to run, and try to disable later.
        RescheduleDisable();
        return true;
      }
    }
    ULONG rc = sdk_->SetPower(gobi::kPersistentLowPower);
    if (rc == gobi::kErrorReceivingQmiRequest ||
        rc == gobi::kTimeoutReceivingQmiRequest)
      // SetPower() sometimes fail with one of these errors and retrying
      // the call appears to succeed.
      rc = sdk_->SetPower(gobi::kPersistentLowPower);
    if (rc != 0) {
      error.set(kSdkError, "SetPower");
      LOG(WARNING) << "SetPower failed : " << rc;
      return false;
    }
    SetMmState(MM_MODEM_STATE_DISABLING, MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
    return true;
  }
  // The operation is already done!
  if (!error)
    LOG(WARNING) << "Operation Enable(" << enable
                 << ") has no effect on modem in state: " << Enabled();
  else
    LOG(WARNING) << "Operation Enable(" << enable
                 << ") on modem in state: " << Enabled()
                 << " returning error \"" << error.name() << " - "
                 << error.message() << "\"";
  return false;
}

// DBUS Methods: Modem
void GobiModem::Enable(const bool& enable, DBus::Error& error) {
  bool operation_pending;

  LOG(INFO) << "Enable: " << Enabled() << " => " << enable;

  if (pending_enable_ != NULL) {
    LOG(INFO) << "Already have a pending Enable operation";
    error.set(kModeError, "Already have a pending Enable operation");
    return;
  }
  operation_pending = EnableHelper(enable, error, true);
  if (operation_pending) {
    CHECK(pending_enable_ == NULL);
    CHECK(!error);
    // Cleaned up in PowerModeHandler or SessionStarterDoneCallback
    pending_enable_.reset(new PendingEnable(enable));
    pending_enable_->RecordEnableAndReturnLater(this);
    CHECK(false) << "Not reached";
  }
}

void GobiModem::Connect(const std::string& unused_number, DBus::Error& error) {
  DBusPropertyMap properties;
  Connect(properties, error);
}

ULONG GobiModem::StopDataSession(ULONG session_id)
{
  disconnect_time_.Start();
  ULONG rc = sdk_->StopDataSession(session_id);
  if (rc != 0)
    disconnect_time_.Reset();
  return rc;
}

void GobiModem::Disconnect(DBus::Error& error) {
  LOG(INFO) << "Disconnect(" << session_id_ << ")";
  if (session_id_ == 0) {
    LOG(WARNING) << "Disconnect called when not connected";
    error.set(kDisconnectError, "Not connected");
    return;
  }
  ULONG rc = StopDataSession(session_id_);
  ENSURE_SDK_SUCCESS(StopDataSession, rc, kDisconnectError);
  SetMmState(MM_MODEM_STATE_DISCONNECTING,
             MM_MODEM_STATE_CHANGED_REASON_USER_REQUESTED);
  error.set(kOperationInitiatedError, "");
}

std::string GobiModem::GetUSBAddress() {
  return sysfs_path_.substr(sysfs_path_.find_last_of('/') + 1);
}

DBus::Struct<uint32_t, uint32_t, uint32_t, uint32_t> GobiModem::GetIP4Config(
    DBus::Error& error) {
  DBus::Struct<uint32_t, uint32_t, uint32_t, uint32_t> result;

  LOG(INFO) << "GetIP4Config (unimplemented)";

  return result;
}

void GobiModem::FactoryReset(const std::string& code, DBus::Error& error) {
  ScopedApiConnection connection(*this);
  connection.ApiConnect(error);
  if (error.is_set())
    return;

  LOG(INFO) << "ResetToFactoryDefaults";
  ULONG rc = sdk_->ResetToFactoryDefaults(const_cast<CHAR *>(code.c_str()));
  ENSURE_SDK_SUCCESS(ResetToFactoryDefaults, rc, kSdkError);
  LOG(INFO) << "FactoryReset succeeded. Device should disappear and reappear.";
}

DBus::Struct<std::string, std::string, std::string> GobiModem::GetInfo(
    DBus::Error& error) {
  // (manufacturer, modem, version).
  DBus::Struct<std::string, std::string, std::string> result;

  char buffer[kDefaultBufferSize];

  ULONG rc = sdk_->GetManufacturer(sizeof(buffer), buffer);
  ENSURE_SDK_SUCCESS_WITH_RESULT(GetManufacturer, rc, kSdkError, result);
  result._1 = buffer;
  rc = sdk_->GetModelID(sizeof(buffer), buffer);
  ENSURE_SDK_SUCCESS_WITH_RESULT(GetModelID, rc, kSdkError, result);
  result._2 = buffer;
  rc = sdk_->GetHardwareRevision(sizeof(buffer), buffer);
  ENSURE_SDK_SUCCESS_WITH_RESULT(GetHardwareRevision, rc, kSdkError, result);
  result._3 = buffer;

  LOG(INFO) << "Manufacturer: " << result._1;
  LOG(INFO) << "Modem: " << result._2;
  LOG(INFO) << "Version: " << result._3;
  return result;
}

//======================================================================
// DBUS Methods: Modem.Simple

void GobiModem::Connect(const DBusPropertyMap& properties, DBus::Error& error) {
  if (!Enabled()) {
    LOG(WARNING) << "Connect on disabled modem";
    error.set(kConnectError, "Modem is disabled");
    return;
  }
  if (pending_enable_ != NULL) {
    LOG(WARNING) << "Connect while modem "
                 << (pending_enable_->enable_ ? "enabling" : "disabling")
                 << ".";
    error.set(kConnectError, "Enable operation in progress");
    return;
  }
  if (exiting_) {
    LOG(WARNING) << "Connect when exiting";
    error.set(kConnectError, "Cromo is exiting");
    return;
  }
  if (session_starter_in_flight_) {
    LOG(WARNING) << "Session start already in flight";
    error.set(kConnectError, "Connect already in progress");
    return;
  }
  const char* apn = utilities::ExtractString(properties, "apn", NULL, error);
  const char* username =
      utilities::ExtractString(properties, "username", NULL, error);
  const char* password =
      utilities::ExtractString(properties, "password", NULL, error);

  if (apn !=  NULL)
    LOG(INFO) << "Starting data session for APN " << apn;

  SessionStarter *starter = new SessionStarter(sdk_,
                                               this,
                                               apn,
                                               username,
                                               password);
  session_starter_in_flight_ = true;
  if (mm_state_ == MM_MODEM_STATE_REGISTERED)
    SetMmState(MM_MODEM_STATE_CONNECTING,
               MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
  starter->StartDataSession(error);

  return_later(&starter->continuation_tag_);
}

void GobiModem::FinishDeferredCall(DBus::Tag *tag, const DBus::Error &error) {
  // find_continuation, return_error, and return_now are defined in
  // <dbus-c++/object.h>
  DBus::ObjectAdaptor::Continuation *c = find_continuation(tag);
  if (!c) {
    LOG(ERROR) << "Could not find continuation: tag = " << std::ios::hex << tag;
    return;
  }
  if (error.is_set()) {
    return_error(c, error);
  } else {
    return_now(c);
  }
}

void GobiModem::FinishEnable(const DBus::Error &error)
{
  scoped_ptr<PendingEnable> scoped_enable(pending_enable_.release());
  retry_disable_callback_source_.Remove();
  FinishDeferredCall(&scoped_enable->tag_, error);
}

gobi::RegistrationState GobiModem::GetRegistrationState(gobi::Sdk *sdk) {
  ULONG rc = 0;
  ULONG gobi_reg_state = gobi::kRegistrationStateUnknown;
  ULONG roaming_state;
  ULONG ran;
  WORD mcc, mnc;
  CHAR netname[32];
  BYTE radio_interfaces[10];
  BYTE num_radio_interfaces = arraysize(radio_interfaces);
  rc = sdk->GetServingNetwork(&gobi_reg_state, &ran,
                              &num_radio_interfaces,
                              radio_interfaces, &roaming_state,
                              &mcc, &mnc,
                              sizeof(netname), netname);
  if (rc) {
    LOG(ERROR) << "Failed to get current registration state: " << rc;
    return gobi::kRegistrationStateUnknown;
  }
  return static_cast<gobi::RegistrationState>(gobi_reg_state);
}

void GobiModem::PerformDeferredDisable() {
  if (pending_enable_ != NULL) {
    DBus::Error disable_error;
    bool operation_pending;
    CHECK(pending_enable_->enable_ == false);
    operation_pending = EnableHelper(false, disable_error, false);
    CHECK(operation_pending || disable_error);
    if (disable_error) {
      FinishEnable(disable_error);
    }
    // NOTE: if !disable_error, there is nothing to do, because
    // PowerModeHandler will eventually return a value.
  }
}

void GobiModem::SessionStarterDoneCallback(SessionStarter *starter) {

  session_starter_in_flight_ = false;
  if (injected_faults_["ConnectFailsWithErrorSendingQmiRequest"]) {
    LOG(ERROR) << "Fault injection: Making StartDataSession return QMI error";
    starter->return_value_ = gobi::kErrorSendingQmiRequest;
  }

  DBus::Error error;
  if (starter->return_value_ == 0) {
    session_id_ = starter->session_id_;

    if (pending_enable_ != NULL) {
      error.set(kConnectError, "StartDataSession Cancelled");
      LOG(INFO) << "Cancellation arrived after connect succeeded";
      ULONG rc = StopDataSession(session_id_);
      if (rc != 0) {
        LOG(ERROR) << "Could not disconnect: " << rc;
      } else {
        SetMmState(MM_MODEM_STATE_DISCONNECTING,
                   MM_MODEM_STATE_CHANGED_REASON_USER_REQUESTED);
      }
      // SessionStateHandler will clear session_id_
    }
  } else {
    LOG(WARNING) << "StartDataSession failed: " << starter->return_value_;
    const char* err_name;
    const char* err_msg;
    switch (starter->return_value_) {
      case gobi::kCallFailed:
        LOG(WARNING) << "Failure Reason " <<  starter->failure_reason_;
        err_name = QMICallFailureToMMError(starter->failure_reason_);
        err_msg = "Connect failed";
        break;
      case gobi::kErrorSendingQmiRequest:
      case gobi::kErrorReceivingQmiRequest:
        if (pending_enable_ == NULL) {
          // Normally the SDK enqueues an SdkErrorHandler event when
          // it sees these errors.  But, since these errors occur
          // benignly on StartDataSession cancellation, the SDK
          // doesn't do that automatically for StartDataSession. If we
          // have no cancellation, then this is a for-real problem,
          // and we reboot cromo
          SinkSdkError(path(), "StartDataSession", starter->return_value_);
        }
        // fall through
      default:
        err_name = kConnectError;
        err_msg = "StartDataSession";
        break;
    }
    error.set(err_name, err_msg);
  }
  LOG(INFO) << "Returning deferred connect call";
  FinishDeferredCall(&starter->continuation_tag_, error);

  if (mm_state_ == MM_MODEM_STATE_CONNECTING) {
    if (!error.is_set())
      SetMmState(MM_MODEM_STATE_CONNECTED,
                 MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
    else
      SetMmState(MM_MODEM_STATE_REGISTERED,
                 MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
  }

  if (pending_enable_ != NULL)
    // The pending_enable_ operation (which is most certainly a
    // "DISABLE") should not be run until the SessionStateHandler has
    // run (assuming it gets run).  By defering this call for a
    // second, we give a chance to the SessionStateHandler to run, but
    // also protect ourselves in case the SessionStateHandler never runs.
    RescheduleDisable();
}

void GobiModem::SetMmState(uint32_t new_state, uint32_t reason) {
  if (new_state != mm_state_) {
    LOG(INFO) << "MM state change: " << mm_state_ << " => " << new_state;
    StateChanged(mm_state_, new_state, reason);
    State = new_state;
    mm_state_ = new_state;
  }
}

void GobiModem::GetSerialNumbers(SerialNumbers *out, DBus::Error &error) {
  char esn[kDefaultBufferSize];
  char imei[kDefaultBufferSize];
  char meid[kDefaultBufferSize];

  ULONG rc = sdk_->GetSerialNumbers(kDefaultBufferSize, esn,
                              kDefaultBufferSize, imei,
                              kDefaultBufferSize, meid);
  ENSURE_SDK_SUCCESS(GetSerialNumbers, rc, kSdkError);
  out->esn = esn;
  out->imei = imei;
  out->meid = meid;
}

unsigned int GobiModem::QCStateToMMState(ULONG qcstate) {
  unsigned int mmstate;

  // TODO(ers) if not registered, should return enabled state
  switch (qcstate) {
    case gobi::kConnected:
      mmstate = MM_MODEM_STATE_CONNECTED;
      break;
    case gobi::kAuthenticating:
      mmstate = MM_MODEM_STATE_CONNECTING;
      break;
    case gobi::kDisconnected:
    default:
      ULONG rc;
      ULONG reg_state;
      ULONG l1, l2;      // don't care
      WORD w1, w2;
      BYTE b3[10];
      BYTE b2 = sizeof(b3)/sizeof(BYTE);
      char buf[255];
      rc = sdk_->GetServingNetwork(&reg_state, &l1, &b2, b3, &l2, &w1, &w2,
                                   sizeof(buf), buf);
      if (rc == 0) {
        if (reg_state == gobi::kRegistered) {
          mmstate = MM_MODEM_STATE_REGISTERED;
          break;
        } else if (reg_state == gobi::kSearching) {
          mmstate = MM_MODEM_STATE_SEARCHING;
          break;
        }
      }
      mmstate = MM_MODEM_STATE_UNKNOWN;
  }

  return mmstate;
}

// if we get SDK errors while trying to retrieve information,
// we ignore them, and just don't set the corresponding properties
DBusPropertyMap GobiModem::GetStatus(DBus::Error& error_ignored) {
  DBusPropertyMap result;

  DBus::Error api_connect_error;
  ScopedApiConnection connection(*this);
  // Errors are ignored so data not requiring a connection can be returned
  connection.ApiConnect(api_connect_error);

  int32_t rssi;
  DBus::Error signal_strength_error;
  StrengthMap interface_to_dbm;
  GetSignalStrengthDbm(rssi, &interface_to_dbm, signal_strength_error);
  if (signal_strength_error.is_set() || rssi <= kMinSignalStrengthDbm) {
    // Activate() looks for this key and does not even try if present
    result["no_signal"].writer().append_bool(true);
  } else {
    result["signal_strength_dbm"].writer().append_int32(rssi);
    for (StrengthMap::iterator i = interface_to_dbm.begin();
         i != interface_to_dbm.end();
         ++i) {
      char buf[30];
      snprintf(buf,
               sizeof(buf),
               "interface_%u_dbm",
               static_cast<unsigned int>(i->first));
      result[buf].writer().append_int32(i->second);
    }
  }

  SerialNumbers serials;
  DBus::Error serial_numbers_error;
  this->GetSerialNumbers(&serials, serial_numbers_error);
  if (!serial_numbers_error.is_set()) {
    if (serials.esn.length()) {
      result["esn"].writer().append_string(serials.esn.c_str());
    }
    if (serials.meid.length()) {
      result["meid"].writer().append_string(serials.meid.c_str());
    }
    if (serials.imei.length()) {
      result["imei"].writer().append_string(serials.imei.c_str());
    }
  }
  char imsi[kDefaultBufferSize];
  ULONG rc = sdk_->GetIMSI(kDefaultBufferSize, imsi);
  if (rc == 0 && strlen(imsi) != 0)
    result["imsi"].writer().append_string(imsi);

  ULONG firmware_id;
  ULONG technology_id;
  ULONG carrier_id;
  ULONG region;
  ULONG gps_capability;
  const Carrier *carrier = NULL;
  rc = sdk_->GetFirmwareInfo(&firmware_id,
                             &technology_id,
                             &carrier_id,
                             &region,
                             &gps_capability);
  if (rc == 0) {
    carrier = handler_->server().FindCarrierByCarrierId(carrier_id);
    if (carrier != NULL)
      result["carrier"].writer().append_string(carrier->name());
    else
      LOG(WARNING) << "Carrier lookup failed for ID " << carrier_id;

    // TODO(ers) we'd like to return "operator_name", but the
    // SDK provides no apparent means of determining it.

    const char* technology;
    if (technology_id == 0)
      technology = "CDMA";
    else if (technology_id == 1)
      technology = "UMTS";
    else
      technology = "unknown";
    result["technology"].writer().append_string(technology);
  } else {
    LOG(WARNING) << "GetFirmwareInfo failed: " << rc;
  }

  char mdn[kDefaultBufferSize], min[kDefaultBufferSize];
  rc = sdk_->GetVoiceNumber(kDefaultBufferSize, mdn,
                            kDefaultBufferSize, min);
  if (rc == 0) {
    result["mdn"].writer().append_string(mdn);
    result["min"].writer().append_string(min);
  } else if (rc != gobi::kNotProvisioned) {
    LOG(WARNING) << "GetVoiceNumber failed: " << rc;
  }

  char firmware_revision[kDefaultBufferSize];
  rc = sdk_->GetFirmwareRevision(sizeof(firmware_revision), firmware_revision);
  if (rc == 0 && strlen(firmware_revision) != 0) {
    result["firmware_revision"].writer().append_string(firmware_revision);
  }

  GetTechnologySpecificStatus(&result);
  if (carrier != NULL)
    carrier-> ModifyModemStatusReturn(&result);

  return result;
}

// This is only in debug builds; if you add actual code here, see
// RegisterCallbacks().
static void ByteTotalsCallback(ULONGLONG tx, ULONGLONG rx) {

}

// This is only in debug builds; if you add actual code here, see
// RegisterCallbacks().
gboolean GobiModem::DormancyStatusCallback(gpointer data) {
  DormancyStatusArgs *args = reinterpret_cast<DormancyStatusArgs*>(data);
  GobiModem *modem = handler_->LookupByDbusPath(*args->path);
  if (modem->event_enabled[GOBI_EVENT_DORMANCY]) {
    modem->DormancyStatus(args->status == gobi::kDormant);
  }
  return FALSE;
}

static void MobileIPStatusCallback(ULONG status) {
  LOG(INFO) << "MobileIPStatusCallback: " << status;
}

static void LURejectCallback(ULONG domain, ULONG cause) {
  LOG(INFO) << "LURejectCallback: domain " << domain << " cause " << cause;
}

static void PDSStateCallback(ULONG enabled, ULONG tracking) {
  LOG(INFO) << "PDSStateCallback: enabled " << enabled
            << " tracking " << tracking;
}

void GobiModem::RegisterCallbacks() {
  sdk_->SetMobileIPStatusCallback(MobileIPStatusCallback);
  sdk_->SetRFInfoCallback(RFInfoCallbackTrampoline);
  sdk_->SetLURejectCallback(LURejectCallback);
  sdk_->SetPDSStateCallback(PDSStateCallback);

  sdk_->SetPowerCallback(PowerCallbackTrampoline);
  sdk_->SetSessionStateCallback(SessionStateCallbackTrampoline);
  sdk_->SetDataBearerCallback(DataBearerCallbackTrampoline);
  sdk_->SetRoamingIndicatorCallback(RoamingIndicatorCallbackTrampoline);
  sdk_->SetDataCapabilitiesCallback(DataCapabilitiesCallbackTrampoline);

  if (DEBUG) {
    // These are only used for logging. If you make one of these a non-debug
    // callback, see EventKeyToIndex() below, which will need to be updated.
    sdk_->SetByteTotalsCallback(ByteTotalsCallback, 60);
    sdk_->SetDormancyStatusCallback(DormancyStatusCallbackTrampoline);
  }

  static int num_thresholds = kSignalStrengthNumLevels - 1;
  int interval =
      (kMaxSignalStrengthDbm - kMinSignalStrengthDbm) /
      (kSignalStrengthNumLevels - 1);
  INT8 thresholds[num_thresholds];
  for (int i = 0; i < num_thresholds; i++) {
    thresholds[i] = kMinSignalStrengthDbm + interval * i;
  }
  sdk_->SetSignalStrengthCallback(SignalStrengthCallbackTrampoline,
                                  num_thresholds,
                                  thresholds);
}

bool GobiModem::CanMakeMethodCalls(void) {
  // The Gobi has been observed (at least once - see chromium-os:7172) to get
  // into a state where we can set up a QMI channel to it (so QCWWANConnect()
  // succeeds) but not actually invoke any functions. We'll force the issue here
  // by calling GetSerialNumbers so we can detect this failure mode early.
  ULONG rc;
  char esn[kDefaultBufferSize];
  char imei[kDefaultBufferSize];
  char meid[kDefaultBufferSize];
  rc = sdk_->GetSerialNumbers(sizeof(esn), esn, sizeof(imei), imei,
                              sizeof(meid), meid);
  if (rc != 0) {
    LOG(ERROR) << "GetSerialNumbers() failed: " << rc;
  }

  return rc == 0;
}

void GobiModem::ApiConnect(DBus::Error& error) {
  // It is safe to test for NULL outside of a lock because ApiConnect
  // is only called by the main thread, and only the main thread can
  // modify connected_modem_.
  if (connected_modem_ != NULL) {
    LOG(INFO) << "ApiAlready connected: connected_modem_=0x" << connected_modem_
              << "this=0x" << this;
    error.set(kErrorOperationNotAllowed,
              "Only one modem can be connected via Api");
    return;
  }
  LOG(INFO) << "Connecting to QCWWAN";
  pthread_mutex_lock(&modem_mutex_.mutex_);
  connected_modem_ = this;
  if (getting_deallocated_) {
    LOG(INFO) << "Modem getting deallocated, not connecting";
    pthread_mutex_unlock(&modem_mutex_.mutex_);
    error.set(kErrorOperationNotAllowed, "Modem is getting deallocated");
    return;
  }
  pthread_mutex_unlock(&modem_mutex_.mutex_);

  ULONG rc = sdk_->QCWWANConnect(device_.deviceNode, device_.deviceKey);
  if (rc != 0 || !CanMakeMethodCalls()) {
    LOG(ERROR) << "QCWWANConnect() failed.  Exiting so modem can reset." << rc;
    ExitAndResetDevice(rc);
  }
  RegisterCallbacks();
}


ULONG GobiModem::ApiDisconnect(void) {
  ULONG rc = 0;
  pthread_mutex_lock(&modem_mutex_.mutex_);
  if (connected_modem_ == this) {
    LOG(INFO) << "Disconnecting from QCWWAN.  this_=0x" << this;
    if (session_starter_in_flight_) {
      SessionStarter::CancelDataSession(sdk_);
    }
    connected_modem_ = NULL;
    pthread_mutex_unlock(&modem_mutex_.mutex_);
    rc = sdk_->QCWWANDisconnect();
  } else {
    LOG(INFO) << "Not connected.  this_=0x" << this;
    pthread_mutex_unlock(&modem_mutex_.mutex_);
  }
  return rc;
}

void GobiModem::LogGobiInformation() {
  ULONG rc;

  char buffer[kDefaultBufferSize];
  rc = sdk_->GetManufacturer(sizeof(buffer), buffer);
  if (rc == 0) {
    LOG(INFO) << "Manufacturer: " << buffer;
  }

  ULONG firmware_id;
  ULONG technology;
  ULONG carrier;
  ULONG region;
  ULONG gps_capability;
  rc = sdk_->GetFirmwareInfo(&firmware_id,
                             &technology,
                             &carrier,
                             &region,
                             &gps_capability);
  if (rc == 0) {
    LOG(INFO) << "Firmware info: "
              << "firmware_id: " << firmware_id
              << " technology: " << technology
              << " carrier: " << carrier
              << " region: " << region
              << " gps_capability: " << gps_capability;
  } else {
    LOG(WARNING) << "Cannot get firmware info: " << rc;
  }

  char amss[kDefaultBufferSize], boot[kDefaultBufferSize];
  char pri[kDefaultBufferSize];

  rc = sdk_->GetFirmwareRevisions(kDefaultBufferSize, amss,
                                  kDefaultBufferSize, boot,
                                  kDefaultBufferSize, pri);
  if (rc == 0) {
    LOG(INFO) << "Firmware Revisions: AMSS: " << amss
              << " boot: " << boot
              << " pri: " << pri;
  } else {
    LOG(WARNING) << "Cannot get firmware revision info: " << rc;
  }

  SerialNumbers serials;
  DBus::Error error;
  GetSerialNumbers(&serials, error);
  if (!error.is_set()) {
    DLOG(INFO) << "ESN " << serials.esn
               << " IMEI " << serials.imei
               << " MEID " << serials.meid;
  } else {
    LOG(WARNING) << "Cannot get serial numbers: " << error;
  }

  char number[kDefaultBufferSize], min_array[kDefaultBufferSize];
  rc = sdk_->GetVoiceNumber(kDefaultBufferSize, number,
                            kDefaultBufferSize, min_array);
  if (rc == 0) {
    char masked_min[kDefaultBufferSize + 1];
    strncpy(masked_min, min_array, sizeof(masked_min));
    if (strlen(masked_min) >= 4)
      strcpy(masked_min + strlen(masked_min) - 4, "XXXX");
    char masked_voice[kDefaultBufferSize + 1];
    strncpy(masked_voice, number, sizeof(masked_voice));
    if (strlen(masked_voice) >= 4)
      strcpy(masked_voice + strlen(masked_voice) - 4, "XXXX");
    LOG(INFO) << "Voice: " << masked_voice
              << " MIN: " << masked_min;
  } else if (rc != gobi::kNotProvisioned) {
    LOG(WARNING) << "GetVoiceNumber failed: " << rc;
  }

  BYTE index;
  rc = sdk_->GetActiveMobileIPProfile(&index);
  if (rc != 0 && rc != gobi::kNotSupportedByDevice) {
    LOG(WARNING) << "GetAMIPP: " << rc;
  } else {
    LOG(INFO) << "Mobile IP profile: " << (int)index;
  }
}

void GobiModem::SoftReset(DBus::Error& error) {
  ResetModem(error);
}

void GobiModem::PowerCycle(DBus::Error &error) {
  LOG(INFO) << "Initiating modem powercycle";
  ULONG rc = sdk_->SetPower(gobi::kPowerOff);
  ENSURE_SDK_SUCCESS(SetPower, rc, kSdkError);
}

void GobiModem::ResetModem(DBus::Error& error) {
  SetEnabled(false);
  SetMmState(MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
  LOG(INFO) << "Offline";

  // Resetting the modem will cause it to disappear and reappear.
  ULONG rc = sdk_->SetPower(gobi::kOffline);
  ENSURE_SDK_SUCCESS(SetPower, rc, kSdkError);

  LOG(INFO) << "Reset";
  rc = sdk_->SetPower(gobi::kReset);
  ENSURE_SDK_SUCCESS(SetPower, rc, kSdkError);

  rc = ApiDisconnect();
  ENSURE_SDK_SUCCESS(QCWWanDisconnect, rc, kSdkError);

  // WARNING: This modem became invalid when we called SetPower(gobi::kReset)
  // above; any further attempts to make method calls might result in us trying
  // to open a /dev/qcqmi which doesn't exist yet (the modem being in the middle
  // of a reset operation).
  //
  // Note that after the unregister_obj(), methods on us can't be called any
  // more; it would be rude to have signals originating from this object after
  // Remove() returns, since Remove() declares us to no longer exist.
  unregister_obj();
  handler_->Remove(this);
}

void GobiModem::SetCarrier(const std::string& carrier_name,
                           DBus::Error& error) {
  modem_helper_->SetCarrier(this, handler_, carrier_name, error);
}

uint32_t GobiModem::CommonGetSignalQuality(DBus::Error& error) {
  if (!Enabled()) {
    LOG(WARNING) << "GetSignalQuality on disabled modem";
    error.set(kModeError, "Modem is disabled");
  } else {
    int32_t signal_strength_dbm;
    GetSignalStrengthDbm(signal_strength_dbm, NULL, error);
    if (!error.is_set()) {
      uint32_t result = MapDbmToPercent(signal_strength_dbm);
      LOG(INFO) << "GetSignalQuality => " << result << "%";
      return result;
    }
  }
  // for the error cases, return an impossible value
  return 999;
}

void GobiModem::GetSignalStrengthDbm(int& output,
                                     StrengthMap *interface_to_dbm,
                                     DBus::Error& error) {
  ULONG kSignals = 10;
  ULONG signals = kSignals;
  INT8 strengths[kSignals];
  ULONG interfaces[kSignals];

  signal_available_ = false;
  ULONG rc = sdk_->GetSignalStrengths(&signals, strengths, interfaces);
  if (rc == gobi::kNoAvailableSignal) {
    output = kMinSignalStrengthDbm-1;
    return;
  }
  ENSURE_SDK_SUCCESS(GetSignalStrengths, rc, kSdkError);
  signal_available_ = true;

  signals = std::min(kSignals, signals);

  if (interface_to_dbm) {
    for (ULONG i = 0; i < signals; ++i) {
      (*interface_to_dbm)[interfaces[i]] = strengths[i];
    }
  }

  INT8 max_strength = kint8min;
  for (ULONG i = 0; i < signals; ++i) {
    DLOG(INFO) << "Interface " << i << ": " << static_cast<int>(strengths[i])
               << " dBM technology: " << interfaces[i];
    // TODO(ers) mark radio interface technology as registered?
    if (strengths[i] > max_strength) {
      max_strength = strengths[i];
    }
  }

  // If we're in the connected state, pick the signal strength for the radio
  // interface that's being used. Otherwise, pick the strongest signal.
  if (session_id_) {
    ULONG db_technology;
    rc =  sdk_->GetDataBearerTechnology(&db_technology);
    if (rc != 0) {
      LOG(WARNING) << "GetDataBearerTechnology failed: " << rc;
      error.set(kSdkError, "GetDataBearerTechnology");
      return;
    }
    ULONG rfi_technology = MapDataBearerToRfi(db_technology);
    for (ULONG i = 0; i < signals; ++i) {
      if (interfaces[i] == rfi_technology) {
        output = strengths[i];
        return;
      }
    }
  }
  output = max_strength;
}

void GobiModem::GetPowerState() {
  ULONG power_mode;
  ULONG rc = sdk_->GetPower(&power_mode);
  if (rc != 0)
    LOG(INFO) << "Cannot determine initial power mode: Error " << rc;
  else {
    LOG(INFO) << "Initial power mode: " << power_mode;
    if (power_mode == gobi::kOnline) {
      SetEnabled(true);
      State = mm_state_ = MM_MODEM_STATE_ENABLED;
      RegistrationStateHandler();
    } else {
      SetEnabled(false);
      State = mm_state_ = MM_MODEM_STATE_DISABLED;
    }
  }
}

// Set properties for which a connection to the SDK is required
// to obtain the needed information. If this is called before
// the modem is enabled, we connect to the SDK, get the properties
// we need, and then disconnect from the SDK. Otherwise, we
// stay connected.
void GobiModem::SetModemProperties() {
  DBus::Error error;

  ApiConnect(error);
  if (error.is_set()) {
    Type = MM_MODEM_TYPE_CDMA;
    return;
  }

  GetPowerState();

  ULONG rc;
  ULONG u1, u2, u3, u4;
  BYTE radioInterfaces[10];
  ULONG numRadioInterfaces = sizeof(radioInterfaces)/sizeof(BYTE);
  rc = sdk_->GetDeviceCapabilities(&u1, &u2, &u3, &u4,
                                         &numRadioInterfaces,
                                         radioInterfaces);
  if (rc == 0) {
    if (numRadioInterfaces != 0) {
      if (radioInterfaces[0] == gobi::kRfiGsm ||
          radioInterfaces[0] == gobi::kRfiUmts) {
        Type = MM_MODEM_TYPE_GSM;
      } else {
        Type = MM_MODEM_TYPE_CDMA;
      }
    }
  }
  SetTechnologySpecificProperties();
  if (mm_state_ == MM_MODEM_STATE_UNKNOWN ||
      mm_state_ == MM_MODEM_STATE_DISABLED)
    ApiDisconnect();
}

// DBUS message handler.
void GobiModem::SetAutomaticTracking(const bool& service_enable,
                                     const bool& port_enable,
                                     DBus::Error& error) {
  ULONG rc;
  rc = sdk_->SetServiceAutomaticTracking(service_enable);
  ENSURE_SDK_SUCCESS(SetServiceAutomaticTracking, rc, kSdkError);
  LOG(INFO) << "Service automatic tracking " << (service_enable ?
          "enabled" : "disabled");

  rc = sdk_->SetPortAutomaticTracking(port_enable);
  ENSURE_SDK_SUCCESS(SetPortAutomaticTracking, rc, kSdkError);
  LOG(INFO) << "Port automatic tracking " << (port_enable ?
          "enabled" : "disabled");
}

void GobiModem::InjectFault(const std::string& name,
                            const int32_t &value,
                            DBus::Error& error) {
  if (name == "ClearFaults") {
    LOG(ERROR) << "Clearing injected faults";
    sdk_->InjectFaultSdkError(0);
    injected_faults_.clear();
  } else if (name == "SdkError") {
    LOG(ERROR) << "Injecting fault:  All Sdk calls will return " << value;
    sdk_->InjectFaultSdkError(value);
  } else {
    LOG(ERROR) << "Injecting fault " << name << ": " << value;
    injected_faults_[name] = value;
  }
}

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::ForceModemActivatedStatus(DBus::Error& error) {
}

void GobiModem::ClearIdleCallbacks() {
  for (std::set<guint>::iterator it = idle_callback_ids_.begin();
       it != idle_callback_ids_.end();
       ++it) {
    g_source_remove(*it);
  }
  idle_callback_ids_.clear();
}

void GobiModem::SinkSdkError(const std::string& modem_path,
                             const std::string& sdk_function,
                             ULONG error) {
  LOG(ERROR) << sdk_function << ": unrecoverable error " << error
             << " on modem " << modem_path;
  PostCallbackRequest(GobiModem::SdkErrorHandler, new SdkErrorArgs(error));
}

// Callbacks:  Run in the context of the main thread
gboolean GobiModem::SdkErrorHandler(gpointer data) {
  SdkErrorArgs *args = static_cast<SdkErrorArgs *>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL) {
    modem->ExitAndResetDevice(args->error);
  } else {
    LOG(INFO) << "Reset received for obsolete path "
              << args->path;
  }
  return FALSE;
}

gboolean GobiModem::SignalStrengthCallback(gpointer data) {
  SignalStrengthArgs* args = static_cast<SignalStrengthArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->SignalStrengthHandler(args->signal_strength, args->radio_interface);
  return FALSE;
}

gboolean GobiModem::PowerCallback(gpointer data) {
  CallbackArgs* args = static_cast<CallbackArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->PowerModeHandler();
  return FALSE;
}

gboolean GobiModem::SessionStateCallback(gpointer data) {
  SessionStateArgs* args = static_cast<SessionStateArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->SessionStateHandler(args->state, args->session_end_reason);
  return FALSE;
}

gboolean GobiModem::RegistrationStateCallback(gpointer data) {
  CallbackArgs* args = static_cast<CallbackArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->RegistrationStateHandler();
  return FALSE;
}

gboolean GobiModem::DataCapabilitiesCallback(gpointer data) {
  DataCapabilitiesArgs* args = static_cast<DataCapabilitiesArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->DataCapabilitiesHandler(args->num_data_caps, args->data_caps);
  return FALSE;
}

gboolean GobiModem::DataBearerTechnologyCallback(gpointer data) {
  DataBearerTechnologyArgs* args = static_cast<DataBearerTechnologyArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem != NULL)
    modem->DataBearerTechnologyHandler(args->technology);
  return FALSE;
}

void GobiModem::PowerModeHandler() {
  ULONG power_mode;
  DBus::Error error;
  ULONG rc = sdk_->GetPower(&power_mode);
  if (rc != 0) {
    LOG(INFO) << "Cannot determine power mode: Error " << rc;
    error.set(kSdkError, "GetPowerMode");
  } else {
    LOG(INFO) << "PowerModeHandler: " << power_mode;
    if (power_mode == gobi::kOnline) {
      SetEnabled(true);
      SetMmState(MM_MODEM_STATE_ENABLED, MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
      registration_time_.Start();    // Stopped in
      // GobiCdmaModem::RegistrationStateHandler,
      // if appropriate
    } else {
      ApiDisconnect();
      SetEnabled(false);
      SetMmState(MM_MODEM_STATE_DISABLED,
                 MM_MODEM_STATE_CHANGED_REASON_UNKNOWN);
    }
  }
  if (pending_enable_ != NULL) {
    FinishEnable(error);
    LOG(INFO) << "PowerModeHandler: finishing deferred call";
  }
}

void GobiModem::SessionStateHandler(ULONG state, ULONG session_end_reason) {
  LOG(INFO) << "SessionStateHandler state: " << state
            << " reason: "
            << (state == gobi::kConnected ? 0 : session_end_reason);
  if (state == gobi::kConnected) {
    ULONG data_bearer_technology;
    sdk_->GetDataBearerTechnology(&data_bearer_technology);
    // TODO(ers) send a signal or change a property to notify
    // listeners about the change in data bearer technology
  }

  if (state == gobi::kDisconnected) {
    disconnect_time_.Stop();
    session_id_ = 0;
    unsigned int reason = QMIReasonToMMReason(session_end_reason);
    if (pending_enable_ != NULL)
      PerformDeferredDisable();
    else
      SetMmState(QCStateToMMState(state), reason);
  } else if (state == gobi::kConnected) {
    // Nothing to do here; this is handled in SessionStarterDoneCallback
  }
}

void GobiModem::DataBearerTechnologyHandler(ULONG technology) {
  // Default is to ignore the argument and treat this as a
  // registration state change. This behavior can be overridden.
  RegistrationStateHandler();
}

// Set DBus properties that pertain to the modem hardware device.
// The properties set here are Device, MasterDevice, and Driver.
void GobiModem::SetDeviceProperties()
{
  struct udev *udev = udev_new();
  if (udev == NULL) {
    LOG(WARNING) << "udev == NULL";
    return;
  }

  struct udev_enumerate *udev_enumerate = enumerate_net_devices(udev);
  if (udev_enumerate == NULL) {
    LOG(WARNING) << "udev_enumerate == NULL";
    udev_unref(udev);
    return;
  }

  struct udev_list_entry *entry;
  for (entry = udev_enumerate_get_list_entry(udev_enumerate);
       entry != NULL;
       entry = udev_list_entry_get_next(entry)) {

    std::string syspath(udev_list_entry_get_name(entry));

    struct udev_device *udev_device =
        udev_device_new_from_syspath(udev, syspath.c_str());
    if (udev_device == NULL)
      continue;

    std::string driver;
    struct udev_device *parent = udev_device_get_parent(udev_device);
    if (parent != NULL) {
      const char *udev_driver = udev_device_get_driver(parent);
      if (udev_driver != NULL) {
        driver = udev_driver;
      }
    }

    if (driver == k2kNetworkDriver ||
        driver == k3kNetworkDriver ||
        driver == kUnifiedNetworkDriver) {
      // Extract last portion of syspath...
      size_t found = syspath.find_last_of('/');
      if (found != std::string::npos) {
        Device = syspath.substr(found + 1);
        struct udev_device *grandparent;
        if (parent != NULL) {
          grandparent = udev_device_get_parent(parent);
          if (grandparent != NULL) {
            sysfs_path_ = udev_device_get_syspath(grandparent);
            LOG(INFO) << "sysfs path: " << sysfs_path_;
            MasterDevice = sysfs_path_;
          }
        }
        Driver = driver;
        udev_device_unref(udev_device);

        // TODO(jglasgow): Support multiple devices.
        // This functions returns the first network device whose
        // driver is a qualcomm network device driver.  This will not
        // work properly if a machine has multiple devices that use the
        // Qualcomm network device driver.
        break;
      }
    }
    udev_device_unref(udev_device);
  }
  udev_enumerate_unref(udev_enumerate);
  udev_unref(udev);
}

bool GobiModem::StartExit() {
  exiting_ = true;
  return (ForceDisconnect() == 0);
}

const char* QMIReturnCodeToMMError(unsigned int qmicode) {
  switch (qmicode) {
    case gobi::kIncorrectPinId:
      return kErrorIncorrectPassword;
    case gobi::kInvalidPinId:
    case gobi::kAccessToRequiredEntityNotAvailable:
      return kErrorSimPinRequired;
    case gobi::kPinBlocked:
    case gobi::kPinPermanentlyBlocked:
      // blocked vs. permanently block is distinguished by
      // looking at the value of UnlockRetries. If it is
      // zero, then the SIM is permanently blocked.
      return kErrorSimPukRequired;
    default:
      return NULL;
  }
}

// Map call failure reasons into ModemManager errors
const char* QMICallFailureToMMError(unsigned int qmireason) {
  switch (qmireason) {
    case gobi::kReasonBadApn:
    case gobi::kReasonNotSubscribed:
      return kErrorGprsNotSubscribed;
    default:
      return kErrorGsmUnknown;
  }
}

unsigned int QMIReasonToMMReason(unsigned int qmireason) {
  switch (qmireason) {
    case gobi::kReasonClientEndedCall:
      return MM_MODEM_STATE_CHANGED_REASON_USER_REQUESTED;
    default:
      return MM_MODEM_STATE_CHANGED_REASON_UNKNOWN;
  }
}

// Return true if a data session has started, or is in the process of starting.
bool GobiModem::is_connecting_or_connected() {
  return session_starter_in_flight_ || session_id_;
}

// Force a disconnect of a data session, or stop the process of
// starting a datasession
//
// Return 0 on success, gobi error code otherwise
ULONG GobiModem::ForceDisconnect() {
  ULONG rc = 0;
  if (session_id_) {
    LOG(INFO) << "ForceDisconnect: Stopping data session";
    rc = StopDataSession(session_id_);
    SetMmState(MM_MODEM_STATE_DISCONNECTING,
               MM_MODEM_STATE_CHANGED_REASON_USER_REQUESTED);
    if (rc != 0)
      LOG(WARNING) << "ForceDisconnect: StopDataSessionFailed: " << rc;
  } else if (session_starter_in_flight_) {
    LOG(INFO) << "ForceDisconnect: Canceling StartDataSession";
    rc = SessionStarter::CancelDataSession(sdk_);
    if (rc != 0)
      LOG(WARNING) << "ForceDisconnect: CancelDataSessionFailed: " << rc;
    else
      SetMmState(QCStateToMMState(gobi::kDisconnected),
                 MM_MODEM_STATE_CHANGED_REASON_USER_REQUESTED);
  }
  return rc;
}

// Tokenizes a string of the form (<[+-]ident>)* into a list of strings of the
// form [+-]ident.
static std::vector<std::string> TokenizeRequest(const std::string& req) {
  std::vector<std::string> tokens;
  std::string token;
  size_t start, end;

  start = req.find_first_of("+-");
  while (start != req.npos) {
    end = req.find_first_of("+-", start + 1);
    if (end == req.npos)
      token = req.substr(start);
    else
      token = req.substr(start, end - start);
    tokens.push_back(token);
    start = end;
  }

  return tokens;
}

int GobiModem::EventKeyToIndex(const char *key) {
  if (DEBUG && !strcmp(key, "dormancy"))
    return GOBI_EVENT_DORMANCY;
  return -1;
}

void GobiModem::RequestEvent(const std::string request, DBus::Error& error) {
  const char *req = request.c_str();
  const char *key = req + 1;

  if (!strcmp(key, "*")) {
    for (int i = 0; i < GOBI_EVENT_MAX; i++) {
      event_enabled[i] = (req[0] == '+');
    }
    return;
  }

  int idx = EventKeyToIndex(key);
  if (idx < 0) {
    error.set(kInvalidArgumentError, "Unknown event requested.");
    return;
  }

  event_enabled[idx] = (req[0] == '+');
}

void GobiModem::RequestEvents(const std::string& events, DBus::Error& error) {
  std::vector<std::string> requests = TokenizeRequest(events);
  std::vector<std::string>::iterator it;
  for (it = requests.begin(); it != requests.end(); it++) {
    RequestEvent(*it, error);
  }
}

void GobiModem::RecordResetReason(ULONG reason) {
  static const ULONG distinguished_errors[] = {
    gobi::kErrorSendingQmiRequest,    // 0
    gobi::kErrorReceivingQmiRequest,  // 1
    gobi::kErrorNeedsReset,           // 2
  };
  // Leave some room for other errors
  const int kMaxError = 10;
  int bucket = kMaxError;
  for (size_t i = 0; i < arraysize(distinguished_errors); ++i) {
    if (reason == distinguished_errors[i]) {
      bucket = i;
    }
  }
  metrics_lib_->SendEnumToUMA(
      METRIC_BASE_NAME "ResetReason", bucket, kMaxError + 1);
}

void GobiModem::ExitAndResetDevice(ULONG reason) {
  ApiDisconnect();
  if (reason)
    RecordResetReason(reason);

  handler_->ExitLeavingModemsForCleanup();
}

// DBus-exported
void GobiModem::Reset(DBus::Error& error) {
  // NB: If we have multiple modems, this is going to disconnect those
  // other modems.  If this becomes a problem, previous versions of
  // the code forked off a suid-root process to kick the device off
  // the bus; that code is still in the git repo.

  ExitAndResetDevice(0);
}

void GobiModem::SetEnabled(bool enabled) {
  Enabled = enabled;
  LOG(INFO) << "MM sending Enabled property changed signal: " << enabled;
  utilities::DBusPropertyMap props;
  props["Enabled"].writer().append_bool(enabled);
  MmPropertiesChanged(
      org::freedesktop::ModemManager::Modem_adaptor::introspect()->name,
      props);
}
