// Copyright 2014 The Chromium 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 "device/usb/usb_device_handle_impl.h"

#include <algorithm>
#include <memory>
#include <numeric>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "device/usb/usb_context.h"
#include "device/usb/usb_descriptors.h"
#include "device/usb/usb_device_impl.h"
#include "device/usb/usb_error.h"
#include "device/usb/usb_service.h"
#include "net/base/io_buffer.h"
#include "third_party/libusb/src/libusb/libusb.h"

namespace device {

typedef libusb_device* PlatformUsbDevice;

void HandleTransferCompletion(PlatformUsbTransferHandle transfer);

namespace {

uint8_t ConvertTransferDirection(UsbEndpointDirection direction) {
  switch (direction) {
    case USB_DIRECTION_INBOUND:
      return LIBUSB_ENDPOINT_IN;
    case USB_DIRECTION_OUTBOUND:
      return LIBUSB_ENDPOINT_OUT;
    default:
      NOTREACHED();
      return LIBUSB_ENDPOINT_IN;
  }
}

uint8_t CreateRequestType(UsbEndpointDirection direction,
                          UsbDeviceHandle::TransferRequestType request_type,
                          UsbDeviceHandle::TransferRecipient recipient) {
  uint8_t result = ConvertTransferDirection(direction);

  switch (request_type) {
    case UsbDeviceHandle::STANDARD:
      result |= LIBUSB_REQUEST_TYPE_STANDARD;
      break;
    case UsbDeviceHandle::CLASS:
      result |= LIBUSB_REQUEST_TYPE_CLASS;
      break;
    case UsbDeviceHandle::VENDOR:
      result |= LIBUSB_REQUEST_TYPE_VENDOR;
      break;
    case UsbDeviceHandle::RESERVED:
      result |= LIBUSB_REQUEST_TYPE_RESERVED;
      break;
  }

  switch (recipient) {
    case UsbDeviceHandle::DEVICE:
      result |= LIBUSB_RECIPIENT_DEVICE;
      break;
    case UsbDeviceHandle::INTERFACE:
      result |= LIBUSB_RECIPIENT_INTERFACE;
      break;
    case UsbDeviceHandle::ENDPOINT:
      result |= LIBUSB_RECIPIENT_ENDPOINT;
      break;
    case UsbDeviceHandle::OTHER:
      result |= LIBUSB_RECIPIENT_OTHER;
      break;
  }

  return result;
}

static UsbTransferStatus ConvertTransferStatus(
    const libusb_transfer_status status) {
  switch (status) {
    case LIBUSB_TRANSFER_COMPLETED:
      return USB_TRANSFER_COMPLETED;
    case LIBUSB_TRANSFER_ERROR:
      return USB_TRANSFER_ERROR;
    case LIBUSB_TRANSFER_TIMED_OUT:
      return USB_TRANSFER_TIMEOUT;
    case LIBUSB_TRANSFER_STALL:
      return USB_TRANSFER_STALLED;
    case LIBUSB_TRANSFER_NO_DEVICE:
      return USB_TRANSFER_DISCONNECT;
    case LIBUSB_TRANSFER_OVERFLOW:
      return USB_TRANSFER_OVERFLOW;
    case LIBUSB_TRANSFER_CANCELLED:
      return USB_TRANSFER_CANCELLED;
    default:
      NOTREACHED();
      return USB_TRANSFER_ERROR;
  }
}

static void RunTransferCallback(
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const UsbDeviceHandle::TransferCallback& callback,
    UsbTransferStatus status,
    scoped_refptr<net::IOBuffer> buffer,
    size_t result) {
  if (callback_task_runner->RunsTasksOnCurrentThread()) {
    callback.Run(status, buffer, result);
  } else {
    callback_task_runner->PostTask(
        FROM_HERE, base::Bind(callback, status, buffer, result));
  }
}

void ReportIsochronousTransferError(
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const UsbDeviceHandle::IsochronousTransferCallback& callback,
    const std::vector<uint32_t> packet_lengths,
    UsbTransferStatus status) {
  std::vector<UsbDeviceHandle::IsochronousPacket> packets(
      packet_lengths.size());
  for (size_t i = 0; i < packet_lengths.size(); ++i) {
    packets[i].length = packet_lengths[i];
    packets[i].transferred_length = 0;
    packets[i].status = status;
  }
  if (callback_task_runner->RunsTasksOnCurrentThread()) {
    callback.Run(nullptr, packets);
  } else {
    callback_task_runner->PostTask(FROM_HERE,
                                   base::Bind(callback, nullptr, packets));
  }
}

}  // namespace

class UsbDeviceHandleImpl::InterfaceClaimer
    : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> {
 public:
  InterfaceClaimer(scoped_refptr<UsbDeviceHandleImpl> handle,
                   int interface_number,
                   scoped_refptr<base::SingleThreadTaskRunner> task_runner);

  int interface_number() const { return interface_number_; }
  int alternate_setting() const { return alternate_setting_; }
  void set_alternate_setting(const int alternate_setting) {
    alternate_setting_ = alternate_setting;
  }

  void set_release_callback(const ResultCallback& callback) {
    release_callback_ = callback;
  }

 private:
  friend class base::RefCountedThreadSafe<InterfaceClaimer>;
  ~InterfaceClaimer();

  const scoped_refptr<UsbDeviceHandleImpl> handle_;
  const int interface_number_;
  int alternate_setting_;
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  ResultCallback release_callback_;
  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
};

UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
    scoped_refptr<UsbDeviceHandleImpl> handle,
    int interface_number,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    : handle_(handle),
      interface_number_(interface_number),
      alternate_setting_(0),
      task_runner_(task_runner) {}

UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
  DCHECK(thread_checker_.CalledOnValidThread());
  int rc = libusb_release_interface(handle_->handle(), interface_number_);
  if (rc != LIBUSB_SUCCESS) {
    USB_LOG(DEBUG) << "Failed to release interface: "
                   << ConvertPlatformUsbErrorToString(rc);
  }
  if (!release_callback_.is_null()) {
    task_runner_->PostTask(FROM_HERE,
                           base::Bind(release_callback_, rc == LIBUSB_SUCCESS));
  }
}

