// Copyright 2016 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_usbfs.h"

#include <linux/usb/ch9.h>

#include <linux/usbdevice_fs.h>
#include <sys/ioctl.h>

#include <numeric>

#include "base/bind.h"
#include "base/cancelable_callback.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "device/usb/usb_device_linux.h"

namespace device {

namespace {

uint8_t ConvertEndpointDirection(UsbTransferDirection direction) {
  switch (direction) {
    case UsbTransferDirection::INBOUND:
      return USB_DIR_IN;
    case UsbTransferDirection::OUTBOUND:
      return USB_DIR_OUT;
  }
  NOTREACHED();
  return 0;
}

uint8_t ConvertRequestType(UsbControlTransferType request_type) {
  switch (request_type) {
    case UsbControlTransferType::STANDARD:
      return USB_TYPE_STANDARD;
    case UsbControlTransferType::CLASS:
      return USB_TYPE_CLASS;
    case UsbControlTransferType::VENDOR:
      return USB_TYPE_VENDOR;
    case UsbControlTransferType::RESERVED:
      return USB_TYPE_RESERVED;
  }
  NOTREACHED();
  return 0;
}

uint8_t ConvertRecipient(UsbControlTransferRecipient recipient) {
  switch (recipient) {
    case UsbControlTransferRecipient::DEVICE:
      return USB_RECIP_DEVICE;
    case UsbControlTransferRecipient::INTERFACE:
      return USB_RECIP_INTERFACE;
    case UsbControlTransferRecipient::ENDPOINT:
      return USB_RECIP_ENDPOINT;
    case UsbControlTransferRecipient::OTHER:
      return USB_RECIP_OTHER;
  }
  NOTREACHED();
  return 0;
}

scoped_refptr<base::RefCountedBytes> BuildControlTransferBuffer(
    UsbTransferDirection direction,
    UsbControlTransferType request_type,
    UsbControlTransferRecipient recipient,
    uint8_t request,
    uint16_t value,
    uint16_t index,
    scoped_refptr<base::RefCountedBytes> original_buffer) {
  auto new_buffer = base::MakeRefCounted<base::RefCountedBytes>(
      original_buffer->size() + sizeof(usb_ctrlrequest));
  usb_ctrlrequest* setup = new_buffer->front_as<usb_ctrlrequest>();
  setup->bRequestType = ConvertEndpointDirection(direction) |
                        ConvertRequestType(request_type) |
                        ConvertRecipient(recipient);
  setup->bRequest = request;
  setup->wValue = value;
  setup->wIndex = index;
  setup->wLength = original_buffer->size();
  memcpy(new_buffer->front() + sizeof(usb_ctrlrequest),
         original_buffer->front(), original_buffer->size());
  return new_buffer;
}

uint8_t ConvertTransferType(UsbTransferType type) {
  switch (type) {
    case UsbTransferType::CONTROL:
      return USBDEVFS_URB_TYPE_CONTROL;
    case UsbTransferType::ISOCHRONOUS:
      return USBDEVFS_URB_TYPE_ISO;
    case UsbTransferType::BULK:
      return USBDEVFS_URB_TYPE_BULK;
    case UsbTransferType::INTERRUPT:
      return USBDEVFS_URB_TYPE_INTERRUPT;
  }
  NOTREACHED();
  return 0;
}

UsbTransferStatus ConvertTransferResult(int rc) {
  switch (rc) {
    case 0:
      return UsbTransferStatus::COMPLETED;
    case EOVERFLOW:
      return UsbTransferStatus::BABBLE;
    case EPIPE:
      return UsbTransferStatus::STALLED;
    default:
      // Other errors are difficult to map to UsbTransferStatus and may be
      // emitted in situations that vary by host controller. Log the specific
      // error and return a generic one.
      USB_LOG(ERROR) << "Low-level transfer error: "
                     << logging::SystemErrorCodeToString(rc);
      return UsbTransferStatus::TRANSFER_ERROR;
  }
}

}  // namespace

class UsbDeviceHandleUsbfs::BlockingTaskHelper {
 public:
  BlockingTaskHelper(base::ScopedFD fd,
                     scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
                     scoped_refptr<base::SequencedTaskRunner> task_runner);
  ~BlockingTaskHelper();

