5 #include "sw/device/lib/testing/usb_testutils.h"
8 #include "sw/device/lib/testing/test_framework/check.h"
12 #define MODULE_ID MAKE_MODULE_ID('u', 's', 't')
14 #define USBDEV_BASE_ADDR TOP_EARLGREY_USBDEV_BASE_ADDR
16 static dif_usbdev_t usbdev;
25 CHECK(ctx && transfer && last);
35 unsigned max_packet = USBDEV_MAX_PACKET_SIZE;
36 if (transfer->
flags & kUsbTestutilsXfrMaxPacketSupplied) {
37 max_packet = (unsigned)(transfer->
flags & kUsbTestutilsXfrMaxPacketMask);
42 if (part_len > max_packet) {
43 part_len = max_packet;
45 size_t bytes_written = 0U;
49 part_len, &bytes_written));
52 uint32_t next_offset = transfer->
offset + bytes_written;
54 if (bytes_written == max_packet) {
55 if (next_offset < transfer->length ||
56 (transfer->
flags & kUsbTestutilsXfrEmployZLP)) {
60 CHECK(bytes_written < max_packet);
63 transfer->
offset = next_offset;
68 static bool usb_testutils_transfer_next_part(
72 !usb_testutils_part_prepare(ctx, transfer, &transfer->
next_part,
83 if ((transfer->
flags & kUsbTestutilsXfrDoubleBuffered) && !transfer->
last) {
84 transfer->
next_valid = usb_testutils_part_prepare(
95 TRY(dif_usbdev_irq_get_state(ctx->dev, &istate));
104 if (istate & (1u << kDifUsbdevIrqPktSent)) {
110 if (sentep & (1u << ep)) {
117 usb_testutils_xfr_result_t res = kUsbTestutilsXfrResultOk;
121 if (usb_testutils_transfer_next_part(ctx, (uint8_t)ep, transfer)) {
124 res = kUsbTestutilsXfrResultFailed;
134 if (done && ctx->
in[ep].tx_done_callback) {
135 TRY(ctx->
in[ep].tx_done_callback(ctx->
in[ep].ep_ctx, res));
137 sentep &= ~(1u << ep);
146 if (istate & (1u << kDifUsbdevIrqPktReceived)) {
161 if (ctx->
out[ep].rx_callback) {
162 TRY(ctx->
out[ep].rx_callback(ctx->
out[ep].ep_ctx, packet_info, buffer));
165 TRC_S(
"USB: unexpected RX ");
171 if (istate & (1u << kDifUsbdevIrqLinkReset)) {
172 TRC_S(
"USB: Bus reset");
178 if (ctx->
in[ep].reset) {
179 TRY(ctx->
in[ep].reset(ctx->
in[ep].ep_ctx));
181 if (ctx->
out[ep].reset) {
182 TRY(ctx->
out[ep].reset(ctx->
out[ep].ep_ctx));
188 TRY(dif_usbdev_irq_acknowledge_state(ctx->dev, istate));
191 if ((istate & (1u << kDifUsbdevIrqFrame))) {
199 const dif_usbdev_irq_state_snapshot_t kIrqsLink =
200 (1u << kDifUsbdevIrqPowered) | (1u << kDifUsbdevIrqDisconnected) |
201 (1u << kDifUsbdevIrqHostLost) | (1u << kDifUsbdevIrqLinkReset) |
202 (1u << kDifUsbdevIrqLinkSuspend) | (1u << kDifUsbdevIrqLinkResume) |
203 (1u << kDifUsbdevIrqFrame);
204 if (istate & kIrqsLink) {
226 ~((1u << kDifUsbdevIrqLinkReset) | (1u << kDifUsbdevIrqPktReceived) |
227 (1u << kDifUsbdevIrqPktSent) | (1u << kDifUsbdevIrqFrame) |
228 (1u << kDifUsbdevIrqAvSetupEmpty) | (1u << kDifUsbdevIrqAvOutEmpty) |
229 (1u << kDifUsbdevIrqRxFull) | (1u << kDifUsbdevIrqLinkOutErr) |
230 (1u << kDifUsbdevIrqLinkInErr))) {
238 ((1u << kDifUsbdevIrqRxFull) | (1u << kDifUsbdevIrqAvOverflow) |
239 (1u << kDifUsbdevIrqLinkInErr) | (1u << kDifUsbdevIrqRxCrcErr) |
240 (1u << kDifUsbdevIrqRxPidErr) | (1u << kDifUsbdevIrqRxBitstuffErr) |
241 (1u << kDifUsbdevIrqLinkOutErr))) {
242 LOG_INFO(
"USB: Unexpected interrupts: 0x%08x", istate);
257 if (ctx->flushed == 0) {
259 if (ctx->
in[ep].flush) {
260 TRY(ctx->
in[ep].flush(ctx->
in[ep].ep_ctx));
273 usb_testutils_link_handler_t link,
287 const uint8_t *data, uint32_t length,
288 usb_testutils_xfr_flags_t flags) {
294 return OK_STATUS(
false);
300 transfer->
length = length;
301 transfer->
flags = flags;
304 if (!usb_testutils_transfer_next_part(ctx, ep, transfer)) {
307 return OK_STATUS(
false);
311 return OK_STATUS(
true);
314 status_t usb_testutils_in_endpoint_setup(
316 void *ep_ctx, usb_testutils_tx_done_handler_t tx_done,
317 usb_testutils_tx_flush_handler_t flush,
318 usb_testutils_reset_handler_t reset) {
320 ctx->
in[ep].ep_type = ep_type;
321 ctx->
in[ep].ep_ctx = ep_ctx;
322 ctx->
in[ep].tx_done_callback = tx_done;
323 ctx->
in[ep].flush = flush;
324 ctx->
in[ep].reset = reset;
328 .direction = USBDEV_ENDPOINT_DIR_IN,
335 if (ep_type == kUsbTransferTypeIsochronous) {
345 status_t usb_testutils_out_endpoint_setup(
347 usb_testutils_out_transfer_mode_t out_mode,
void *ep_ctx,
348 usb_testutils_rx_handler_t rx, usb_testutils_reset_handler_t reset) {
350 ctx->
out[ep].ep_type = ep_type;
351 ctx->
out[ep].ep_ctx = ep_ctx;
352 ctx->
out[ep].rx_callback = rx;
353 ctx->
out[ep].reset = reset;
357 .direction = USBDEV_ENDPOINT_DIR_OUT,
364 if (ep_type == kUsbTransferTypeIsochronous) {
371 if (out_mode == kUsbdevOutDisabled) {
377 if (out_mode == kUsbdevOutMessage) {
388 status_t usb_testutils_endpoint_setup(
390 usb_testutils_transfer_type_t out_type,
391 usb_testutils_out_transfer_mode_t out_mode,
void *ep_ctx,
392 usb_testutils_tx_done_handler_t tx_done, usb_testutils_rx_handler_t rx,
393 usb_testutils_tx_flush_handler_t flush,
394 usb_testutils_reset_handler_t reset) {
395 TRY(usb_testutils_in_endpoint_setup(ctx, ep, in_type, ep_ctx, tx_done, flush,
400 return usb_testutils_out_endpoint_setup(ctx, ep, out_type, out_mode, ep_ctx,
409 .direction = USBDEV_ENDPOINT_DIR_IN,
414 ctx->
in[ep].tx_done_callback = NULL;
415 ctx->
in[ep].flush = NULL;
416 ctx->
in[ep].reset = NULL;
426 .direction = USBDEV_ENDPOINT_DIR_OUT,
437 ctx->
out[ep].rx_callback = NULL;
438 ctx->
out[ep].reset = NULL;
444 TRY(usb_testutils_in_endpoint_remove(ctx, ep));
445 return usb_testutils_out_endpoint_remove(ctx, ep);
449 bool en_diff_rcvr,
bool tx_use_d_se0) {
450 TRY_CHECK(ctx != NULL);
452 ctx->buffer_pool = &buffer_pool;
475 "USBDEV_NUM_ENDPOINTS must fit into uint8_t");
477 TRY(usb_testutils_endpoint_setup(
478 ctx, i, kUsbTransferTypeControl, kUsbTransferTypeControl,
479 kUsbdevOutDisabled, NULL, NULL, NULL, NULL, NULL));
483 TRY(dif_usbdev_irq_disable_all(ctx->dev, NULL));
487 TRY(dif_usbdev_irq_acknowledge_all(ctx->dev));
503 "USBDEV_NUM_ENDPOINTS must fit into uint8_t");
505 "USBDEV_NUM_ENDPOINTS - 1 must not overflow");
509 TRY(usb_testutils_endpoint_remove(ctx, ep));