Skip to content

Commit

Permalink
Alternative way of supporting the USB mode protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
mchack-work committed Feb 5, 2025
1 parent a151673 commit c127ef2
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 29 deletions.
8 changes: 2 additions & 6 deletions include/tkey/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ struct frame_header {

uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status, enum cmdlen len);
int parseframe(uint8_t b, struct frame_header *hdr);
void writebyte(uint8_t b);
void write(const uint8_t *buf, size_t nbytes);
uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left);
int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left);

void write(const uint8_t *buf, size_t nbytes, enum mode mode);
int read(uint8_t *buf, size_t bufsize, size_t nbytes, enum mode expect_mode);
#endif
100 changes: 77 additions & 23 deletions libcommon/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@
#include <tkey/proto.h>
#include <tkey/tk1_mem.h>

// USB Mode Protocol:
// 1 byte mode
// 1 byte length
//
// Our USB Mode Protocol packets has room for 255 bytes according to
// the header but we use a packet size of 64 which neatly fits in with
// the USB packet size from the CH552 to the client.
#define USBMODE_PACKET_SIZE 64

// clang-format off
static volatile uint32_t* const can_rx = (volatile uint32_t *)TK1_MMIO_UART_RX_STATUS;
static volatile uint32_t* const rx = (volatile uint32_t *)TK1_MMIO_UART_RX_DATA;
static volatile uint32_t* const can_tx = (volatile uint32_t *)TK1_MMIO_UART_TX_STATUS;
static volatile uint32_t* const tx = (volatile uint32_t *)TK1_MMIO_UART_TX_DATA;
// clang-format on

static void writebyte(uint8_t b);
static uint8_t readbyte(void);

uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status, enum cmdlen len)
{
return (id << 5) | (endpoint << 3) | (status << 2) | len;
Expand Down Expand Up @@ -56,7 +68,7 @@ int parseframe(uint8_t b, struct frame_header *hdr)
return 0;
}

void writebyte(uint8_t b)
static void writebyte(uint8_t b)
{
for (;;) {
if (*can_tx) {
Expand All @@ -66,48 +78,90 @@ void writebyte(uint8_t b)
}
}

void write(const uint8_t *buf, size_t nbytes)
static void write_with_header(const uint8_t *buf, size_t nbytes, enum mode mode)
{
// Append USB Mode Protocol header:
// 1 byte mode
// 1 byte length

writebyte(mode);
writebyte(nbytes);

for (int i = 0; i < nbytes; i++) {
writebyte(buf[i]);
}
}

uint8_t readbyte_(void)
// write blockingly writes nbytes bytes of data from buf to the UART,
// framing the data in USB Mode Protocol with mode mode, either
// MODE_CDC or MODE_HID.
void write(const uint8_t *buf, size_t nbytes, enum mode mode)
{
for (;;) {
if (*can_rx) {
return *rx;
}
while (nbytes > 0) {
// We split the data into chunks that will fit in the
// USB Mode Protocol with some spare change.
uint8_t len = (nbytes < (USBMODE_PACKET_SIZE))
? nbytes
: (USBMODE_PACKET_SIZE);

write_with_header((const uint8_t *)buf, len, mode);

buf += len;
nbytes -= len;
}
}

uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left)
static uint8_t readbyte(void)
{
if (*mode_bytes_left == 0) {
*mode = readbyte_();
if ((*mode == MODE_CDC) || (*mode == MODE_HID) ||
(*mode == MODE_TKEYCTRL)) {
*mode_bytes_left = readbyte_();
} else {
debug_puts("We only support MODE_CDC, MODE_HID and "
"MODE_TKEYCTRL\n");
for (;;) {
if (*can_rx) {
return *rx;
}
}
uint8_t b = readbyte_();
*mode_bytes_left -= 1;
return b;
}

int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left)
// read blockingly reads nbytes bytes of data into buffer buf, a
// maximum bufsize bytes.
//
// Caller asks for the expected USB mode expect_mode: MODE_CDC or
// MODE_HID, which represents different endpoints on the USB
// controller.
//
// If data is readable but with another mode set, it is silently
// discarded and we keep on reading until nbytes bytes have appeared.
//
int read(uint8_t *buf, size_t bufsize, size_t nbytes, enum mode expect_mode)
{
static uint8_t mode = 0;
static uint8_t mode_bytes_left = 0;

if (nbytes > bufsize) {
return -1;
}

for (int n = 0; n < nbytes; n++) {
buf[n] = readbyte(mode, mode_bytes_left);
int n = 0;
while (n < nbytes) {
if (mode_bytes_left == 0) {
// Read USB Mode Protocol header:
// 1 byte mode
// 1 byte length
mode = readbyte();
mode_bytes_left = readbyte();
}

if (mode == expect_mode) {
// Reading payload.
buf[n] = readbyte();
n++;
mode_bytes_left--;
} else {
// Not the USB mode caller asked for. Eat the rest.
for (int i = 0; i < mode_bytes_left; i++) {
(void)readbyte();
}

mode_bytes_left = 0;
}
}

return 0;
Expand Down

0 comments on commit c127ef2

Please sign in to comment.