// This inner class owns the underlying libusb_transfer and may outlast
// the UsbDeviceHandle that created it.
class UsbDeviceHandleImpl::Transfer {
 public:
  static std::unique_ptr<Transfer> CreateControlTransfer(
      scoped_refptr<UsbDeviceHandleImpl> device_handle,
      uint8_t type,
      uint8_t request,
      uint16_t value,
      uint16_t index,
      uint16_t length,
      scoped_refptr<net::IOBuffer> buffer,
      unsigned int timeout,
      scoped_refptr<base::TaskRunner> callback_task_runner,
      const TransferCallback& callback);
  static std::unique_ptr<Transfer> CreateBulkTransfer(
      scoped_refptr<UsbDeviceHandleImpl> device_handle,
      uint8_t endpoint,
      scoped_refptr<net::IOBuffer> buffer,
      int length,
      unsigned int timeout,
      scoped_refptr<base::TaskRunner> callback_task_runner,
      const TransferCallback& callback);
  static std::unique_ptr<Transfer> CreateInterruptTransfer(
      scoped_refptr<UsbDeviceHandleImpl> device_handle,
      uint8_t endpoint,
      scoped_refptr<net::IOBuffer> buffer,
      int length,
      unsigned int timeout,
      scoped_refptr<base::TaskRunner> callback_task_runner,
      const TransferCallback& callback);
  static std::unique_ptr<Transfer> CreateIsochronousTransfer(
      scoped_refptr<UsbDeviceHandleImpl> device_handle,
      uint8_t endpoint,
      scoped_refptr<net::IOBuffer> buffer,
      size_t length,
      const std::vector<uint32_t>& packet_lengths,
      unsigned int timeout,
      scoped_refptr<base::TaskRunner> callback_task_runner,
      const IsochronousTransferCallback& callback);

  ~Transfer();

  void Submit();
  void Cancel();
  void ProcessCompletion();
  void TransferComplete(UsbTransferStatus status, size_t bytes_transferred);

  const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const {
    return claimed_interface_.get();
  }

  scoped_refptr<base::TaskRunner> callback_task_runner() const {
    return callback_task_runner_;
  }

 private:
  Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
           scoped_refptr<InterfaceClaimer> claimed_interface,
           UsbTransferType transfer_type,
           scoped_refptr<net::IOBuffer> buffer,
           size_t length,
           scoped_refptr<base::TaskRunner> callback_task_runner,
           const TransferCallback& callback);
  Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
           scoped_refptr<InterfaceClaimer> claimed_interface,
           scoped_refptr<net::IOBuffer> buffer,
           scoped_refptr<base::TaskRunner> callback_task_runner,
           const IsochronousTransferCallback& callback);

  static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);

  void IsochronousTransferComplete();

  UsbTransferType transfer_type_;
  scoped_refptr<UsbDeviceHandleImpl> device_handle_;
  PlatformUsbTransferHandle platform_transfer_ = nullptr;
  scoped_refptr<net::IOBuffer> buffer_;
  scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_;
  size_t length_;
  bool cancelled_ = false;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  scoped_refptr<base::TaskRunner> callback_task_runner_;
  TransferCallback callback_;
  IsochronousTransferCallback iso_callback_;
};

