// 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;
  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, 1, 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;
}
