// Copyright (c) 2013 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 "mist/usb_modem_switch_operation.h"

#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>

#include "mist/context.h"
#include "mist/event_dispatcher.h"
#include "mist/proto_bindings/usb_modem_info.pb.h"
#include "mist/usb_bulk_transfer.h"
#include "mist/usb_config_descriptor.h"
#include "mist/usb_constants.h"
#include "mist/usb_device.h"
#include "mist/usb_device_descriptor.h"
#include "mist/usb_device_event_notifier.h"
#include "mist/usb_endpoint_descriptor.h"
#include "mist/usb_interface.h"
#include "mist/usb_interface_descriptor.h"
#include "mist/usb_manager.h"
#include "mist/usb_modem_switch_context.h"

using base::Bind;
using base::CancelableClosure;
using base::StringPrintf;
using base::Unretained;
using std::string;
using std::unique_ptr;
using std::vector;

namespace mist {

namespace {

const int kDefaultUsbInterfaceIndex = 0;
const int kDefaultUsbInterfaceAlternateSettingIndex = 0;

// Expected response length observed in experiments.
const int kExpectedResponseLength = 13;

// TODO(benchan): To be conservative, use large timeout values for now. Add UMA
// metrics to determine appropriate timeout values.
const int64_t kReconnectTimeoutMilliseconds = 15000;
const int64_t kUsbMessageTransferTimeoutMilliseconds = 8000;

}  // namespace

// TODO(benchan): Add unit tests for UsbModemSwitchOperation.

UsbModemSwitchOperation::UsbModemSwitchOperation(
    Context* context, UsbModemSwitchContext* switch_context)
    : context_(context),
      switch_context_(switch_context),
      interface_claimed_(false),
      interface_number_(0),
      in_endpoint_address_(0),
      out_endpoint_address_(0),
      message_index_(0),
      num_usb_messages_(0) {
  CHECK(context_);
  CHECK(switch_context_);
  CHECK(!switch_context_->sys_path().empty());
  CHECK(switch_context_->modem_info());
}

UsbModemSwitchOperation::~UsbModemSwitchOperation() {
  Cancel();
  CloseDevice();

  // If the USB bulk transfer is being cancelled, the UsbBulkTransfer object
  // held by |bulk_transfer_| still need to survive until libusb notifies the
  // cancellation of the underlying transfer via a callback as we have no way to
  // cancel that calback. This should only happen when mist is about to
  // terminate while the transfer is being cancelled. To avoid deferring the
  // termination of mist, we intentionally leak the UsbBulkTransfer object held
  // by |bulk_transfer_| and hope that either the callback is invoked (with an
  // invalidated weak pointer to this object) before mist terminates or is
  // discarded after mist terminates.
  if (bulk_transfer_ && bulk_transfer_->state() == UsbTransfer::kCancelling)
    ignore_result(bulk_transfer_.release());
}

void UsbModemSwitchOperation::Start(
    const CompletionCallback& completion_callback) {
  CHECK(!completion_callback.is_null());

  completion_callback_ = completion_callback;
  VLOG(1) << "Start modem switch operation for device '"
          << switch_context_->sys_path() << "'.";

  // Schedule the execution of the first task using the message loop, even when
  // the initial delay is 0, as multiple UsbModemSwitchOperation objects may be
  // created and started in a tight loop.
  base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(
      switch_context_->modem_info()->initial_delay_ms());
  LOG(INFO) << "Starting the modem switch operation in "
            << initial_delay.InMilliseconds() << " ms.";
  ScheduleDelayedTask(&UsbModemSwitchOperation::OpenDeviceAndSelectInterface,
                      initial_delay);
}

void UsbModemSwitchOperation::Cancel() {
  pending_task_.Cancel();
  reconnect_timeout_callback_.Cancel();
  context_->usb_device_event_notifier()->RemoveObserver(this);

  if (bulk_transfer_)
    bulk_transfer_->Cancel();
}

void UsbModemSwitchOperation::ScheduleTask(Task task) {
  pending_task_.Reset(Bind(task, Unretained(this)));
  context_->event_dispatcher()->PostTask(pending_task_.callback());
}

void UsbModemSwitchOperation::ScheduleDelayedTask(
    Task task, const base::TimeDelta& delay) {
  pending_task_.Reset(Bind(task, Unretained(this)));
  context_->event_dispatcher()->PostDelayedTask(pending_task_.callback(),
                                                delay);
}

void UsbModemSwitchOperation::Complete(bool success) {
  CHECK(!completion_callback_.is_null());

  if (!success) {
    LOG(ERROR) << "Could not switch device '" << switch_context_->sys_path()
               << "' into the modem mode.";
  }

  pending_task_.Cancel();
  reconnect_timeout_callback_.Cancel();
  context_->usb_device_event_notifier()->RemoveObserver(this);

  // Defer the execution of the completion callback for two reasons:
  // 1. To prevent a task in this switch operation from occupying the message
  //    loop for too long as Complete() can be called from one of the tasks.
  // 2. The completion callback may delete this object, so this object should
  //    not be accessed after this method returns.
  context_->event_dispatcher()->PostTask(
      Bind(completion_callback_, Unretained(this), success));
}

void UsbModemSwitchOperation::DetachAllKernelDrivers() {
  unique_ptr<UsbConfigDescriptor> config_descriptor(
      device_->GetActiveConfigDescriptor());
  if (!config_descriptor)
    return;

  for (uint8_t interface_number = 0;
       interface_number < config_descriptor->GetNumInterfaces();
       ++interface_number) {
    if (!device_->DetachKernelDriver(interface_number) &&
        // UsbDevice::DetachKernelDriver returns UsbError::kErrorNotFound when
        // there is no driver attached to the device.
        device_->error().type() != UsbError::kErrorNotFound) {
      LOG(ERROR) << StringPrintf(
          "Could not detach kernel driver from interface %u: %s",
          interface_number, device_->error().ToString());
      // Continue to detach other kernel drivers in case of an error.
    }
  }
}

int UsbModemSwitchOperation::GetMBIMConfigurationValue() {
  CHECK(device_);

  unique_ptr<UsbDeviceDescriptor> device_descriptor(
      device_->GetDeviceDescriptor());
  if (!device_descriptor) {
    LOG(ERROR) << "Could not get device descriptor: " << device_->error();
    return kUsbConfigurationValueInvalid;
  }

  VLOG(2) << *device_descriptor;

  for (uint8_t config_index = 0;
       config_index < device_descriptor->GetNumConfigurations();
       ++config_index) {
    unique_ptr<UsbConfigDescriptor> config_descriptor(
        device_->GetConfigDescriptor(config_index));
    if (!config_descriptor)
      continue;

    VLOG(2) << *config_descriptor;

    for (uint8_t interface_number = 0;
         interface_number < config_descriptor->GetNumInterfaces();
         ++interface_number) {
      unique_ptr<UsbInterface> interface(
          config_descriptor->GetInterface(interface_number));
      if (!interface)
        continue;

      unique_ptr<UsbInterfaceDescriptor> interface_descriptor(
          interface->GetAlternateSetting(
              kDefaultUsbInterfaceAlternateSettingIndex));
      if (!interface_descriptor)
        continue;

      VLOG(2) << *interface_descriptor;

      if (interface_descriptor->GetInterfaceClass() != kUsbClassCommunication ||
          interface_descriptor->GetInterfaceSubclass() != kUsbSubClassMBIM)
        continue;

      int configuration_value = config_descriptor->GetConfigurationValue();
      LOG(INFO) << StringPrintf(
          "Found MBIM support at configuration %d on device '%s'.",
          configuration_value, switch_context_->sys_path().c_str());
      return configuration_value;
    }
  }
  return kUsbConfigurationValueInvalid;
}

bool UsbModemSwitchOperation::SetConfiguration(int configuration) {
  unique_ptr<UsbConfigDescriptor> config_descriptor(
      device_->GetActiveConfigDescriptor());
  if (!config_descriptor) {
    LOG(ERROR) << "Could not get active configuration descriptor: "
               << device_->error();
    return false;
  }

  if (config_descriptor->GetConfigurationValue() == configuration) {
    LOG(INFO) << StringPrintf("Device '%s' is already in configuration %d. ",
                              switch_context_->sys_path().c_str(),
                              configuration);
    return true;
  }

  DetachAllKernelDrivers();
  if (device_->SetConfiguration(configuration)) {
    LOG(INFO) << StringPrintf(
        "Successfully selected configuration %d for device '%s'.",
        configuration, switch_context_->sys_path().c_str());
    return true;
  }

  LOG(ERROR) << StringPrintf(
      "Could not select configuration %d for device '%s': %s", configuration,
      switch_context_->sys_path().c_str(), device_->error().ToString());
  return false;
}

void UsbModemSwitchOperation::CloseDevice() {
  if (!device_)
    return;

  if (interface_claimed_) {
    if (!device_->ReleaseInterface(interface_number_) &&
        // UsbDevice::ReleaseInterface may return UsbError::kErrorNoDevice
        // as the original device may no longer exist after switching to the
        // modem mode. Do not report such an error.
        device_->error().type() != UsbError::kErrorNoDevice) {
      LOG(ERROR) << StringPrintf("Could not release interface %u: %s",
                                 interface_number_,
                                 device_->error().ToString());
    }
    interface_claimed_ = false;
  }

  device_.reset();
}

void UsbModemSwitchOperation::OpenDeviceAndSelectInterface() {
  CHECK(!interface_claimed_);

  device_.reset(context_->usb_manager()->GetDevice(
      switch_context_->bus_number(), switch_context_->device_address(),
      switch_context_->vendor_id(), switch_context_->product_id()));
  if (!device_) {
    LOG(ERROR) << StringPrintf(
        "Could not find USB device '%s' (Bus %03d Address %03d ID %04x:%04x).",
        switch_context_->sys_path().c_str(), switch_context_->bus_number(),
        switch_context_->device_address(), switch_context_->vendor_id(),
        switch_context_->product_id());
    Complete(false);
    return;
  }

  if (!device_->Open()) {
    LOG(ERROR) << "Could not open device '" << switch_context_->sys_path()
               << "'.";
    Complete(false);
    return;
  }

  unique_ptr<UsbConfigDescriptor> config_descriptor(
      device_->GetActiveConfigDescriptor());
  if (!config_descriptor) {
    LOG(ERROR) << "Could not get active configuration descriptor: "
               << device_->error();
    Complete(false);
    return;
  }
  VLOG(2) << *config_descriptor;

  int mbim_configuration_value = GetMBIMConfigurationValue();
  if (mbim_configuration_value != kUsbConfigurationValueInvalid) {
    LOG(INFO) << StringPrintf("Switching device '%s' to MBIM configuration %d.",
                              switch_context_->sys_path().c_str(),
                              mbim_configuration_value);
    Complete(SetConfiguration(mbim_configuration_value));
    return;
  }

  unique_ptr<UsbInterface> interface(
      config_descriptor->GetInterface(kDefaultUsbInterfaceIndex));
  if (!interface) {
    LOG(ERROR) << "Could not get interface 0.";
    Complete(false);
    return;
  }

  unique_ptr<UsbInterfaceDescriptor> interface_descriptor(
      interface->GetAlternateSetting(
          kDefaultUsbInterfaceAlternateSettingIndex));
  if (!interface_descriptor) {
    LOG(ERROR) << "Could not get interface alternate setting 0.";
    Complete(false);
    return;
  }
  VLOG(2) << *interface_descriptor;

  if (interface_descriptor->GetInterfaceClass() != kUsbClassMassStorage) {
    LOG(ERROR) << "Device is not currently in mass storage mode.";
    Complete(false);
    return;
  }

  unique_ptr<UsbEndpointDescriptor> out_endpoint_descriptor(
      interface_descriptor->GetEndpointDescriptorByTransferTypeAndDirection(
          kUsbTransferTypeBulk, kUsbDirectionOut));
  if (!out_endpoint_descriptor) {
    LOG(ERROR) << "Could not find an output bulk endpoint.";
    Complete(false);
    return;
  }
  VLOG(2) << "Bulk output endpoint: " << *out_endpoint_descriptor;

  interface_number_ = interface_descriptor->GetInterfaceNumber();
  out_endpoint_address_ = out_endpoint_descriptor->GetEndpointAddress();

  if (switch_context_->modem_info()->expect_response()) {
    unique_ptr<UsbEndpointDescriptor> in_endpoint_descriptor(
        interface_descriptor->GetEndpointDescriptorByTransferTypeAndDirection(
            kUsbTransferTypeBulk, kUsbDirectionIn));
    if (!in_endpoint_descriptor) {
      LOG(ERROR) << "Could not find an input bulk endpoint.";
      Complete(false);
      return;
    }
    VLOG(2) << "Bulk input endpoint: " << *in_endpoint_descriptor;
    in_endpoint_address_ = in_endpoint_descriptor->GetEndpointAddress();
  }

  if (!device_->DetachKernelDriver(interface_number_) &&
      // UsbDevice::DetachKernelDriver returns UsbError::kErrorNotFound when
      // there is no driver attached to the device.
      device_->error().type() != UsbError::kErrorNotFound) {
    LOG(ERROR) << StringPrintf(
        "Could not detach kernel driver from interface %u: %s",
        interface_number_, device_->error().ToString());
    Complete(false);
    return;
  }

  if (!device_->ClaimInterface(interface_number_)) {
    LOG(ERROR) << StringPrintf("Could not claim interface %u: %s",
                               interface_number_, device_->error().ToString());
    Complete(false);
    return;
  }

  interface_claimed_ = true;
  message_index_ = 0;
  num_usb_messages_ = switch_context_->modem_info()->usb_message_size();
  // TODO(benchan): Remove this check when we support some modem that does not
  // require a special USB message for the switch operation.
  CHECK_GT(num_usb_messages_, 0);

  context_->usb_device_event_notifier()->AddObserver(this);

  ScheduleTask(&UsbModemSwitchOperation::SendMessageToMassStorageEndpoint);
}

bool UsbModemSwitchOperation::ClearHalt(uint8_t endpoint_address) {
  if (device_->ClearHalt(endpoint_address))
    return true;

  LOG(ERROR) << StringPrintf(
      "Could not clear halt condition for endpoint %u: %s", endpoint_address,
      device_->error().ToString());
  return false;
}

void UsbModemSwitchOperation::SendMessageToMassStorageEndpoint() {
  CHECK_LT(message_index_, num_usb_messages_);

  const string& usb_message =
      switch_context_->modem_info()->usb_message(message_index_);
  vector<uint8_t> bytes;
  if (!base::HexStringToBytes(usb_message, &bytes)) {
    LOG(ERROR) << StringPrintf("Invalid USB message (%d/%d): %s",
                               message_index_, num_usb_messages_,
                               usb_message.c_str());
    Complete(false);
    return;
  }

  VLOG(1) << StringPrintf("Prepare to send USB message (%d/%d): %s",
                          message_index_ + 1, num_usb_messages_,
                          usb_message.c_str());

  InitiateUsbBulkTransfer(out_endpoint_address_, &bytes[0], bytes.size(),
                          &UsbModemSwitchOperation::OnSendMessageCompleted);
}

void UsbModemSwitchOperation::ReceiveMessageFromMassStorageEndpoint() {
  CHECK_LT(message_index_, num_usb_messages_);

  VLOG(1) << StringPrintf("Prepare to receive USB message (%d/%d)",
                          message_index_ + 1, num_usb_messages_);

  InitiateUsbBulkTransfer(in_endpoint_address_, nullptr,
                          kExpectedResponseLength,
                          &UsbModemSwitchOperation::OnReceiveMessageCompleted);
}

void UsbModemSwitchOperation::InitiateUsbBulkTransfer(
    uint8_t endpoint_address,
    const uint8_t* data,
    int length,
    UsbTransferCompletionHandler completion_handler) {
  CHECK_GT(length, 0);

  unique_ptr<UsbBulkTransfer> bulk_transfer(new UsbBulkTransfer());
  if (!bulk_transfer->Initialize(*device_, endpoint_address, length,
                                 kUsbMessageTransferTimeoutMilliseconds)) {
    LOG(ERROR) << "Could not create USB bulk transfer: "
               << bulk_transfer->error();
    Complete(false);
    return;
  }

  if (GetUsbDirectionOfEndpointAddress(endpoint_address) == kUsbDirectionOut) {
    CHECK(data);
    memcpy(bulk_transfer->buffer(), data, length);
  }
  // For a device-to-host transfer, |data| is not used and thus ignored.

  // Pass a weak pointer of this operation object to the completion callback
  // of the USB bulk transfer. This avoids the need to defer the destruction
  // of this object in order to wait for the completion callback of the
  // transfer when the transfer is cancelled by this object.
  if (!bulk_transfer->Submit(Bind(completion_handler, AsWeakPtr()))) {
    LOG(ERROR) << "Could not submit USB bulk transfer: "
               << bulk_transfer->error();
    Complete(false);
    return;
  }

  bulk_transfer_ = std::move(bulk_transfer);
}

void UsbModemSwitchOperation::OnSendMessageCompleted(UsbTransfer* transfer) {
  VLOG(1) << "USB bulk output transfer completed: " << *transfer;

  CHECK_EQ(bulk_transfer_.get(), transfer);
  CHECK_EQ(out_endpoint_address_, transfer->GetEndpointAddress());

  // Keep the bulk transfer valid until this method goes out of scope.
  unique_ptr<UsbBulkTransfer> scoped_bulk_transfer = std::move(bulk_transfer_);

  if (transfer->GetStatus() == kUsbTransferStatusStall) {
    if (!ClearHalt(transfer->GetEndpointAddress())) {
      Complete(false);
      return;
    }

    ScheduleTask(&UsbModemSwitchOperation::SendMessageToMassStorageEndpoint);
    return;
  }

  if (!transfer->IsCompletedWithExpectedLength(transfer->GetLength())) {
    LOG(ERROR) << StringPrintf(
        "Could not successfully send USB message (%d/%d).", message_index_ + 1,
        num_usb_messages_);
    Complete(false);
    return;
  }

  LOG(INFO) << StringPrintf("Successfully sent USB message (%d/%d).",
                            message_index_ + 1, num_usb_messages_);

  if (switch_context_->modem_info()->expect_response()) {
    ScheduleTask(
        &UsbModemSwitchOperation::ReceiveMessageFromMassStorageEndpoint);
    return;
  }

  ScheduleNextMessageToMassStorageEndpoint();
}

void UsbModemSwitchOperation::OnReceiveMessageCompleted(UsbTransfer* transfer) {
  VLOG(1) << "USB bulk input transfer completed: " << *transfer;

  CHECK_EQ(bulk_transfer_.get(), transfer);
  CHECK_EQ(in_endpoint_address_, transfer->GetEndpointAddress());

  // Keep the bulk transfer valid until this method goes out of scope.
  unique_ptr<UsbBulkTransfer> scoped_bulk_transfer = std::move(bulk_transfer_);

  if (transfer->GetStatus() == kUsbTransferStatusStall) {
    if (!ClearHalt(transfer->GetEndpointAddress())) {
      Complete(false);
      return;
    }

    ScheduleTask(
        &UsbModemSwitchOperation::ReceiveMessageFromMassStorageEndpoint);
    return;
  }

  if (!transfer->IsCompletedWithExpectedLength(kExpectedResponseLength)) {
    LOG(ERROR) << StringPrintf(
        "Could not successfully receive USB message (%d/%d).",
        message_index_ + 1, num_usb_messages_);
    Complete(false);
    return;
  }

  LOG(INFO) << StringPrintf("Successfully received USB message (%d/%d).",
                            message_index_ + 1, num_usb_messages_);

  ScheduleNextMessageToMassStorageEndpoint();
}

void UsbModemSwitchOperation::ScheduleNextMessageToMassStorageEndpoint() {
  ++message_index_;
  if (message_index_ < num_usb_messages_) {
    ScheduleTask(&UsbModemSwitchOperation::SendMessageToMassStorageEndpoint);
    return;
  }

  // After sending the last message (and receiving its response, if expected),
  // wait for the device to reconnect.
  pending_task_.Cancel();
  reconnect_timeout_callback_.Reset(
      Bind(&UsbModemSwitchOperation::OnReconnectTimeout, Unretained(this)));
  context_->event_dispatcher()->PostDelayedTask(
      reconnect_timeout_callback_.callback(),
      base::TimeDelta::FromMilliseconds(kReconnectTimeoutMilliseconds));
}

void UsbModemSwitchOperation::OnReconnectTimeout() {
  LOG(ERROR) << "Timed out waiting for the device to reconnect.";
  Complete(false);
}

void UsbModemSwitchOperation::OnUsbDeviceAdded(const string& sys_path,
                                               uint8_t bus_number,
                                               uint8_t device_address,
                                               uint16_t vendor_id,
                                               uint16_t product_id) {
  if (sys_path != switch_context_->sys_path())
    return;

  const UsbModemInfo* modem_info = switch_context_->modem_info();
  if (modem_info->final_usb_id_size() == 0) {
    VLOG(1) << "No final USB identifiers are specified. Assuming device '"
            << switch_context_->sys_path()
            << "' has been switched to the modem mode.";
    Complete(true);
    return;
  }

  for (int i = 0; i < modem_info->final_usb_id_size(); ++i) {
    const UsbId& final_usb_id = modem_info->final_usb_id(i);
    if (vendor_id == final_usb_id.vendor_id() &&
        product_id == final_usb_id.product_id()) {
      const UsbId& initial_usb_id = modem_info->initial_usb_id();
      LOG(INFO) << StringPrintf(
          "Successfully switched device '%s' from %04x:%04x to %04x:%04x.",
          switch_context_->sys_path().c_str(), initial_usb_id.vendor_id(),
          initial_usb_id.product_id(), final_usb_id.vendor_id(),
          final_usb_id.product_id());
      Complete(true);
      return;
    }
  }
}

void UsbModemSwitchOperation::OnUsbDeviceRemoved(const string& sys_path) {
  if (sys_path == switch_context_->sys_path()) {
    VLOG(1) << "Device '" << switch_context_->sys_path()
            << "' has been removed and is switching to the modem mode.";
    // TODO(benchan): Investigate if the device will always be removed from
    // the bus before it reconnects. If so, add a check.
  }
}

}  // namespace mist