// static
std::unique_ptr<UsbDeviceHandleImpl::Transfer>
UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    uint8_t type,
    uint8_t request,
    uint16_t value,
    uint16_t index,
    uint16_t length,
    scoped_refptr<net::IOBuffer> buffer,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback) {
  std::unique_ptr<Transfer> transfer(new Transfer(
      device_handle, nullptr, USB_TRANSFER_CONTROL, buffer,
      length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, callback));

  transfer->platform_transfer_ = libusb_alloc_transfer(0);
  if (!transfer->platform_transfer_) {
    USB_LOG(ERROR) << "Failed to allocate control transfer.";
    return nullptr;
  }

  libusb_fill_control_setup(reinterpret_cast<uint8_t*>(buffer->data()), type,
                            request, value, index, length);
  libusb_fill_control_transfer(transfer->platform_transfer_,
                               device_handle->handle_,
                               reinterpret_cast<uint8_t*>(buffer->data()),
                               &UsbDeviceHandleImpl::Transfer::PlatformCallback,
                               transfer.get(), timeout);

  return transfer;
}

// static
std::unique_ptr<UsbDeviceHandleImpl::Transfer>
UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    uint8_t endpoint,
    scoped_refptr<net::IOBuffer> buffer,
    int length,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback) {
  std::unique_ptr<Transfer> transfer(new Transfer(
      device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
      USB_TRANSFER_BULK, buffer, length, callback_task_runner, callback));

  transfer->platform_transfer_ = libusb_alloc_transfer(0);
  if (!transfer->platform_transfer_) {
    USB_LOG(ERROR) << "Failed to allocate bulk transfer.";
    return nullptr;
  }

  libusb_fill_bulk_transfer(transfer->platform_transfer_,
                            device_handle->handle_, endpoint,
                            reinterpret_cast<uint8_t*>(buffer->data()), length,
                            &UsbDeviceHandleImpl::Transfer::PlatformCallback,
                            transfer.get(), timeout);

  return transfer;
}

// static
std::unique_ptr<UsbDeviceHandleImpl::Transfer>
UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    uint8_t endpoint,
    scoped_refptr<net::IOBuffer> buffer,
    int length,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback) {
  std::unique_ptr<Transfer> transfer(new Transfer(
      device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
      USB_TRANSFER_INTERRUPT, buffer, length, callback_task_runner, callback));

  transfer->platform_transfer_ = libusb_alloc_transfer(0);
  if (!transfer->platform_transfer_) {
    USB_LOG(ERROR) << "Failed to allocate interrupt transfer.";
    return nullptr;
  }

  libusb_fill_interrupt_transfer(
      transfer->platform_transfer_, device_handle->handle_, endpoint,
      reinterpret_cast<uint8_t*>(buffer->data()), length,
      &UsbDeviceHandleImpl::Transfer::PlatformCallback, transfer.get(),
      timeout);

  return transfer;
}

// static
std::unique_ptr<UsbDeviceHandleImpl::Transfer>
UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    uint8_t endpoint,
    scoped_refptr<net::IOBuffer> buffer,
    size_t length,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const IsochronousTransferCallback& callback) {
  std::unique_ptr<Transfer> transfer(new Transfer(
      device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
      buffer, callback_task_runner, callback));

  int num_packets = static_cast<int>(packet_lengths.size());
  transfer->platform_transfer_ = libusb_alloc_transfer(num_packets);
  if (!transfer->platform_transfer_) {
    USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
    return nullptr;
  }

  libusb_fill_iso_transfer(
      transfer->platform_transfer_, device_handle->handle_, endpoint,
      reinterpret_cast<uint8_t*>(buffer->data()), static_cast<int>(length),
      num_packets, &Transfer::PlatformCallback, transfer.get(), timeout);

  for (size_t i = 0; i < packet_lengths.size(); ++i)
    transfer->platform_transfer_->iso_packet_desc[i].length = packet_lengths[i];

  return transfer;
}

