From a09426b98402f9eed19c42affca2f258f768040a Mon Sep 17 00:00:00 2001 From: Tom Marble Date: Wed, 18 Mar 2015 17:38:41 -0500 Subject: [PATCH] usbtrng-v2.0 version 1.6.4 Fixed hangup bug on startup: now POST works properly on USB insertion Added 'F' command to fetch random hex digits (in addition to raw binary) Added ao-usbtrng -R flag to reset the TRNG --- ao-tools/ao-usbtrng/ao-usbtrng.c | 41 ++++++----- src/drivers/ao_trng.c | 115 ++++++++++++++++++++++++------- 2 files changed, 115 insertions(+), 41 deletions(-) diff --git a/ao-tools/ao-usbtrng/ao-usbtrng.c b/ao-tools/ao-usbtrng/ao-usbtrng.c index 456885d9..3eb2b4d5 100644 --- a/ao-tools/ao-usbtrng/ao-usbtrng.c +++ b/ao-tools/ao-usbtrng/ao-usbtrng.c @@ -62,12 +62,13 @@ main (int argc, char **argv) struct cc_usb *cc = NULL; char *tty = NULL; int verbose = 0; + int reset = 0; int ret = 0; int kbytes = 0; /* 0 == continuous */ int written; uint8_t bits[1024]; - while ((c = getopt_long(argc, argv, "vT:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "vRT:D:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -75,6 +76,9 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'R': + reset++; + break; case 'v': verbose++; break; @@ -104,23 +108,26 @@ main (int argc, char **argv) if (!cc) exit(1); - if (kbytes) { - cc_usb_printf(cc, "f %d\n", kbytes); + if (reset) { + cc_usb_printf(cc, "R\n"); + } else { + if (kbytes) { + cc_usb_printf(cc, "f %d\n", kbytes); - while (kbytes--) { - for (i = 0; i < 1024; i++) - bits[i] = cc_usb_getchar(cc); - write(1, bits, 1024); - } - } else { /* 0 == continuous */ - written = 0; - while (written >= 0) { - cc_usb_printf(cc, "f 1\n"); - for (i = 0; i < 1024; i++) - bits[i] = cc_usb_getchar(cc); - written = write(1, bits, 1024); + while (kbytes--) { + for (i = 0; i < 1024; i++) + bits[i] = cc_usb_getchar(cc); + write(1, bits, 1024); + } + } else { /* 0 == continuous */ + written = 0; + while (written >= 0) { + cc_usb_printf(cc, "f\n"); + for (i = 0; i < 1024; i++) + bits[i] = cc_usb_getchar(cc); + written = write(1, bits, 1024); + } } - } - + } done(cc, ret); } diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c index d3c2823a..496c5ce7 100644 --- a/src/drivers/ao_trng.c +++ b/src/drivers/ao_trng.c @@ -20,6 +20,18 @@ #include #include +/* It is difficult to know exactly when we are connected. + This flag will be set once one of *our* commands has been called */ +static uint8_t ao_connected = 0; + +/* note: refactor this with ao_monitor.c? see ao_cmd_put16() */ +static const char xdigit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +#define byte_to_hex(b) ((xdigit[(b) >> 4] << 8 ) | xdigit[(b) & 0xf]) + static struct ao_task ao_blink_green_task; static uint8_t ao_blinking_green = 0; @@ -40,6 +52,7 @@ ao_blink_green(void) static void ao_blink_green_toggle(void) { + ao_connected = 1; ao_blinking_green = !ao_blinking_green; if (!ao_blinking_green) ao_led_off(AO_LED_GREEN); @@ -47,7 +60,8 @@ ao_blink_green_toggle(void) } static struct ao_task ao_blink_red_task; -static int8_t ao_failed = -1; /* -1 need POST, 0 NOMINAL, 1 FAILED */ +static uint8_t ao_failed = 0; /* 0 NOMINAL, 1 FAILED */ +static uint8_t ao_post = 0; /* 0 POST needed, 1 powered up */ /* On handling failure, keithp said: We could disconnect from USB easily enough, or disconnect and come back @@ -55,22 +69,31 @@ static int8_t ao_failed = -1; /* -1 need POST, 0 NOMINAL, 1 FAILED */ error. Lots of options. */ void -ao_trng_failure(void) +ao_trng_failure() { ao_failed = 1; ao_wakeup(&ao_failed); } +void +ao_trng_failure_cmd(void) +{ + ao_trng_failure(); +} + static void -ao_trng_fetch(uint32_t kbytes) +ao_trng_fetch(uint32_t kbytes, uint8_t printhex) { static uint16_t *buffer[2]; uint32_t count; int usb_buf_id; uint16_t i; + uint32_t cur; + uint32_t prev = 0; + uint32_t prev_set = 0; /* prev has been set */ uint16_t *buf; uint32_t *rnd; - uint32_t prev, cur; + uint16_t r; /* random word */ if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -80,35 +103,46 @@ ao_trng_fetch(uint32_t kbytes) } usb_buf_id = 0; - count = kbytes * (1024/AO_USB_IN_SIZE); + /* if we print in hex each byte requires two bytes output */ + count = (kbytes * (1024/AO_USB_IN_SIZE)) << printhex; ao_crc_reset(); ao_led_on(AO_LED_TRNG_READ); while (count--) { /* one 16-bit value per output byte */ - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE + 2); + rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); buf = buffer[usb_buf_id]; - prev = *rnd++; for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { cur = *rnd++; - if (cur == prev) + if (prev_set && (cur == prev)) ao_trng_failure(); - *buf++ = ao_crc_in_32_out_16(cur); + r = ao_crc_in_32_out_16(cur); + if (printhex) { + *buf++ = byte_to_hex(r >> 8); + *buf++ = byte_to_hex(r & 0xff); + i++; + } else { + *buf++ = r; + } prev = cur; + prev_set++; } ao_adc_ack(AO_USB_IN_SIZE); - ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); - ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); - ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + if (ao_connected) { + ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); + ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + } usb_buf_id = 1-usb_buf_id; } ao_led_off(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); - flush(); + if (ao_connected) + flush(); } -static void -ao_trng_fetch_cmd(void) +static uint32_t +ao_trng_get_kbytes(void) { uint32_t kbytes = 1; @@ -117,23 +151,45 @@ ao_trng_fetch_cmd(void) kbytes = ao_cmd_lex_u32; else ao_cmd_status = ao_cmd_success; - ao_trng_fetch(kbytes); + return kbytes; +} + +static void +ao_trng_fetch_cmd(void) +{ + ao_connected = 1; + if (!ao_failed) + ao_trng_fetch(ao_trng_get_kbytes(), 0); +} + +static void +ao_trng_fetch_hex(void) +{ + ao_connected = 1; + if (!ao_failed) + ao_trng_fetch(ao_trng_get_kbytes(), 1); + putchar('\n'); } /* NOTE: the reset function also functions as the Power On Self Test */ void ao_trng_reset(void) { - printf("Power On Self Test\n"); /* DEBUGGING */ + if (ao_connected) + printf("Resetting...\n"); ao_failed = 0; ao_led_off(AO_LED_RED); ao_wakeup(&ao_failed); /* get the first 1k bits and ensure there are no duplicates */ - ao_trng_fetch(1); + ao_trng_fetch(1, 1); + if (ao_connected) + putchar('\n'); if (ao_failed) { /* show failure */ - printf("FAILED self test\n"); + if (ao_connected) + printf("FAILED self test\n"); } else { /* show success */ - printf("PASS - operation NOMINAL\n"); + if (ao_connected) + printf("PASS - operation NOMINAL\n"); /* this blocks! */ ao_led_on(AO_LED_GREEN); ao_delay(AO_MS_TO_TICKS(1000)); @@ -141,11 +197,20 @@ ao_trng_reset(void) } } +void +ao_trng_reset_cmd(void) +{ + ao_connected = 1; + ao_trng_reset(); +} + static void ao_blink_red(void) { - if (ao_failed < 0) - ao_trng_reset(); /* lazy POST */ + if (!ao_post) { + ao_trng_reset(); /* POST */ + ao_post = 1; + } for (;;) { while (!ao_failed) ao_sleep(&ao_failed); @@ -159,6 +224,7 @@ ao_blink_red(void) static void ao_trng_status(void) { + ao_connected = 1; if (ao_failed) printf("FAILED\n"); else @@ -167,10 +233,11 @@ ao_trng_status(void) static const struct ao_cmds ao_trng_cmds[] = { { ao_trng_fetch_cmd, "f \0Fetch a block of numbers" }, - { ao_trng_reset, "R\0Reset" }, + { ao_trng_fetch_hex, "F \0Fetch a block of numbers (in hex)" }, + { ao_trng_reset_cmd, "R\0Reset" }, { ao_blink_green_toggle, "G\0Toggle green LED blinking" }, { ao_trng_status, "s\0Show status" }, - { ao_trng_failure, "z\0Simulate failure" }, + { ao_trng_failure_cmd, "z\0Simulate failure" }, { 0, NULL }, }; -- 2.47.2