gintctl/src/usb_commands.c

106 lines
2.8 KiB
C

#include <gint/usb.h>
#include <gint/usb-ff-bulk.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <endian.h>
#include <ctype.h>
static void drop(usb_fxlink_header_t const *h)
{
USB_LOG("[gintctl] dropping %.16s.%.16s\n", h->application, h->type);
usb_fxlink_drop_transaction();
USB_LOG("[gintctl] done dropping\n");
}
void gintctl_handle_usb_command(usb_fxlink_header_t const *h)
{
if(strcmp(h->application, "gintctl") != 0)
return drop(h);
if(!strcmp(h->type, "echo-bounds")) {
int buffer[128], first = 0, last = 0, total = 0;
int block = USB_READ_BLOCK;
while(1) {
timeout_t tm = timeout_make_ms(1000);
int rc = usb_read_async(usb_ff_bulk_input(), buffer, sizeof buffer,
USB_READ_WAIT | block, NULL, &tm, GINT_CALL_NULL);
if(rc < 0)
break;
block = 0;
if(total == 0)
first = le32toh(buffer[0]);
if(rc >= 4)
last = le32toh(buffer[rc / 4 - 1]);
total += rc;
if(rc != sizeof buffer)
break;
}
char str[64];
sprintf(str, "first=%08x last=%08x total=%d B\n", first, last, total);
usb_fxlink_text(str, 0);
return;
}
if(!strcmp(h->type, "garbage")) {
/* Purposefully don't read the transaction's contents so they get
interpreted as garbage headers; this is to stress test the function
that reads & interprets headers. */
return;
}
if(!strcmp(h->type, "read-unaligned")) {
/* Read by little bits depending on given mode */
char mode;
usb_read_sync(usb_ff_bulk_input(), &mode, 1, false);
char *buf = malloc(h->size);
if(!buf) {
usb_fxlink_drop_transaction();
return;
}
USB_LOG("[gintctl] Read unaligned size %d mode '%c'\n",
h->size-1, mode);
if(mode == 'r')
srand(0xc0ffee);
size_t i = 0;
int round_number = 0;
while(i < h->size - 1) {
size_t round = 1;
/* Determine the size of this next round */
if(isdigit(mode)) {
round = mode - '0';
}
else if(mode == 'i') {
round = (round_number & 3) + 1;
}
else if(mode == 'r') {
round = rand() & 15;
}
if(round > (h->size - 1) - i)
round = h->size - 1 - i;
usb_read_sync(usb_ff_bulk_input(), buf + i, round, false);
i += round;
round_number++;
}
/* Echo the result */
buf[h->size - 1] = 0;
USB_LOG("Final result: %s\n", buf);
usb_fxlink_text(buf, h->size - 1);
free(buf);
return;
}
drop(h);
}