// Copyright 2020 The Fuchsia 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 "src/devices/usb/drivers/xhci/xhci-event-ring.h"

#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <zircon/errors.h>

#include <atomic>
#include <list>
#include <memory>
#include <thread>

#include <fake-dma-buffer/fake-dma-buffer.h>
#include <fake-mmio-reg/fake-mmio-reg.h>
#include <fbl/algorithm.h>
#include <usb/usb.h>
#include <zxtest/zxtest.h>

#include "src/devices/testing/mock-ddk/mock-device.h"
#include "src/devices/usb/drivers/xhci/registers.h"
#include "src/devices/usb/drivers/xhci/usb-xhci.h"
#include "src/devices/usb/drivers/xhci/xhci-event-ring.h"

namespace usb_xhci {

const zx::bti kFakeBti(42);
constexpr size_t kErstMax = 42;
constexpr size_t kShortTransferLength0 = 97;
constexpr size_t kShortTransferLength1 = 102;
constexpr size_t kFinalTransferLength = 87;
constexpr size_t kShortTransferLength = 800;
constexpr size_t kFakeTrb = 0x3924ff0913;
constexpr size_t kFakeTrbVirt = 0x8411487132;
constexpr auto kPortNo = 5;

enum class CommandType {
  EnumerateDevice,
  ResetEndpoint,
};

struct Command : public fbl::DoublyLinkedListable<std::unique_ptr<Command>> {
  uint8_t port;
  std::optional<HubInfo> hub;
  fpromise::completer<TRB*, zx_status_t> completer;
  CommandType type;
  uint8_t endpoint;
  uint32_t device_id;
};

class EventRingHarness : public zxtest::Test {
 public:
  EventRingHarness()
      : trb_context_allocator_(-1, true),
        hci_(root_.get(), ddk_fake::CreateBufferFactory(), loop_.dispatcher()) {}
  void SetUp() override {
    // Globals
    constexpr auto kRuntimeRegisterOffset = 6 * sizeof(uint32_t);
    constexpr auto kErdp = 2062 * sizeof(uint32_t);
    region_.emplace(sizeof(uint32_t), 4096);
    buffer_.emplace(region_->GetMmioBuffer());

    // Core registers
    (*region_)[kRuntimeRegisterOffset].SetReadCallback([=]() { return 0x2000; });
    (*region_)[kErdp].SetReadCallback([=]() { return erdp_; });
    (*region_)[kErdp].SetWriteCallback([=](uint64_t value) {
      ERDP reg;
      reg.set_reg_value(value);
      erdp_ = reg.Pointer();
    });

    // Port/per-slot registers
    (*region_)[PORTSC::Get(0, kPortNo).addr()].SetReadCallback(
        [=]() { return port_sc_.reg_value(); });
    (*region_)[PORTSC::Get(0, kPortNo).addr()].SetWriteCallback([=](uint64_t value) {
      PORTSC sc;
      sc.set_reg_value(static_cast<uint32_t>(value));
      if (sc.PR()) {
        port_sc_.set_PR(true);
      }
    });
    hci_.SetTestHarness(this);

    // Initialization
    ASSERT_OK(hci_.InitThread());
  }

  void TearDown() override {}

  void Interrupt() { ring_->HandleIRQ(); }

  void AddTRB(const TRB& trb) {
    auto ptr = ddk_fake::PhysToVirt<TRB*>(erdp_);
    *ptr = trb;
    Control::FromTRB(ptr).set_Cycle(1).ToTrb(ptr);
    erdp_ += sizeof(TRB);
  }

  void ConnectDevice() {
    port_sc_.set_CCS(true);
    port_sc_.set_PED(true);
    port_sc_.set_PR(false);
    port_sc_.set_PLS(PORTSC::Polling);
    port_sc_.set_CSC(true);
  }

  void DisconnectDevice() {
    port_sc_.set_CCS(false);
    port_sc_.set_CSC(true);
  }

  void MakeQuantumPort() {
    // Port is enabled and disabled simultaneously
    port_sc_.set_PLS(PORTSC::Disabled);
    port_sc_.set_PED(1);
  }