UsbDeviceHandleImpl::Transfer::Transfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    scoped_refptr<InterfaceClaimer> claimed_interface,
    UsbTransferType transfer_type,
    scoped_refptr<net::IOBuffer> buffer,
    size_t length,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback)
    : transfer_type_(transfer_type),
      device_handle_(device_handle),
      buffer_(buffer),
      claimed_interface_(claimed_interface),
      length_(length),
      callback_task_runner_(callback_task_runner),
      callback_(callback) {
  task_runner_ = base::ThreadTaskRunnerHandle::Get();
}

UsbDeviceHandleImpl::Transfer::Transfer(
    scoped_refptr<UsbDeviceHandleImpl> device_handle,
    scoped_refptr<InterfaceClaimer> claimed_interface,
    scoped_refptr<net::IOBuffer> buffer,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const IsochronousTransferCallback& callback)
    : transfer_type_(USB_TRANSFER_ISOCHRONOUS),
      device_handle_(device_handle),
      buffer_(buffer),
      claimed_interface_(claimed_interface),
      callback_task_runner_(callback_task_runner),
      iso_callback_(callback) {
  task_runner_ = base::ThreadTaskRunnerHandle::Get();
}

UsbDeviceHandleImpl::Transfer::~Transfer() {
  if (platform_transfer_) {
    libusb_free_transfer(platform_transfer_);
  }
}

void UsbDeviceHandleImpl::Transfer::Submit() {
  const int rv = libusb_submit_transfer(platform_transfer_);
  if (rv != LIBUSB_SUCCESS) {
    USB_LOG(EVENT) << "Failed to submit transfer: "
                   << ConvertPlatformUsbErrorToString(rv);
    TransferComplete(USB_TRANSFER_ERROR, 0);
  }
}

void UsbDeviceHandleImpl::Transfer::Cancel() {
  if (!cancelled_) {
    libusb_cancel_transfer(platform_transfer_);
    claimed_interface_ = nullptr;
  }
  cancelled_ = true;
}

void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
  DCHECK_GE(platform_transfer_->actual_length, 0)
      << "Negative actual length received";
  size_t actual_length =
      static_cast<size_t>(std::max(platform_transfer_->actual_length, 0));

  DCHECK(length_ >= actual_length)
      << "data too big for our buffer (libusb failure?)";

  switch (transfer_type_) {
    case USB_TRANSFER_CONTROL:
      // If the transfer is a control transfer we do not expose the control
      // setup header to the caller. This logic strips off the header if
      // present before invoking the callback provided with the transfer.
      if (actual_length > 0) {
        CHECK(length_ >= LIBUSB_CONTROL_SETUP_SIZE)
            << "buffer was not correctly set: too small for the control header";

        if (length_ >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) {
          // If the payload is zero bytes long, pad out the allocated buffer
          // size to one byte so that an IOBuffer of that size can be allocated.
          scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer(
              std::max(actual_length, static_cast<size_t>(1)));
          memcpy(resized_buffer->data(),
                 buffer_->data() + LIBUSB_CONTROL_SETUP_SIZE, actual_length);
          buffer_ = resized_buffer;
        }
      }
    // Fall through!

    case USB_TRANSFER_BULK:
    case USB_TRANSFER_INTERRUPT:
      TransferComplete(ConvertTransferStatus(platform_transfer_->status),
                       actual_length);
      break;

    case USB_TRANSFER_ISOCHRONOUS:
      IsochronousTransferComplete();
      break;

    default:
      NOTREACHED() << "Invalid usb transfer type";
      break;
  }
}

/* static */
void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
    PlatformUsbTransferHandle platform_transfer) {
  Transfer* transfer =
      reinterpret_cast<Transfer*>(platform_transfer->user_data);
  DCHECK(transfer->platform_transfer_ == platform_transfer);
  transfer->ProcessCompletion();
}

void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
                                                     size_t bytes_transferred) {
  base::Closure closure;
  if (transfer_type_ == USB_TRANSFER_ISOCHRONOUS) {
    DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status);
    std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets);
    for (size_t i = 0; i < packets.size(); ++i) {
      packets[i].length = platform_transfer_->iso_packet_desc[i].length;
      packets[i].transferred_length = 0;
      packets[i].status = status;
    }
    closure = base::Bind(iso_callback_, buffer_, packets);
  } else {
    closure = base::Bind(callback_, status, buffer_, bytes_transferred);
  }
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::TransferComplete,
                            device_handle_, base::Unretained(this), closure));
}

