blob: 05a799db606b4343a59bf7e1b9f95396a0f5969c [file] [log] [blame]
// 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/testing/usb_testutils_simpleserial.h"
#include "sw/device/lib/dif/dif_usbdev.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/usb_testutils.h"
#define MAX_GATHER 16
static void ss_rx(void *ssctx_v, dif_usbdev_rx_packet_info_t packet_info,
dif_usbdev_buffer_t buffer) {
usb_testutils_ss_ctx_t *ssctx = (usb_testutils_ss_ctx_t *)ssctx_v;
usb_testutils_ctx_t *ctx = ssctx->ctx;
while (packet_info.length--) {
uint8_t data;
size_t bytes_written;
CHECK_DIF_OK(dif_usbdev_buffer_read(ctx->dev, ctx->buffer_pool, &buffer,
&data, sizeof(data), &bytes_written));
ssctx->got_byte(data);
}
}
// Called periodically by the main loop to ensure characters don't
// stick around too long
static void ss_flush(void *ssctx_v) {
usb_testutils_ss_ctx_t *ssctx = (usb_testutils_ss_ctx_t *)ssctx_v;
usb_testutils_ctx_t *ctx = ssctx->ctx;
if (ssctx->cur_cpos <= 0) {
return;
}
if ((ssctx->cur_cpos & 0x3) != 0) {
size_t bytes_written;
CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &ssctx->cur_buf,
ssctx->chold.data_b, /*src_len=*/4,
&bytes_written));
}
CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ssctx->ep, &ssctx->cur_buf));
ssctx->cur_cpos = -1; // given it to the hardware
}
// Simple send byte will gather data for a while and send
void usb_testutils_simpleserial_send_byte(usb_testutils_ss_ctx_t *ssctx,
uint8_t c) {
usb_testutils_ctx_t *ctx = ssctx->ctx;
if (ssctx->cur_cpos == -1) {
CHECK_DIF_OK(
dif_usbdev_buffer_request(ctx->dev, ctx->buffer_pool, &ssctx->cur_buf));
ssctx->cur_cpos = 0;
}
ssctx->chold.data_b[ssctx->cur_cpos++ & 0x3] = c;
if ((ssctx->cur_cpos & 0x3) == 0) {
size_t bytes_written;
CHECK_DIF_OK(dif_usbdev_buffer_write(ctx->dev, &ssctx->cur_buf,
ssctx->chold.data_b, /*src_len=*/4,
&bytes_written));
if (ssctx->cur_cpos >= MAX_GATHER) {
CHECK_DIF_OK(dif_usbdev_send(ctx->dev, ssctx->ep, &ssctx->cur_buf));
ssctx->cur_cpos = -1; // given it to the hardware
}
}
}
void usb_testutils_simpleserial_init(usb_testutils_ss_ctx_t *ssctx,
usb_testutils_ctx_t *ctx, int ep,
void (*got_byte)(uint8_t)) {
usb_testutils_endpoint_setup(ctx, ep, kUsbdevOutStream, ssctx, NULL, ss_rx,
ss_flush, NULL);
ssctx->ctx = ctx;
ssctx->ep = ep;
ssctx->got_byte = got_byte;
ssctx->cur_cpos = -1;
}