// 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_transfer.h"

#include <base/logging.h>
#include <base/strings/stringprintf.h>

#include <libusb.h>

using base::StringPrintf;
using std::ostream;
using std::string;

namespace mist {

UsbTransfer::UsbTransfer()
    : transfer_(nullptr),
      buffer_length_(0),
      state_(kIdle) {}

UsbTransfer::~UsbTransfer() {
  Free();
}

bool UsbTransfer::Submit(const CompletionCallback& completion_callback) {
  if (!VerifyAllocated())
    return false;

  if (state_ != kIdle) {
    error_.set_type(UsbError::kErrorTransferAlreadySubmitted);
    return false;
  }

  completion_callback_ = completion_callback;

  VLOG(1) << "Submit USB transfer: " << *this;
  int result = libusb_submit_transfer(transfer_);
  if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) {
    state_ = kInProgress;
    return true;
  }
  return false;
}

bool UsbTransfer::Cancel() {
  if (state_ == kIdle) {
    error_.set_type(UsbError::kErrorTransferNotSubmitted);
    return false;
  }

  if (state_ == kCancelling) {
    error_.set_type(UsbError::kErrorTransferBeingCancelled);
    return false;
  }

  int result = libusb_cancel_transfer(transfer_);
  if (error_.SetFromLibUsbError(static_cast<libusb_error>(result))) {
    state_ = kCancelling;
    return true;
  }
  return false;
}

uint8_t UsbTransfer::GetEndpointAddress() const {
  return transfer_ ? transfer_->endpoint : 0;
}

UsbTransferType UsbTransfer::GetType() const {
  if (!transfer_)
    return kUsbTransferTypeUnknown;

  switch (transfer_->type) {
    case LIBUSB_TRANSFER_TYPE_CONTROL:
      return kUsbTransferTypeControl;
    case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
      return kUsbTransferTypeIsochronous;
    case LIBUSB_TRANSFER_TYPE_BULK:
      return kUsbTransferTypeBulk;
    case LIBUSB_TRANSFER_TYPE_INTERRUPT:
      return kUsbTransferTypeInterrupt;
  }
  return kUsbTransferTypeUnknown;
}

UsbTransferStatus UsbTransfer::GetStatus() const {
  if (!transfer_)
    return kUsbTransferStatusUnknown;

  switch (transfer_->status) {
    case LIBUSB_TRANSFER_COMPLETED:
      return kUsbTransferStatusCompleted;
    case LIBUSB_TRANSFER_ERROR:
      return kUsbTransferStatusError;
    case LIBUSB_TRANSFER_TIMED_OUT:
      return kUsbTransferStatusTimedOut;
    case LIBUSB_TRANSFER_CANCELLED:
      return kUsbTransferStatusCancelled;
    case LIBUSB_TRANSFER_STALL:
      return kUsbTransferStatusStall;
    case LIBUSB_TRANSFER_NO_DEVICE:
      return kUsbTransferStatusNoDevice;
    case LIBUSB_TRANSFER_OVERFLOW:
      return kUsbTransferStatusOverflow;
  }
  return kUsbTransferStatusUnknown;
}

int UsbTransfer::GetLength() const {
  return transfer_ ? transfer_->length : 0;
}

int UsbTransfer::GetActualLength() const {
  return transfer_ ? transfer_->actual_length : 0;
}

bool UsbTransfer::IsCompletedWithExpectedLength(int expected_length) const {
  return GetStatus() == kUsbTransferStatusCompleted &&
         GetActualLength() == expected_length;
}

string UsbTransfer::ToString() const {
  if (!transfer_)
    return "Transfer (not allocated)";

  return StringPrintf("Transfer %p (Type=%s, "
                      "Flags=0x%08x, "
                      "DeviceHandle=%p, "
                      "EndpointAddress=%u, "
                      "NumIsoPackets=%d, "
                      "Buffer=%p, "
                      "Length=%d, "
                      "Transferred=%d, "
                      "Timeout=%u, "
                      "Status=%s)",
                      transfer_,
                      UsbTransferTypeToString(GetType()),
                      transfer_->flags,
                      transfer_->dev_handle,
                      transfer_->endpoint,
                      transfer_->num_iso_packets,
                      transfer_->buffer,
                      transfer_->length,
                      transfer_->actual_length,
                      transfer_->timeout,
                      UsbTransferStatusToString(GetStatus()));
}

bool UsbTransfer::VerifyAllocated() {
  if (transfer_)
    return true;

  LOG(ERROR) << "USB transfer is not allocated.";
  error_.set_type(UsbError::kErrorTransferNotAllocated);
  return false;
}

bool UsbTransfer::Allocate(int num_iso_packets) {
  if (transfer_) {
    LOG(ERROR) << "USB transfer already allocated.";
    error_.set_type(UsbError::kErrorTransferAlreadyAllocated);
    return false;
  }

  transfer_ = libusb_alloc_transfer(num_iso_packets);
  if (!transfer_) {
    LOG(ERROR) << "Could not allocate USB transfer.";
    error_.set_type(UsbError::kErrorNoMemory);
    return false;
  }

  VLOG(2) << StringPrintf("Allocated USB transfer %p.", transfer_);
  error_.Clear();
  return true;
}

void UsbTransfer::Free() {
  // It is not ok to free a transfer while it is still in progress or being
  // cancelled.
  CHECK_EQ(kIdle, state_);

  if (transfer_) {
    libusb_free_transfer(transfer_);
    VLOG(2) << StringPrintf("Freed USB transfer %p.", transfer_);
    transfer_ = nullptr;
  }
}

bool UsbTransfer::AllocateBuffer(int length) {
  if (state_ != kIdle) {
    error_.set_type(UsbError::kErrorTransferAlreadySubmitted);
    return false;
  }

  buffer_.reset(new uint8_t[length]);
  if (buffer_) {
    buffer_length_ = length;
    VLOG(2) << StringPrintf("Allocated data buffer %p for USB transfer %p.",
                            buffer_.get(),
                            transfer_);
    return true;
  }

  buffer_length_ = 0;
  LOG(ERROR) << StringPrintf(
      "Could not allocate data buffer for USB transfer %p.", transfer_);
  error_.set_type(UsbError::kErrorNoMemory);
  return false;
}

void UsbTransfer::OnCompleted(libusb_transfer* transfer) {
  CHECK(transfer);
  UsbTransfer* usb_transfer =
      reinterpret_cast<UsbTransfer*>(transfer->user_data);
  CHECK(usb_transfer);
  CHECK_EQ(transfer, usb_transfer->transfer_);

  VLOG(1) << StringPrintf("USB transfer %p completed.", usb_transfer);
  usb_transfer->Complete();
}

void UsbTransfer::Complete() {
  // Change the state to idle before calling the completion callback as this
  // object may be destructed in the completion callback and Free(), which is
  // called in the destructor of this object, expects the state to be idle.
  state_ = kIdle;
  if (!completion_callback_.is_null()) {
    VLOG(2) << StringPrintf("Invoke completion callback for USB transfer %p.",
                            transfer_);
    completion_callback_.Run(this);
  }
}

}  // namespace mist

ostream& operator<<(ostream& stream, const mist::UsbTransfer& transfer) {
  stream << transfer.ToString();
  return stream;
}