void UsbDeviceHandleImpl::Transfer::IsochronousTransferComplete() {
  std::vector<IsochronousPacket> packets(platform_transfer_->num_iso_packets);
  for (size_t i = 0; i < packets.size(); ++i) {
    packets[i].length = platform_transfer_->iso_packet_desc[i].length;
    packets[i].transferred_length =
        platform_transfer_->iso_packet_desc[i].actual_length;
    packets[i].status =
        ConvertTransferStatus(platform_transfer_->iso_packet_desc[i].status);
  }
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::TransferComplete,
                            device_handle_, base::Unretained(this),
                            base::Bind(iso_callback_, buffer_, packets)));
}

scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
  return device_;
}

void UsbDeviceHandleImpl::Close() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_)
    return;

  // Cancel all the transfers, their callbacks will be called some time later.
  for (Transfer* transfer : transfers_)
    transfer->Cancel();

  // Release all remaining interfaces once their transfers have completed.
  // This loop must ensure that what may be the final reference is released on
  // the right thread.
  for (auto& map_entry : claimed_interfaces_) {
    InterfaceClaimer* interface_claimer = map_entry.second.get();
    interface_claimer->AddRef();
    map_entry.second = nullptr;
    blocking_task_runner_->ReleaseSoon(FROM_HERE, interface_claimer);
  }

  device_->HandleClosed(this);
  device_ = nullptr;

  // The device handle cannot be closed here. When libusb_cancel_transfer is
  // finished the last references to this device will be released and the
  // destructor will close the handle.
}

void UsbDeviceHandleImpl::SetConfiguration(int configuration_value,
                                           const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_) {
    callback.Run(false);
    return;
  }

  for (Transfer* transfer : transfers_) {
    transfer->Cancel();
  }
  claimed_interfaces_.clear();

  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&UsbDeviceHandleImpl::SetConfigurationOnBlockingThread, this,
                 configuration_value, callback));
}

void UsbDeviceHandleImpl::ClaimInterface(int interface_number,
                                         const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_) {
    callback.Run(false);
    return;
  }
  if (base::ContainsKey(claimed_interfaces_, interface_number)) {
    callback.Run(true);
    return;
  }

  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread, this,
                 interface_number, callback));
}

void UsbDeviceHandleImpl::ReleaseInterface(int interface_number,
                                           const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_ || !base::ContainsKey(claimed_interfaces_, interface_number)) {
    task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
    return;
  }

  // Cancel all the transfers on that interface.
  InterfaceClaimer* interface_claimer =
      claimed_interfaces_[interface_number].get();
  for (Transfer* transfer : transfers_) {
    if (transfer->claimed_interface() == interface_claimer) {
      transfer->Cancel();
    }
  }
  interface_claimer->AddRef();
  interface_claimer->set_release_callback(callback);
  blocking_task_runner_->ReleaseSoon(FROM_HERE, interface_claimer);
  claimed_interfaces_.erase(interface_number);

  RefreshEndpointMap();
}

void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
    int interface_number,
    int alternate_setting,
    const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_ || !base::ContainsKey(claimed_interfaces_, interface_number)) {
    callback.Run(false);
    return;
  }

  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(
          &UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread,
          this, interface_number, alternate_setting, callback));
}

void UsbDeviceHandleImpl::ResetDevice(const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_) {
    callback.Run(false);
    return;
  }

  blocking_task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ResetDeviceOnBlockingThread,
                            this, callback));
}

void UsbDeviceHandleImpl::ClearHalt(uint8_t endpoint,
                                    const ResultCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!device_) {
    callback.Run(false);
    return;
  }

  InterfaceClaimer* interface_claimer =
      GetClaimedInterfaceForEndpoint(endpoint).get();
  for (Transfer* transfer : transfers_) {
    if (transfer->claimed_interface() == interface_claimer) {
      transfer->Cancel();
    }
  }

  blocking_task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClearHaltOnBlockingThread,
                            this, endpoint, callback));
}

void UsbDeviceHandleImpl::ControlTransfer(UsbEndpointDirection direction,
                                          TransferRequestType request_type,
                                          TransferRecipient recipient,
                                          uint8_t request,
                                          uint16_t value,
                                          uint16_t index,
                                          scoped_refptr<net::IOBuffer> buffer,
                                          size_t length,
                                          unsigned int timeout,
                                          const TransferCallback& callback) {
  if (task_runner_->BelongsToCurrentThread()) {
    ControlTransferInternal(direction, request_type, recipient, request, value,
                            index, buffer, length, timeout, task_runner_,
                            callback);
  } else {
    task_runner_->PostTask(
        FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ControlTransferInternal,
                              this, direction, request_type, recipient, request,
                              value, index, buffer, length, timeout,
                              base::ThreadTaskRunnerHandle::Get(), callback));
  }
}