  void Start();
  void ReleaseFileDescriptor();

  void SetConfiguration(int configuration_value, ResultCallback callback);
  void ReleaseInterface(int interface_number, ResultCallback callback);
  void SetInterface(int interface_number,
                    int alternate_setting,
                    ResultCallback callback);
  void ResetDevice(ResultCallback callback);
  void ClearHalt(uint8_t endpoint_address, ResultCallback callback);
  void DiscardUrb(Transfer* transfer);

 private:
  // Called when |fd_| is writable without blocking.
  void OnFileCanWriteWithoutBlocking();

  base::ScopedFD fd_;
  scoped_refptr<UsbDeviceHandleUsbfs> device_handle_;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
  base::SequenceChecker sequence_checker_;

  DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper);
};

struct UsbDeviceHandleUsbfs::Transfer {
  Transfer() = delete;
  Transfer(scoped_refptr<base::RefCountedBytes> buffer,
           TransferCallback callback);
  Transfer(scoped_refptr<base::RefCountedBytes> buffer,
           IsochronousTransferCallback callback);
  ~Transfer();

  void* operator new(std::size_t size, size_t number_of_iso_packets);
  void RunCallback(UsbTransferStatus status, size_t bytes_transferred);
  void RunIsochronousCallback(const std::vector<IsochronousPacket>& packets);

  scoped_refptr<base::RefCountedBytes> control_transfer_buffer;
  scoped_refptr<base::RefCountedBytes> buffer;
  base::CancelableClosure timeout_closure;
  bool cancelled = false;

  // When the URB is |cancelled| these two flags track whether the URB has both
  // been |discarded| and |reaped| since the possiblity of last-minute
  // completion makes these two conditions race.
  bool discarded = false;
  bool reaped = false;

  TransferCallback callback;
  IsochronousTransferCallback isoc_callback;

 private:
  DISALLOW_COPY_AND_ASSIGN(Transfer);

 public:
  // The |urb| field must be the last in the struct so that the extra space
  // allocated by the overridden new function above extends the length of its
  // |iso_frame_desc| field.
  usbdevfs_urb urb;
};

UsbDeviceHandleUsbfs::BlockingTaskHelper::BlockingTaskHelper(
    base::ScopedFD fd,
    scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
    scoped_refptr<base::SequencedTaskRunner> task_runner)
    : fd_(std::move(fd)),
      device_handle_(std::move(device_handle)),
      task_runner_(std::move(task_runner)) {}

