// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/usb_controlep.h"

#include "sw/device/lib/usb_consts.h"
#include "sw/device/lib/usbdev.h"

// Device descriptor
static uint8_t dev_dscr[] = {
    18,    // bLength
    1,     // bDescriptorType
    0x00,  // bcdUSB[0]
    0x02,  // bcdUSB[1]
    0x00,  // bDeviceClass (defined at interface level)
    0x00,  // bDeviceSubClass
    0x00,  // bDeviceProtocol
    64,    // bMaxPacketSize0

    0xd1,  // idVendor[0] 0x18d1 Google Inc.
    0x18,  // idVendor[1]
    0x3a,  // idProduct[0] lowRISC generic FS USB
    0x50,  // idProduct[1] (allocated by Google)

    0,    // bcdDevice[0]
    0x1,  // bcdDevice[1]
    0,    // iManufacturer
    0,    // iProduct
    0,    // iSerialNumber
    1     // bNumConfigurations
};

static ctstate_t setup_req(usb_controlep_ctx_t *ctctx, void *ctx,
                           usbbufid_t buf, int bmRequestType, int bRequest,
                           int wValue, int wIndex, int wLength) {
  size_t len;
  uint32_t stat;
  int zero, type;
  switch (bRequest) {
    case kUsbSetupReqGetDescriptor:
      if ((wValue & 0xff00) == 0x100) {
        // Device descriptor
        len = sizeof(dev_dscr);
        if (wLength < len) {
          len = wLength;
        }
        usbdev_buf_copyto_byid(ctx, buf, dev_dscr, len);
        usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
        return kCtWaitIn;
      } else if ((wValue & 0xff00) == 0x200) {
        // Configuration descriptor
        len = ctctx->cfg_dscr_len;
        if (wLength < len) {
          len = wLength;
        }
        usbdev_buf_copyto_byid(ctx, buf, ctctx->cfg_dscr, len);
        usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
        return kCtWaitIn;
      }
      return kCtError;  // unknown

    case kUsbSetupReqSetAddress:
      ctctx->new_dev = wValue & 0x7f;
      // send zero length packet for status phase
      usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
      return kCtAddrStatIn;

    case kUsbSetupReqSetConfiguration:
      // only ever expect this to be 1 since there is one config descriptor
      ctctx->usb_config = wValue;
      // send zero length packet for status phase
      usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
      ctctx->device_state = kUsbDeviceConfigured;
      return kCtStatIn;

    case kUsbSetupReqGetConfiguration:
      len = sizeof(ctctx->usb_config);
      if (wLength < len) {
        len = wLength;
      }
      // return the value that was set
      usbdev_buf_copyto_byid(ctx, buf, &ctctx->usb_config, len);
      usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
      return kCtWaitIn;

    case kUsbSetupReqSetFeature:
      if (wValue == kUsbFeatureEndpointHalt) {
        usbdev_halt(ctx, wIndex, 1);
      } else if (wValue == kUsbFeatureDeviceRemoteWakeup) {
        usbdev_rem_wake_en(ctx, 1);
      }
      // send zero length packet for status phase
      usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
      return kCtStatIn;

    case kUsbSetupReqClearFeature:
      if (wValue == kUsbFeatureEndpointHalt) {
        usbdev_halt(ctx, wIndex, 0);
      } else if (wValue == kUsbFeatureDeviceRemoteWakeup) {
        usbdev_rem_wake_en(ctx, 0);
      }
      // send zero length packet for status phase
      usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
      return kCtStatIn;

    case kUsbSetupReqGetStatus:
      len = 2;
      type = bmRequestType & kUsbReqTypeRecipientMask;
      if (type == kUsbReqTypeDevice) {
        stat = (usbdev_can_rem_wake(ctx) ? kUsbStatusRemWake : 0) |
               kUsbStatusSelfPowered;
      } else if (type == kUsbReqTypeEndpoint) {
        stat = usbdev_halted(ctx, wIndex) ? kUsbStatusHalted : 0;
      } else {
        stat = 0;
      }
      if (wLength < len) {
        len = wLength;
      }
      // return the value that was set
      usbdev_buf_copyto_byid(ctx, buf, &stat, len);
      usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
      return kCtWaitIn;

    case kUsbSetupReqSetInterface:
      // Don't support alternate interfaces, so just ignore
      // send zero length packet for status phase
      usbdev_sendbuf_byid(ctx, buf, 0, ctctx->ep);
      return kCtStatIn;

    case kUsbSetupReqGetInterface:
      zero = 0;
      len = 1;
      if (wLength < len) {
        len = wLength;
      }
      // Don't support interface, so return zero
      usbdev_buf_copyto_byid(ctx, buf, &zero, len);
      usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
      return kCtWaitIn;

    case kUsbSetupReqSynchFrame:
      zero = 0;
      len = 2;
      if (wLength < len) {
        len = wLength;
      }
      // Don't support synch_frame so return zero
      usbdev_buf_copyto_byid(ctx, buf, &zero, len);
      usbdev_sendbuf_byid(ctx, buf, len, ctctx->ep);
      return kCtWaitIn;

    default:
      return kCtError;
  }
  return kCtError;
}