void UsbDeviceHandleImpl::IsochronousTransferIn(
    uint8_t endpoint_number,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    const IsochronousTransferCallback& callback) {
  uint8_t endpoint_address =
      ConvertTransferDirection(USB_DIRECTION_INBOUND) | endpoint_number;
  if (task_runner_->BelongsToCurrentThread()) {
    IsochronousTransferInInternal(endpoint_address, packet_lengths, timeout,
                                  task_runner_, callback);
  } else {
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&UsbDeviceHandleImpl::IsochronousTransferInInternal, this,
                   endpoint_address, packet_lengths, timeout,
                   base::ThreadTaskRunnerHandle::Get(), callback));
  }
}

void UsbDeviceHandleImpl::IsochronousTransferOut(
    uint8_t endpoint_number,
    scoped_refptr<net::IOBuffer> buffer,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    const IsochronousTransferCallback& callback) {
  uint8_t endpoint_address =
      ConvertTransferDirection(USB_DIRECTION_OUTBOUND) | endpoint_number;
  if (task_runner_->BelongsToCurrentThread()) {
    IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths,
                                   timeout, task_runner_, callback);
  } else {
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&UsbDeviceHandleImpl::IsochronousTransferOutInternal, this,
                   endpoint_address, buffer, packet_lengths, timeout,
                   base::ThreadTaskRunnerHandle::Get(), callback));
  }
}

void UsbDeviceHandleImpl::GenericTransfer(UsbEndpointDirection direction,
                                          uint8_t endpoint_number,
                                          scoped_refptr<net::IOBuffer> buffer,
                                          size_t length,
                                          unsigned int timeout,
                                          const TransferCallback& callback) {
  uint8_t endpoint_address =
      ConvertTransferDirection(direction) | endpoint_number;
  if (task_runner_->BelongsToCurrentThread()) {
    GenericTransferInternal(endpoint_address, buffer, length, timeout,
                            task_runner_, callback);
  } else {
    task_runner_->PostTask(
        FROM_HERE, base::Bind(&UsbDeviceHandleImpl::GenericTransferInternal,
                              this, endpoint_address, buffer, length, timeout,
                              base::ThreadTaskRunnerHandle::Get(), callback));
  }
}

const UsbInterfaceDescriptor* UsbDeviceHandleImpl::FindInterfaceByEndpoint(
    uint8_t endpoint_address) {
  DCHECK(thread_checker_.CalledOnValidThread());
  const auto endpoint_it = endpoint_map_.find(endpoint_address);
  if (endpoint_it != endpoint_map_.end())
    return endpoint_it->second.interface;
  return nullptr;
}

UsbDeviceHandleImpl::UsbDeviceHandleImpl(
    scoped_refptr<UsbContext> context,
    scoped_refptr<UsbDeviceImpl> device,
    PlatformUsbDeviceHandle handle,
    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
    : device_(device),
      handle_(handle),
      context_(context),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      blocking_task_runner_(blocking_task_runner) {
  DCHECK(handle) << "Cannot create device with NULL handle.";
}

UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
  DCHECK(!device_) << "UsbDeviceHandle must be closed before it is destroyed.";

  // This class is RefCountedThreadSafe and so the destructor may be called on
  // any thread. libusb is not safe to reentrancy so be sure not to try to close
  // the device from inside a transfer completion callback.
  if (blocking_task_runner_->RunsTasksOnCurrentThread()) {
    libusb_close(handle_);
  } else {
    blocking_task_runner_->PostTask(FROM_HERE,
                                    base::Bind(&libusb_close, handle_));
  }
}

void UsbDeviceHandleImpl::SetConfigurationOnBlockingThread(
    int configuration_value,
    const ResultCallback& callback) {
  int rv = libusb_set_configuration(handle_, configuration_value);
  if (rv != LIBUSB_SUCCESS) {
    USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
                   << ": " << ConvertPlatformUsbErrorToString(rv);
  }
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::SetConfigurationComplete,
                            this, rv == LIBUSB_SUCCESS, callback));
}

