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