// 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_simpleserial.h"

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

#define MAX_GATHER 16

static void ss_rx(void *ssctx_v, usbbufid_t buf, int size, int setup) {
  usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v;
  void *ctx = ssctx->ctx;
  volatile uint8_t *bp = (volatile uint8_t *)usbdev_buf_idtoaddr(ctx, buf);

  if (size > BUF_LENGTH) {
    size = BUF_LENGTH;
  }

  while (size--) {
    ssctx->got_byte(*bp++);
  }
}

// Called periodically by the main loop to ensure characters don't
// stick around too long
static void ss_flush(void *ssctx_v) {
  usb_ss_ctx_t *ssctx = (usb_ss_ctx_t *)ssctx_v;
  void *ctx = ssctx->ctx;
  volatile uint32_t *bp_w;
  if ((ssctx->cur_buf == -1) || (ssctx->cur_cpos <= 0)) {
    return;
  }
  if ((ssctx->cur_cpos & 0x3) != 0) {
    // unwritten data to copy over
    bp_w = usbdev_buf_idtoaddr(ctx, ssctx->cur_buf);
    // no -1 here because cpos is in the word we are writing
    bp_w[(ssctx->cur_cpos / 4)] = ssctx->chold.data_w;
  }
  usbdev_sendbuf_byid(ctx, ssctx->cur_buf, ssctx->cur_cpos, ssctx->ep);
  ssctx->cur_buf = -1;  // given it to the hardware
}

// Simple send byte will gather data for a while and send
void usb_simpleserial_send_byte(usb_ss_ctx_t *ssctx, uint8_t c) {
  volatile uint32_t *bp_w;
  if (ssctx->cur_buf == -1) {
    ssctx->cur_buf = usbdev_buf_allocate_byid(ssctx->ctx);
    ssctx->cur_cpos = 0;
  }
  // Abort if completely out of buffers and allocation returned -1
  if (ssctx->cur_buf < 0) {
    return;
  }
  ssctx->chold.data_b[ssctx->cur_cpos++ & 0x3] = c;
  if ((ssctx->cur_cpos & 0x3) == 0) {
    // just wrote last byte in word
    bp_w = usbdev_buf_idtoaddr(ssctx->ctx, ssctx->cur_buf);
    // -1 here because cpos already incremented to next word
    bp_w[(ssctx->cur_cpos / 4) - 1] = ssctx->chold.data_w;
    if (ssctx->cur_cpos >= MAX_GATHER) {
      usbdev_sendbuf_byid(ssctx->ctx, ssctx->cur_buf, ssctx->cur_cpos,
                          ssctx->ep);
      ssctx->cur_buf = -1;  // given it to the hardware
    }
  }
}

void usb_simpleserial_init(usb_ss_ctx_t *ssctx, usbdev_ctx_t *ctx, int ep,
                           void (*got_byte)(uint8_t)) {
  usbdev_endpoint_setup(ctx, ep, 1, ssctx, NULL, ss_rx, ss_flush, NULL);
  ssctx->ctx = ctx;
  ssctx->ep = ep;
  ssctx->got_byte = got_byte;
  ssctx->cur_buf = -1;
}