void UsbDeviceHandleImpl::SetConfigurationComplete(
    bool success,
    const ResultCallback& callback) {
  if (success) {
    device_->RefreshActiveConfiguration();
    RefreshEndpointMap();
  }
  callback.Run(success);
}

void UsbDeviceHandleImpl::ClaimInterfaceOnBlockingThread(
    int interface_number,
    const ResultCallback& callback) {
  int rv = libusb_claim_interface(handle_, interface_number);
  scoped_refptr<InterfaceClaimer> interface_claimer;
  if (rv == LIBUSB_SUCCESS) {
    interface_claimer =
        new InterfaceClaimer(this, interface_number, task_runner_);
  } else {
    USB_LOG(EVENT) << "Failed to claim interface: "
                   << ConvertPlatformUsbErrorToString(rv);
  }
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&UsbDeviceHandleImpl::ClaimInterfaceComplete, this,
                            interface_claimer, callback));
}

void UsbDeviceHandleImpl::ClaimInterfaceComplete(
    scoped_refptr<InterfaceClaimer> interface_claimer,
    const ResultCallback& callback) {
  if (interface_claimer) {
    claimed_interfaces_[interface_claimer->interface_number()] =
        interface_claimer;
    RefreshEndpointMap();
  }
  callback.Run(static_cast<bool>(interface_claimer));
}

void UsbDeviceHandleImpl::SetInterfaceAlternateSettingOnBlockingThread(
    int interface_number,
    int alternate_setting,
    const ResultCallback& callback) {
  int rv = libusb_set_interface_alt_setting(handle_, interface_number,
                                            alternate_setting);
  if (rv != LIBUSB_SUCCESS) {
    USB_LOG(EVENT) << "Failed to set interface " << interface_number
                   << " to alternate setting " << alternate_setting << ": "
                   << ConvertPlatformUsbErrorToString(rv);
  }
  task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete,
                 this, interface_number, alternate_setting,
                 rv == LIBUSB_SUCCESS, callback));
}

void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
    int interface_number,
    int alternate_setting,
    bool success,
    const ResultCallback& callback) {
  if (success) {
    claimed_interfaces_[interface_number]->set_alternate_setting(
        alternate_setting);
    RefreshEndpointMap();
  }
  callback.Run(success);
}

void UsbDeviceHandleImpl::ResetDeviceOnBlockingThread(
    const ResultCallback& callback) {
  int rv = libusb_reset_device(handle_);
  if (rv != LIBUSB_SUCCESS) {
    USB_LOG(EVENT) << "Failed to reset device: "
                   << ConvertPlatformUsbErrorToString(rv);
  }
  task_runner_->PostTask(FROM_HERE, base::Bind(callback, rv == LIBUSB_SUCCESS));
}

void UsbDeviceHandleImpl::ClearHaltOnBlockingThread(
    uint8_t endpoint,
    const ResultCallback& callback) {
  int rv = libusb_clear_halt(handle_, endpoint);
  if (rv != LIBUSB_SUCCESS) {
    USB_LOG(EVENT) << "Failed to clear halt: "
                   << ConvertPlatformUsbErrorToString(rv);
  }
  task_runner_->PostTask(FROM_HERE, base::Bind(callback, rv == LIBUSB_SUCCESS));
}

void UsbDeviceHandleImpl::RefreshEndpointMap() {
  DCHECK(thread_checker_.CalledOnValidThread());
  endpoint_map_.clear();
  const UsbConfigDescriptor* config = device_->active_configuration();
  if (config) {
    for (const auto& map_entry : claimed_interfaces_) {
      int interface_number = map_entry.first;
      const scoped_refptr<InterfaceClaimer>& claimed_iface = map_entry.second;

      for (const UsbInterfaceDescriptor& iface : config->interfaces) {
        if (iface.interface_number == interface_number &&
            iface.alternate_setting == claimed_iface->alternate_setting()) {
          for (const UsbEndpointDescriptor& endpoint : iface.endpoints) {
            endpoint_map_[endpoint.address] = {&iface, &endpoint};
          }
          break;
        }
      }
    }
  }
}

scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8_t endpoint) {
  const auto endpoint_it = endpoint_map_.find(endpoint);
  if (endpoint_it != endpoint_map_.end())
    return claimed_interfaces_[endpoint_it->second.interface->interface_number];
  return nullptr;
}

