summaryrefslogtreecommitdiff
path: root/fw/src
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2021-03-23 19:04:11 +0100
committerjaseg <git@jaseg.de>2021-03-23 19:04:11 +0100
commit32da9c4e8cb2b5252c13b363db7c28675cf60bb5 (patch)
tree24f736687777a0a0aff704ede81ea2d88ba9806d /fw/src
parent88379634a8b07015698811b01f91ae331e1ea57b (diff)
downloadsecure-hid-32da9c4e8cb2b5252c13b363db7c28675cf60bb5.tar.gz
secure-hid-32da9c4e8cb2b5252c13b363db7c28675cf60bb5.tar.bz2
secure-hid-32da9c4e8cb2b5252c13b363db7c28675cf60bb5.zip
Fix up firmware and demos
Diffstat (limited to 'fw/src')
m---------fw/src/crypto/noise-c0
-rw-r--r--fw/src/demo.c102
-rw-r--r--fw/src/noise.c34
-rw-r--r--fw/src/packet_interface.c40
-rw-r--r--fw/src/packet_interface.h2
-rw-r--r--fw/src/rand_stm32.c2
-rw-r--r--fw/src/usbh_lld_stm32f4.c4
-rw-r--r--fw/src/words.c512
8 files changed, 367 insertions, 329 deletions
diff --git a/fw/src/crypto/noise-c b/fw/src/crypto/noise-c
new file mode 160000
+Subproject 604d48fc99b1ae349d4ceb01176a1adf83cb1b3
diff --git a/fw/src/demo.c b/fw/src/demo.c
index 4d6a040..f20e35c 100644
--- a/fw/src/demo.c
+++ b/fw/src/demo.c
@@ -24,8 +24,8 @@
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/timer.h>
-#include <libopencm3/stm32/otg_hs.h>
-#include <libopencm3/stm32/otg_fs.h>
+#include <libopencm3/usb/dwc/otg_hs.h>
+#include <libopencm3/usb/dwc/otg_fs.h>
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/cm3/nvic.h>
@@ -87,15 +87,16 @@ static inline void delay(uint32_t n) {
/* Set STM32 to 168 MHz. */
static void clock_setup(void) {
- rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
+ rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOB);
+ rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_GPIOD);
rcc_periph_clock_enable(RCC_GPIOE);
rcc_periph_clock_enable(RCC_USART1);
- rcc_periph_clock_enable(RCC_USART2);
+ rcc_periph_clock_enable(RCC_UART4);
rcc_periph_clock_enable(RCC_OTGFS);
rcc_periph_clock_enable(RCC_TIM6);
rcc_periph_clock_enable(RCC_DMA2);
@@ -139,7 +140,7 @@ static void finish_interrupted_scrub(void) {
/* setup 10kHz timer */
static void tim6_setup(void) {
- timer_reset(TIM6);
+ rcc_periph_reset_pulse(RST_TIM6);
timer_set_prescaler(TIM6, 8400 - 1); // 84Mhz/10kHz - 1
timer_set_period(TIM6, 65535); // Overflow in ~6.5 seconds
timer_enable_irq(TIM6, TIM_DIER_UIE);
@@ -180,13 +181,16 @@ static void gpio_setup(void)
//gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6 | GPIO7);
//gpio_set(GPIOA, GPIO6 | GPIO7);
- /* Status LEDs (PE4-15) */
- gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 0xfff0);
-
/* Alarm LEDs (PA6,7) */
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6 | GPIO7);
gpio_set(GPIOA, GPIO6 | GPIO7);
+ /* Mode LEDs */
+ gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO13 | GPIO14);
+
+ /* Mode button */
+ gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO15);
+
/* Speaker */
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO10);
gpio_set(GPIOB, GPIO10);
@@ -199,12 +203,9 @@ static void gpio_setup(void)
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO10);
gpio_set_af(GPIOA, GPIO_AF7, GPIO9 | GPIO10);
- /* USART2 (host link) */
- gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
- gpio_set_af(GPIOA, GPIO_AF7, GPIO2 | GPIO3);
-
- /* K0 (PE4)/K1 (PE3) buttons */
- //gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO3 | GPIO4);
+ /* UART4 (host link) */
+ gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO10 | GPIO11);
+ gpio_set_af(GPIOC, GPIO_AF8, GPIO10 | GPIO11);
}
struct hid_report {
@@ -221,7 +222,7 @@ void pairing_input(uint8_t modbyte, uint8_t keycode);
void pairing_parse_report(struct hid_report *buf, uint8_t len);
/* Minimum number of bytes of handshake hash to confirm during pairing */
-#define MIN_PAIRING_SEQUENCE_LENGTH 8
+#define MIN_PAIRING_SEQUENCE_LENGTH 4
int pairing_check(struct NoiseState *st, const char *buf) {
//LOG_PRINTF("Checking pairing\n");
@@ -491,10 +492,10 @@ void DMA_ISR(DEBUG_USART_DMA_NUM, DEBUG_USART_DMA_STREAM_NUM)(void) {
/*@ requires \valid_read(&pkt->type) && \valid_read(pkt->payload + (0..payload_length-1));
requires \valid(st);
requires \valid(st->handshake);
- requires \separated(st, st->rx_cipher, st->tx_cipher, st->handshake, (uint8_t *)pkt->payload, &usart2_out, &st->handshake_hash);
- requires \valid(usart2_out);
+ requires \separated(st, st->rx_cipher, st->tx_cipher, st->handshake, (uint8_t *)pkt->payload, &uart4_out, &st->handshake_hash);
+ requires \valid(uart4_out);
- assigns pairing_buf_pos, *usart2_out, *st;
+ assigns pairing_buf_pos, *uart4_out, *st;
assigns st->handshake, st->handshake_state, st->rx_cipher, st->tx_cipher;
@*/
@@ -515,7 +516,7 @@ void handle_host_packet(struct NoiseState *st, const struct control_packet *pkt,
} else {
LOG_PRINTF("Too many failed handshake attempts, not starting another one\n");
struct control_packet out = { .type=HOST_TOO_MANY_FAILS };
- send_packet(usart2_out, (uint8_t *)&out, sizeof(out));
+ send_packet(uart4_out, (uint8_t *)&out, sizeof(out));
}
} else if (pkt->type == HOST_HANDSHAKE) {
@@ -525,7 +526,7 @@ void handle_host_packet(struct NoiseState *st, const struct control_packet *pkt,
TRACING_CLEAR(TR_NOISE_HANDSHAKE);
LOG_PRINTF("Reporting handshake error to host\n");
struct control_packet out = { .type=HOST_CRYPTO_ERROR };
- send_packet(usart2_out, (uint8_t *)&out, sizeof(out));
+ send_packet(uart4_out, (uint8_t *)&out, sizeof(out));
} else TRACING_CLEAR(TR_NOISE_HANDSHAKE);
} else {
@@ -555,10 +556,10 @@ int main(void)
/* end unsafe debug code */
#endif
- usart_dma_init(usart2_out);
- usart_enable_rx_interrupt(USART2);
- nvic_enable_irq(NVIC_USART2_IRQ);
- nvic_set_priority(NVIC_USART2_IRQ, 3<<4);
+ usart_dma_init(uart4_out);
+ usart_enable_rx_interrupt(UART4);
+ nvic_enable_irq(NVIC_UART4_IRQ);
+ nvic_set_priority(NVIC_UART4_IRQ, 3<<4);
nvic_set_priority(debug_out_s.irqn, 1<<4);
LOG_PRINTF("\n==================================\n");
@@ -602,20 +603,52 @@ int main(void)
gpio_clear(GPIOA, GPIO6);
gpio_clear(GPIOA, GPIO7);
gpio_clear(GPIOB, GPIO10);
+
+ int last_btn_st = 0;
+ int debounce_ctr = 0;
+ int mode_debug = 0;
+#define DEBOUNCE_IVL 1000
+ gpio_set(GPIOE, GPIO13);
+ gpio_clear(GPIOE, GPIO14);
+
while (23) {
delay(1);
+ if (debounce_ctr > 0) {
+ debounce_ctr -= 1;
+
+ } else {
+ if (gpio_get(GPIOE, GPIO15)) {
+ if (!last_btn_st) {
+ debounce_ctr = DEBOUNCE_IVL;
+
+ mode_debug = !mode_debug;
+
+ if (mode_debug) {
+ gpio_clear(GPIOE, GPIO13);
+ gpio_set(GPIOE, GPIO14);
+
+ } else {
+ gpio_set(GPIOE, GPIO13);
+ gpio_clear(GPIOE, GPIO14);
+ }
+ }
+
+ last_btn_st = 1;
+
+ } else {
+ last_btn_st = 0;
+ }
+ }
+
+ /*
led_ctr++;
if (led_ctr == 10) {
gpio_clear(GPIOA, GPIO6);
gpio_clear(GPIOA, GPIO7);
- } else if (led_ctr == 300) {
- gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 0xfff0);
} else if (led_ctr == 400) {
if (++led_idx == 12)
led_idx = 0;
- gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1<<(4+led_idx));
- gpio_clear(GPIOE, 0xfff0);
if (led_idx & 1)
gpio_set(GPIOA, GPIO6);
else
@@ -638,7 +671,7 @@ int main(void)
} else {
gpio_clear(GPIOB, GPIO10);
}
- continue;
+ */
if (++poll_ctr == 10) {
poll_ctr = 0;
@@ -652,12 +685,13 @@ int main(void)
host_packet_length = 0; /* Acknowledge to USART ISR the buffer has been handled */
} else if (host_packet_length < 0) { /* USART error */
+ ssize_t err = host_packet_length;
host_packet_length = 0; /* Acknowledge to USART ISR the error has been handled */
if (noise_state.handshake_state < HANDSHAKE_DONE_UNKNOWN_HOST) {
- LOG_PRINTF("USART error, aborting handshake\n");
+ LOG_PRINTF("USART error, aborting handshake: %zd\n", err);
struct control_packet pkt = { .type=HOST_COMM_ERROR };
- send_packet(usart2_out, (uint8_t *)&pkt, sizeof(pkt));
+ send_packet(uart4_out, (uint8_t *)&pkt, sizeof(pkt));
if (reset_protocol_handshake(&noise_state))
LOG_PRINTF("Error starting protocol handshake.\n");
@@ -666,15 +700,17 @@ int main(void)
}
}
- if (noise_state.handshake_state == HANDSHAKE_IN_PROGRESS) {
+#if 0
+ if (noise_state.handshake_state == HANDSHAKE_PHASE1 || noise_state.handshake_state == HANDSHAKE_PHASE2) {
TRACING_SET(TR_NOISE_HANDSHAKE);
if (try_continue_noise_handshake(&noise_state, NULL, 0)) { /* handle outgoing messages */
TRACING_CLEAR(TR_NOISE_HANDSHAKE);
LOG_PRINTF("Reporting handshake error to host\n");
struct control_packet pkt = { .type=HOST_CRYPTO_ERROR };
- send_packet(usart2_out, (uint8_t *)&pkt, sizeof(pkt));
+ send_packet(uart4_out, (uint8_t *)&pkt, sizeof(pkt));
} else TRACING_CLEAR(TR_NOISE_HANDSHAKE);
}
+#endif
}
}
diff --git a/fw/src/noise.c b/fw/src/noise.c
index bd0974c..90aaf36 100644
--- a/fw/src/noise.c
+++ b/fw/src/noise.c
@@ -192,15 +192,15 @@ void uninit_handshake(struct NoiseState *st, enum handshake_state new_state) {
}
/*@
- requires validity: \valid(st) && \valid(usart2_out) && \valid(st->handshake);
+ requires validity: \valid(st) && \valid(uart4_out) && \valid(st->handshake);
requires validity: \valid(st->remote_key + (0..sizeof(st->remote_key)-1));
requires validity: \valid(st->handshake_hash + (0..sizeof(st->handshake_hash)-1));
- requires separation: \separated(usart2_out, st, buf, st->handshake);
+ requires separation: \separated(uart4_out, st, buf, st->handshake);
ensures \result \in {-1, 0};
- assigns *usart2_out, *st->handshake;
+ assigns *uart4_out, *st->handshake;
@*/
int handshake_phase1(struct NoiseState * const st, uint8_t *buf, size_t len) {
int err;
@@ -218,7 +218,7 @@ int handshake_phase1(struct NoiseState * const st, uint8_t *buf, size_t len) {
pkt.header.type = HOST_HANDSHAKE;
noise_buffer_set_output(noise_msg, &pkt.payload, sizeof(pkt.payload));
HANDLE_NOISE_ERROR(noise_handshakestate_write_message(st->handshake, &noise_msg, NULL), "writing handshake message");
- send_packet(usart2_out, (uint8_t *)&pkt, noise_msg.size + sizeof(pkt.header));
+ send_packet(uart4_out, (uint8_t *)&pkt, noise_msg.size + sizeof(pkt.header));
return 0;
errout: /* for HANDLE_NOISE_ERROR macro */
@@ -228,14 +228,14 @@ errout: /* for HANDLE_NOISE_ERROR macro */
//@ ghost int key_checked_trace;
//@ ghost int key_match_trace;
/*@
- requires validity: \valid(st) && \valid(usart2_out) && \valid(st->handshake);
+ requires validity: \valid(st) && \valid(uart4_out) && \valid(st->handshake);
requires validity: \valid(st->remote_key + (0..sizeof(st->remote_key)-1));
requires validity: \valid_read(st->remote_key_reference + (0..sizeof(st->remote_key)-1));
requires validity: \valid(st->handshake_hash + (0..sizeof(st->handshake_hash)-1));
- requires separation: \separated(usart2_out, st);
+ requires separation: \separated(uart4_out, st);
requires sanity: 0 <= st->failed_handshakes < 100;
- requires separation: \separated(&usart2_out, st, buf, st->handshake);
+ requires separation: \separated(&uart4_out, st, buf, st->handshake);
ensures result: \result \in {-1, 0, 1};
ensures sanity: 0 <= st->failed_handshakes <= 102;
@@ -244,7 +244,7 @@ errout: /* for HANDLE_NOISE_ERROR macro */
ensures permission_valid: \result != -1 ==> key_checked_trace == 1;
ensures permission_valid: \result == 1 ==> key_match_trace == 1;
//
- assigns *usart2_out, *st, *st->handshake, key_checked_trace, key_match_trace;
+ assigns *uart4_out, *st, *st->handshake, key_checked_trace, key_match_trace;
@*/
int handshake_phase2(struct NoiseState * const st, uint8_t *buf, size_t len) {
//@ ghost int old_failed_handshakes = st->failed_handshakes;
@@ -288,7 +288,7 @@ int handshake_phase2(struct NoiseState * const st, uint8_t *buf, size_t len) {
uint8_t remote_fp[BLAKE2S_HASH_SIZE];
BLAKE2s_context_t bc;
BLAKE2s_reset(&bc);
- fc_BLAKE2s_update_uint8(&bc, st->remote_key, sizeof(st->remote_key));
+ BLAKE2s_update(&bc, st->remote_key, sizeof(st->remote_key));
BLAKE2s_finish(&bc, remote_fp);
//@ ghost key_checked_trace = 1;
@@ -319,13 +319,13 @@ errout:
return -1;
}
/*@
- requires validity: \valid(st) && \valid(usart2_out) && \valid(st->handshake);
+ requires validity: \valid(st) && \valid(uart4_out) && \valid(st->handshake);
requires validity: \valid(st->remote_key + (0..sizeof(st->remote_key)-1));
requires validity: \valid(st->remote_key_reference + (0..sizeof(st->remote_key)-1));
requires validity: \valid(st->handshake_hash + (0..sizeof(st->handshake_hash)-1));
requires sanity: 0 <= st->failed_handshakes < 100;
- requires separation: \separated(usart2_out, st, buf, st->handshake);
+ requires separation: \separated(uart4_out, st, buf, st->handshake);
ensures result: \result \in {0, -1};
@@ -343,7 +343,7 @@ errout:
ensures state_advance_condition: (st->handshake_state == HANDSHAKE_DONE_KNOWN_HOST) ==> key_match_trace == 1;
- //assigns *usart2_out, *st, *st->rx_cipher, *st->tx_cipher, *st->handshake;
+ //assigns *uart4_out, *st, *st->rx_cipher, *st->tx_cipher, *st->handshake;
//assigns key_checked_trace, key_match_trace;
@*/
int try_continue_noise_handshake(struct NoiseState * const st, uint8_t *buf, size_t len) {
@@ -400,18 +400,18 @@ errout:
void persist_remote_key(struct NoiseState *st) {
BLAKE2s_context_t bc;
BLAKE2s_reset(&bc);
- fc_BLAKE2s_update_uint8(&bc, st->remote_key, sizeof(st->remote_key));
+ BLAKE2s_update(&bc, st->remote_key, sizeof(st->remote_key));
BLAKE2s_finish(&bc, st->remote_key_reference);
st->handshake_state = HANDSHAKE_DONE_KNOWN_HOST;
}
/*@
- requires validity: \valid(st) && \valid(usart2_out) && \valid(st->tx_cipher) && \valid_read(msg + (0..len-1));
- requires separation: \separated(usart2_out, st);
+ requires validity: \valid(st) && \valid(uart4_out) && \valid(st->tx_cipher) && \valid_read(msg + (0..len-1));
+ requires separation: \separated(uart4_out, st);
ensures length: !(0 <= len <= MAX_HOST_PACKET_SIZE) <==> \result == -3;
ensures \result \in {0, -1, -2, -3};
- assigns *st->tx_cipher, *usart2_out;
+ assigns *st->tx_cipher, *uart4_out;
*/
int send_encrypted_message(struct NoiseState *st, const uint8_t *msg, size_t len) {
int err;
@@ -436,7 +436,7 @@ int send_encrypted_message(struct NoiseState *st, const uint8_t *msg, size_t len
noise_buffer_set_inout(noise_buf, pkt.payload, len, sizeof(pkt.payload));
HANDLE_NOISE_ERROR(noise_cipherstate_encrypt(st->tx_cipher, &noise_buf), "encrypting data");
- send_packet(usart2_out, (uint8_t *)&pkt, noise_buf.size + sizeof(pkt.header));
+ send_packet(uart4_out, (uint8_t *)&pkt, noise_buf.size + sizeof(pkt.header));
return 0;
errout:
diff --git a/fw/src/packet_interface.c b/fw/src/packet_interface.c
index 98a1ef2..c6c54cb 100644
--- a/fw/src/packet_interface.c
+++ b/fw/src/packet_interface.c
@@ -12,54 +12,54 @@
volatile struct {
struct dma_buf dma;
uint8_t data[256];
-} usart2_buf = { .dma = { .len = sizeof(usart2_buf.data) } };
+} uart4_buf = { .dma = { .len = sizeof(uart4_buf.data) } };
-struct dma_usart_file usart2_out_s = {
- .usart = USART2,
+struct dma_usart_file uart4_out_s = {
+ .usart = UART4,
.baudrate = 115200,
.dma = DMA1,
- .stream = 6,
+ .stream = 4,
.channel = 4,
- .irqn = NVIC_DMA_IRQ(1, 6),
- .buf = &usart2_buf.dma
+ .irqn = NVIC_DMA_IRQ(1, 4),
+ .buf = &uart4_buf.dma
};
-struct dma_usart_file *usart2_out = &usart2_out_s;
+struct dma_usart_file *uart4_out = &uart4_out_s;
-void dma1_stream6_isr(void) {
+void dma1_stream4_isr(void) {
TRACING_SET(TR_HOST_IF_DMA_IRQ);
static unsigned int fifo_errors = 0; /* debug */
- if (dma_get_interrupt_flag(usart2_out->dma, usart2_out->stream, DMA_FEIF)) {
+ if (dma_get_interrupt_flag(uart4_out->dma, uart4_out->stream, DMA_FEIF)) {
/* Ignore FIFO errors as they're 100% non-critical for UART applications */
- dma_clear_interrupt_flags(usart2_out->dma, usart2_out->stream, DMA_FEIF);
+ dma_clear_interrupt_flags(uart4_out->dma, uart4_out->stream, DMA_FEIF);
fifo_errors++;
TRACING_CLEAR(TR_HOST_IF_DMA_IRQ);
return;
}
/* Transfer complete interrupt */
- dma_clear_interrupt_flags(usart2_out->dma, usart2_out->stream, DMA_TCIF);
+ dma_clear_interrupt_flags(uart4_out->dma, uart4_out->stream, DMA_TCIF);
- if (usart2_out->buf->wr_pos != usart2_out->buf->xfr_end) /* buffer not empty */
- schedule_dma(usart2_out);
+ if (uart4_out->buf->wr_pos != uart4_out->buf->xfr_end) /* buffer not empty */
+ schedule_dma(uart4_out);
TRACING_CLEAR(TR_HOST_IF_DMA_IRQ);
}
-void usart2_isr(void) {
+void uart4_isr(void) {
TRACING_SET(TR_HOST_IF_USART_IRQ);
static struct cobs_decode_state host_cobs_state = {0};
- if (USART2_SR & USART_SR_ORE) { /* Overrun handling */
- LOG_PRINTF("USART2 data register overrun\n");
+ if (UART4_SR & USART_SR_ORE) { /* Overrun handling */
+ LOG_PRINTF("UART4 data register overrun\n");
/* Clear interrupt flag */
- (void)USART2_DR; /* FIXME make sure this read is not optimized out */
+ (void)UART4_DR; /* FIXME make sure this read is not optimized out */
host_packet_length = -1;
TRACING_CLEAR(TR_HOST_IF_USART_IRQ);
return;
}
- uint8_t data = USART2_DR; /* This automatically acknowledges the IRQ */
+ uint8_t data = UART4_DR; /* This automatically acknowledges the IRQ */
if (host_packet_length) {
- LOG_PRINTF("USART2 COBS buffer overrun\n");
+ LOG_PRINTF("UART4 COBS buffer overrun\n");
host_packet_length = -1;
TRACING_CLEAR(TR_HOST_IF_USART_IRQ);
return;
@@ -78,7 +78,7 @@ void usart2_isr(void) {
} else if (rv == -3) {
/* invalid empty frame */
LOG_PRINTF("Got double null byte from host\n");
- host_packet_length = -1;
+ /* FIXME DEBUG host_packet_length = -1; */
} else if (rv == -4) {
/* frame too large */
LOG_PRINTF("Got too large frame from host\n");
diff --git a/fw/src/packet_interface.h b/fw/src/packet_interface.h
index 35e9758..2f60f9f 100644
--- a/fw/src/packet_interface.h
+++ b/fw/src/packet_interface.h
@@ -4,7 +4,7 @@
#include "usart_helpers.h"
-extern struct dma_usart_file *usart2_out;
+extern struct dma_usart_file *uart4_out;
enum control_packet_types {
_HOST_RESERVED = 0,
diff --git a/fw/src/rand_stm32.c b/fw/src/rand_stm32.c
index 87bea8f..dcb634a 100644
--- a/fw/src/rand_stm32.c
+++ b/fw/src/rand_stm32.c
@@ -38,6 +38,8 @@
#include <stdlib.h>
#include <string.h>
+#include <usbh_core.h>
+
#include <libopencm3/stm32/f4/rng.h>
#include "usart_helpers.h"
diff --git a/fw/src/usbh_lld_stm32f4.c b/fw/src/usbh_lld_stm32f4.c
index 3fcd51a..20fd0d8 100644
--- a/fw/src/usbh_lld_stm32f4.c
+++ b/fw/src/usbh_lld_stm32f4.c
@@ -26,8 +26,8 @@
#include <string.h>
#include <stdint.h>
-#include <libopencm3/stm32/otg_hs.h>
-#include <libopencm3/stm32/otg_fs.h>
+#include <libopencm3/usb/dwc/otg_hs.h>
+#include <libopencm3/usb/dwc/otg_fs.h>
diff --git a/fw/src/words.c b/fw/src/words.c
index 387d23b..7f2f6d2 100644
--- a/fw/src/words.c
+++ b/fw/src/words.c
@@ -261,261 +261,261 @@ const char * const even[256] = {
};
const char * const odd[256] = {
- "aardvark", /* 00 */
- "absurd", /* 01 */
- "accrue", /* 02 */
- "acme", /* 03 */
- "adrift", /* 04 */
- "adult", /* 05 */
- "afflict", /* 06 */
- "ahead", /* 07 */
- "aimless", /* 08 */
- "Algol", /* 09 */
- "allow", /* 0A */
- "alone", /* 0B */
- "ammo", /* 0C */
- "ancient", /* 0D */
- "apple", /* 0E */
- "artist", /* 0F */
- "assume", /* 10 */
- "Athens", /* 11 */
- "atlas", /* 12 */
- "Aztec", /* 13 */
- "baboon", /* 14 */
- "backfield", /* 15 */
- "backward", /* 16 */
- "banjo", /* 17 */
- "beaming", /* 18 */
- "bedlamp", /* 19 */
- "beehive", /* 1A */
- "beeswax", /* 1B */
- "befriend", /* 1C */
- "Belfast", /* 1D */
- "berserk", /* 1E */
- "billiard", /* 1F */
- "bison", /* 20 */
- "blackjack", /* 21 */
- "blockade", /* 22 */
- "blowtorch", /* 23 */
- "bluebird", /* 24 */
- "bombast", /* 25 */
- "bookshelf", /* 26 */
- "brackish", /* 27 */
- "breadline", /* 28 */
- "breakup", /* 29 */
- "brickyard", /* 2A */
- "briefcase", /* 2B */
- "Burbank", /* 2C */
- "button", /* 2D */
- "buzzard", /* 2E */
- "cement", /* 2F */
- "chairlift", /* 30 */
- "chatter", /* 31 */
- "checkup", /* 32 */
- "chisel", /* 33 */
- "choking", /* 34 */
- "chopper", /* 35 */
- "Christmas", /* 36 */
- "clamshell", /* 37 */
- "classic", /* 38 */
- "classroom", /* 39 */
- "cleanup", /* 3A */
- "clockwork", /* 3B */
- "cobra", /* 3C */
- "commence", /* 3D */
- "concert", /* 3E */
- "cowbell", /* 3F */
- "crackdown", /* 40 */
- "cranky", /* 41 */
- "crowfoot", /* 42 */
- "crucial", /* 43 */
- "crumpled", /* 44 */
- "crusade", /* 45 */
- "cubic", /* 46 */
- "dashboard", /* 47 */
- "deadbolt", /* 48 */
- "deckhand", /* 49 */
- "dogsled", /* 4A */
- "dragnet", /* 4B */
- "drainage", /* 4C */
- "dreadful", /* 4D */
- "drifter", /* 4E */
- "dropper", /* 4F */
- "drumbeat", /* 50 */
- "drunken", /* 51 */
- "Dupont", /* 52 */
- "dwelling", /* 53 */
- "eating", /* 54 */
- "edict", /* 55 */
- "egghead", /* 56 */
- "eightball", /* 57 */
- "endorse", /* 58 */
- "endow", /* 59 */
- "enlist", /* 5A */
- "erase", /* 5B */
- "escape", /* 5C */
- "exceed", /* 5D */
- "eyeglass", /* 5E */
- "eyetooth", /* 5F */
- "facial", /* 60 */
- "fallout", /* 61 */
- "flagpole", /* 62 */
- "flatfoot", /* 63 */
- "flytrap", /* 64 */
- "fracture", /* 65 */
- "framework", /* 66 */
- "freedom", /* 67 */
- "frighten", /* 68 */
- "gazelle", /* 69 */
- "Geiger", /* 6A */
- "glitter", /* 6B */
- "glucose", /* 6C */
- "goggles", /* 6D */
- "goldfish", /* 6E */
- "gremlin", /* 6F */
- "guidance", /* 70 */
- "hamlet", /* 71 */
- "highchair", /* 72 */
- "hockey", /* 73 */
- "indoors", /* 74 */
- "indulge", /* 75 */
- "inverse", /* 76 */
- "involve", /* 77 */
- "island", /* 78 */
- "jawbone", /* 79 */
- "keyboard", /* 7A */
- "kickoff", /* 7B */
- "kiwi", /* 7C */
- "klaxon", /* 7D */
- "locale", /* 7E */
- "lockup", /* 7F */
- "merit", /* 80 */
- "minnow", /* 81 */
- "miser", /* 82 */
- "Mohawk", /* 83 */
- "mural", /* 84 */
- "music", /* 85 */
- "necklace", /* 86 */
- "Neptune", /* 87 */
- "newborn", /* 88 */
- "nightbird", /* 89 */
- "Oakland", /* 8A */
- "obtuse", /* 8B */
- "offload", /* 8C */
- "optic", /* 8D */
- "orca", /* 8E */
- "payday", /* 8F */
- "peachy", /* 90 */
- "pheasant", /* 91 */
- "physique", /* 92 */
- "playhouse", /* 93 */
- "Pluto", /* 94 */
- "preclude", /* 95 */
- "prefer", /* 96 */
- "preshrunk", /* 97 */
- "printer", /* 98 */
- "prowler", /* 99 */
- "pupil", /* 9A */
- "puppy", /* 9B */
- "python", /* 9C */
- "quadrant", /* 9D */
- "quiver", /* 9E */
- "quota", /* 9F */
- "ragtime", /* A0 */
- "ratchet", /* A1 */
- "rebirth", /* A2 */
- "reform", /* A3 */
- "regain", /* A4 */
- "reindeer", /* A5 */
- "rematch", /* A6 */
- "repay", /* A7 */
- "retouch", /* A8 */
- "revenge", /* A9 */
- "reward", /* AA */
- "rhythm", /* AB */
- "ribcage", /* AC */
- "ringbolt", /* AD */
- "robust", /* AE */
- "rocker", /* AF */
- "ruffled", /* B0 */
- "sailboat", /* B1 */
- "sawdust", /* B2 */
- "scallion", /* B3 */
- "scenic", /* B4 */
- "scorecard", /* B5 */
- "Scotland", /* B6 */
- "seabird", /* B7 */
- "select", /* B8 */
- "sentence", /* B9 */
- "shadow", /* BA */
- "shamrock", /* BB */
- "showgirl", /* BC */
- "skullcap", /* BD */
- "skydive", /* BE */
- "slingshot", /* BF */
- "slowdown", /* C0 */
- "snapline", /* C1 */
- "snapshot", /* C2 */
- "snowcap", /* C3 */
- "snowslide", /* C4 */
- "solo", /* C5 */
- "southward", /* C6 */
- "soybean", /* C7 */
- "spaniel", /* C8 */
- "spearhead", /* C9 */
- "spellbind", /* CA */
- "spheroid", /* CB */
- "spigot", /* CC */
- "spindle", /* CD */
- "spyglass", /* CE */
- "stagehand", /* CF */
- "stagnate", /* D0 */
- "stairway", /* D1 */
- "standard", /* D2 */
- "stapler", /* D3 */
- "steamship", /* D4 */
- "sterling", /* D5 */
- "stockman", /* D6 */
- "stopwatch", /* D7 */
- "stormy", /* D8 */
- "sugar", /* D9 */
- "surmount", /* DA */
- "suspense", /* DB */
- "sweatband", /* DC */
- "swelter", /* DD */
- "tactics", /* DE */
- "talon", /* DF */
- "tapeworm", /* E0 */
- "tempest", /* E1 */
- "tiger", /* E2 */
- "tissue", /* E3 */
- "tonic", /* E4 */
- "topmost", /* E5 */
- "tracker", /* E6 */
- "transit", /* E7 */
- "trauma", /* E8 */
- "treadmill", /* E9 */
- "Trojan", /* EA */
- "trouble", /* EB */
- "tumor", /* EC */
- "tunnel", /* ED */
- "tycoon", /* EE */
- "uncut", /* EF */
- "unearth", /* F0 */
- "unwind", /* F1 */
- "uproot", /* F2 */
- "upset", /* F3 */
- "upshot", /* F4 */
- "vapor", /* F5 */
- "village", /* F6 */
- "virus", /* F7 */
- "Vulcan", /* F8 */
- "waffle", /* F9 */
- "wallet", /* FA */
- "watchword", /* FB */
- "wayside", /* FC */
- "willow", /* FD */
- "woodlark", /* FE */
- "Zulu", /* FF */
+ "adroitness", /* 00 */
+ "adviser", /* 01 */
+ "aftermath", /* 02 */
+ "aggregate", /* 03 */
+ "alkali", /* 04 */
+ "almighty", /* 05 */
+ "amulet", /* 06 */
+ "amusement", /* 07 */
+ "antenna", /* 08 */
+ "applicant", /* 09 */
+ "Apollo", /* 0A */
+ "armistice", /* 0B */
+ "article", /* 0C */
+ "asteroid", /* 0D */
+ "Atlantic", /* 0E */
+ "atmosphere", /* 0F */
+ "autopsy", /* 10 */
+ "Babylon", /* 11 */
+ "backwater", /* 12 */
+ "barbecue", /* 13 */
+ "belowground", /* 14 */
+ "bifocals", /* 15 */
+ "bodyguard", /* 16 */
+ "bookseller", /* 17 */
+ "borderline", /* 18 */
+ "bottomless", /* 19 */
+ "Bradbury", /* 1A */
+ "bravado", /* 1B */
+ "Brazilian", /* 1C */
+ "breakaway", /* 1D */
+ "Burlington", /* 1E */
+ "businessman", /* 1F */
+ "butterfat", /* 20 */
+ "Camelot", /* 21 */
+ "candidate", /* 22 */
+ "cannonball", /* 23 */
+ "Capricorn", /* 24 */
+ "caravan", /* 25 */
+ "caretaker", /* 26 */
+ "celebrate", /* 27 */
+ "cellulose", /* 28 */
+ "certify", /* 29 */
+ "chambermaid", /* 2A */
+ "Cherokee", /* 2B */
+ "Chicago", /* 2C */
+ "clergyman", /* 2D */
+ "coherence", /* 2E */
+ "combustion", /* 2F */
+ "commando", /* 30 */
+ "company", /* 31 */
+ "component", /* 32 */
+ "concurrent", /* 33 */
+ "confidence", /* 34 */
+ "conformist", /* 35 */
+ "congregate", /* 36 */
+ "consensus", /* 37 */
+ "consulting", /* 38 */
+ "corporate", /* 39 */
+ "corrosion", /* 3A */
+ "councilman", /* 3B */
+ "crossover", /* 3C */
+ "crucifix", /* 3D */
+ "cumbersome", /* 3E */
+ "customer", /* 3F */
+ "Dakota", /* 40 */
+ "decadence", /* 41 */
+ "December", /* 42 */
+ "decimal", /* 43 */
+ "designing", /* 44 */
+ "detector", /* 45 */
+ "detergent", /* 46 */
+ "determine", /* 47 */
+ "dictator", /* 48 */
+ "dinosaur", /* 49 */
+ "direction", /* 4A */
+ "disable", /* 4B */
+ "disbelief", /* 4C */
+ "disruptive", /* 4D */
+ "distortion", /* 4E */
+ "document", /* 4F */
+ "embezzle", /* 50 */
+ "enchanting", /* 51 */
+ "enrollment", /* 52 */
+ "enterprise", /* 53 */
+ "equation", /* 54 */
+ "equipment", /* 55 */
+ "escapade", /* 56 */
+ "Eskimo", /* 57 */
+ "everyday", /* 58 */
+ "examine", /* 59 */
+ "existence", /* 5A */
+ "exodus", /* 5B */
+ "fascinate", /* 5C */
+ "filament", /* 5D */
+ "finicky", /* 5E */
+ "forever", /* 5F */
+ "fortitude", /* 60 */
+ "frequency", /* 61 */
+ "gadgetry", /* 62 */
+ "Galveston", /* 63 */
+ "getaway", /* 64 */
+ "glossary", /* 65 */
+ "gossamer", /* 66 */
+ "graduate", /* 67 */
+ "gravity", /* 68 */
+ "guitarist", /* 69 */
+ "hamburger", /* 6A */
+ "Hamilton", /* 6B */
+ "handiwork", /* 6C */
+ "hazardous", /* 6D */
+ "headwaters", /* 6E */
+ "hemisphere", /* 6F */
+ "hesitate", /* 70 */
+ "hideaway", /* 71 */
+ "holiness", /* 72 */
+ "hurricane", /* 73 */
+ "hydraulic", /* 74 */
+ "impartial", /* 75 */
+ "impetus", /* 76 */
+ "inception", /* 77 */
+ "indigo", /* 78 */
+ "inertia", /* 79 */
+ "infancy", /* 7A */
+ "inferno", /* 7B */
+ "informant", /* 7C */
+ "insincere", /* 7D */
+ "insurgent", /* 7E */
+ "integrate", /* 7F */
+ "intention", /* 80 */
+ "inventive", /* 81 */
+ "Istanbul", /* 82 */
+ "Jamaica", /* 83 */
+ "Jupiter", /* 84 */
+ "leprosy", /* 85 */
+ "letterhead", /* 86 */
+ "liberty", /* 87 */
+ "maritime", /* 88 */
+ "matchmaker", /* 89 */
+ "maverick", /* 8A */
+ "Medusa", /* 8B */
+ "megaton", /* 8C */
+ "microscope", /* 8D */
+ "microwave", /* 8E */
+ "midsummer", /* 8F */
+ "millionaire", /* 90 */
+ "miracle", /* 91 */
+ "misnomer", /* 92 */
+ "molasses", /* 93 */
+ "molecule", /* 94 */
+ "Montana", /* 95 */
+ "monument", /* 96 */
+ "mosquito", /* 97 */
+ "narrative", /* 98 */
+ "nebula", /* 99 */
+ "newsletter", /* 9A */
+ "Norwegian", /* 9B */
+ "October", /* 9C */
+ "Ohio", /* 9D */
+ "onlooker", /* 9E */
+ "opulent", /* 9F */
+ "Orlando", /* A0 */
+ "outfielder", /* A1 */
+ "Pacific", /* A2 */
+ "pandemic", /* A3 */
+ "Pandora", /* A4 */
+ "paperweight", /* A5 */
+ "paragon", /* A6 */
+ "paragraph", /* A7 */
+ "paramount", /* A8 */
+ "passenger", /* A9 */
+ "pedigree", /* AA */
+ "Pegasus", /* AB */
+ "penetrate", /* AC */
+ "perceptive", /* AD */
+ "performance", /* AE */
+ "pharmacy", /* AF */
+ "phonetic", /* B0 */
+ "photograph", /* B1 */
+ "pioneer", /* B2 */
+ "pocketful", /* B3 */
+ "politeness", /* B4 */
+ "positive", /* B5 */
+ "potato", /* B6 */
+ "processor", /* B7 */
+ "provincial", /* B8 */
+ "proximate", /* B9 */
+ "puberty", /* BA */
+ "publisher", /* BB */
+ "pyramid", /* BC */
+ "quantity", /* BD */
+ "racketeer", /* BE */
+ "rebellion", /* BF */
+ "recipe", /* C0 */
+ "recover", /* C1 */
+ "repellent", /* C2 */
+ "replica", /* C3 */
+ "reproduce", /* C4 */
+ "resistor", /* C5 */
+ "responsive", /* C6 */
+ "retraction", /* C7 */
+ "retrieval", /* C8 */
+ "retrospect", /* C9 */
+ "revenue", /* CA */
+ "revival", /* CB */
+ "revolver", /* CC */
+ "sandalwood", /* CD */
+ "sardonic", /* CE */
+ "Saturday", /* CF */
+ "savagery", /* D0 */
+ "scavenger", /* D1 */
+ "sensation", /* D2 */
+ "sociable", /* D3 */
+ "souvenir", /* D4 */
+ "specialist", /* D5 */
+ "speculate", /* D6 */
+ "stethoscope", /* D7 */
+ "stupendous", /* D8 */
+ "supportive", /* D9 */
+ "surrender", /* DA */
+ "suspicious", /* DB */
+ "sympathy", /* DC */
+ "tambourine", /* DD */
+ "telephone", /* DE */
+ "therapist", /* DF */
+ "tobacco", /* E0 */
+ "tolerance", /* E1 */
+ "tomorrow", /* E2 */
+ "torpedo", /* E3 */
+ "tradition", /* E4 */
+ "travesty", /* E5 */
+ "trombonist", /* E6 */
+ "truncated", /* E7 */
+ "typewriter", /* E8 */
+ "ultimate", /* E9 */
+ "undaunted", /* EA */
+ "underfoot", /* EB */
+ "unicorn", /* EC */
+ "unify", /* ED */
+ "universe", /* EE */
+ "unravel", /* EF */
+ "upcoming", /* F0 */
+ "vacancy", /* F1 */
+ "vagabond", /* F2 */
+ "vertigo", /* F3 */
+ "Virginia", /* F4 */
+ "visitor", /* F5 */
+ "vocalist", /* F6 */
+ "voyager", /* F7 */
+ "warranty", /* F8 */
+ "Waterloo", /* F9 */
+ "whimsical", /* FA */
+ "Wichita", /* FB */
+ "Wilmington", /* FC */
+ "Wyoming", /* FD */
+ "yesteryear", /* FE */
+ "Yucatan" /* FF */
};