Get a basic USB device working

It enumerates, takes its address, gets configured, and then Linux kind
of gives up because it has no endpoints.

Change-Id: I01f75acee419b585e455f428ee45bcd37f0ce189
diff --git a/motors/usb/usb.h b/motors/usb/usb.h
new file mode 100644
index 0000000..1322ce1
--- /dev/null
+++ b/motors/usb/usb.h
@@ -0,0 +1,506 @@
+#ifndef MOTORS_USB_USB_H_
+#define MOTORS_USB_USB_H_
+
+#include <assert.h>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "aos/common/macros.h"
+#include "motors/core/kinetis.h"
+#include "motors/usb/constants.h"
+
+namespace frc971 {
+namespace teensy {
+
+// A sufficient memory barrier between writing some data and telling the USB
+// hardware to read it or having the USB hardware say some data is readable and
+// actually reading it.
+static inline void dma_memory_barrier() {
+  __asm__ __volatile__("" :: : "memory");
+}
+
+// Aligned for faster access via memcpy etc.
+typedef void *DataPointer __attribute__((aligned(4)));
+
+// An entry in the Buffer Descriptor Table.
+struct BdtEntry {
+  uint32_t buffer_descriptor;
+  DataPointer address;
+};
+
+#define V_USB_BD_BC(value) \
+  static_cast<uint32_t>(static_cast<uint32_t>(value) << 16)
+#define G_USB_BD_BC(bd) (((bd) >> 16) & UINT32_C(0x3FF))
+#define M_USB_BD_OWN UINT32_C(1 << 7)
+#define M_USB_BD_DATA1 UINT32_C(1 << 6)
+static_assert(static_cast<uint32_t>(Data01::kData1) == M_USB_BD_DATA1,
+              "Wrong value");
+#define M_USB_BD_KEEP UINT32_C(1 << 5)
+#define M_USB_BD_NINC UINT32_C(1 << 4)
+#define M_USB_BD_DTS UINT32_C(1 << 3)
+#define M_USB_BD_STALL UINT32_C(1 << 2)
+#define V_USB_BD_PID(value) \
+  static_cast<uint32_t>(static_cast<uint32_t>(value) << 2)
+#define G_USB_BD_PID(bd) static_cast<UsbPid>(((bd) >> 2) & UINT32_C(0xF))
+
+#define G_USB_STAT_ENDP(stat) (((stat) >> 4) & UINT32_C(0xF))
+#define M_USB_STAT_TX UINT32_C(1 << 3)
+#define M_USB_STAT_ODD UINT32_C(1 << 2)
+
+// The various types of descriptors defined in the standard for retrieval via
+// GetDescriptor.
+static constexpr uint8_t kUsbDescriptorTypeMin = 1;
+static constexpr uint8_t kUsbDescriptorTypeMax = 11;
+enum class UsbDescriptorType : uint8_t {
+  kDevice = 1,
+  kConfiguration = 2,
+  kString = 3,
+  kInterface = 4,
+  kEndpoint = 5,
+  kDeviceQualifier = 6,
+  kOtherSpeedConfiguration = 7,
+  kInterfacePower = 8,
+  kOtg = 9,
+  kDebug = 10,
+  kInterfaceAssociation = 11,
+};
+
+// The class-specific descriptor types.
+enum class UsbClassDescriptorType : uint8_t {
+  kDevice = 0x21,
+  kConfiguration = 0x22,
+  kString = 0x23,
+  kInterface = 0x24,
+  kEndpoint = 0x25,
+};
+
+// The names of the setup request types from the standard.
+enum class SetupRequestType {
+  kStandard = 0,
+  kClass = 1,
+  kVendor = 2,
+  kReserved = 3,
+};
+
+// Set means device-to-host, clear means host-to-device.
+#define M_SETUP_REQUEST_TYPE_IN UINT8_C(1 << 7)
+#define G_SETUP_REQUEST_TYPE_TYPE(type) \
+  static_cast<SetupRequestType>(((type) >> 5) & UINT8_C(3))
+#define G_SETUP_REQUEST_TYPE_RECIPIENT(type) ((type)&UINT8_C(0x1F))
+#define G_SETUP_REQUEST_INDEX_ENDPOINT(index) ((index)&UINT8_C(0x7F))
+
+// The names of the standard recipients for setup requests.
+namespace standard_setup_recipients {
+constexpr int kDevice = 0;
+constexpr int kInterface = 1;
+constexpr int kEndpoint = 2;
+constexpr int kOther = 3;
+}  // namespace standard_setup_recipients
+
+class UsbFunction;
+
+// Allows building up a list of descriptors. This supports a much nicer API than
+// the usual "hard-code a char[] with all the sizes and offsets at compile
+// time". Space for each descriptor is reserved, and then it may be filled out
+// from beginning to end at any time.
+//
+// An instance is the thing that the GetDescriptor operation sends to the host.
+// This is not the concept that the core and class standards call "Foo
+// Descriptor" etc; see Descriptor for that.
+class UsbDescriptorList {
+ public:
+  // Represents a single descriptor. All of the contents must be written before
+  // this object is destroyed.
+  //
+  // Create one via UsbDescriptorList::CreateDescriptor.
+  class Descriptor {
+   public:
+    // All of the allocated space must be filled first.
+    ~Descriptor() {
+      if (descriptor_list_ == nullptr) {
+        return;
+      }
+      // Verify we wrote all the bytes first.
+      assert(next_index_ == end_index_);
+      --descriptor_list_->open_descriptors_;
+    }
+
+    void AddUint16(uint16_t value) {
+      AddByte(value & 0xFF);
+      AddByte((value >> 8) & 0xFF);
+    }
+
+    void AddByte(uint8_t value) {
+      assert(next_index_ < end_index_);
+      data()[next_index_] = value;
+      ++next_index_;
+    }
+
+    // Overwrites an already-written byte.
+    void SetByte(int index, uint8_t value) {
+      assert(index + start_index_ < end_index_);
+      data()[index + start_index_] = value;
+    }
+
+   private:
+    Descriptor(UsbDescriptorList *descriptor_list, int start_index,
+               int end_index)
+        : descriptor_list_(descriptor_list),
+          start_index_(start_index),
+          end_index_(end_index),
+          next_index_(start_index_) {}
+
+    char *data() const {
+      return &descriptor_list_->data_[0];
+    }
+
+    UsbDescriptorList *const descriptor_list_;
+    const int start_index_, end_index_;
+    int next_index_;
+
+    friend class UsbDescriptorList;
+
+    DISALLOW_COPY_AND_ASSIGN(Descriptor);
+  };
+
+  UsbDescriptorList() = default;
+  ~UsbDescriptorList() = default;
+
+  // Creates a new descriptor at the end of the list.
+  // length is the number of bytes, including the length byte.
+  // descriptor_type is the descriptor type, which is the second byte after the
+  // length.
+  ::std::unique_ptr<Descriptor> CreateDescriptor(
+      uint8_t length, UsbDescriptorType descriptor_type) {
+    return CreateDescriptor(length, static_cast<uint8_t>(descriptor_type));
+  }
+
+  ::std::unique_ptr<Descriptor> CreateDescriptor(
+      uint8_t length, UsbClassDescriptorType descriptor_type) {
+    assert(data_.size() > 0);
+    return CreateDescriptor(length, static_cast<uint8_t>(descriptor_type));
+  }
+
+  void CheckFinished() const { assert(open_descriptors_ == 0); }
+
+  int CurrentSize() const { return data_.size(); }
+
+ private:
+  ::std::unique_ptr<Descriptor> CreateDescriptor(uint8_t length,
+                                                 uint8_t descriptor_type) {
+    const int start_index = data_.size();
+    const int end_index = start_index + length;
+    data_.resize(end_index);
+    ++open_descriptors_;
+    auto r = ::std::unique_ptr<Descriptor>(
+        new Descriptor(this, start_index, end_index));
+    r->AddByte(length);           // bLength
+    r->AddByte(descriptor_type);  // bDescriptorType
+    return r;
+  }
+
+  int open_descriptors_ = 0;
+
+  ::std::string data_;
+
+  friend class UsbDevice;
+
+  DISALLOW_COPY_AND_ASSIGN(UsbDescriptorList);
+};
+
+extern "C" void usb_isr(void);
+
+// USB state events are managed by asking each function if it wants to handle
+// them, sequentially. For the small number of functions which can be
+// practically supported with the limited number of endpoints, this performs
+// better than fancier things like hash maps.
+
+// Manages one of the Teensy's USB peripherals as a USB slave device.
+//
+// This supports being a composite device with multiple functions.
+//
+// Attaching functions etc is called "setup", and must be completed before
+// Initialize() is called.
+//
+// Detaching functions is called "teardown" and must happen after Shutdown().
+// TODO(Brian): Implement Shutdown().
+class UsbDevice final {
+ public:
+  // Represents the data that comes with a UsbPid::kSetup.
+  // Note that the order etc is important because we memcpy into this.
+  struct SetupPacket {
+    uint8_t request_type;  // bmRequestType
+    uint8_t request;       // bRequest
+    uint16_t value;        // wValue
+    uint16_t index;        // wIndex
+    uint16_t length;       // wLength
+  } __attribute__((aligned(4)));
+  static_assert(sizeof(SetupPacket) == 8, "wrong size");
+
+  enum class SetupResponse {
+    // Indicates this function doesn't recognize the setup packet.
+    kIgnored,
+
+    // Indicates the endpoint should be stalled.
+    //
+    // Don't return this if the packet is for another function.
+    kStall,
+
+    // Indicates this setup packet was handled. Functions must avoid eating
+    // packets intended for other functions.
+    kHandled,
+  };
+
+  static constexpr int kEndpoint0MaxSize = 64;
+
+  // The only language code we support.
+  static constexpr uint16_t english_us_code() { return 0x0409; }
+
+  UsbDevice(int index, uint16_t vendor_id, uint16_t product_id);
+  ~UsbDevice();
+
+  // Ends setup and starts being an actual USB device.
+  void Initialize();
+
+  // Adds a string to the table and returns its index.
+  //
+  // For simplicity, we only support strings with english_us_code().
+  //
+  // May only be called during setup.
+  int AddString(const ::std::string &string) {
+    assert(!is_set_up_);
+    const int r = strings_.size();
+    strings_.emplace_back(string.size() * 2 + 2, '\0');
+    strings_.back()[0] = 2 + string.size() * 2;
+    strings_.back()[1] = static_cast<uint8_t>(UsbDescriptorType::kString);
+    for (size_t i = 0; i < string.size(); ++i) {
+      strings_.back()[i * 2 + 2] = string[i];
+    }
+    return r;
+  }
+
+  // Sets the manufacturer string.
+  //
+  // May only be called during setup.
+  void SetManufacturer(const ::std::string &string) {
+    device_descriptor_->SetByte(14, AddString(string));  // iManufacturer
+  }
+
+  // Sets the product string.
+  //
+  // May only be called during setup.
+  void SetProduct(const ::std::string &string) {
+    device_descriptor_->SetByte(15, AddString(string));  // iProduct
+  }
+
+  // Sets the serial number string.
+  //
+  // May only be called during setup.
+  void SetSerialNumber(const ::std::string &string) {
+    device_descriptor_->SetByte(16, AddString(string));  // iSerialNumber
+  }
+
+  // Queues up an empty IN packet for endpoint 0. This is a common way to
+  // respond to various kinds of configuration commands.
+  //
+  // This may only be called from the appropriate function callbacks.
+  void SendEmptyEndpoint0Packet();
+
+  // Queues some data to send on endpoint 0. This includes putting the initial
+  // packets into the TX buffers.
+  //
+  // This may only be called from the appropriate function callbacks.
+  void QueueEndpoint0Data(const char *data, int size);
+
+  // Stalls an endpoint until it's cleared.
+  //
+  // This should only be called by or on behalf of the function which owns
+  // endpoint.
+  void StallEndpoint(int endpoint);
+
+  // Configures an endpoint to send and/or receive, with or without DATA0/DATA1
+  // handshaking. handshake should probably be true for everything except
+  // isochronous endpoints.
+  //
+  // This should only be called by or on behalf of the function which owns
+  // endpoint.
+  void ConfigureEndpointFor(int endpoint, bool rx, bool tx, bool handshake);
+
+  void SetBdtEntry(int endpoint, Direction direction, EvenOdd odd,
+                   BdtEntry bdt_entry);
+
+ private:
+  // Clears all pending interrupts.
+  void ClearInterrupts();
+
+  // Deals with an interrupt that has occured.
+  void HandleInterrupt();
+
+  // Processes a token on endpoint 0.
+  void HandleEndpoint0Token(uint8_t stat);
+
+  // Processes a setup packet on endpoint 0.
+  void HandleEndpoint0SetupPacket(const SetupPacket &setup_packet);
+
+  // Sets endpoint 0 to return STALL tokens. We clear this condition upon
+  // receiving the next SETUP token.
+  void StallEndpoint0();
+
+  // Places the first packet from {endpoint0_data_, endpoint0_data_left_} into
+  // the TX buffers (if there is any data). This may only be called when the
+  // next TX buffer is empty.
+  bool BufferEndpoint0TxPacket();
+
+  // Which USB peripheral this is.
+  const int index_;
+
+  // The string descriptors in order.
+  ::std::vector<::std::string> strings_;
+
+  // TODO(Brian): Refactor into something more generic, because I think this is
+  // shared with all non-isochronous endpoints?
+  Data01 endpoint0_tx_toggle_;
+  EvenOdd endpoint0_tx_odd_;
+  uint8_t endpoint0_receive_buffer_[2][kEndpoint0MaxSize]
+      __attribute__((aligned(4)));
+
+  // A temporary buffer for holding data to transmit on endpoint 0. Sometimes
+  // this is used and sometimes the data is sent directly from some other
+  // location (like for descriptors).
+  char endpoint0_transmit_buffer_[kEndpoint0MaxSize];
+
+  // The data we're waiting to send from endpoint 0. The data must remain
+  // constant until this transmission is done.
+  //
+  // When overwriting this, we ignore if it's already non-nullptr. The host is
+  // supposed to read all of the data before asking for more. If it doesn't do
+  // that, it will just get garbage data because it's unclear what it expects.
+  //
+  // Do note that endpoint0_data_ != nullptr && endpoint0_data_left_ == 0 is an
+  // important state. This means we're going to return a 0-length packet the
+  // next time the host asks. However, depending on the length it asked for,
+  // that might never happen.
+  const char *endpoint0_data_ = nullptr;
+  int endpoint0_data_left_ = 0;
+
+  // If non-0, the new address we're going to start using once the status stage
+  // of the current setup request is finished.
+  uint16_t new_address_ = 0;
+
+  UsbDescriptorList device_descriptor_list_;
+  UsbDescriptorList config_descriptor_list_;
+
+  ::std::unique_ptr<UsbDescriptorList::Descriptor> device_descriptor_,
+      config_descriptor_;
+
+  int configuration_ = 0;
+
+  bool is_set_up_ = false;
+
+  // The function which owns each endpoint.
+  ::std::vector<UsbFunction *> endpoint_mapping_;
+  // The function which owns each interface.
+  ::std::vector<UsbFunction *> interface_mapping_;
+  // All of the functions (without duplicates).
+  ::std::vector<UsbFunction *> functions_;
+
+  friend void usb_isr(void);
+  friend class UsbFunction;
+};
+
+// Represents a USB function. This consists of a set of descriptors and
+// interfaces.
+//
+// Each instance is a single function, so there can be multiple instances of the
+// same subclass in the same devices (ie two serial ports).
+class UsbFunction {
+ public:
+  UsbFunction(UsbDevice *device) : device_(device) {
+    device_->functions_.push_back(this);
+  }
+  virtual ~UsbFunction() = default;
+
+ protected:
+  using SetupResponse = UsbDevice::SetupResponse;
+
+  static constexpr uint8_t iad_descriptor_length() { return 8; }
+  static constexpr uint8_t interface_descriptor_length() { return 9; }
+  static constexpr uint8_t endpoint_descriptor_length() { return 7; }
+
+  static constexpr uint8_t m_endpoint_address_in() { return 1 << 7; }
+  static constexpr uint8_t m_endpoint_attributes_control() { return 0x00; }
+  static constexpr uint8_t m_endpoint_attributes_isochronous() { return 0x01; }
+  static constexpr uint8_t m_endpoint_attributes_bulk() { return 0x03; }
+  static constexpr uint8_t m_endpoint_attributes_interrupt() { return 0x03; }
+
+  // Adds a new endpoint and returns its index.
+  //
+  // Note that at least one descriptor for this newly created endpoint must be
+  // added via CreateConfigDescriptor.
+  //
+  // TODO(Brian): Does this hardware actually only support a single direction
+  // per endpoint number, or can it get a total of 30 endpoints max?
+  //
+  // May only be called during setup.
+  int AddEndpoint();
+
+  // Adds a new interface and returns its index.
+  //
+  // You'll probably want to put this new interface in at least one descriptor
+  // added via CreateConfigDescriptor.
+  //
+  // May only be called during setup.
+  int AddInterface();
+
+  // Adds a new descriptor in the configuration descriptor list. See
+  // UsbDescriptorList::CreateDescriptor for details.
+  //
+  // Note that the order of calls to this is highly significant. In general,
+  // this should only be called from Initialize().
+  //
+  // May only be called during setup.
+  template <typename T>
+  ::std::unique_ptr<UsbDescriptorList::Descriptor> CreateDescriptor(
+      uint8_t length, T descriptor_type) {
+    return device_->config_descriptor_list_.CreateDescriptor(length,
+                                                             descriptor_type);
+  }
+
+  UsbDevice *device() const { return device_; }
+
+ private:
+  virtual void Initialize() = 0;
+
+  virtual SetupResponse HandleEndpoint0SetupPacket(
+      const UsbDevice::SetupPacket & /*setup_packet*/) {
+    return SetupResponse::kIgnored;
+  }
+
+  virtual SetupResponse HandleEndpoint0OutPacket(void * /*data*/,
+                                                 int /*data_length*/) {
+    return SetupResponse::kIgnored;
+  }
+
+  virtual void HandleOutFinished(int endpoint, BdtEntry *bdt_entry) = 0;
+  virtual void HandleInFinished(int endpoint, BdtEntry *bdt_entry,
+                                EvenOdd odd) = 0;
+
+  // Called when a given interface is configured (aka "experiences a
+  // configuration event"). This means all rx and tx buffers have been cleared
+  // and should be filled as appropriate, starting from data0. Also,
+  // ConfigureEndpointFor should be called with the appropriate arguments.
+  virtual void HandleConfigured(int endpoint) = 0;
+
+  // Should reset everything to use the even buffers next.
+  virtual void HandleReset() = 0;
+
+  UsbDevice *const device_;
+
+  friend class UsbDevice;
+};
+
+}  // namespace teensy
+}  // namespace frc971
+
+#endif  // MOTORS_USB_USB_H_