UsbDeviceHandleUsbfs::BlockingTaskHelper::~BlockingTaskHelper() {
  DCHECK(sequence_checker_.CalledOnValidSequence());
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::Start() {
  sequence_checker_.DetachFromSequence();
  DCHECK(sequence_checker_.CalledOnValidSequence());

  // Linux indicates that URBs are available to reap by marking the file
  // descriptor writable.
  watch_controller_ = base::FileDescriptorWatcher::WatchWritable(
      fd_.get(),
      base::BindRepeating(&BlockingTaskHelper::OnFileCanWriteWithoutBlocking,
                          base::Unretained(this)));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::ReleaseFileDescriptor() {
  // This method intentionally leaks the file descriptor.
  DCHECK(sequence_checker_.CalledOnValidSequence());
  watch_controller_.reset();
  ignore_result(fd_.release());
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::SetConfiguration(
    int configuration_value,
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  int rc = HANDLE_EINTR(
      ioctl(fd_.get(), USBDEVFS_SETCONFIGURATION, &configuration_value));
  if (rc)
    USB_PLOG(DEBUG) << "Failed to set configuration " << configuration_value;
  task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::SetConfigurationComplete,
                                device_handle_, configuration_value, rc == 0,
                                std::move(callback)));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::ReleaseInterface(
    int interface_number,
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  int rc = HANDLE_EINTR(
      ioctl(fd_.get(), USBDEVFS_RELEASEINTERFACE, &interface_number));
  if (rc) {
    USB_PLOG(DEBUG) << "Failed to release interface " << interface_number;
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
  } else {
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&UsbDeviceHandleUsbfs::ReleaseInterfaceComplete,
                       device_handle_, interface_number, std::move(callback)));
  }
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::SetInterface(
    int interface_number,
    int alternate_setting,
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  usbdevfs_setinterface cmd = {0};
  cmd.interface = interface_number;
  cmd.altsetting = alternate_setting;

  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_SETINTERFACE, &cmd));
  if (rc) {
    USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
                    << " to alternate setting " << alternate_setting;
  }
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(std::move(callback), rc == 0));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::ResetDevice(
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  // TODO(reillyg): libusb releases interfaces before and then reclaims
  // interfaces after a reset. We should probably do this too or document that
  // callers have to call ClaimInterface as well.
  int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_RESET, nullptr));
  if (rc)
    USB_PLOG(DEBUG) << "Failed to reset the device";
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(std::move(callback), rc == 0));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::ClearHalt(
    uint8_t endpoint_address,
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  int tmp_endpoint = endpoint_address;
  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_CLEAR_HALT, &tmp_endpoint));
  if (rc) {
    USB_PLOG(DEBUG) << "Failed to clear the stall condition on endpoint "
                    << static_cast<int>(endpoint_address);
  }
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(std::move(callback), rc == 0));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::DiscardUrb(Transfer* transfer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);
  HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_DISCARDURB, &transfer->urb));

  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(&UsbDeviceHandleUsbfs::UrbDiscarded,
                                        device_handle_, transfer));
}

void UsbDeviceHandleUsbfs::BlockingTaskHelper::OnFileCanWriteWithoutBlocking() {
  DCHECK(sequence_checker_.CalledOnValidSequence());

  const size_t MAX_URBS_PER_EVENT = 10;
  std::vector<usbdevfs_urb*> urbs;
  urbs.reserve(MAX_URBS_PER_EVENT);
  for (size_t i = 0; i < MAX_URBS_PER_EVENT; ++i) {
    base::ScopedBlockingCall scoped_blocking_call(
        base::BlockingType::MAY_BLOCK);
    usbdevfs_urb* urb;
    int rc = HANDLE_EINTR(ioctl(fd_.get(), USBDEVFS_REAPURBNDELAY, &urb));
    if (rc) {
      if (errno == EAGAIN)
        break;
      USB_PLOG(DEBUG) << "Failed to reap urbs";
      if (errno == ENODEV) {
        // Device has disconnected. Stop watching the file descriptor to avoid
        // looping until |device_handle_| is closed.
        watch_controller_.reset();
        break;
      }
    } else {
      urbs.push_back(urb);
    }
  }

  task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&UsbDeviceHandleUsbfs::ReapedUrbs, device_handle_, urbs));
}

UsbDeviceHandleUsbfs::Transfer::Transfer(
    scoped_refptr<base::RefCountedBytes> buffer,
    TransferCallback callback)
    : buffer(buffer), callback(std::move(callback)) {
  memset(&urb, 0, sizeof(urb));
  urb.usercontext = this;
  urb.buffer = buffer->front();
}

UsbDeviceHandleUsbfs::Transfer::Transfer(
    scoped_refptr<base::RefCountedBytes> buffer,
    IsochronousTransferCallback callback)
    : buffer(buffer), isoc_callback(std::move(callback)) {
  memset(&urb, 0, sizeof(urb) +
                      sizeof(usbdevfs_iso_packet_desc) * urb.number_of_packets);
  urb.usercontext = this;
  urb.buffer = buffer->front();
}

UsbDeviceHandleUsbfs::Transfer::~Transfer() = default;

void* UsbDeviceHandleUsbfs::Transfer::operator new(
    std::size_t size,
    size_t number_of_iso_packets) {
  void* p = ::operator new(
      size + sizeof(usbdevfs_iso_packet_desc) * number_of_iso_packets);
  Transfer* transfer = static_cast<Transfer*>(p);
  transfer->urb.number_of_packets = number_of_iso_packets;
  return p;
}

