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