5 #include "sw/device/lib/testing/usb_logging.h"
11 #include "sw/device/lib/testing/pinmux_testutils.h"
12 #include "sw/device/lib/testing/usb_testutils.h"
13 #include "sw/device/lib/testing/usb_testutils_controlep.h"
15 #define MODULE_ID MAKE_MODULE_ID('u', 's', 'l')
21 kUSBLogBufferSize = 0x800u,
24 kUSBLogNumBuffers = 8u,
28 kUSBLogFlushInterval = 500u * 1000u,
35 kUSBLogMaxStreams * (USB_INTERFACE_DSCR_LEN + 1u * USB_EP_DSCR_LEN)),
54 uint8_t
data[kUSBLogBufferSize];
137 static dif_pinmux_t pinmux;
143 static const bool kDevLogging =
false;
150 static const uint32_t kCtrlChars =
151 ((uint32_t)1u <<
'\t') | ((uint32_t)1u <<
'\n') | ((uint32_t)1u <<
'\r');
152 static const uint32_t kMap[0x100u / 0x20u] = {
154 kCtrlChars, ~0u, ~0u, 0x7fffffffu,
159 static size_t usb_log(
void *data,
const char *buf,
size_t len);
164 static uint8_t config_descriptors[kCfgDscrLenMax];
168 static bool isprintable(uint8_t ch) {
169 return ((kMap[ch >> 5] >> (ch & 0x1fu)) & 1u) != 0u;
175 unsigned idx = kUSBLogNumBuffers;
179 prev = &ctx->
buf[idx];
209 LOG_INFO(
"sending %p %p %u\n", ctx, data, len);
212 TRY(usb_testutils_transfer_send(ctx->
usbutils, s->
ep, data, len,
213 kUsbTestutilsXfrDoubleBuffered));
226 prev = &(*prev)->
next;
234 res = buffer_send(ctx, s);
246 buffer_completed(ctx, s);
253 static status_t tx_done(
void *s_v, usb_testutils_xfr_result_t result) {
261 TRY_CHECK(buf != NULL);
263 buffer_release(ctx, buf);
267 TRY(buffer_send(ctx, s));
274 static status_t tx_flush(
void *s_v) {
284 buffer_completed(ctx, s);
301 TRY(usb_testutils_poll(ctx->
usbutils));
305 s->
wr_buf = buffer_claim(ctx);
311 size_t chunk = kUSBLogBufferSize - buf->
bytes_used;
319 for (
size_t i = 0u; i < chunk; ++i) {
320 dp[i] = isprintable(data[i]) ? data[i] :
'.';
338 buffer_completed(ctx, s);
350 status_t usb_logging_data(uint8_t s,
const uint8_t *data,
size_t len) {
352 TRY_CHECK(s < ctx->nstreams);
354 return usb_logging_send(ctx, &ctx->
streams[s], data, len);
358 status_t usb_logging_text(uint8_t s,
const char *text) {
360 TRY_CHECK(s < ctx->nstreams);
364 uint32_t len = (uint32_t)((
char *)
memchr(text, 0, SIZE_MAX) - text);
365 return usb_logging_send(ctx, &ctx->
streams[s], (
const uint8_t *)text, len);
369 static size_t usb_log(
void *data,
const char *buf,
size_t len) {
373 status_t res = usb_logging_send(ctx, s, (uint8_t *)buf, len);
374 if (status_ok(res)) {
388 TRY(usb_logging_init(ctx->
usbutils, 1u, 1u, 1u,
false));
401 uint8_t nstreams, uint32_t reliable,
bool remap) {
405 TRY_CHECK(nstreams > 0u && nstreams <= kUSBLogMaxStreams);
420 pinmux_testutils_init(&pinmux);
426 size_t cfg_len = USB_CFG_DSCR_LEN +
427 nstreams * (USB_INTERFACE_DSCR_LEN + USB_EP_DSCR_LEN);
428 TRY_CHECK(cfg_len <=
sizeof(config_descriptors));
431 uint8_t *cfg = config_descriptors;
432 uint8_t head[USB_CFG_DSCR_LEN] = {
433 USB_CFG_DSCR_HEAD((uint16_t)cfg_len, (uint8_t)nstreams)};
434 memcpy(cfg, head, USB_CFG_DSCR_LEN);
435 cfg += USB_CFG_DSCR_LEN;
438 for (uint8_t
id = 0U;
id < nstreams; ++id) {
439 uint8_t ep_in = ep_first + id;
441 uint8_t int_dscr[USB_INTERFACE_DSCR_LEN + USB_EP_DSCR_LEN] = {
442 VEND_INTERFACE_DSCR(
id, 1, 0x50, 1),
445 USB_EP_DSCR(1, ep_in, (uint8_t)kUsbTransferTypeBulk,
446 USBDEV_MAX_PACKET_SIZE, 0),
450 memcpy(cfg, int_dscr,
sizeof(int_dscr));
451 cfg +=
sizeof(int_dscr);
457 TRY(usb_testutils_init(ctx->
usbutils,
false,
460 TRY(usb_testutils_controlep_init(&usbdev_control, ctx->
usbutils, 0,
461 config_descriptors, cfg_len, NULL,
471 const uint32_t flush_inc = kUSBLogFlushInterval / nstreams;
472 uint32_t interval_us = kUSBLogFlushInterval / 2u;
474 for (uint8_t s = 0u; s < nstreams; ++s) {
479 stream->
reliable = (((reliable >> s) & 1u) != 0u);
481 stream->
remap = remap;
491 interval_us += flush_inc;
495 TRY(usb_testutils_in_endpoint_setup(ctx->
usbutils, stream->
ep,
496 kUsbTransferTypeBulk, stream, tx_done,
503 const uint32_t kTimeoutUsecs = 30 * 1000000;
505 while (usbdev_control.device_state != kUsbTestutilsDeviceConfigured &&
507 TRY(usb_testutils_poll(ctx->
usbutils));
509 if (usbdev_control.device_state != kUsbTestutilsDeviceConfigured) {
511 return UNAVAILABLE();
521 status_t usb_logging_fin(
bool wait,
bool disconnect) {
527 while (s < ctx->nstreams) {
529 if (!stream_close(ctx, stream)) {
530 TRY(usb_testutils_poll(ctx->
usbutils));
541 TRY(usb_testutils_fin(ctx->
usbutils));