void UsbDeviceHandleUsbfs::Transfer::RunCallback(UsbTransferStatus status,
                                                 size_t bytes_transferred) {
  DCHECK_NE(urb.type, USBDEVFS_URB_TYPE_ISO);
  DCHECK(callback);
  std::move(callback).Run(status, buffer, bytes_transferred);
}

void UsbDeviceHandleUsbfs::Transfer::RunIsochronousCallback(
    const std::vector<IsochronousPacket>& packets) {
  DCHECK_EQ(urb.type, USBDEVFS_URB_TYPE_ISO);
  DCHECK(isoc_callback);
  std::move(isoc_callback).Run(buffer, packets);
}

UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs(
    scoped_refptr<UsbDevice> device,
    base::ScopedFD fd,
    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
    : device_(device),
      fd_(fd.get()),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      blocking_task_runner_(blocking_task_runner) {
  DCHECK(device_);
  DCHECK(fd.is_valid());
  DCHECK(blocking_task_runner_);

  helper_.reset(new BlockingTaskHelper(std::move(fd), this, task_runner_));
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&BlockingTaskHelper::Start,
                                base::Unretained(helper_.get())));
}

scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  return device_;
}

void UsbDeviceHandleUsbfs::Close() {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_)
    return;  // Already closed.

  // Cancelling transfers may run or destroy callbacks holding the last
  // reference to this object so hold a reference for the rest of this method.
  scoped_refptr<UsbDeviceHandleUsbfs> self(this);
  for (const auto& transfer : transfers_)
    CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED);

  // On the |task_runner_| thread check |device_| to see if the handle is
  // closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to
  // see if the handle is closed.
  device_->HandleClosed(this);
  device_ = nullptr;

  // Releases |helper_|.
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::CloseBlocking, this));
}

void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value,
                                            ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // USBDEVFS_SETCONFIGURATION synchronously issues a SET_CONFIGURATION request
  // to the device so it must be performed on a thread where it is okay to
  // block.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &UsbDeviceHandleUsbfs::BlockingTaskHelper::SetConfiguration,
          base::Unretained(helper_.get()), configuration_value,
          std::move(callback)));
}

void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number,
                                          ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  if (base::ContainsKey(interfaces_, interface_number)) {
    USB_LOG(DEBUG) << "Interface " << interface_number << " already claimed.";
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // It appears safe to assume that this ioctl will not block.
  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_CLAIMINTERFACE, &interface_number));
  if (rc) {
    USB_PLOG(DEBUG) << "Failed to claim interface " << interface_number;
  } else {
    interfaces_[interface_number].alternate_setting = 0;
    RefreshEndpointInfo();
  }
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(std::move(callback), rc == 0));
}

void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number,
                                            ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // USBDEVFS_RELEASEINTERFACE may issue a SET_INTERFACE request to the
  // device to restore alternate setting 0 so it must be performed on a thread
  // where it is okay to block.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &UsbDeviceHandleUsbfs::BlockingTaskHelper::ReleaseInterface,
          base::Unretained(helper_.get()), interface_number,
          std::move(callback)));
}

void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting(
    int interface_number,
    int alternate_setting,
    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // USBDEVFS_SETINTERFACE is synchronous because it issues a SET_INTERFACE
  // request to the device so it must be performed on a thread where it is okay
  // to block.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&UsbDeviceHandleUsbfs::BlockingTaskHelper::SetInterface,
                     base::Unretained(helper_.get()), interface_number,
                     alternate_setting, std::move(callback)));
}

void UsbDeviceHandleUsbfs::ResetDevice(ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // USBDEVFS_RESET is synchronous because it waits for the port to be reset
  // and the device re-enumerated so it must be performed on a thread where it
  // is okay to block.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&UsbDeviceHandleUsbfs::BlockingTaskHelper::ResetDevice,
                     base::Unretained(helper_.get()), std::move(callback)));
}

void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address,
                                     ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(std::move(callback), false));
    return;
  }

  // USBDEVFS_CLEAR_HALT is synchronous because it issues a CLEAR_FEATURE
  // request to the device so it must be performed on a thread where it is okay
  // to block.
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&UsbDeviceHandleUsbfs::BlockingTaskHelper::ClearHalt,
                     base::Unretained(helper_.get()), endpoint_address,
                     std::move(callback)));
}

