// 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/stringprintf.h>

#include <libusb.h>

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

namespace mist {

UsbTransfer::UsbTransfer()
    : transfer_(NULL),
      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 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_ = NULL;
  }
}

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

  buffer_.reset(new uint8[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;
}
