Get soft reboot working

Change-Id: I7b2707fef62ae7b3878ca3d6ed6991bea41d7d6e
diff --git a/motors/usb/BUILD b/motors/usb/BUILD
index 0696354..950de0a 100644
--- a/motors/usb/BUILD
+++ b/motors/usb/BUILD
@@ -56,6 +56,7 @@
   deps = [
     ':usb',
     ':queue',
+    '//motors/core',
     '//motors:util',
   ],
   restricted_to = mcu_cpus,
diff --git a/motors/usb/cdc.cc b/motors/usb/cdc.cc
index b082750..0b59aef 100644
--- a/motors/usb/cdc.cc
+++ b/motors/usb/cdc.cc
@@ -1,6 +1,9 @@
 #include "motors/usb/cdc.h"
 
 #include <string.h>
+#include <stdint.h>
+
+#include "motors/core/time.h"
 
 #define CHECK(c)                             \
   do {                                       \
@@ -301,11 +304,18 @@
       return SetupResponse::kIgnored;
 
     case NextEndpoint0Out::kLineCoding:
+      next_endpoint0_out_ = NextEndpoint0Out::kNone;
       if (data_length != sizeof(line_coding_)) {
         return SetupResponse::kStall;
       }
       memcpy(&line_coding_, data, data_length);
       device()->SendEmptyEndpoint0Packet();
+      // If we're supposed to reboot, then do it.
+      if (line_coding_.rate == UINT32_C(0x97101678)) {
+        // Delay for a bit so the empty IN packet gets back to the host.
+        delay(5);
+        __asm__ __volatile__("bkpt");
+      }
       return SetupResponse::kHandled;
 
     default:
diff --git a/motors/usb/usb.cc b/motors/usb/usb.cc
index 3067695..0a05fad 100644
--- a/motors/usb/usb.cc
+++ b/motors/usb/usb.cc
@@ -250,6 +250,7 @@
     // If we just finished processing a token.
     if (status & USB_ISTAT_TOKDNE) {
       const uint8_t stat = USB0_STAT;
+      USB0_ISTAT = USB_ISTAT_TOKDNE;
       const int endpoint = G_USB_STAT_ENDP(stat);
 
       if (endpoint == 0) {
@@ -281,8 +282,6 @@
           }
         }
       }
-
-      USB0_ISTAT = USB_ISTAT_TOKDNE;
     }
 
     if (status & USB_ISTAT_USBRST) {
@@ -355,14 +354,16 @@
       dma_memory_barrier();
       // Next IN and OUT packet for this endpoint (data stage/status stage)
       // should both be DATA1.
-      // TODO(Brian): Does this actually deal with received toggles correctly?
-      bdt_entry->buffer_descriptor =
-          M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(kEndpoint0MaxSize);
       MutableBdtEntryFromStat(stat ^ M_USB_STAT_ODD)->buffer_descriptor =
           M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(kEndpoint0MaxSize) |
           M_USB_BD_DATA1;
       endpoint0_tx_toggle_ = Data01::kData1;
 
+      // Give this buffer back. It should be DATA0 because it'll be the second
+      // received packet.
+      bdt_entry->buffer_descriptor =
+          M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(kEndpoint0MaxSize);
+
       // TODO(Brian): Tell the functions a new setup packet is starting.
       // CdcTty: next_endpoint0_out_ = NextEndpoint0Out::kNone;
 
diff --git a/motors/usb/usb.h b/motors/usb/usb.h
index 1322ce1..1d7606f 100644
--- a/motors/usb/usb.h
+++ b/motors/usb/usb.h
@@ -21,6 +21,9 @@
 }
 
 // Aligned for faster access via memcpy etc.
+//
+// Also, the Freescale example stack forces aligned buffers to work around some
+// hardware limitations which may or may not apply to our chips.
 typedef void *DataPointer __attribute__((aligned(4)));
 
 // An entry in the Buffer Descriptor Table.