void UsbDeviceHandleUsbfs::ControlTransfer(
    UsbTransferDirection direction,
    UsbControlTransferType request_type,
    UsbControlTransferRecipient recipient,
    uint8_t request,
    uint16_t value,
    uint16_t index,
    scoped_refptr<base::RefCountedBytes> buffer,
    unsigned int timeout,
    TransferCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback),
                                  UsbTransferStatus::DISCONNECT, nullptr, 0));
    return;
  }

  std::unique_ptr<Transfer> transfer(new (0)
                                         Transfer(buffer, std::move(callback)));
  transfer->control_transfer_buffer = BuildControlTransferBuffer(
      direction, request_type, recipient, request, value, index, buffer);
  transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL;
  transfer->urb.endpoint = 0;
  transfer->urb.buffer = transfer->control_transfer_buffer->front();
  transfer->urb.buffer_length = transfer->control_transfer_buffer->size();

  // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
  // by USBDEVFS_REAPURBNDELAY.
  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
  if (rc) {
    rc = logging::GetLastSystemErrorCode();
    USB_PLOG(DEBUG) << "Failed to submit control transfer";
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(std::move(transfer->callback),
                                  ConvertTransferResult(rc), nullptr, 0));
  } else {
    SetUpTimeoutCallback(transfer.get(), timeout);
    transfers_.push_back(std::move(transfer));
  }
}

void UsbDeviceHandleUsbfs::IsochronousTransferIn(
    uint8_t endpoint_number,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    IsochronousTransferCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  uint8_t endpoint_address = USB_DIR_IN | endpoint_number;
  size_t total_length =
      std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  auto buffer = base::MakeRefCounted<base::RefCountedBytes>(total_length);
  IsochronousTransferInternal(endpoint_address, buffer, total_length,
                              packet_lengths, timeout, std::move(callback));
}

void UsbDeviceHandleUsbfs::IsochronousTransferOut(
    uint8_t endpoint_number,
    scoped_refptr<base::RefCountedBytes> buffer,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    IsochronousTransferCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  uint8_t endpoint_address = USB_DIR_OUT | endpoint_number;
  size_t total_length =
      std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  IsochronousTransferInternal(endpoint_address, buffer, total_length,
                              packet_lengths, timeout, std::move(callback));
}

void UsbDeviceHandleUsbfs::GenericTransfer(
    UsbTransferDirection direction,
    uint8_t endpoint_number,
    scoped_refptr<base::RefCountedBytes> buffer,
    unsigned int timeout,
    TransferCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback),
                                  UsbTransferStatus::DISCONNECT, nullptr, 0));
    return;
  }

  uint8_t endpoint_address =
      ConvertEndpointDirection(direction) | endpoint_number;
  auto it = endpoints_.find(endpoint_address);
  if (it == endpoints_.end()) {
    USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address)
                  << " is not part of a claimed interface.";
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
                       nullptr, 0));
    return;
  }

  std::unique_ptr<Transfer> transfer(new (0)
                                         Transfer(buffer, std::move(callback)));
  transfer->urb.endpoint = endpoint_address;
  transfer->urb.buffer_length = buffer->size();
  transfer->urb.type = ConvertTransferType(it->second.type);

  // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
  // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can
  // accept arbitrarily large transfer requests, hopefully also using a scatter-
  // gather list.
  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
  if (rc) {
    rc = logging::GetLastSystemErrorCode();
    USB_PLOG(DEBUG) << "Failed to submit transfer";
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(std::move(transfer->callback),
                                  ConvertTransferResult(rc), nullptr, 0));
  } else {
    SetUpTimeoutCallback(transfer.get(), timeout);
    transfers_.push_back(std::move(transfer));
  }
}

const UsbInterfaceDescriptor* UsbDeviceHandleUsbfs::FindInterfaceByEndpoint(
    uint8_t endpoint_address) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  auto it = endpoints_.find(endpoint_address);
  if (it != endpoints_.end())
    return it->second.interface;
  return nullptr;
}

