// 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-cromo-plugin/gobi_modem.h"

#include <algorithm>
#include <sstream>
#include <vector>

#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/strings/stringprintf.h>
#include <cromo/carrier.h>
#include <cromo/cromo_server.h>
#include <cromo/utilities.h>

#include "gobi-cromo-plugin/gobi_modem_handler.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-cromo-plugin/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(
          nullptr,
          apn_.get(),
          nullptr,  // 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 nullptr;
  }

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

    int join_rc = pthread_join(s->thread_, nullptr);
    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) {
      // 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_, nullptr /* 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:
  friend class GobiModem;

  DISALLOW_COPY_AND_ASSIGN(SessionStarter);
};

// 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:
  explicit PendingEnable(bool enable) : enable_(enable) {}
  ~PendingEnable() {}

  // NB: contrary to our style guide, this throws an exception that
  // dbus catches
  void RecordEnableAndReturnLater(GobiModem *modem) {
    modem->return_later(&tag_);
  }

  DBus::Tag tag_;
  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) {
    return nullptr;
  }

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

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

GobiModem* GobiModem::connected_modem_(nullptr);
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_) {
    // 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) {
    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_) {
    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_);
    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_) {
    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", nullptr, error);
  const char* username =
      utilities::ExtractString(properties, "username", nullptr, error);
  const char* password =
      utilities::ExtractString(properties, "password", nullptr, error);

  if (apn !=  nullptr)
    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) {
  std::unique_ptr<PendingEnable> scoped_enable = std::move(pending_enable_);
  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_) {
    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_) {
      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_) {
          // 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_)
    // 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 = nullptr;
  rc = sdk_->GetFirmwareInfo(&firmware_id,
                             &technology_id,
                             &carrier_id,
                             &region,
                             &gps_capability);
  if (rc == 0) {
    carrier = handler_->server().FindCarrierByCarrierId(carrier_id);
    if (carrier)
      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)
    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 nullptr 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_) {
    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_ = nullptr;
    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: " << static_cast<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, nullptr, 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) {
    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)
    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)
    modem->PowerModeHandler();
  return FALSE;
}

gboolean GobiModem::SessionStateCallback(gpointer data) {
  SessionStateArgs* args = static_cast<SessionStateArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem)
    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)
    modem->RegistrationStateHandler();
  return FALSE;
}

gboolean GobiModem::DataCapabilitiesCallback(gpointer data) {
  DataCapabilitiesArgs* args = static_cast<DataCapabilitiesArgs*>(data);
  GobiModem* modem = handler_->LookupByDbusPath(*args->path);
  if (modem)
    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)
    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_) {
    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_)
      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) {
    LOG(WARNING) << "udev == nullptr";
    return;
  }

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

  struct udev_list_entry *entry;
  for (entry = udev_enumerate_get_list_entry(udev_enumerate);
       entry != nullptr;
       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)
      continue;

    std::string driver;
    struct udev_device *parent = udev_device_get_parent(udev_device);
    if (parent) {
      const char *udev_driver = udev_device_get_driver(parent);
      if (udev_driver) {
        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) {
          grandparent = udev_device_get_parent(parent);
          if (grandparent) {
            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 nullptr;
  }
}

// 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);
}
