// Copyright 2019 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 "usb-device.h"

#include <zircon/status.h>

#include <ddk/debug.h>
#include <soc/mt8167/mt8167-usb.h>

#include "trace.h"

namespace mt_usb_hci {

namespace regs = board_mt8167;

zx_status_t HardwareDevice::HandleRequest(usb::BorrowedRequest<> req) {
  auto ep = static_cast<uint8_t>(usb_ep_num2(req.request()->header.ep_address));
  ZX_ASSERT_MSG(ep_q_.at(ep), "endpoint not configured");
  return ep_q_[ep]->QueueRequest(std::move(req));
}

zx_status_t HardwareDevice::Enumerate() {
  TRACE();
  // Note that per the USB spec., endpoint-0 is always a ControlEndpoint.
  auto ep0 = static_cast<ControlQueue*>(ep_q_[0].get());

  usb_device_descriptor_t desc;
  auto status = ep0->GetDeviceDescriptor(&desc);
  if (status != ZX_OK) {
    zxlogf(ERROR, "GET_DESCRIPTOR (device) error: %s", zx_status_get_string(status));
    return status;
  }

  // TODO(hansens) add support for multipoint devices (i.e. downstream hubs).
  if (desc.bDeviceClass == USB_CLASS_HUB) {
    zxlogf(ERROR, "usb host does not currently support downstream hubs");
    return ZX_ERR_NOT_SUPPORTED;
  }

  status = ep0->SetAddress(static_cast<uint8_t>(id_));
  if (status != ZX_OK) {
    zxlogf(ERROR, "SET_ADDRESS error: %s", zx_status_get_string(status));
    return status;
  }

  // Having processed a SET_ADDRESS transaction, the device is now in the ADDRESS state (see: USB
  // 2.0 spec. section 9.1) and is ready to be managed by the upper USB layers.  The necessary
  // enumeration steps to follow will be performed by the usb stack and need not be executed here.
  //
  // Currently, the device only has one configured endpoint: the control endpoint (which all
  // devices have).  To further dispatch and process incoming enumeration transactions, we'll kick
  // the ControlQueue's processing thread into execution.

  // TODO(hansens) use the queue to enumerate the device instead of discrete endpoint routines.
  status = ep0->StartQueueThread();
  if (status != ZX_OK) {
    zxlogf(ERROR, "endpoint thread init error: %s", zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

void HardwareDevice::Disconnect() {
  for (uint8_t i = 0; i < kMaxEndpointCount; i++) {
    if (ep_q_[i]) {
      ep_q_[i]->Halt();
    }
  }
}

zx_status_t HardwareDevice::CancelAll(uint8_t ep) {
  // We cannot guarantee the endpoint is configured.
  if (ep_q_[ep]) {
    ep_q_[ep]->CancelAll();
  }
  return ZX_OK;
}

void HardwareDevice::ResizeFifo(uint8_t ep, size_t pkt_sz) {
  uint8_t fifo_size;

  // For table details, see: MUSBMHDRC section 3.10.1.
  if (pkt_sz <= 8) {
    fifo_size = 0;
  } else if (pkt_sz <= 16) {
    fifo_size = 1;
  } else if (pkt_sz <= 32) {
    fifo_size = 2;
  } else if (pkt_sz <= 64) {
    fifo_size = 3;
  } else if (pkt_sz <= 128) {
    fifo_size = 4;
  } else if (pkt_sz <= 256) {
    fifo_size = 5;
  } else if (pkt_sz <= 512) {
    fifo_size = 6;
  } else if (pkt_sz <= 1024) {
    fifo_size = 7;
  } else if (pkt_sz <= 2048) {
    fifo_size = 8;
  } else {
    fifo_size = 9;  // Max single-buffered FIFO size.
  }

  regs::INDEX::Get().FromValue(0).set_selected_endpoint(ep).WriteTo(&usb_);
  regs::TXFIFOSZ::Get().FromValue(0).set_txsz(fifo_size).WriteTo(&usb_);
  regs::RXFIFOSZ::Get().FromValue(0).set_rxsz(fifo_size).WriteTo(&usb_);
  regs::INDEX::Get().FromValue(0).set_selected_endpoint(0).WriteTo(&usb_);
}

zx_status_t HardwareDevice::EnableEndpoint(const usb_endpoint_descriptor_t& descriptor) {
  const uint8_t ep = usb_ep_num(&descriptor);
  const uint8_t type = usb_ep_type(&descriptor);

  // Note that control endpoints are always present and thus not created from a descriptor.
  switch (type) {
    case USB_ENDPOINT_BULK:
      ep_q_[ep] = std::make_unique<BulkQueue>(usb_.View(0), id_, descriptor);
      break;
    case USB_ENDPOINT_INTERRUPT:
      ep_q_[ep] = std::make_unique<InterruptQueue>(usb_.View(0), id_, descriptor);
      break;
    default:
      zxlogf(ERROR, "unsupported endpoint type: 0x%x", type);
      break;
  }

  // Perform direction-specific config.
  if (usb_ep_direction(&descriptor) == USB_ENDPOINT_IN) {
    auto intrrxe = regs::INTRRXE::Get().ReadFrom(&usb_);
    auto val = static_cast<uint16_t>(intrrxe.ep_rx());
    val |= static_cast<uint16_t>(1 << ep);
    intrrxe.set_ep_rx(val).WriteTo(&usb_);

    regs::RXCSR_HOST::Get(ep).ReadFrom(&usb_).set_clrdatatog(1).WriteTo(&usb_);
  } else {  // USB_ENDPOINT_OUT
    auto intrtxe = regs::INTRTXE::Get().ReadFrom(&usb_);
    auto val = static_cast<uint16_t>(intrtxe.ep_tx());
    val |= static_cast<uint16_t>(1 << ep);
    intrtxe.set_ep_tx(val).WriteTo(&usb_);

    regs::TXCSR_HOST::Get(ep).ReadFrom(&usb_).set_clrdatatog(1).WriteTo(&usb_);
  }

  RequestQueue* queue = ep_q_[ep].get();
  ResizeFifo(ep, queue->GetMaxTransferSize());
  return queue->StartQueueThread();
}

zx_status_t HardwareDevice::DisableEndpoint(const usb_endpoint_descriptor_t& desc) {
  const uint8_t ep = usb_ep_num(&desc);
  ep_q_[ep].reset();

  // Disable the requisite interrupt.
  if (usb_ep_direction(&desc) == USB_ENDPOINT_IN) {
    auto intrrxe = regs::INTRRXE::Get().ReadFrom(&usb_);
    auto val = static_cast<uint16_t>(intrrxe.ep_rx());
    val &= static_cast<uint16_t>(~(1 << ep));
    intrrxe.set_ep_rx(val).WriteTo(&usb_);
  } else {  // USB_ENDPOINT_OUT
    auto intrtxe = regs::INTRTXE::Get().ReadFrom(&usb_);
    auto val = static_cast<uint16_t>(intrtxe.ep_tx());
    val &= static_cast<uint16_t>(~(1 << ep));
    intrtxe.set_ep_tx(val).WriteTo(&usb_);
  }

  ResizeFifo(ep, kFifoMaxSize);
  return ZX_OK;
}

size_t HardwareDevice::GetMaxTransferSize(uint8_t ep) {
  if (ep >= kMaxEndpointCount || !ep_q_[ep]) {
    zxlogf(ERROR, "%s: unconfigured endpoint: %d", __func__, ep);
    return 0;
  }
  return ep_q_[ep]->GetMaxTransferSize();
}

}  // namespace mt_usb_hci