UsbDeviceHandleUsbfs::~UsbDeviceHandleUsbfs() {
  DCHECK(!device_) << "Handle must be closed before it is destroyed.";
}

void UsbDeviceHandleUsbfs::ReleaseFileDescriptor() {
  // Calls to this method must be posted to |blocking_task_runner_|.
  helper_->ReleaseFileDescriptor();
  helper_.reset();
}

void UsbDeviceHandleUsbfs::CloseBlocking() {
  // Calls to this method must be posted to |blocking_task_runner_|.
  helper_.reset();
}

void UsbDeviceHandleUsbfs::SetConfigurationComplete(int configuration_value,
                                                    bool success,
                                                    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (success && device_) {
    device_->ActiveConfigurationChanged(configuration_value);
    // TODO(reillyg): If all interfaces are unclaimed before a new configuration
    // is set then this will do nothing. Investigate.
    RefreshEndpointInfo();
  }
  std::move(callback).Run(success);
}

void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(int interface_number,
                                                    ResultCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  auto it = interfaces_.find(interface_number);
  DCHECK(it != interfaces_.end());
  interfaces_.erase(it);
  RefreshEndpointInfo();
  std::move(callback).Run(true);
}

void UsbDeviceHandleUsbfs::IsochronousTransferInternal(
    uint8_t endpoint_address,
    scoped_refptr<base::RefCountedBytes> buffer,
    size_t total_length,
    const std::vector<uint32_t>& packet_lengths,
    unsigned int timeout,
    IsochronousTransferCallback callback) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (!device_) {
    ReportIsochronousError(packet_lengths, std::move(callback),
                           UsbTransferStatus::DISCONNECT);
    return;
  }

  auto it = endpoints_.find(endpoint_address);
  if (it == endpoints_.end()) {
    USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address)
                  << " is not part of a claimed interface.";
    ReportIsochronousError(packet_lengths, std::move(callback),
                           UsbTransferStatus::TRANSFER_ERROR);
    return;
  }

  DCHECK_GE(buffer->size(), total_length);
  std::unique_ptr<Transfer> transfer(new (packet_lengths.size())
                                         Transfer(buffer, std::move(callback)));
  transfer->urb.type = USBDEVFS_URB_TYPE_ISO;
  transfer->urb.endpoint = endpoint_address;
  transfer->urb.buffer_length = total_length;

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

  // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported
  // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can
  // accept arbitrarily large transfer requests, hopefully also using a scatter-
  // gather list.
  int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb));
  if (rc) {
    rc = logging::GetLastSystemErrorCode();
    USB_PLOG(DEBUG) << "Failed to submit transfer";
    ReportIsochronousError(packet_lengths, std::move(transfer->isoc_callback),
                           ConvertTransferResult(rc));
  } else {
    SetUpTimeoutCallback(transfer.get(), timeout);
    transfers_.push_back(std::move(transfer));
  }
}

void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  for (auto* urb : urbs) {
    Transfer* transfer = static_cast<Transfer*>(urb->usercontext);
    DCHECK_EQ(urb, &transfer->urb);

    if (transfer->cancelled) {
      transfer->reaped = true;
      if (transfer->discarded)
        RemoveFromTransferList(transfer);
    } else {
      TransferComplete(RemoveFromTransferList(transfer));
    }
  }
}

void UsbDeviceHandleUsbfs::TransferComplete(
    std::unique_ptr<Transfer> transfer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (transfer->cancelled)
    return;

  // The transfer will soon be freed. Cancel the timeout callback so that the
  // raw pointer it holds to |transfer| is not used.
  transfer->timeout_closure.Cancel();

  if (transfer->urb.type == USBDEVFS_URB_TYPE_ISO) {
    std::vector<IsochronousPacket> packets(transfer->urb.number_of_packets);
    for (size_t i = 0; i < packets.size(); ++i) {
      packets[i].length = transfer->urb.iso_frame_desc[i].length;
      packets[i].transferred_length =
          transfer->urb.iso_frame_desc[i].actual_length;
      packets[i].status = ConvertTransferResult(
          transfer->urb.status == 0 ? transfer->urb.iso_frame_desc[i].status
                                    : transfer->urb.status);
    }

    transfer->RunIsochronousCallback(packets);
  } else {
    if (transfer->urb.status == 0 &&
        transfer->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
      // Copy the result of the control transfer back into the original buffer.
      memcpy(transfer->buffer->front(),
             transfer->control_transfer_buffer->front() + 8,
             transfer->urb.actual_length);
    }

    transfer->RunCallback(ConvertTransferResult(-transfer->urb.status),
                          transfer->urb.actual_length);
  }
}