void UsbDeviceHandleImpl::ControlTransferInternal(
    UsbEndpointDirection direction,
    TransferRequestType request_type,
    TransferRecipient recipient,
    uint8_t request,
    uint16_t value,
    uint16_t index,
    scoped_refptr<net::IOBuffer> buffer,
    size_t length,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (!device_) {
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
                        buffer, 0);
    return;
  }

  if (!base::IsValueInRangeForNumericType<uint16_t>(length)) {
    USB_LOG(USER) << "Transfer too long.";
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }

  const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
  scoped_refptr<net::IOBuffer> resized_buffer =
      new net::IOBufferWithSize(resized_length);
  if (!resized_buffer.get()) {
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }
  memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
         length);

  std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer(
      this, CreateRequestType(direction, request_type, recipient), request,
      value, index, static_cast<uint16_t>(length), resized_buffer, timeout,
      callback_task_runner, callback);
  if (!transfer) {
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }

  SubmitTransfer(std::move(transfer));
}

void UsbDeviceHandleImpl::IsochronousTransferInInternal(
    uint8_t endpoint_address,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const IsochronousTransferCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (!device_) {
    ReportIsochronousTransferError(callback_task_runner, callback,
                                   packet_lengths, USB_TRANSFER_DISCONNECT);
    return;
  }

  size_t length =
      std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(length));
  std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
      this, endpoint_address, buffer, length, packet_lengths, timeout,
      callback_task_runner, callback);

  SubmitTransfer(std::move(transfer));
}

void UsbDeviceHandleImpl::IsochronousTransferOutInternal(
    uint8_t endpoint_address,
    scoped_refptr<net::IOBuffer> buffer,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const IsochronousTransferCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (!device_) {
    ReportIsochronousTransferError(callback_task_runner, callback,
                                   packet_lengths, USB_TRANSFER_DISCONNECT);
    return;
  }

  size_t length =
      std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
      this, endpoint_address, buffer, length, packet_lengths, timeout,
      callback_task_runner, callback);

  SubmitTransfer(std::move(transfer));
}

void UsbDeviceHandleImpl::GenericTransferInternal(
    uint8_t endpoint_address,
    scoped_refptr<net::IOBuffer> buffer,
    size_t length,
    unsigned int timeout,
    scoped_refptr<base::TaskRunner> callback_task_runner,
    const TransferCallback& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (!device_) {
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_DISCONNECT,
                        buffer, 0);
    return;
  }

  const auto endpoint_it = endpoint_map_.find(endpoint_address);
  if (endpoint_it == endpoint_map_.end()) {
    USB_LOG(DEBUG) << "Failed to submit transfer because endpoint "
                   << static_cast<int>(endpoint_address)
                   << " not part of a claimed interface.";
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }

  if (!base::IsValueInRangeForNumericType<int>(length)) {
    USB_LOG(DEBUG) << "Transfer too long.";
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }

  std::unique_ptr<Transfer> transfer;
  UsbTransferType transfer_type = endpoint_it->second.endpoint->transfer_type;
  if (transfer_type == USB_TRANSFER_BULK) {
    transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer,
                                            static_cast<int>(length), timeout,
                                            callback_task_runner, callback);
  } else if (transfer_type == USB_TRANSFER_INTERRUPT) {
    transfer = Transfer::CreateInterruptTransfer(
        this, endpoint_address, buffer, static_cast<int>(length), timeout,
        callback_task_runner, callback);
  } else {
    USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address)
                   << " is not a bulk or interrupt endpoint.";
    RunTransferCallback(callback_task_runner, callback, USB_TRANSFER_ERROR,
                        buffer, 0);
    return;
  }

  SubmitTransfer(std::move(transfer));
}

void UsbDeviceHandleImpl::SubmitTransfer(std::unique_ptr<Transfer> transfer) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // Transfer is owned by libusb until its completion callback is run. This
  // object holds a weak reference.
  transfers_.insert(transfer.get());
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&Transfer::Submit, base::Unretained(transfer.release())));
}

void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
                                           const base::Closure& callback) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(base::ContainsKey(transfers_, transfer))
      << "Missing transfer completed";
  transfers_.erase(transfer);

  if (transfer->callback_task_runner()->RunsTasksOnCurrentThread()) {
    callback.Run();
  } else {
    transfer->callback_task_runner()->PostTask(FROM_HERE, callback);
  }

  // libusb_free_transfer races with libusb_submit_transfer and only work-
  // around is to make sure to call them on the same thread.
  blocking_task_runner_->DeleteSoon(FROM_HERE, transfer);
}

}  // namespace device