static void ctrl_tx_done(void *ctctx_v) {
  usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
  void *ctx = ctctx->ctx;
  TRC_C('A' + ctctx->ctrlstate);
  switch (ctctx->ctrlstate) {
    case kCtAddrStatIn:
      // Now the status was sent on device 0 can switch to new device ID
      usbdev_set_deviceid(ctx, ctctx->new_dev);
      TRC_I(ctctx->new_dev, 8);
      ctctx->ctrlstate = kCtIdle;
      // Should be kUsbDeviceAddressed only, but test controller is borked
      // ctctx->device_state = kUsbDeviceAddressed;
      ctctx->device_state = kUsbDeviceConfigured;
      return;
    case kCtStatIn:
      ctctx->ctrlstate = kCtIdle;
      return;
    case kCtWaitIn:
      ctctx->ctrlstate = kCtStatOut;
      return;
    default:
      break;
  }
  TRC_S("USB: unexpected IN ");
  TRC_I((ctctx->ctrlstate << 24), 32);
}

static void ctrl_rx(void *ctctx_v, usbbufid_t buf, int size, int setup) {
  usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
  void *ctx = ctctx->ctx;
  usbdev_clear_out_nak(ctx, 0);
  volatile uint8_t *bp = (volatile uint8_t *)usbdev_buf_idtoaddr(ctx, buf);
  if (size > BUF_LENGTH) {
    size = BUF_LENGTH;
  }

  TRC_C('0' + ctctx->ctrlstate);
  switch (ctctx->ctrlstate) {
    case kCtIdle:
      // Waiting to be set up
      if (setup && (size == 8)) {
        int bmRequestType = bp[0];
        int bRequest = bp[1];
        int wValue = (bp[3] << 8) | bp[2];
        int wIndex = (bp[5] << 8) | bp[4];
        int wLength = (bp[7] << 8) | bp[6];
        TRC_C('0' + bRequest);

        ctctx->ctrlstate = setup_req(ctctx, ctx, buf, bmRequestType, bRequest,
                                     wValue, wIndex, wLength);
        if (ctctx->ctrlstate != kCtError) {
          return;
        }
      }
      break;

    case kCtStatOut:
      // Have sent some data, waiting STATUS stage
      if (!setup && (size == 0)) {
        ctctx->ctrlstate = kCtIdle;
        return;
      }
      // anything else is unexpected
      break;

    default:
      // Error
      break;
  }
  usbdev_set_ep0_stall(ctx, 1);  // send a STALL, will be cleared by the HW
  TRC_S("USB: unCT ");
  TRC_I((ctctx->ctrlstate << 24) | setup << 16 | size, 32);
  TRC_C(':');
  for (int i = 0; i < size; i++) {
    TRC_I(bp[i], 8);
    TRC_C(' ');
  }
  usbdev_buf_free_byid(ctx, buf);
  ctctx->ctrlstate = kCtIdle;
}

// Callback for the USB link reset
void ctrl_reset(void *ctctx_v) {
  usb_controlep_ctx_t *ctctx = (usb_controlep_ctx_t *)ctctx_v;
  ctctx->ctrlstate = kCtIdle;
}

void usb_controlep_init(usb_controlep_ctx_t *ctctx, usbdev_ctx_t *ctx, int ep,
                        const uint8_t *cfg_dscr, size_t cfg_dscr_len) {
  ctctx->ctx = ctx;
  usbdev_endpoint_setup(ctx, ep, kUsbdevOutMessage, ctctx, ctrl_tx_done,
                        ctrl_rx, NULL, ctrl_reset);
  ctctx->ctrlstate = kCtIdle;
  ctctx->cfg_dscr = cfg_dscr;
  ctctx->cfg_dscr_len = cfg_dscr_len;
  usbdev_connect(ctx);
  ctctx->device_state = kUsbDeviceDefault;
}
