diff --git a/CMakeLists.txt b/CMakeLists.txt index 54102a7..877ae24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(SOURCES src/gintctl.c src/menu.c src/plot.c + src/usb_commands.c src/util.c src/gint/cpumem.c src/gint/dma.c diff --git a/include/gintctl/util.h b/include/gintctl/util.h index 53c094d..fa3e486 100644 --- a/include/gintctl/util.h +++ b/include/gintctl/util.h @@ -8,6 +8,7 @@ #include #include #include +#include //--- // Platform disambiguation functions @@ -94,6 +95,12 @@ void fkey_button(int position, char const *text); /* fkey_menu(): A rectangular F-key with the bottom right corner removed */ void fkey_menu(int position, char const *text); +//--- +// USB commands +//--- + +void gintctl_handle_usb_command(usb_fxlink_header_t const *header); + #endif /* FXCG50 */ #endif /* GINTCTL_UTIL */ diff --git a/src/gint/usb.c b/src/gint/usb.c index b21a935..c700a3f 100644 --- a/src/gint/usb.c +++ b/src/gint/usb.c @@ -582,5 +582,6 @@ void gintctl_gint_usb(void) alignment_write_tests(&awd); } + usb_set_log(NULL); global_interrupt_flag = NULL; } diff --git a/src/gintctl.c b/src/gintctl.c index 6316037..9747fc7 100644 --- a/src/gintctl.c +++ b/src/gintctl.c @@ -182,13 +182,8 @@ key_event_t gintctl_getkey_opt(int options) while(1) { key_event_t ev = getkey_opt(options, &gintctl_interrupt); - - while(usb_fxlink_handle_messages(&header)) { - USB_LOG("[gintctl] dropping %.16s.%.16s\n", - header.application, header.type); - usb_fxlink_drop_transaction(); - USB_LOG("[gintctl] done dropping\n"); - } + while(usb_fxlink_handle_messages(&header)) + gintctl_handle_usb_command(&header); /* Keep waiting only if we were interrupted *and* the interrupt only set bit #31 */ diff --git a/src/usb_commands.c b/src/usb_commands.c new file mode 100644 index 0000000..1045550 --- /dev/null +++ b/src/usb_commands.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include + +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); +}