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

// Get NULL from here
#include "usb_controlep.h"

#include <stddef.h>

#include "common.h"
#include "usb_consts.h"
#include "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 kCtIdle;  // 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);
      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;
  }
  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;
      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;
  }
  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;
}

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);
  ctctx->ctrlstate = kCtIdle;
  ctctx->cfg_dscr = cfg_dscr;
  ctctx->cfg_dscr_len = cfg_dscr_len;
}
