usbtrng-v2.0 version 1.6.4
authorTom Marble <tmarble@info9.net>
Wed, 18 Mar 2015 22:38:41 +0000 (17:38 -0500)
committerTom Marble <tmarble@info9.net>
Wed, 18 Mar 2015 22:38:41 +0000 (17:38 -0500)
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
src/drivers/ao_trng.c

index 456885d9b4871b205d3d5cad13e8f7c2921fb7ec..3eb2b4d5faf0bdebaeb20fa780ec3bb20ddda802 100644 (file)
@@ -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);
 }
index d3c2823a50d180249d19559107e5f8e8f148e86b..496c5ce7c1a52f2acaba39629b873af118d66749 100644 (file)
 #include <ao_crc.h>
 #include <ao_trng.h>
 
+/* 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 <kbytes>\0Fetch a block of numbers" },
-       { ao_trng_reset, "R\0Reset" },
+       { ao_trng_fetch_hex, "F <kbytes>\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 },
 };