  void LinkUp() {
    port_sc_.set_PR(false);
    port_sc_.set_PLS(PORTSC::U0);
  }

  bool PortResetPending() { return port_sc_.PR(); }

  void InsertPortStatusChangeEvent() {
    TRB trb;
    trb.ptr = 0;
    Control::FromTRB(&trb).set_Type(Control::PortStatusChangeEvent).ToTrb(&trb);
    auto evt = static_cast<PortStatusChangeEvent*>(&trb);
    evt->set_PortID(kPortNo);
    auto command_completion = static_cast<CommandCompletionEvent*>(&trb);
    command_completion->set_CompletionCode(CommandCompletionEvent::Success);
    AddTRB(trb);
  }

  TRB* trb() { return ddk_fake::PhysToVirt<TRB*>(erdp_); }

  using TestRequest = usb::CallbackRequest<sizeof(max_align_t)>;
  template <typename Callback>
  zx_status_t AllocateRequest(std::optional<TestRequest>* request, uint32_t device_id,
                              uint64_t data_size, uint8_t endpoint, Callback callback) {
    zx_status_t status = TestRequest::Alloc(request, data_size, endpoint,
                                            hci_.UsbHciGetRequestSize(), std::move(callback));
    if (status != ZX_OK) {
      return status;
    }
    request->value().request()->header.device_id = device_id;
    return ZX_OK;
  }

  std::unique_ptr<TRBContext> AllocateContext() { return trb_context_allocator_.New(); }

  void RequestQueue(usb_request_t* usb_request,
                    const usb_request_complete_callback_t* complete_cb) {
    pending_req_ = Request(usb_request, *complete_cb, sizeof(usb_request_t));
  }

  Request Borrow(TestRequest request) {
    request.Queue(*this);
    return std::move(*pending_req_);
  }

  zx_status_t InitRing(EventRing* ring) {
    ring_ = ring;
    auto regoffset = RuntimeRegisterOffset::Get().ReadFrom(&buffer_.value());
    zx_status_t status =
        ring->Init(zx_system_get_page_size(), kFakeBti, &buffer_.value(), false, kErstMax,
                   ERSTSZ::Get(regoffset, 0).ReadFrom(&buffer_.value()),
                   ERDP::Get(regoffset, 0).ReadFrom(&buffer_.value()),
                   IMAN::Get(regoffset, 0).ReadFrom(&buffer_.value()),
                   CapLength::Get().ReadFrom(&buffer_.value()).Length(),
                   HCSPARAMS1::Get().ReadFrom(&buffer_.value()), &command_ring_,
                   DoorbellOffset::Get().ReadFrom(&buffer_.value()), &hci_,
                   HCCPARAMS1::Get().ReadFrom(&buffer_.value()), dcbaa_, 0, nullptr);
    if (status != ZX_OK) {
      return status;
    }
    status = ring_->AddSegmentIfNoneLock();
    if (status != ZX_OK) {
      return status;
    }
    ERDP reg;
    reg.set_Pointer(ddk_fake::PhysToVirt<zx_paddr_t*>(ring_->erst())[0]);
    (*region_)[2062 * sizeof(uint32_t)].Write(reg.reg_value());
    return ZX_OK;
  }
  void SetShortPacketHandler(fit::function<void(usb_xhci::TRB*, size_t, usb_xhci::TRB**)> handler) {
    short_packet_handler_ = std::move(handler);
  }

  void HandleShortPacket(TRB* short_trb, size_t short_length, TRB** first_trb) {
    (*short_packet_handler_)(short_trb, short_length, first_trb);
  }

  zx_status_t CompleteTRB(TRB* trb, std::unique_ptr<TRBContext>* context) {
    if (trb != expected_completion_) {
      return ZX_ERR_IO;
    }
    *context = pending_contexts_.pop_front();
    return ZX_OK;
  }

  void SetCompletion(TRB* expected) { expected_completion_ = expected; }

  void AddContext(std::unique_ptr<TRBContext> context) {
    pending_contexts_.push_back(std::move(context));
  }

  void AddCommand(std::unique_ptr<Command> command) { commands_.push_back(std::move(command)); }

  std::unique_ptr<Command> GetCommand() { return commands_.pop_front(); }

