tillitis-key/hw/application_fpga/apps/loopbackapp/main.c
Daniel Jobson a37f687881 Change license to BSD-2-Clause
This was announced on the Tillitis Blog the 2nd of October 2024, for
more info visit https://tillitis.se
2025-10-30 13:07:59 +01:00

143 lines
3.1 KiB
C

// Copyright (C) 2022, 2023 - Tillitis AB
// SPDX-License-Identifier: BSD-2-Clause
#include <stdbool.h>
#include <stdint.h>
#include <tkey/assert.h>
#include <tkey/io.h>
#include <tkey/led.h>
#include <tkey/lib.h>
#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;
}
}
}