void UsbDeviceHandleUsbfs::RefreshEndpointInfo() {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  endpoints_.clear();

  const UsbConfigDescriptor* config = device_->active_configuration();
  if (!config)
    return;

  for (const auto& entry : interfaces_) {
    auto interface_it = std::find_if(
        config->interfaces.begin(), config->interfaces.end(),
        [entry](const UsbInterfaceDescriptor& interface) {
          uint8_t interface_number = entry.first;
          uint8_t alternate_setting = entry.second.alternate_setting;
          return interface.interface_number == interface_number &&
                 interface.alternate_setting == alternate_setting;
        });
    DCHECK(interface_it != config->interfaces.end());

    for (const auto& endpoint : interface_it->endpoints) {
      EndpointInfo& info = endpoints_[endpoint.address];
      info.type = endpoint.transfer_type;
      info.interface = &*interface_it;
    }
  }
}

void UsbDeviceHandleUsbfs::ReportIsochronousError(
    const std::vector<uint32_t>& packet_lengths,
    UsbDeviceHandle::IsochronousTransferCallback callback,
    UsbTransferStatus status) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  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;
  }
  task_runner_->PostTask(FROM_HERE,
                         base::BindOnce(std::move(callback), nullptr, packets));
}

void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer,
                                                unsigned int timeout) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  if (timeout == 0)
    return;

  transfer->timeout_closure.Reset(
      base::Bind(&UsbDeviceHandleUsbfs::OnTimeout, this, transfer));
  task_runner_->PostDelayedTask(FROM_HERE, transfer->timeout_closure.callback(),
                                base::TimeDelta::FromMilliseconds(timeout));
}

void UsbDeviceHandleUsbfs::OnTimeout(Transfer* transfer) {
  CancelTransfer(transfer, UsbTransferStatus::TIMEOUT);
}

std::unique_ptr<UsbDeviceHandleUsbfs::Transfer>
UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  auto it = std::find_if(
      transfers_.begin(), transfers_.end(),
      [transfer_ptr](const std::unique_ptr<Transfer>& transfer) -> bool {
        return transfer.get() == transfer_ptr;
      });
  DCHECK(it != transfers_.end());
  std::unique_ptr<Transfer> transfer = std::move(*it);
  transfers_.erase(it);
  return transfer;
}

void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer,
                                          UsbTransferStatus status) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  DCHECK(device_);

  if (transfer->cancelled)
    return;

  // |transfer| must stay in |transfers_| as it is still being processed by the
  // kernel and will be reaped later.
  transfer->cancelled = true;

  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&UsbDeviceHandleUsbfs::BlockingTaskHelper::DiscardUrb,
                     base::Unretained(helper_.get()), transfer));

  // Cancelling |timeout_closure| and running completion callbacks may free
  // |this| so these operations must be performed at the end of this function.
  transfer->timeout_closure.Cancel();

  if (transfer->urb.type == USBDEVFS_URB_TYPE_ISO) {
    std::vector<IsochronousPacket> packets(transfer->urb.number_of_packets);
    for (size_t i = 0; i < packets.size(); ++i) {
      packets[i].length = transfer->urb.iso_frame_desc[i].length;
      packets[i].transferred_length = 0;
      packets[i].status = status;
    }
    transfer->RunIsochronousCallback(packets);
  } else {
    transfer->RunCallback(status, 0);
  }
}

void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) {
  DCHECK(sequence_checker_.CalledOnValidSequence());
  transfer->discarded = true;
  if (transfer->reaped)
    RemoveFromTransferList(transfer);
}

}  // namespace device