  bool HasCommand() { return !commands_.is_empty(); }

  void InitSlot(uint8_t i) {
    // Enable SlotID i for testing with arbitrary port 1.
    auto& state = hci_.GetDeviceState()[i - 1];
    ASSERT_NOT_NULL(state);
    fbl::AutoLock _(&state->transaction_lock());
    state->SetDeviceInformation(i, 1, std::nullopt);
  }

 private:
  async::Loop loop_{&kAsyncLoopConfigNeverAttachToThread};
  std::shared_ptr<MockDevice> root_ = MockDevice::FakeRootParent();
  std::optional<Request> pending_req_;
  std::optional<fit::function<void(usb_xhci::TRB*, size_t, usb_xhci::TRB**)>> short_packet_handler_;
  using AllocatorTraits = fbl::InstancedSlabAllocatorTraits<std::unique_ptr<TRBContext>, 4096U>;
  using AllocatorType = fbl::SlabAllocator<AllocatorTraits>;
  AllocatorType trb_context_allocator_;
  TRB* expected_completion_ = nullptr;
  fbl::DoublyLinkedList<std::unique_ptr<Command>> commands_;
  fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> pending_contexts_;
  std::optional<fdf::MmioBuffer> buffer_;
  EventRing* ring_;
  UsbXhci hci_;
  PORTSC port_sc_;
  CommandRing command_ring_;
  uint64_t dcbaa_[128];
  uint64_t erdp_;
  std::optional<ddk_fake::FakeMmioRegRegion> region_;
};

void UsbXhci::ConnectToEndpoint(ConnectToEndpointRequest& request,
                                ConnectToEndpointCompleter::Sync& completer) {
  completer.Reply(fit::as_error(ZX_ERR_NOT_SUPPORTED));
}

void UsbXhci::UsbHciSetBusInterface(const usb_bus_interface_protocol_t* bus_intf) {}

size_t UsbXhci::UsbHciGetMaxDeviceCount() { return 0; }

zx_status_t UsbXhci::UsbHciEnableEndpoint(uint32_t device_id,
                                          const usb_endpoint_descriptor_t* ep_desc,
                                          const usb_ss_ep_comp_descriptor_t* ss_com_desc,
                                          bool enable) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t UsbXhci::InitThread() {
  fbl::AllocChecker ac;
  interrupters_ = fbl::MakeArray<Interrupter>(&ac, 1);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  max_slots_ = 32;
  device_state_ = fbl::MakeArray<fbl::RefPtr<DeviceState>>(&ac, max_slots_);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  for (size_t i = 0; i < max_slots_; i++) {
    device_state_[i] = fbl::MakeRefCounted<DeviceState>(static_cast<uint32_t>(i), this);
    fbl::AutoLock l(&device_state_[i]->transaction_lock());
    for (size_t c = 0; c < max_slots_; c++) {
      device_state_[i]->InitEndpoint(static_cast<uint8_t>(c), nullptr, nullptr);
    }
  }
  port_state_ = fbl::MakeArray<PortState>(&ac, 32);
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  return static_cast<EventRingHarness*>(GetTestHarness())->InitRing(&interrupters_[0].ring());
}

uint64_t UsbXhci::UsbHciGetCurrentFrame() { return 0; }

zx_status_t UsbXhci::UsbHciConfigureHub(uint32_t device_id, usb_speed_t speed,
                                        const usb_hub_descriptor_t* desc, bool multi_tt) {
  return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t UsbXhci::UsbHciHubDeviceAdded(uint32_t device_id, uint32_t port, usb_speed_t speed) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t UsbXhci::UsbHciHubDeviceRemoved(uint32_t device_id, uint32_t port) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t UsbXhci::UsbHciHubDeviceReset(uint32_t device_id, uint32_t port) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t UsbXhci::UsbHciResetEndpoint(uint32_t device_id, uint8_t ep_address) {
  return ZX_ERR_NOT_SUPPORTED;
}

fpromise::promise<void, zx_status_t> UsbXhci::UsbHciResetEndpointAsync(uint32_t device_id,
                                                                       uint8_t ep_address) {
  auto harness = static_cast<EventRingHarness*>(GetTestHarness());
  std::unique_ptr<Command> command = std::make_unique<Command>();
  fpromise::bridge<TRB*, zx_status_t> bridge;
  command->type = CommandType::ResetEndpoint;
  command->device_id = device_id;
  command->endpoint = ep_address;
  command->completer = std::move(bridge.completer);
  harness->AddCommand(std::move(command));
  return bridge.consumer.promise().discard_value();
}

zx_status_t UsbXhci::UsbHciResetDevice(uint32_t hub_address, uint32_t device_id) {
  return ZX_ERR_NOT_SUPPORTED;
}

size_t UsbXhci::UsbHciGetMaxTransferSize(uint32_t device_id, uint8_t ep_address) { return 0; }

zx_status_t UsbXhci::UsbHciCancelAll(uint32_t device_id, uint8_t ep_address) {
  return ZX_ERR_NOT_SUPPORTED;
}

size_t UsbXhci::UsbHciGetRequestSize() { return Request::RequestSize(sizeof(usb_request_t)); }

void UsbXhci::UsbHciRequestQueue(usb_request_t* usb_request,
                                 const usb_request_complete_callback_t* complete_cb) {}

uint16_t UsbXhci::InterrupterMapping() { return 0; }

fpromise::promise<void, zx_status_t> UsbXhci::Timeout(uint16_t target_interrupter,
                                                      zx::time deadline) {
  return fpromise::make_result_promise<void, zx_status_t>(fpromise::ok());
}

zx_status_t TransferRing::Init(size_t page_size, const zx::bti& bti, EventRing* ring, bool is_32bit,
                               fdf::MmioBuffer* mmio, UsbXhci* hci) {
  fbl::AutoLock _(&mutex_);
  hci_ = hci;
  return ZX_OK;
}

void UsbXhci::Shutdown(zx_status_t status) {}

zx_status_t TransferRing::HandleShortPacket(TRB* short_trb, size_t short_length, TRB** first_trb) {
  static_cast<EventRingHarness*>(hci_->GetTestHarness())
      ->HandleShortPacket(short_trb, short_length, first_trb);
  return ZX_OK;
}

fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> TransferRing::TakePendingTRBsUntil(TRB* end) {
  fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> empty;
  return empty;
}

fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> TransferRing::TakePendingTRBs() {
  fbl::DoublyLinkedList<std::unique_ptr<TRBContext>> empty;
  return empty;
}

fpromise::promise<void, zx_status_t> UsbXhci::DeviceOffline(uint32_t slot) {
  return fpromise::make_error_promise<zx_status_t>(ZX_ERR_NOT_SUPPORTED);
}

fpromise::promise<void, zx_status_t> EnumerateDevice(UsbXhci* hci, uint8_t port,
                                                     std::optional<HubInfo> hub_info) {
  auto harness = static_cast<EventRingHarness*>(hci->GetTestHarness());
  std::unique_ptr<Command> command = std::make_unique<Command>();
  fpromise::bridge<TRB*, zx_status_t> bridge;
  command->type = CommandType::EnumerateDevice;
  command->port = port;
  command->hub = hub_info;
  command->completer = std::move(bridge.completer);
  harness->AddCommand(std::move(command));
  return bridge.consumer.promise().discard_value();
}

TRB* TransferRing::PhysToVirt(zx_paddr_t paddr) {
  return (paddr == kFakeTrb) ? reinterpret_cast<TRB*>(kFakeTrbVirt) : nullptr;
}

zx_status_t TransferRing::CompleteTRB(TRB* trb, std::unique_ptr<TRBContext>* context) {
  return static_cast<EventRingHarness*>(hci_->GetTestHarness())->CompleteTRB(trb, context);
}

zx_status_t TransferRing::DeinitIfActive() { return ZX_OK; }

Endpoint::Endpoint(UsbXhci* hci, uint32_t device_id, uint8_t address)
    : usb_endpoint::UsbEndpoint(hci->bti(), address), hci_(hci) {}
zx_status_t Endpoint::Init(EventRing* event_ring, fdf::MmioBuffer* mmio) {
  return transfer_ring_.Init(zx_system_get_page_size(), kFakeBti, event_ring, false, mmio, hci_);
}
void Endpoint::QueueRequests(QueueRequestsRequest& request,
                             QueueRequestsCompleter::Sync& completer) {}
void Endpoint::CancelAll(CancelAllCompleter::Sync& completer) {
  completer.Reply(fit::as_error(ZX_ERR_NOT_SUPPORTED));
}
void Endpoint::OnUnbound(fidl::UnbindInfo info,
                         fidl::ServerEnd<fuchsia_hardware_usb_endpoint::Endpoint> server_end) {}
zx_status_t DeviceState::InitEndpoint(uint8_t ep_addr, EventRing* event_ring, fdf::MmioBuffer* mmio)
    __TA_REQUIRES(transaction_lock_) {
  rings_[ep_addr].emplace(hci_, device_id_, ep_addr);
  return rings_[ep_addr]->Init(event_ring, mmio);
}
DeviceState::~DeviceState() = default;

TEST_F(EventRingHarness, ShortTransferTest) {
  InitSlot(1);
  TRB* start = trb();
  TRB trb;
  trb.ptr = kFakeTrb;
  Control::FromTRB(&trb).set_Type(Control::TransferEvent).ToTrb(&trb);
  TransferEvent* evt = static_cast<TransferEvent*>(&trb);
  evt->set_SlotID(1);
  evt->set_EndpointID(2);
  evt->set_CompletionCode(CommandCompletionEvent::ShortPacket);
  evt->set_TransferLength(kShortTransferLength0);
  AddTRB(trb);
  evt->set_TransferLength(kShortTransferLength1);
  AddTRB(trb);
  evt->set_CompletionCode(CommandCompletionEvent::Success);
  evt->set_TransferLength(kFinalTransferLength);
  AddTRB(trb);
  size_t index = 0;
  TRB* trb_list[2];
  size_t shorts[2];
  SetShortPacketHandler([&](TRB* short_trb, size_t short_length, usb_xhci::TRB** first_trb) {
    *first_trb = nullptr;
    trb_list[index] = short_trb;
    shorts[index] = short_length;
    index++;
  });
  auto ctx = AllocateContext();
  size_t transfer_len;
  zx_status_t transfer_status;
  ctx->trb = start;
  std::optional<TestRequest> request;
  AllocateRequest(&request, 1, zx_system_get_page_size() * 3, 5, [&](TestRequest request) {
    transfer_status = request.request()->response.status;
    transfer_len = request.request()->response.actual;
  });
  ctx->short_transfer_len = kShortTransferLength;
  ctx->request = Borrow(std::move(*request));
  AddContext(std::move(ctx));
  SetCompletion(reinterpret_cast<TRB*>(kFakeTrbVirt));
  Interrupt();
  ASSERT_OK(transfer_status);
  ASSERT_EQ(transfer_len, kShortTransferLength);
  ASSERT_EQ(shorts[0], kShortTransferLength0);
  ASSERT_EQ(shorts[1], kShortTransferLength1);
  ASSERT_EQ(trb_list[0], reinterpret_cast<TRB*>(kFakeTrbVirt));
  ASSERT_EQ(trb_list[1], reinterpret_cast<TRB*>(kFakeTrbVirt));
}

TEST_F(EventRingHarness, NormalStall) {
  InitSlot(1);
  TRB* start = trb();
  TRB trb;
  trb.ptr = kFakeTrb;
  Control::FromTRB(&trb).set_Type(Control::TransferEvent).ToTrb(&trb);
  TransferEvent* evt = static_cast<TransferEvent*>(&trb);
  evt->set_SlotID(1);
  evt->set_EndpointID(2);
  evt->set_CompletionCode(CommandCompletionEvent::StallError);
  evt->set_TransferLength(0);
  AddTRB(trb);
  auto ctx = AllocateContext();
  size_t transfer_len;
  zx_status_t transfer_status;
  ctx->trb = start;
  std::optional<TestRequest> request;
  AllocateRequest(&request, 1, zx_system_get_page_size() * 3, 5, [&](TestRequest request) {
    transfer_status = request.request()->response.status;
    transfer_len = request.request()->response.actual;
  });
  ctx->request = Borrow(std::move(*request));
  AddContext(std::move(ctx));
  SetCompletion(reinterpret_cast<TRB*>(kFakeTrbVirt));
  Interrupt();
  ASSERT_EQ(transfer_status, ZX_ERR_IO_REFUSED);
  ASSERT_EQ(transfer_len, 0);
}

TEST_F(EventRingHarness, BadHubStallOnDtDeviceQualifier) {
  InitSlot(1);
  TRB* start = trb();
  TRB trb;
  trb.ptr = kFakeTrb;
  Control::FromTRB(&trb).set_Type(Control::TransferEvent).ToTrb(&trb);
  TransferEvent* evt = static_cast<TransferEvent*>(&trb);
  evt->set_SlotID(1);
  evt->set_EndpointID(2);
  evt->set_CompletionCode(CommandCompletionEvent::StallError);
  evt->set_TransferLength(0);
  AddTRB(trb);
  auto ctx = AllocateContext();
  size_t transfer_len;
  zx_status_t transfer_status;
  ctx->trb = start;
  std::optional<TestRequest> request;
  usb_device_qualifier_descriptor_t descriptor;
  AllocateRequest(&request, 1, sizeof(usb_device_qualifier_descriptor_t), 0,
                  [&](TestRequest request) {
                    transfer_status = request.request()->response.status;
                    transfer_len = request.request()->response.actual;
                    usb_device_qualifier_descriptor_t* result;
                    request.Mmap(reinterpret_cast<void**>(&result));
                    memcpy(&descriptor, result, sizeof(usb_device_qualifier_descriptor_t));
                  });
  request->request()->setup.b_request = USB_REQ_GET_DESCRIPTOR;
  request->request()->setup.w_index = 0;
  request->request()->setup.w_value = USB_DT_DEVICE_QUALIFIER << 8;
  request->request()->header.length = sizeof(usb_device_qualifier_descriptor_t);

  ctx->request = Borrow(std::move(*request));
  AddContext(std::move(ctx));
  SetCompletion(reinterpret_cast<TRB*>(kFakeTrbVirt));
  Interrupt();
  auto cmd = GetCommand();
  ASSERT_EQ(cmd->type, CommandType::ResetEndpoint);
  ASSERT_EQ(cmd->endpoint, 0);
  ASSERT_EQ(cmd->device_id, 1);
  cmd->completer.complete_ok(nullptr);
  Interrupt();

  ASSERT_EQ(transfer_status, ZX_OK);
  ASSERT_EQ(transfer_len, sizeof(usb_device_qualifier_descriptor_t));
  ASSERT_EQ(descriptor.b_device_protocol, 0);
}

TEST_F(EventRingHarness, USB2DeviceAttach) {
  ConnectDevice();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_TRUE(PortResetPending());
  ASSERT_FALSE(HasCommand());
  LinkUp();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_TRUE(HasCommand());
  auto cmd = GetCommand();
  ASSERT_EQ(cmd->port, kPortNo);
  ASSERT_EQ(cmd->type, CommandType::EnumerateDevice);
  ASSERT_FALSE(cmd->hub);
}

TEST_F(EventRingHarness, USB2DeviceAttachBadStateTransition) {
  ConnectDevice();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_TRUE(PortResetPending());
  ASSERT_FALSE(HasCommand());
  LinkUp();
  MakeQuantumPort();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_FALSE(HasCommand());
  LinkUp();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_TRUE(HasCommand());
  auto cmd = GetCommand();
  ASSERT_EQ(cmd->port, kPortNo);
  ASSERT_EQ(cmd->type, CommandType::EnumerateDevice);
  ASSERT_FALSE(cmd->hub);
}

TEST_F(EventRingHarness, Usb3DeviceAttach) {
  ConnectDevice();
  LinkUp();
  InsertPortStatusChangeEvent();
  Interrupt();
  ASSERT_TRUE(HasCommand());
  auto cmd = GetCommand();
  ASSERT_EQ(cmd->port, kPortNo);
  ASSERT_EQ(cmd->type, CommandType::EnumerateDevice);
  ASSERT_FALSE(cmd->hub);
}

}  // namespace usb_xhci
