diff --git a/hw/application_fpga/apps/Makefile b/hw/application_fpga/apps/Makefile index b8ce38c..a43b6cf 100644 --- a/hw/application_fpga/apps/Makefile +++ b/hw/application_fpga/apps/Makefile @@ -41,7 +41,7 @@ LDFLAGS = \ -L $(LIBDIR) -lcrt0 -lcommon -lmonocypher -lblake2s .PHONY: all -all: defaultapp.bin reset_test.bin testapp.bin testloadapp.bin +all: defaultapp.bin loopbackapp.bin reset_test.bin testapp.bin testloadapp.bin # Turn elf into bin for device %.bin: %.elf @@ -66,6 +66,14 @@ DEFAULTAPP_OBJS = \ defaultapp.elf: tkey-libs $(OBJS) $(DEFAULTAPP_OBJS) $(CC) $(CFLAGS) $(OBJS) $(DEFAULTAPP_OBJS) $(LDFLAGS) -o $@ +# loopbackapp + +LOOPBACKAPP_OBJS = \ + $(P)/loopbackapp/main.o + +loopbackapp.elf: tkey-libs $(LOOPBACKAPP_OBJS) + $(CC) $(CFLAGS) $(LOOPBACKAPP_OBJS) $(LDFLAGS) -o $@ + # reset_test RESET_TEST_FMTFILES = *.[ch] @@ -97,6 +105,9 @@ fmt: clang-format --dry-run --ferror-limit=0 defaultapp/*.[ch] clang-format --verbose -i defaultapp/*.[ch] + clang-format --dry-run --ferror-limit=0 loopbackapp/*.[ch] + clang-format --verbose -i loopbackapp/*.[ch] + clang-format --dry-run --ferror-limit=0 reset_test/*.[ch] clang-format --verbose -i reset_test/*.[ch] @@ -110,6 +121,8 @@ fmt: checkfmt: clang-format --dry-run --ferror-limit=0 defaultapp/*.[ch] + clang-format --dry-run --ferror-limit=0 loopbackapp/*.[ch] + clang-format --dry-run --ferror-limit=0 reset_test/*.[ch] clang-format --dry-run --ferror-limit=0 testapp/*.[ch] @@ -118,6 +131,6 @@ checkfmt: .PHONY: clean clean: - rm -f *.elf *.bin $(OBJS) $(DEFAULTAPP_OBJS) $(RESET_TEST_OBJS) \ - $(TESTAPP_OBJS) $(TESTLOADAPP_OBJS) + rm -f *.elf *.bin $(OBJS) $(DEFAULTAPP_OBJS) $(LOOPBACKAPP_OBJS) \ + $(RESET_TEST_OBJS) $(TESTAPP_OBJS) $(TESTLOADAPP_OBJS) diff --git a/hw/application_fpga/apps/loopbackapp/main.c b/hw/application_fpga/apps/loopbackapp/main.c new file mode 100644 index 0000000..0121d0f --- /dev/null +++ b/hw/application_fpga/apps/loopbackapp/main.c @@ -0,0 +1,143 @@ +// Copyright (C) 2022, 2023 - Tillitis AB +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 256 +#define HEADER_SIZE 2 +#define HID_PACKET_SIZE 64 +#define MAX_PAYLOAD_SIZE 64 +#define SLEEPTIME 100000 + +void sleep(uint32_t n) +{ + for (volatile int i = 0; i < n; i++) + ; +} + +int main(void) +{ + uint8_t available = 0; + uint8_t cmdbuf[BUFSIZE] = {0}; + enum ioend endpoint = IO_NONE; + bool waiting_for_more_data = false; + uint8_t dest_endpoint = IO_NONE; + uint8_t payload_length = 0; + uint8_t payload_left = 0; + uint8_t payloadbuf[MAX_PAYLOAD_SIZE] = {0}; + uint8_t first_packet_len = HID_PACKET_SIZE - HEADER_SIZE; + uint8_t endpoints = IO_DEBUG; + led_set(LED_BLUE); + + // Give time to CH552 to settle USB enumeration at power on + sleep(SLEEPTIME * 5); + + // Setup available endpoints + endpoints |= IO_CDC | IO_FIDO; + config_endpoints(endpoints); + + while (1) { + // Wait for data + if (readselect(endpoints, &endpoint, &available) != 0) { + assert(1 == 2); + } + + switch (endpoint) { + case IO_CDC: + cmdbuf[0] = IO_CDC; + cmdbuf[1] = available; + if (read(IO_CDC, cmdbuf + 2, BUFSIZE - 2, available) < + 0) { + assert(1 == 2); + } + write(IO_DEBUG, cmdbuf, available + 2); + memset(cmdbuf, 0, BUFSIZE); + break; + + case IO_FIDO: + cmdbuf[0] = IO_FIDO; + cmdbuf[1] = available; + if (read(IO_FIDO, cmdbuf + 2, BUFSIZE - 2, available) < + 0) { + assert(1 == 2); + } + write(IO_DEBUG, cmdbuf, available + 2); + memset(cmdbuf, 0, BUFSIZE); + break; + + case IO_CCID: + cmdbuf[0] = IO_CCID; + cmdbuf[1] = available; + if (read(IO_CCID, cmdbuf + 2, BUFSIZE - 2, available) < + 0) { + assert(1 == 2); + } + write(IO_DEBUG, cmdbuf, available + 2); + memset(cmdbuf, 0, BUFSIZE); + break; + + case IO_DEBUG: + if (available != HID_PACKET_SIZE) { + led_set(LED_RED); + while (1) + ; + } + + if (read(IO_DEBUG, cmdbuf, BUFSIZE, available) < 0) { + assert(1 == 2); + } + + if (!waiting_for_more_data) { + dest_endpoint = cmdbuf[0]; + payload_length = cmdbuf[1]; + + // Check that destination endpoint is ok + if (dest_endpoint != IO_CDC && + dest_endpoint != IO_FIDO && + dest_endpoint != IO_CCID) { + led_set(LED_RED); + while (1) + ; + } + + // Check payload size + if (payload_length > MAX_PAYLOAD_SIZE) { + led_set(LED_RED); + while (1) + ; + } + + // Complete payload fits in this packet + if (payload_length <= first_packet_len) { + write(dest_endpoint, cmdbuf + 2, + payload_length); + memset(cmdbuf, 0, BUFSIZE); + } else { // More payload will come in next + // packet + memcpy(payloadbuf, cmdbuf + 2, + first_packet_len); + payload_left = + payload_length - first_packet_len; + waiting_for_more_data = true; + } + } else { + memcpy(payloadbuf + first_packet_len, cmdbuf, + payload_left); + write(dest_endpoint, payloadbuf, + payload_length); + memset(payloadbuf, 0, MAX_PAYLOAD_SIZE); + memset(cmdbuf, 0, BUFSIZE); + waiting_for_more_data = false; + } + break; + + default: + break; + } + } +}