USB Host WAN Dongle library

Fork of USBHostWANDongle_bleedingedge by Donatien Garnier

Files at this revision

API Documentation at this revision

Comitter:
donatien
Date:
Thu May 24 16:39:35 2012 +0000
Child:
1:49df46e3295c
Commit message:
Initial Commit

Changed in this revision

USB3GModule/IUSBHostSerial.h Show annotated file Show diff for this revision Revisions of this file
USB3GModule/IUSBHostSerialListener.h Show annotated file Show diff for this revision Revisions of this file
USB3GModule/WANDongle.cpp Show annotated file Show diff for this revision Revisions of this file
USB3GModule/WANDongle.h Show annotated file Show diff for this revision Revisions of this file
USBHost/Endpoint.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/Endpoint.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBDeviceConnected.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBDeviceConnected.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHALHost.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHALHost.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHost.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHost.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHostTypes.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/IUSBHostSerial.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,90 @@
+/* IUSBHostSerial.h */
+/*
+Copyright (C) 2012 ARM Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+
+#ifndef IUSBHOSTSERIAL_H_
+#define IUSBHOSTSERIAL_H_
+
+/**
+ * Generic interface to abstract 3G dongles' impl
+ */
+
+#include "IUSBHostSerialListener.h"
+
+class IUSBHostSerial {
+public:
+
+    enum IrqType {
+        RxIrq,
+        TxIrq
+    };
+
+    /*
+    * Get a char from the dongle's serial interface
+    */
+    virtual int getc() = 0;
+
+    /*
+    * Put a char to the dongle's serial interface
+    */
+    virtual int putc(int c) = 0;
+
+    /*
+     *  Read a packet from the dongle's serial interface, to be called after multiple getc() calls
+     */
+    virtual int readPacket() = 0;
+
+    /*
+     *  Write a packet to the dongle's serial interface, to be called after multiple putc() calls
+     */
+    virtual int writePacket() = 0;
+
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    virtual int readable() = 0;
+
+    /**
+    * Check the free space in output.
+    *
+    * @returns the number of bytes available
+    */
+    virtual int writeable() = 0;
+
+    /**
+     *  Attach a handler to call when a packet is received / when a packet has been transmitted.
+     *
+     *  @param pListener instance of the listener deriving from the IUSBHostSerialListener
+     */
+    virtual void attach(IUSBHostSerialListener* pListener) = 0;
+
+    /**
+     * Enable or disable readable/writeable callbacks
+     */
+    virtual void setupIrq(bool en, IrqType irq = RxIrq) = 0;
+
+};
+
+#endif /* IUSBHOSTSERIAL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/IUSBHostSerialListener.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,36 @@
+/* IUSBHostSerialListener.h */
+/*
+Copyright (C) 2012 ARM Limited.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+
+#ifndef IUSBHOSTSERIALLISTENER_H_
+#define IUSBHOSTSERIALLISTENER_H_
+
+class IUSBHostSerialListener
+{
+public:
+  virtual void readable() = 0; //Called when new data is available
+  virtual void writeable() = 0; //Called when new space is available
+};
+
+
+#endif /* IUSBHOSTSERIALLISTENER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongle.cpp	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,441 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define __DEBUG__ 4 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "WANDongle.cpp"
+#endif
+
+#include "dbg.h"
+#include <cstdint>
+#include "rtos.h"
+
+#include "WANDongle.h"
+
+//TODO refactor
+
+//Huawei K3770 (Vodafone)
+uint8_t vodafone_k3770_switch_packet[] = {
+    0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0x11, 0x06, 0x20, 0, 0, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+WANDongle::WANDongle() : cb_tx_en(false), cb_rx_en(false), listener(NULL)
+{
+    host = USBHost::getHostInst();
+    init();
+}
+
+
+bool WANDongle::connected() {
+  return dev_connected;
+}
+
+bool WANDongle::tryConnect()
+{
+  bool found = false;
+
+  //FIXME should run on USB thread
+
+  DBG("Trying to connect device");
+
+  if (dev_connected) {
+      return true;
+  }
+
+  host->lock();
+
+  for (int i = 0; i < MAX_DEVICE_NB; i++) {
+      if ((dev = host->getDevice(i)) != NULL) {
+
+          DBG("Found one device, reset it");
+          host->resetDevice(dev);
+
+          DBG("Enumerate");
+          host->enumerate(dev);
+
+          //Vodafone K3770
+          if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14D1)) {
+              DBG("Vodafone K3370 dongle detected!!!");
+
+              for (int j = 0; j < dev->getNbInterface(); j++) {
+
+                  if (dev->getInterface(j)->intf_class == MSD_CLASS) {
+
+                      if ( (bulk_out = dev->getEndpoint(j, BULK_ENDPOINT, OUT)) != NULL )  {
+
+                          DBG("MSD FOUND on device %p, intf %d, WILL NOW SWITCH MODE!!!", (void *)dev, j);
+
+                          host->bulkWrite(dev, (Endpoint *)bulk_out, vodafone_k3770_switch_packet, 31);
+
+                          DBG("SWITCH PACKET SENT");
+                          host->unlock();
+
+
+                          Thread::wait(500); //Not in a thread
+
+                          // now wait for the new device connected......... :(
+                          while (1) {
+
+                              if (found) {
+                                  break;
+                              }
+
+                              Thread::wait(100);
+
+                              host->lock();
+
+
+                              for (int i = 0; i < MAX_DEVICE_NB; i++) {
+                                  if ((dev = host->getDevice(i)) != NULL) {
+                                      host->resetDevice(dev);
+                                      host->enumerate(dev);
+
+                                      //Vodafone K3770
+                                      if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14C9)) {
+                                          DBG("SWITCH MODE OK!!!!!!!!!!\r\n");
+                                          found = true;
+                                          break;
+                                      }
+                                  }
+                              }
+
+                              host->unlock();
+
+                          }
+                          host->lock();
+
+                          if (fetchEndpoints()) {
+                            DBG("ep: %p, %p\r\n", bulk_in, bulk_out);
+                            max_out_size = bulk_out->getSize();
+                            if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
+                            {
+                              max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
+                            }
+                            host->unlock();
+                            return true;
+                          }
+                          host->unlock();
+                      }
+                  }
+              }
+          } else if ((dev->getVid() == 0x12D1) && (dev->getPid() == 0x14C9)) {
+              if (fetchEndpoints()) {
+                DBG("ep: %p, %p\r\n", bulk_in, bulk_out);
+                max_out_size = bulk_out->getSize();
+                if( max_out_size > WANDONGLE_MAX_OUTEP_SIZE )
+                {
+                  max_out_size = WANDONGLE_MAX_OUTEP_SIZE;
+                }
+                host->unlock();
+                return true;
+              }
+          }
+      }
+  }
+  host->unlock();
+  bulk_in = NULL;
+  bulk_out = NULL;
+  dev_connected = false;
+  return false;
+}
+
+int WANDongle::readPacket()
+{
+  rx_mtx.lock();
+  if(lock_rx)
+  {
+    ERR("Fail");
+    rx_mtx.unlock();
+    return -1;
+  }
+
+  lock_rx = true; //Receiving
+  rx_mtx.unlock();
+//  DBG("readPacket");
+  //lock_rx.lock();
+  host->lock();
+  USB_TYPE res = host->bulkRead(dev, (Endpoint *)bulk_in, buf_in, ((Endpoint *)bulk_in)->getSize(), false); //Queue transfer
+  if(res != USB_TYPE_PROCESSING)
+  {
+    host->unlock();
+    //lock_rx.unlock();
+    ERR("host->bulkRead() returned %d", res);
+    Thread::wait(100);
+    return -1;
+  }
+  host->unlock();
+  return 0;
+}
+
+int WANDongle::writePacket()
+{
+  tx_mtx.lock();
+  if(lock_tx)
+  {
+    ERR("Fail");
+    tx_mtx.unlock();
+    return -1;
+  }
+
+  lock_tx = true; //Transmitting
+  tx_mtx.unlock();
+//  DBG("writePacket");
+
+  //lock_tx.lock();
+  host->lock();
+  USB_TYPE res = host->bulkWrite(dev, (Endpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer
+  if(res != USB_TYPE_PROCESSING)
+  {
+    host->unlock();
+    //lock_tx.unlock();
+    ERR("host->bulkWrite() returned %d", res);
+    Thread::wait(100);
+    return -1;
+  }
+  host->unlock();
+  return 0;
+}
+
+int WANDongle::putc(int c)
+{
+  tx_mtx.lock();
+  if(!lock_tx)
+  {
+    if(buf_out_len < max_out_size)
+    {
+      buf_out[buf_out_len] = (uint8_t)c;
+      buf_out_len++;
+    }
+  }
+  else
+  {
+    ERR("CAN'T WRITE!");
+  }
+  tx_mtx.unlock();
+  return c;
+}
+
+int WANDongle::getc()
+{
+  rx_mtx.lock();
+  int c = 0;
+  if(!lock_rx)
+  {
+    if(buf_in_read_pos < buf_in_len)
+    {
+      c = (int)buf_in[buf_in_read_pos];
+      buf_in_read_pos++;
+    }
+  }
+  else
+  {
+    ERR("CAN'T READ!");
+  }
+  rx_mtx.unlock();
+  return c;
+}
+
+int WANDongle::readable()
+{
+  rx_mtx.lock();
+  if (lock_rx)
+  {
+    rx_mtx.unlock();
+    return 0;
+  }
+
+ /* if( !lock_rx.trylock() )
+  {
+    return 0;
+  }*/
+  int res = buf_in_len - buf_in_read_pos;
+  //lock_rx.unlock();
+  rx_mtx.unlock();
+  return res;
+}
+
+int WANDongle::writeable()
+{
+  tx_mtx.lock();
+  if (lock_tx)
+  {
+    tx_mtx.unlock();
+    return 0;
+  }
+
+  /*if( !lock_tx.trylock() )
+  {
+    return 0;
+  }*/
+  int res = max_out_size - buf_out_len;
+  tx_mtx.unlock();
+ //lock_tx.unlock();
+  return res;
+}
+
+void WANDongle::attach(IUSBHostSerialListener* pListener)
+{
+  if(pListener == NULL)
+  {
+    setupIrq(false, RxIrq);
+    setupIrq(false, TxIrq);
+  }
+  listener = pListener;
+  if(pListener != NULL)
+  {
+    setupIrq(true, RxIrq);
+    setupIrq(true, TxIrq);
+  }
+}
+
+void WANDongle::setupIrq(bool en, IrqType irq /*= RxIrq*/)
+{
+  switch(irq)
+  {
+  case RxIrq:
+    rx_mtx.lock();
+    cb_rx_en = en;
+    if(en && cb_rx_pending)
+    {
+      cb_rx_pending = false;
+      rx_mtx.unlock();
+      listener->readable(); //Process the interrupt that was raised
+    }
+    else
+    {
+      rx_mtx.unlock();
+    }
+    break;
+  case TxIrq:
+    tx_mtx.lock();
+    cb_tx_en = en;
+    if(en && cb_tx_pending)
+    {
+      cb_tx_pending = false;
+      tx_mtx.unlock();
+      listener->writeable(); //Process the interrupt that was raised
+    }
+    else
+    {
+      tx_mtx.unlock();
+    }
+    break;
+  }
+}
+
+//Private methods
+
+void WANDongle::init()
+{
+  dev_connected = false;
+
+  bulk_in = NULL;
+  bulk_out = NULL;
+
+  buf_out_len = 0;
+  lock_tx = false;
+  cb_tx_en = false;
+  cb_tx_pending = false;
+
+  buf_in_len = 0;
+  buf_in_read_pos = 0;
+  lock_rx = false;
+  cb_rx_en = false;
+  cb_rx_pending = false;
+
+}
+
+bool WANDongle::fetchEndpoints()
+{
+  bulk_in = dev->getEndpoint(0, BULK_ENDPOINT, IN);
+  bulk_out = dev->getEndpoint(0, BULK_ENDPOINT, OUT);
+  if ((bulk_in != NULL) && (bulk_out != NULL))
+  {
+
+    DBG("SERIAL FOUND on device %p, intf %d, bulk_in: %p, bulk_out: %p\r\n",
+        (void *)dev, 0, (void *)bulk_in, (void *)bulk_out);
+
+    bulk_in->attach(this, &WANDongle::rxHandler);
+    bulk_out->attach(this, &WANDongle::txHandler);
+    host->lock();
+    host->registerDriver(dev, 0, this, &WANDongle::init);
+    host->unlock();
+    dev_connected = true;
+
+    readPacket(); //Start receiving data
+
+    return true;
+  }
+  return false;
+}
+
+void WANDongle::rxHandler()
+{
+  if (((Endpoint *) bulk_in)->getState() == USB_TYPE_IDLE) //Success
+  {
+    buf_in_read_pos = 0;
+    buf_in_len = ((Endpoint *) bulk_in)->getLengthTransferred(); //Update length
+    //lock_rx.unlock();
+    rx_mtx.lock();
+    lock_rx = false; //Transmission complete
+    if(cb_rx_en)
+    {
+      rx_mtx.unlock();
+      listener->readable(); //Call handler from the IRQ context
+      //readPacket() should be called by the handler subsequently once the buffer has been emptied
+    }
+    else
+    {
+      cb_rx_pending = true; //Queue the callback
+      rx_mtx.unlock();
+    }
+
+  }
+  else //Error, try reading again
+  {
+    //lock_rx.unlock();
+    readPacket();
+  }
+}
+
+void WANDongle::txHandler()
+{
+  if (((Endpoint *) bulk_out)->getState() == USB_TYPE_IDLE) //Success
+  {
+    tx_mtx.lock();
+    buf_out_len = 0; //Reset length
+    lock_tx = false; //Transmission complete
+    //lock_tx.unlock();
+    if(cb_tx_en)
+    {
+      tx_mtx.unlock();
+      listener->writeable(); //Call handler from the IRQ context
+      //writePacket() should be called by the handler subsequently once the buffer has been filled
+    }
+    else
+    {
+      cb_tx_pending = true; //Queue the callback
+      tx_mtx.unlock();
+    }
+  }
+  else //Error, try reading again
+  {
+    //lock_tx.unlock();
+    writePacket();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USB3GModule/WANDongle.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,140 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef WANDONGLE_H
+#define WANDONGLE_H
+
+#include "USBHost.h"
+#include "IUSBHostSerial.h"
+
+#include "rtos.h"
+
+
+#define WANDONGLE_MAX_OUTEP_SIZE 64
+#define WANDONGLE_MAX_INEP_SIZE 64
+
+/** A class to use a WAN (3G/LTE) access dongle
+ *
+ */
+class WANDongle : public IUSBHostSerial {
+public:
+    /*
+    * Constructor
+    *
+    * @param rootdir mount name
+    */
+    WANDongle();
+
+    /*
+    * Check if a serial port device is connected
+    *
+    * @return true if a serial device is connected
+    */
+    bool connected();
+    
+    /*
+     * Try to connect device
+     *
+     * * @return true if connection was successful
+     */
+    bool tryConnect();
+
+    /*
+    * Get a char from the dongle's serial interface
+    */
+    virtual int getc();
+
+    /*
+    * Put a char to the dongle's serial interface
+    */
+    virtual int putc(int c);
+    
+    //void test();
+
+    /*
+     *  Read a packet from the dongle's serial interface, to be called after multiple getc() calls
+     */
+    virtual int readPacket();
+
+    /*
+     *  Write a packet to the dongle's serial interface, to be called after multiple putc() calls
+     */
+    virtual int writePacket();
+
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    virtual int readable();
+
+    /**
+    * Check the free space in output.
+    *
+    * @returns the number of bytes available
+    */
+    virtual int writeable();
+
+    /**
+     *  Attach a handler to call when a packet is received / when a packet has been transmitted.
+     *
+     *  @param pListener instance of the listener deriving from the IUSBHostSerialListener
+     */
+    virtual void attach(IUSBHostSerialListener* pListener);
+    
+    /**
+     * Enable or disable readable/writeable callbacks
+     */
+    virtual void setupIrq(bool en, IrqType irq = RxIrq);
+
+    
+protected:
+    Endpoint * bulk_in;
+    Endpoint * bulk_out;
+    USBHost * host;
+    USBDeviceConnected * dev;
+    bool dev_connected;
+
+    uint8_t buf_out[WANDONGLE_MAX_OUTEP_SIZE];
+    volatile uint32_t buf_out_len;
+    uint32_t max_out_size;
+    volatile bool lock_tx;
+    //Mutex lock_tx;
+    volatile bool cb_tx_en;
+    volatile bool cb_tx_pending;
+    Mutex tx_mtx;
+
+    uint8_t buf_in[WANDONGLE_MAX_INEP_SIZE];
+    volatile uint32_t buf_in_len;
+    volatile uint32_t buf_in_read_pos;
+    volatile bool lock_rx;
+    //Mutex lock_rx;
+    volatile bool cb_rx_en;
+    volatile bool cb_rx_pending;
+    Mutex rx_mtx;
+    
+    IUSBHostSerialListener* listener;
+    
+    void init();
+    void rxHandler();
+    void txHandler();
+    bool fetchEndpoints();
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/Endpoint.cpp	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,228 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#define __DEBUG__ 0 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "Endpoint.cpp"
+#endif
+
+#include "dbg.h"
+#include <cstdint>
+
+#include "Endpoint.h"
+
+
+void Endpoint::init(HCED * hced, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t ep_number, HCTD* td_list[2]) {
+    this->hced = hced;
+    this->type = type;
+    this->dir = /*(type == CONTROL_ENDPOINT) ? OUT :*/ dir;
+    setup = (type == CONTROL_ENDPOINT) ? true : false;
+
+    //TDs have been allocated by the host
+    memcpy((HCTD**)this->td_list, td_list, sizeof(HCTD*)*2); //TODO: Maybe should add a param for td_list size... at least a define
+    memcpy(td_list[0], 0, sizeof(HCTD));
+    memcpy(td_list[1], 0, sizeof(HCTD));
+
+    this->hced->control = 0;
+    //Empty queue
+    this->hced->tailTD = (uint32_t)td_list[0];
+    this->hced->headTD = (uint32_t)td_list[0];
+    this->hced->nextED = 0;
+
+    this->hced->control = ((ep_number & 0x7F) << 7)                         // Endpoint address
+                          | (type != CONTROL_ENDPOINT ? ( dir << 11) : 0 )  // direction : Out = 1, 2 = In
+                          | ((size & 0x3ff) << 16);                         // MaxPkt Size
+                          
+    //carry = false;
+    transfer_len = 0;
+    transferred = 0;
+    buf_start = 0;
+    nextEp = NULL;
+
+    td_current = td_list[0];
+    td_next = td_list[1];
+
+    state = USB_TYPE_IDLE;
+}
+
+void Endpoint::setSize(uint32_t size) {
+    hced->control &= ~(0x3ff << 16);
+    hced->control |= (size << 16);
+}
+
+
+uint32_t Endpoint::getSize() {
+    return (hced->control >> 16) & 0x3ff;
+}
+
+void Endpoint::setDeviceAddress(uint8_t addr) {
+    hced->control &= ~(0x7f);
+    hced->control |= (addr & 0x7F);
+}
+
+uint8_t Endpoint::getDeviceAddress() {
+    return hced->control & 0x7f;
+}
+
+void Endpoint::setSpeed(uint8_t speed) {
+    if(speed) {
+        DBG("SET LOW SPEED");
+    }
+    hced->control &= ~(1 << 13);
+    hced->control |= (speed << 13);
+}
+
+
+void Endpoint::setNextToken(uint32_t token) { //Only for control Eps
+    switch (token) {
+        case TD_SETUP:
+            dir = OUT;
+            setup = true;
+            break;
+        case TD_IN:
+            dir = IN;
+            setup = false;
+            break;
+        case TD_OUT:
+            dir = OUT;
+            setup = false;
+            break;
+    }
+}
+
+volatile HCTD* Endpoint::getNextTD()
+{
+  return td_current/*(HCTD*) hced->tailTD*/; //It's the tailing one
+}
+
+void Endpoint::queueTransfer() {
+  //Try with OHCI impl
+  //Caller of getNextTD() has now populated the td
+  //So insert it into queue
+
+  //Find an OTHER free td
+  //TODO: if we had more than 2 tds, this would have to be changed
+  /*HCTD* toSendTD = (HCTD*) hced->tailTD;*/
+  //HCTD* freeTD;
+/*
+  if( hced->tailTD == td_list[0] )
+  {
+    freeTD = td_list[1];
+  }
+  else *//*if( hced->tailTD == (uint32_t) td_list[1] )*/
+  /*{
+    freeTD = td_list[0];
+  }
+  */
+
+  /*
+  freeTD->control = 0;
+  freeTD->currBufPtr = 0;
+  freeTD->bufEnd = 0;
+  freeTD->nextTD = 0;
+
+  td_current = toSendTD;
+*/
+  transfer_len = td_current->bufEnd - td_current->currBufPtr + 1;
+  transferred = transfer_len;
+  buf_start = td_current->currBufPtr;
+
+  //No add this free TD at this end of the queue
+  state = USB_TYPE_PROCESSING;
+  td_current->nextTD = (volatile uint32_t)td_next;
+  hced->tailTD = (volatile uint32_t)td_next;
+
+  #if 0
+    // if TD list empty -> we put the head of the list
+    if (!hced->headTD) {
+        state = USB_TYPE_IDLE;
+        hced->headTD = (uint32_t)(td);
+        hced->tailTD = (uint32_t)(td);
+        tailTD = (HCTD *) (hced->headTD);
+        //DBG("queue null transfer: endpoint: %p,  %08X\r\n", this, (uint32_t)(td));
+    } else {
+        state = USB_TYPE_PROCESSING;
+        td->nextTD = (uint32_t)headTD & ~(0x0f);
+        hced->headTD = (uint32_t)(td) | ((carry) ? 0x2 : 0);
+    }
+    headTD = (HCTD *) ((hced->headTD) & ~(0x3));
+    transfer_len = td->bufEnd - td->currBufPtr + 1;
+    transferred = transfer_len;
+    buf_start = td->currBufPtr;
+#endif
+    //printf("queue real transfer: endpoint: %p \t headTD: %p \t head: %08X \t tail: %08X \t td: %08X \t nexttd: %08X\r\n", this, hced->headTD, hced->headTD, ((HCTD *)((hced->headTD) & ~(0x0f)))->nextTD, toSendTD, toSendTD->nextTD);
+}
+
+volatile HCTD * Endpoint::getProcessedTD()
+{
+  return td_current;
+}
+
+void Endpoint::setLengthTransferred(int len) {
+    transferred = len;
+}
+
+uint32_t Endpoint::getBufStart() {
+    return buf_start;
+}
+
+void Endpoint::unqueueTransfer(volatile HCTD * td) {
+    //printf("unqueue transfer: %p on endpoint: %p\r\n", (void *)td, this);
+    //headTD = tailTD; //FIXME FIXME
+//  hced->headTD = hced->headTD | (td->  & 0x02);
+  if(td != td_current)
+  {
+    ERR("MISMATCH");
+    ERR("this=%p, td_current = %p, td_next=%p, td=%p", this, td_current, td_next, td);
+    error("");
+  }
+  td->control=0;
+  td->currBufPtr=0;
+  td->bufEnd=0;
+  td->nextTD=0;
+  hced->headTD = hced->tailTD | (hced->headTD & 0x2); //Carry bit
+  td_current = td_next;
+  td_next = td;
+  DBG("current:%p, next:%p", td_current, td_next);
+}
+
+ENDPOINT_TYPE Endpoint::getType() {
+    return type;
+}
+
+
+Endpoint * Endpoint::nextEndpoint() {
+    return (Endpoint*)nextEp;
+}
+
+
+void Endpoint::queueEndpoint(Endpoint * ed) {
+    nextEp = ed;
+    hced->nextED = (ed == NULL) ? 0 : (uint32_t)ed->getHCED();
+}
+
+volatile HCED * Endpoint::getHCED() {
+    return hced;
+}
+
+
+volatile HCTD * Endpoint::getHeadTD() {
+    //return headTD;
+  return (volatile HCTD*) (hced->headTD & ~0xF);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/Endpoint.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,188 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef ENDPOINT_H
+#define ENDPOINT_H
+
+#include "stdint.h"
+#include "FunctionPointer.h"
+#include "USBHostTypes.h"
+
+
+enum ENDPOINT_TYPE {
+    CONTROL_ENDPOINT = 0,
+    ISOCHRONOUS_ENDPOINT,
+    BULK_ENDPOINT,
+    INTERRUPT_ENDPOINT
+};
+
+enum ENDPOINT_DIRECTION {
+    OUT = 1,
+    IN  
+};
+
+class Endpoint {
+public:
+    /*
+    * Constructor
+    */
+    Endpoint() {state = USB_TYPE_FREE; nextEp = NULL;};
+    
+    /*
+    * Initialize an endpoint
+    *
+    * @param hced hced associated to the endpoint
+    * @param type endpoint type
+    * @param dir endpoint direction
+    * @param size endpoint size
+    * @param ep_number endpoint number
+    */
+    void init(HCED * hced, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t ep_number, HCTD* td_list[2]);
+    
+    /*
+    * Set next token. Warining: only useful for the control endpoint
+    *
+    * @param token IN, OUT or SETUP token
+    */
+    void setNextToken(uint32_t token);
+    
+    /*
+    * Queue an endpoint
+    *
+    * endpoint endpoint which will be queued in the linked list
+    */
+    void queueEndpoint(Endpoint * endpoint);
+    
+    /*
+    * Get a td to be queued
+    *
+    * @returns td hctd which will be queued
+    */
+    volatile HCTD* getNextTD();
+
+    /*
+    * Queue a transfer on the endpoint
+    *
+    */
+    void queueTransfer();
+    
+    /*
+    * Get the currently processed td
+    *
+    * @returns td hctd that was queued
+    */
+    volatile HCTD * getProcessedTD();
+
+    /*
+    * Unqueue a transfer from the endpoint
+    *
+    * @param td hctd which will be unqueued
+    */
+    void unqueueTransfer(volatile HCTD * td);
+    
+    /*
+    * Return the next endpoint in the linked list
+    *
+    * @returns next endpoint
+    */
+    Endpoint * nextEndpoint();
+    
+    /**
+     *  Attach a member function to call when a transfer is finished
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void)) {
+        if((mptr != NULL) && (tptr != NULL)) {
+            rx.attach(tptr, mptr);
+        }
+    }
+
+    /**
+     * Attach a callback called when a transfer is finished
+     *
+     * @param fptr function pointer
+     */
+    void attach(void (*fn)(void)) {
+        if(fn != NULL) {
+            rx.attach(fn);
+        }
+    }
+    
+    /*
+    * Call the handler associted to the end of a transfer
+    */
+    void call() {
+        rx.call();
+    };
+    
+    
+    /*
+    * Setters
+    */
+    void setState(USB_TYPE st) {state = st;}
+    void setDeviceAddress(uint8_t addr);
+    void setLengthTransferred(int len);
+    void setSpeed(uint8_t speed);
+    void setSize(uint32_t size);
+    void setDir(ENDPOINT_DIRECTION d) {dir = d;}
+    
+    /*
+    * Getters
+    */
+    USB_TYPE            getState() {return state;}
+    ENDPOINT_TYPE       getType();
+    uint8_t             getDeviceAddress();
+    int        getLengthTransferred() {return transferred;}
+    uint32_t   getBufStart();
+    uint32_t            getSize();
+    volatile HCTD *     getHeadTD();
+    volatile HCED *     getHCED();
+    ENDPOINT_DIRECTION  getDir() {return dir;}
+    bool                isSetup() {return setup;}
+    
+    
+private:
+    ENDPOINT_TYPE type;
+    volatile USB_TYPE state;
+    ENDPOINT_DIRECTION dir;
+    bool setup;
+    
+    int transfer_len;
+    int transferred;
+    uint32_t buf_start;
+    
+    FunctionPointer rx;
+    
+    Endpoint* nextEp;
+    
+    // Endpoint descriptor
+    volatile HCED * hced;
+    
+    volatile HCTD * td_list[2];
+    volatile HCTD * td_current;
+    volatile HCTD * td_next;
+    /*bool carry;*/
+    
+    int count;
+    
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBDeviceConnected.cpp	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "USBDeviceConnected.h"
+
+USBDeviceConnected::USBDeviceConnected() {
+    init();
+}
+
+void USBDeviceConnected::init() {
+    hub = 0;
+    port = 0;
+    vid = 0;
+    pid = 0;
+    nb_interf = 0;
+    enumerated = false;
+    activeAddr = false;
+    sizeControlEndpoint = 8;
+    device_class = 0;
+    device_subclass = 0;
+    proto = 0;
+    speed = false;
+    for (int i = 0; i < MAX_INTF; i++) {
+        memset((void *)&intf[i], 0, sizeof(INTERFACE));
+        intf[i].in_use = false;
+        for (int j = 0; j < MAX_ENDPOINT_PER_INTERFACE; j++) {
+            intf[i].ep[j] = NULL;
+        }
+    }
+}
+
+INTERFACE * USBDeviceConnected::getInterface(uint8_t index) {
+    if (index >= MAX_INTF) {
+        return NULL;
+    }
+    return &intf[index];
+}
+
+bool USBDeviceConnected::addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) {
+    if ((intf_nb >= MAX_INTF) || (intf[intf_nb].in_use)) {
+        return false;
+    }
+    intf[intf_nb].in_use = true;
+    intf[intf_nb].intf_class = intf_class;
+    intf[intf_nb].intf_subclass = intf_subclass;
+    intf[intf_nb].intf_protocol = intf_protocol;
+    intf[intf_nb].nb_endpoint = 0;
+    nb_interf++;
+    return true;
+}
+
+bool USBDeviceConnected::addEndpoint(uint8_t intf_nb, Endpoint * ept) {
+    if ((intf_nb >= MAX_INTF) || (intf[intf_nb].in_use == false) || (intf[intf_nb].nb_endpoint >= MAX_ENDPOINT_PER_INTERFACE)) {
+        return false;
+    }
+    intf[intf_nb].nb_endpoint++;
+
+    for (int i = 0; i < MAX_ENDPOINT_PER_INTERFACE; i++) {
+        if (intf[intf_nb].ep[i] == NULL) {
+            intf[intf_nb].ep[i] = ept;
+            return true;
+        }
+    }
+    return false;
+}
+
+void USBDeviceConnected::init(uint8_t hub, uint8_t port, bool lowSpeed) {
+    init();
+    this->hub = hub;
+    this->port = port;
+    this->speed = lowSpeed;
+}
+
+void USBDeviceConnected::disconnect() {
+    for(int i = 0; i < nb_interf; i++) {
+        intf[i].detach.call();
+    }
+    init();
+}
+
+
+
+Endpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) {
+    if (intf_nb >= MAX_INTF) {
+        return NULL;
+    }
+    for (int i = 0; i < MAX_ENDPOINT_PER_INTERFACE; i++) {
+        if ((intf[intf_nb].ep[i]->getType() == type) && (intf[intf_nb].ep[i]->getDir() == dir)) {
+            return intf[intf_nb].ep[i];
+        }
+    }
+    return NULL;
+}
+
+Endpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, uint8_t index) {
+    if ((intf_nb >= MAX_INTF) || (index >= MAX_ENDPOINT_PER_INTERFACE)) {
+        return NULL;
+    }
+    return intf[intf_nb].ep[index];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBDeviceConnected.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,203 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBDEVICECONNECTED_H
+#define USBDEVICECONNECTED_H
+
+#include "stdint.h"
+#include "Endpoint.h"
+
+#define MAX_ENDPOINT_PER_INTERFACE  4
+#define MAX_INTF                    4
+
+typedef struct {
+    bool in_use;
+    uint8_t nb_endpoint;
+    uint8_t intf_class;
+    uint8_t intf_subclass;
+    uint8_t intf_protocol;
+    Endpoint * ep[MAX_ENDPOINT_PER_INTERFACE];
+    FunctionPointer detach;
+}INTERFACE;
+
+
+class USBDeviceConnected {
+public:
+
+    /*
+    * Constructor
+    */
+    USBDeviceConnected();
+
+    /*
+    * Attach an endpoint to this device
+    *
+    * @param ep pointeur on the endpoint which will be attached
+    * @returns true if successful, false otherwise
+    */
+    bool addEndpoint(uint8_t intf_nb, Endpoint * ep);
+
+    /*
+    * Retrieve an endpoint by its TYPE and DIRECTION
+    *
+    * @param type type of the endpoint looked for
+    * @param direction of the endpoint looked for
+    * @returns pointer on the endpoint if found, NULL otherwise
+    */
+    Endpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir);
+    
+    /*
+    * Retrieve an endpoint by its index
+    *
+    * @param index index of the endpoint
+    * @returns pointer on the endpoint if found, NULL otherwise
+    */
+    Endpoint * getEndpoint(uint8_t intf_nb, uint8_t index);
+    
+    bool addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol);
+    
+    uint8_t getNbInterface() {return nb_interf;};
+    
+    INTERFACE * getInterface(uint8_t index);
+
+    /**
+     *  Attach a member function to call when a the device has been disconnected
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void onDisconnect(uint8_t intf_nb, T* tptr, void (T::*mptr)(void)) {
+        if ((mptr != NULL) && (tptr != NULL)) {
+            intf[intf_nb].detach.attach(tptr, mptr);
+        }
+    }
+
+    /**
+     * Attach a callback called when the device has been disconnected
+     *
+     * @param fptr function pointer
+     */
+    void onDisconnect(uint8_t intf_nb, void (*fn)(void)) {
+        if (fn != NULL) {
+            intf[intf_nb].detach.attach(fn);
+        }
+    }
+
+    /*
+    * Disconnect the device by calling a callback function registered by a driver
+    */
+    void disconnect();
+
+    /*
+    * Setters
+    */
+    void init(uint8_t hub, uint8_t port, bool lowSpeed);
+    void setAddress(uint8_t addr) {
+        this->addr = addr;
+    };
+    void setVid(uint16_t vid) {
+        this->vid = vid;
+    };
+    void setPid(uint16_t pid) {
+        this->pid = pid;
+    };
+    void setClass(uint8_t device_class) {
+        this->device_class = device_class;
+    };
+    void setSubClass(uint8_t device_subclass) {
+        this->device_subclass = device_subclass;
+    };
+    void setProtocol(uint8_t pr) {
+        proto = pr;
+    };
+    void setSizeControlEndpoint(uint32_t size) {
+        sizeControlEndpoint = size;
+    };
+    void activeAddress() {
+        activeAddr = true;
+    };
+    void setEnumerated() {
+        enumerated = true;
+    };
+
+    /*
+    * Getters
+    */
+    uint8_t     getPort() {
+        return port;
+    };
+    uint8_t     getHub() {
+        return hub;
+    };
+    uint8_t     getAddress() {
+        return addr;
+    };
+    uint16_t    getVid() {
+        return vid;
+    };
+    uint16_t    getPid() {
+        return pid;
+    };
+    uint8_t     getClass() {
+        return device_class;
+    };
+    uint8_t     getSubClass() {
+        return device_subclass;
+    };
+    uint8_t     getProtocol() {
+        return proto;
+    };
+    bool        getSpeed() {
+        return speed;
+    };
+    uint32_t    getSizeControlEndpoint() {
+        return sizeControlEndpoint;
+    };
+    bool        isActiveAddress() {
+        return activeAddr;
+    };
+    bool        isEnumerated() {
+        return enumerated;
+    };
+
+
+private:
+    INTERFACE intf[MAX_INTF];
+    //Endpoint * ep[MAX_ENDPOINT_PER_DEVICE];
+    uint32_t sizeControlEndpoint;
+    uint8_t hub;
+    uint8_t port;
+    uint16_t vid;
+    uint16_t pid;
+    uint8_t addr;
+    uint8_t device_class;
+    uint8_t device_subclass;
+    uint8_t proto;
+    bool speed;
+    bool activeAddr;
+    bool enumerated;
+    
+    uint8_t nb_interf;
+
+    
+    void init();
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.cpp	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,404 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/
+
+
+#define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT...
+#ifndef __MODULE__
+#define __MODULE__ "USBHALHost.cpp"
+#endif
+
+#include "dbg.h"
+#include <cstdint>
+
+#include "mbed.h"
+#include "USBHALHost.h"
+
+// bits of the USB/OTG clock control register
+#define HOST_CLK_EN     (1<<0)
+#define DEV_CLK_EN      (1<<1)
+#define PORTSEL_CLK_EN  (1<<3)
+#define AHB_CLK_EN      (1<<4)
+
+// bits of the USB/OTG clock status register
+#define HOST_CLK_ON     (1<<0)
+#define DEV_CLK_ON      (1<<1)
+#define PORTSEL_CLK_ON  (1<<3)
+#define AHB_CLK_ON      (1<<4)
+
+// we need host clock, OTG/portsel clock and AHB clock
+#define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
+
+
+
+#define HCCA_SIZE 0x100
+#define ED_SIZE 0x10
+#define TD_SIZE 0x10
+
+#define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
+
+static volatile __align(256) uint8_t usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM0"),aligned));  //256 bytes aligned!
+
+USBHALHost * USBHALHost::instHost;
+
+USBHALHost::USBHALHost() : thread(USBHALHost::staticCb, (void*)this, osPriorityNormal, 4*128) {
+    instHost = this;
+    memInit();
+    memset((void*)usb_hcca, 0, HCCA_SIZE);
+    for (int i = 0; i < MAX_ENDPOINT; i++) {
+        edBufAlloc[i] = false;
+    }
+    for (int i = 0; i < MAX_TD; i++) {
+        tdBufAlloc[i] = false;
+    }
+}
+
+
+void USBHALHost::init() {
+  thread.signal_set(USBHALHOST_SIG_INIT);
+}
+
+
+uint32_t USBHALHost::controlHeadED() {
+    return LPC_USB->HcControlHeadED;
+}
+
+uint32_t USBHALHost::bulkHeadED() {
+    return LPC_USB->HcBulkHeadED;
+}
+
+uint32_t USBHALHost::interruptHeadED() {
+    return usb_hcca->IntTable[0];
+}
+
+void USBHALHost::updateBulkHeadED(uint32_t addr) {
+    LPC_USB->HcBulkHeadED = addr;
+}
+
+
+void USBHALHost::updateControlHeadED(uint32_t addr) {
+    LPC_USB->HcControlHeadED = addr;
+}
+
+void USBHALHost::updateInterruptHeadED(uint32_t addr) {
+    usb_hcca->IntTable[0] = addr;
+}
+
+
+void USBHALHost::enableControlList() {
+    LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
+    LPC_USB->HcControl       |= OR_CONTROL_CLE; //Enable control list
+}
+
+void USBHALHost::enableBulkList() {
+    LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
+    LPC_USB->HcControl       |= OR_CONTROL_BLE; //Enable bulk list
+}
+
+void USBHALHost::enableInterruptList() {
+    LPC_USB->HcControl |= OR_CONTROL_PLE;
+}
+
+bool USBHALHost::disableControlList() {
+    if(LPC_USB->HcControl & OR_CONTROL_CLE)
+    {
+      LPC_USB->HcControl       &= ~OR_CONTROL_CLE; //Disable control list
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+}
+
+bool USBHALHost::disableBulkList() {
+    if(LPC_USB->HcControl & OR_CONTROL_BLE)
+    {
+      LPC_USB->HcControl       &= ~OR_CONTROL_BLE; //Disable bulk list
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+}
+
+bool USBHALHost::disableInterruptList() {
+    if(LPC_USB->HcControl & OR_CONTROL_PLE)
+    {
+      LPC_USB->HcControl       &= ~OR_CONTROL_PLE; //Disable interrupt list
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+}
+
+//Lock processing
+void USBHALHost::lock()
+{
+  mtx.lock();
+}
+
+void USBHALHost::unlock()
+{
+  mtx.unlock();
+}
+
+void USBHALHost::memInit() {
+    usb_hcca = (volatile HCCA *)usb_buf;
+    usb_edBuf = usb_buf + HCCA_SIZE;
+    usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
+}
+
+volatile uint8_t * USBHALHost::getED() {
+    for (int i = 0; i < MAX_ENDPOINT; i++) {
+        if ( !edBufAlloc[i] ) {
+            edBufAlloc[i] = true;
+            return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
+        }
+    }
+    perror("Could not allocate ED\r\n");
+    return NULL; //Could not alloc ED
+}
+
+volatile uint8_t * USBHALHost::getTD() {
+    int i;
+    for (i = 0; i < MAX_TD; i++) {
+        if ( !tdBufAlloc[i] ) {
+            tdBufAlloc[i] = true;
+            return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
+        }
+    }
+    perror("Could not allocate TD\r\n");
+    return NULL; //Could not alloc TD
+}
+
+
+void USBHALHost::freeED(volatile uint8_t * ed) {
+    int i;
+    i = (ed - usb_edBuf) / ED_SIZE;
+    edBufAlloc[i] = false;
+}
+
+void USBHALHost::freeTD(volatile uint8_t * td) {
+    int i;
+    i = (td - usb_tdBuf) / TD_SIZE;
+    tdBufAlloc[i] = false;
+}
+
+
+void USBHALHost::resetPort(int hub, int port) {
+    DBG("Resetting hub %d, port %d\n", hub, port);
+    if (hub == 0) { //Root hub
+        // USB 2.0 spec says at least 50ms delay before port reset
+        Thread::wait(200);
+        LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
+        while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
+        LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
+        // Wait for 100 MS after port reset
+        Thread::wait(200);
+    } else {
+        //TODO: Hubs
+    }
+}
+
+
+void USBHALHost::_usbisr(void) {
+    if (instHost) {
+        instHost->UsbIrqhandler();
+    }
+}
+
+void USBHALHost::UsbIrqhandler() {
+  if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
+  {
+    NVIC_DisableIRQ(USB_IRQn);
+    NVIC_ClearPendingIRQ(USB_IRQn);
+    thread.signal_set(USBHALHOST_SIG_IRQ); //Signal processing thread
+  }
+
+}
+
+void USBHALHost::process()
+{
+  DBG("USB Process started");
+
+  lock();
+  Thread::signal_wait(USBHALHOST_SIG_INIT);
+
+  NVIC_DisableIRQ(USB_IRQn);                           // Disable the USB interrupt source
+
+  LPC_SC->PCONP       &= ~(1UL<<31); //Cut power
+  Thread::wait(200);
+
+  // turn on power for USB
+  LPC_SC->PCONP       |= (1UL<<31);
+
+  // Enable USB host clock, port selection and AHB clock
+  LPC_USB->USBClkCtrl |= CLOCK_MASK;
+
+  // Wait for clocks to become available
+  while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK);
+
+  // it seems the bits[0:1] mean the following
+  // 0: U1=device, U2=host
+  // 1: U1=host, U2=host
+  // 2: reserved
+  // 3: U1=host, U2=device
+  // NB: this register is only available if OTG clock (aka "port select") is enabled!!
+  // since we don't care about port 2, set just bit 0 to 1 (U1=host)
+  LPC_USB->OTGStCtrl |= 1;
+
+  // now that we've configured the ports, we can turn off the portsel clock
+  LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
+
+  // configure USB D+/D- pins
+  // P0[29] = USB_D+, 01
+  // P0[30] = USB_D-, 01
+  LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
+  LPC_PINCON->PINSEL1 |=  ((1<<26)|(1<<28));     // 0x14000000
+
+  LPC_USB->HcControl       = 0;                       // HARDWARE RESET
+  LPC_USB->HcControlHeadED = 0;                       // Initialize Control list head to Zero
+  LPC_USB->HcBulkHeadED    = 0;                       // Initialize Bulk list head to Zero
+
+  //wait_ms(100);                                   // Wait 50 ms before apply reset
+  Thread::wait(100);
+
+  // SOFTWARE RESET
+  LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
+  LPC_USB->HcFmInterval    = DEFAULT_FMINTERVAL;      // Write Fm Interval and Largest Data Packet Counter
+  LPC_USB->HcPeriodicStart = FI * 90 / 100;
+
+  // Put HC in operational state
+  LPC_USB->HcControl  = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
+  LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;            // Set Global Power
+
+  LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
+  LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;                   // Clear Interrrupt Status
+
+  LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
+
+  //DG: Do not set prio
+  //NVIC_SetPriority(USB_IRQn, 0);       // highest priority
+  // Enable the USB Interrupt
+  NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
+  LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
+  LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
+
+  NVIC_EnableIRQ(USB_IRQn);
+
+
+  // Check for any connected devices
+  if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { //Root device connected
+      //Device connected
+      Thread::wait(500);
+      DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1);
+      deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
+  }
+
+  unlock();
+
+
+  for(;;)
+  {
+    Thread::signal_wait(USBHALHOST_SIG_IRQ); //Wait for IRQ to process
+
+    lock();
+    DBG("Locked");
+
+    WARN("isr %08x [EN %08x]", LPC_USB->HcInterruptStatus, LPC_USB->HcInterruptEnable);
+
+    //Now process IRQ
+    uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
+
+    if (int_status & OR_INTR_STATUS_RHSC)
+    { // Root hub status change interrupt
+      WARN("Port status %08x", LPC_USB->HcRhPortStatus1);
+      if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC)
+      {
+        if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE)
+        {
+
+          // When DRWE is on, Connect Status Change
+          // means a remote wakeup event.
+
+        }
+        else
+        {
+
+          // When DRWE is off, Connect Status Change
+          // is NOT a remote wakeup event
+
+          if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS)
+          { //Root device connected
+            //Device connected
+            WARN("Device connected!!");
+           // Thread::wait(500);
+            deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
+          }
+          else
+          { //Root device disconnected
+            //Device disconnected
+            WARN("Device disconnected!!");
+            Thread::wait(500);
+            if (!(int_status & OR_INTR_STATUS_WDH))
+            {
+              usb_hcca->DoneHead = 0;
+            }
+            deviceDisconnected(0, 1, usb_hcca->DoneHead & 0xFFFFFFFE);
+            if (int_status & OR_INTR_STATUS_WDH)
+            {
+              usb_hcca->DoneHead = 0;
+              LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
+            }
+
+          }
+          //TODO: HUBS
+        }
+        LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
+      }
+      if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC)
+      {
+        LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
+        //int_status &= ~OR_RH_PORT_PRSC;
+      }
+      LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
+    }
+
+    if (int_status & OR_INTR_STATUS_WDH)
+    { // Writeback Done Head interrupt
+      transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
+      LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
+    }
+
+    //IRQ Processed
+
+    DBG("Unlocked");
+
+    NVIC_EnableIRQ(USB_IRQn);
+
+    unlock();
+
+  }
+}
+
+/*static*/ void USBHALHost::staticCb(void const* p)
+{
+  ((USBHALHost*)p)->process();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,206 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBHALHOST_H
+#define USBHALHOST_H
+
+#include "rtos.h"
+
+#include "USBHostTypes.h"
+
+#define MAX_ENDPOINT 6
+#define MAX_TD (MAX_ENDPOINT*2)
+
+#define USBHALHOST_SIG_INIT 0x01
+#define USBHALHOST_SIG_IRQ 0x02
+
+class USBHALHost {
+public:
+
+    /*
+    * Constructor
+    *     init variables and memory where will be stored HCCA, ED and TD
+    */
+    USBHALHost();
+    
+    /*
+    * Initialize host controller. Enable USB interrupts. This part is not in the constructor because, 
+    * this function calls a virtual method if a device is already connected
+    */
+    void init();
+    
+    /*
+    * reset a port of a specific hub
+    * TODO: support hub
+    */
+    void resetPort(int hub, int port);
+    
+    /*
+    * return the value contained in the control HEAD ED register
+    *
+    * @returns address of the control Head ED
+    */
+    uint32_t controlHeadED();
+    
+    /*
+    * return the value contained in the bulk HEAD ED register
+    *
+    * @returns address of the bulk head ED
+    */
+    uint32_t bulkHeadED();
+    
+    /*
+    * return the value of the head interrupt ED contained in the HCCA
+    *
+    * @returns address of the head interrupt ED contained in the HCCA
+    */
+    uint32_t interruptHeadED();
+    
+    
+    /*
+    * Update the head ED for control transfers
+    */
+    void updateControlHeadED(uint32_t addr);
+    
+    /*
+    * Update the head ED for bulk transfers
+    */
+    void updateBulkHeadED(uint32_t addr);
+    
+    /*
+    * Update the head ED for interrupt transfers
+    */
+    void updateInterruptHeadED(uint32_t addr);
+    
+    /* 
+    * Enable control list ED
+    */
+    void enableControlList();
+    
+    /* 
+    * Enable bulk list ED
+    */
+    void enableBulkList();
+    
+    /* 
+    * Enable Interrupt list ED
+    */
+    void enableInterruptList();
+    
+    /*
+    * Disable control list ED
+    */
+    bool disableControlList();
+
+    /*
+    * Disable bulk list ED
+    */
+    bool disableBulkList();
+
+    /*
+    * Disable Interrupt list ED
+    */
+    bool disableInterruptList();
+
+    //Lock processing
+    void lock();
+
+    void unlock();
+
+
+protected:
+    /*
+    * Virtual method called when a device has been connected
+    *
+    * @param hub hub number of the device
+    * @param port port number of the device
+    * @param lowSpeed 1 if low speed, 0 otherwise
+    */
+    virtual void deviceConnected(int hub, int port, bool lowSpeed) {};
+    
+    /*
+    * Virtuel method called when a device has been disconnected
+    *
+    * @param hub hub number of the device
+    * @param port port number of the device
+    * @param addr list of the TDs which have been completed to dequeue freed TDs
+    */
+    virtual void deviceDisconnected(int hub, int port, volatile uint32_t addr) {};
+    
+    /*
+    * Virtual method called when a transfer has been completed
+    *
+    * @param addr list of the TDs which have been completed
+    */
+    virtual void transferCompleted(volatile uint32_t addr){};
+    
+    /*
+    * Find a memory section for a new ED
+    *
+    * @returns the address of this section
+    */
+    volatile uint8_t * getED();
+    
+    /*
+    * Find a memory section for a new TD
+    *
+    * @returns the address of this section
+    */
+    volatile uint8_t * getTD();
+    
+    /*
+    * Release a previous memory section reserved for an ED
+    *
+    * @param ed address of the ED
+    */
+    void freeED(volatile uint8_t * ed);
+    
+    /*
+    * Release a previous memory section reserved for an TD
+    *
+    * @param ed address of the TD
+    */
+    void freeTD(volatile uint8_t * td);
+    
+
+private:
+    static void _usbisr(void);
+    void UsbIrqhandler();
+
+    void memInit();
+
+    void process();
+    
+    static void staticCb(void const* p);
+
+    HCCA volatile * usb_hcca;       //256 bytes aligned!
+    uint8_t volatile  * usb_edBuf;   //4 bytes aligned!
+    uint8_t volatile  * usb_tdBuf;   //4 bytes aligned!
+
+    static USBHALHost * instHost;
+    
+    bool volatile  edBufAlloc[MAX_ENDPOINT];
+    bool volatile tdBufAlloc[MAX_TD];
+    
+    //RTOS impl
+    Thread thread;
+    Mutex mtx;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,945 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT...
+#ifndef __MODULE__
+#define __MODULE__ "USBHost.cpp"
+#endif
+
+#include "dbg.h"
+#include <cstdint>
+
+#include "USBHost.h"
+#include "rtos.h"
+
+
+#define NB_MAX_INTF 3
+
+USBHost * USBHost::instHost = NULL;
+
+USBHost::USBHost()
+#if 0 //try not to use this
+    : m_usbQueue(), m_usbThread(3, this, &USBHost::usbProcess)
+#endif
+{
+  headControlEndpoint = NULL;
+  headBulkEndpoint = NULL;
+  headInterruptEndpoint = NULL;
+  tailControlEndpoint = NULL;
+  tailBulkEndpoint = NULL;
+  tailInterruptEndpoint = NULL;
+
+  nb_devices = 0;
+  lenReportDescr = 0;
+
+  controlEndpointAllocated = false;
+
+  for (int i = 0; i < MAX_DEVICE_NB; i++) {
+    deviceInUse[i] = false;
+    devices[i].setAddress(i + 1);
+    deviceReset[i] = false;
+  }
+}
+
+
+void USBHost::transferCompleted(volatile uint32_t addr)  {
+#if 0 //try not to use this
+  Interrupt::enter();
+  m_usbQueue.post(addr);
+  Interrupt::leave();
+#else
+
+  if(addr == NULL) //Nothing to process?
+  {
+    return;
+  }
+
+  volatile HCTD* tdList = NULL;
+
+  //First we must reverse the list order and dequeue each TD
+  do
+  {
+    volatile HCTD* td = (volatile HCTD*)addr;
+
+    if(td->control & 0xF0000000 != 0)
+    {
+      WARN("Condition code %02x", td->control >> 28);
+    }
+
+    addr = td->nextTD; //Dequeue from physical list
+    td->nextTD = (uint32_t)tdList; //Enqueue into reversed list
+    tdList = td;
+  } while(addr);
+
+  //Now we can process the list
+  Endpoint * volatile iter = NULL;
+
+  while(tdList != NULL)
+  {
+    bool found = false;
+    volatile HCTD* td = tdList;
+    tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below
+    for (int i = 0; i < 3; i++) {
+      if (found) {
+        break;
+      }
+      iter = (i == 0) ? headControlEndpoint : ( (i == 1) ? headBulkEndpoint : headInterruptEndpoint);
+      while (iter != NULL) {
+        if (iter->getProcessedTD() == td) {
+          DBG("td=%p FOUND ed: %08X", td, (void *)iter->getHCED());
+          if (((HCTD *)td)->control >> 28) {
+            DBG("TD Error: %d", td->control >> 28);
+            iter->setState(USB_TYPE_TDFAIL);
+          } else if ((uint32_t)iter->getHCED() & 0x1) {
+            DBG("HALTED");
+            iter->setState(USB_TYPE_HALTED);
+          } else if (!td->currBufPtr) {
+            DBG("!%p", iter);
+            iter->setState(USB_TYPE_IDLE);
+            found=true;
+          } else {
+            DBG("!%p", iter);
+            iter->setState(USB_TYPE_IDLE);
+            iter->setLengthTransferred(td->currBufPtr - iter->getBufStart());
+            found=true;
+          }
+          break;
+        }
+        iter = iter->nextEndpoint();
+      }
+    }
+
+
+    if (found) {
+      iter->unqueueTransfer(td);
+
+      if (iter->getType() != CONTROL_ENDPOINT) {
+        iter->call();
+      }
+    }
+    else
+    {
+      WARN("TD not found!!!");
+      freeTD((uint8_t *)td); //Device must have been disconnected meanwhile
+    }
+
+  }
+#endif
+}
+
+USBHost * USBHost::getHostInst() {
+  if (instHost == NULL) {
+    instHost = new USBHost();
+    instHost->init();
+  }
+  return instHost;
+}
+
+
+/*
+ * Call in ISR when a device has been connected
+ */
+void USBHost::deviceConnected(int hub, int port, bool lowSpeed)  {
+
+  for (int i = 0; i < MAX_DEVICE_NB; i++) {
+    if (!deviceInUse[i]) {
+      deviceInUse[i] = true;
+      WARN("will call init on device %p: speed: %d", (void *)&devices[i], lowSpeed);
+      devices[i].init(hub, port, lowSpeed);
+      deviceReset[i] = false;
+      break;
+    }
+  }
+
+  if (!controlEndpointAllocated) {
+    control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00);
+    addEndpoint(NULL, 0, (Endpoint*)control);
+    controlEndpointAllocated = true;
+  }
+}
+
+/*
+ * Call in ISR when a device has been disconnected
+ */
+void USBHost::deviceDisconnected(int hub, int port, volatile uint32_t addr)  {
+
+  bool controlListState = disableControlList();
+  bool bulkListState = disableBulkList();
+  bool interruptListState = disableInterruptList();
+
+  transferCompleted(addr); //Finish processing any pending completed TD
+
+  for (int i = 0; i < MAX_DEVICE_NB; i++) {
+    if ((devices[i].getHub() == hub) && (devices[i].getPort() == port)) {
+      WARN("device disconnected: %p", (void *)&devices[i]);
+      deviceInUse[i] = false;
+      deviceReset[i] = false;
+      freeDevice((USBDeviceConnected*)&devices[i]);
+      break;
+    }
+  }
+  nb_devices--;
+
+  if (controlListState) enableControlList();
+  if (bulkListState) enableBulkList();
+  if (interruptListState) enableInterruptList();
+}
+
+void USBHost::freeDevice(USBDeviceConnected * dev)  {
+  Endpoint * ep = NULL;
+//  HCTD * td = NULL;
+  HCED * ed = NULL;
+
+  for (int j = 0; j < dev->getNbInterface(); j++) {
+    DBG("FREE INTF %d, %p, nb_endpot: %d", j, (void *)dev->getInterface(j), dev->getInterface(j)->nb_endpoint);
+    for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) {
+      if ((ep = dev->getEndpoint(j, i)) != NULL) {
+        DBG("Freeing endpoint");
+        ed = (HCED *)ep->getHCED();
+        ed->control |= (1 << 13); //sKip bit
+        DBG("Dequeueing endpoint");
+        unqueueEndpoint(ep);
+
+        DBG("Freeing head transfer descriptor");
+        freeTD((volatile uint8_t*)ep->getHeadTD());
+        DBG("Freeing tail transfer descriptor");
+        freeTD((volatile uint8_t*)ep->getNextTD());
+
+        DBG("Freeing endpoint descriptor");
+        freeED((uint8_t *)ep->getHCED());
+      }
+      //printBulk();
+      //printInt();
+    }
+  }
+  DBG("Disconnecting device");
+  dev->disconnect();
+  DBG("Device disconnected");
+}
+
+
+void USBHost::unqueueEndpoint(Endpoint * ep)  {
+  Endpoint * prec = NULL;
+  Endpoint * current = NULL;
+  bool found = false;
+
+  DBG("want to unqueue ep: %p", (void *)ep->getHCED());
+
+  for (int i = 0; i < 2; i++) {
+    if (found) {
+      DBG("endpoint unqueued: %p", (void *)ep->getHCED());
+      break;
+    }
+    current = (i == 0) ? (Endpoint*)headBulkEndpoint : (Endpoint*)headInterruptEndpoint;
+    prec = current;
+    while (current != NULL) {
+      if (current == ep) {
+        if (current->nextEndpoint() != NULL) {
+          prec->queueEndpoint(current->nextEndpoint());
+          if (current == headBulkEndpoint) {
+            updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED());
+            headBulkEndpoint = current->nextEndpoint();
+          }
+          if (current == headInterruptEndpoint) {
+            updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED());
+            headInterruptEndpoint = current->nextEndpoint();
+          }
+        } else {
+          prec->queueEndpoint(NULL);
+          if (current == headBulkEndpoint) {
+            updateBulkHeadED(0);
+            headBulkEndpoint = current->nextEndpoint();
+          }
+          if (current == headInterruptEndpoint) {
+            updateInterruptHeadED(0);
+            headInterruptEndpoint = current->nextEndpoint();
+          }
+        }
+        found = true;
+        current->setState(USB_TYPE_FREE);
+        break;
+      }
+      prec = current;
+      current = current->nextEndpoint();
+    }
+  }
+  //printBulk();
+  //printInt();
+}
+
+
+USBDeviceConnected * USBHost::getDevice(uint8_t index)  {
+  if ((index >= MAX_DEVICE_NB) || (!deviceInUse[index])) {
+    return NULL;
+  }
+  return (USBDeviceConnected*)&devices[index];
+}
+
+
+
+// create an endpoint descriptor. the endpoint is not linked
+Endpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr)  {
+  int i = 0;
+  HCED * ed = (HCED *)getED();
+  HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() };
+
+  memset((void *)td_list[0], 0x00, sizeof(HCTD));
+  memset((void *)td_list[1], 0x00, sizeof(HCTD));
+
+  // search a free endpoint
+  for (i = 0; i < MAX_ENDPOINT; i++) {
+    if (endpoints[i].getState() == USB_TYPE_FREE) {
+      DBG("Trying to create ep");
+      endpoints[i].init(ed, type, dir, size, addr, td_list);
+      //endpoints[i].queueTransfer(nullTd);
+      DBG("Endpoint created (%p): type: %d, dir: %d, size: %d, addr: %d", &endpoints[i], type, dir, size, addr);
+      return &endpoints[i];
+    }
+  }
+  DBG("could not allocate more endpoints!!!!");
+  return NULL;
+}
+
+
+void USBHost::resetDevice(USBDeviceConnected * dev)  {
+  int index = findDevice(dev);
+  if ((index != -1) && (!deviceReset[index])) {
+    resetPort(dev->getHub(), dev->getPort());
+    deviceReset[index] = true;
+  }
+}
+
+// link the endpoint to the linked list and attach an endpoint to a device
+bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, Endpoint * ep)  {
+
+  if (ep == NULL) {
+    return false;
+  }
+
+  DBG("New ep %p", ep);
+
+   HCED * prevEd;
+
+  // set device address in the endpoint descriptor
+  if (dev == NULL) {
+    ep->setDeviceAddress(0);
+  } else {
+    ep->setDeviceAddress(dev->getAddress());
+  }
+
+  if (dev != NULL && dev->getSpeed()) {
+    DBG("add endpoint: set speed");
+    ep->setSpeed(dev->getSpeed());
+  }
+
+  // queue the new endpoint on the ED list
+  switch (ep->getType()) {
+
+  case CONTROL_ENDPOINT:
+    prevEd = ( HCED*) controlHeadED();
+    if (!prevEd) {
+      updateControlHeadED((uint32_t) ep->getHCED());
+      DBG("First control endpoint: %08X", (uint32_t) ep->getHCED());
+      headControlEndpoint = ep;
+      tailControlEndpoint = ep;
+      return true;
+    }
+    tailControlEndpoint->queueEndpoint(ep);
+    tailControlEndpoint = ep;
+    return true;
+
+  case BULK_ENDPOINT:
+    prevEd = ( HCED*) bulkHeadED();
+    if (!prevEd) {
+      updateBulkHeadED((uint32_t) ep->getHCED());
+      //DBG("First bulk endpoint: %08X\r\n", (uint32_t) ep->getHCED());
+      headBulkEndpoint = ep;
+      tailBulkEndpoint = ep;
+      break;
+    }
+    tailBulkEndpoint->queueEndpoint(ep);
+    tailBulkEndpoint = ep;
+    break;
+
+  case INTERRUPT_ENDPOINT:
+    prevEd = ( HCED*) interruptHeadED();
+    if (!prevEd) {
+      updateInterruptHeadED((uint32_t) ep->getHCED());
+      //DBG("First interrupt endpoint: %08X\r\n", (uint32_t) ep->getHCED());
+      headInterruptEndpoint = ep;
+      tailInterruptEndpoint = ep;
+      break;
+    }
+    tailInterruptEndpoint->queueEndpoint(ep);
+    tailInterruptEndpoint = ep;
+    break;
+  default:
+    return false;
+  }
+
+  dev->addEndpoint(intf_nb, ep);
+  //printBulk();
+  //printInt();
+
+  return true;
+}
+
+
+int USBHost::findDevice(USBDeviceConnected * dev)  {
+  for (int i = 0; i < MAX_DEVICE_NB; i++) {
+    if (dev == &devices[i]) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+void USBHost::printBulk() {
+  HCED * hced = (HCED *)bulkHeadED();
+  HCTD * hctd = NULL;
+  printf("---------State of Bulk:--------\r\n");
+  while (hced != NULL) {
+    printf("hced: %p\r\n", hced);
+    hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f));
+    while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) {
+      printf("\thctd: %p\r\n", hctd);
+      hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f));
+    }
+    printf("\thctd: %p\r\n", hctd);
+    hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f));
+  }
+  printf("--------------------\r\n");
+}
+
+void USBHost::printInt() {
+  HCED * hced = (HCED *)interruptHeadED();
+  HCTD * hctd = NULL;
+  printf("---------State of Int:--------\r\n");
+  while (hced != NULL) {
+    printf("hced: %p\r\n", hced);
+    hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f));
+    while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) {
+      printf("\thctd: %p\r\n", hctd);
+      hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f));
+    }
+    printf("\thctd: %p\r\n", hctd);
+    hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f));
+  }
+  printf("--------------------\r\n");
+}
+
+
+// add a transfer on the TD linked list
+USB_TYPE USBHost::addTransfer(Endpoint * ed, uint8_t * buf, uint32_t len)  {
+
+  // allocate a TD which will be freed in TDcompletion
+  volatile HCTD * td = ed->getNextTD();
+  if (td == NULL) {
+    return USB_TYPE_ERROR;
+  }
+
+  DBG("Next td = %p",td);
+
+  uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT ));
+
+  uint32_t td_toggle;
+
+  if (ed->getType() == CONTROL_ENDPOINT) {
+    if (ed->isSetup()) {
+      td_toggle = TD_TOGGLE_0;
+    } else {
+      td_toggle = TD_TOGGLE_1;
+    }
+  } else {
+    td_toggle = 0;
+  }
+
+  DBG("Buf=%d, len=%d", buf, len);
+  td->control      = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC);
+  td->currBufPtr   = (uint32_t) buf;
+  td->bufEnd       = (uint32_t)(buf + (len - 1));
+
+  DBG("Now do queue transfer on ep %p", ed);
+
+  ed->queueTransfer();
+
+  DBG("Enable list if needed");
+
+  switch (ed->getType()) {
+  case CONTROL_ENDPOINT:
+    enableControlList();
+    break;
+  case BULK_ENDPOINT:
+    enableBulkList();
+    break;
+  case INTERRUPT_ENDPOINT:
+    //printInt();
+    enableInterruptList();
+    break;
+  }
+
+  DBG("Wait for HC to process TD");
+
+
+  return USB_TYPE_PROCESSING;
+}
+
+
+
+USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf)  {
+  return controlRead(  dev,
+      USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
+      GET_DESCRIPTOR,
+      (DEVICE_DESCRIPTOR << 8) | (0),
+      0,
+      buf,
+      DEVICE_DESCRIPTOR_LENGTH);
+}
+
+USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint8_t * len_conf_descr)  {
+  USB_TYPE res;
+  uint8_t total_conf_descr_length = 0;
+
+  // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr
+  res = controlRead(  dev,
+      USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
+      GET_DESCRIPTOR,
+      (CONFIGURATION_DESCRIPTOR << 8) | (0),
+      0,
+      buf,
+      CONFIGURATION_DESCRIPTOR_LENGTH);
+
+  if (res != USB_TYPE_OK) {
+    ERR("GET CONF 1 DESCR FAILED");
+    return res;
+  }
+  total_conf_descr_length = buf[2] | (buf[3] << 8);
+  if (len_conf_descr != NULL) {
+    *len_conf_descr = total_conf_descr_length;
+  }
+  DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]);
+
+  return controlRead(  dev,
+      USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
+      GET_DESCRIPTOR,
+      (CONFIGURATION_DESCRIPTOR << 8) | (0),
+      0,
+      buf,
+      total_conf_descr_length);
+
+}
+
+USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf)  {
+  return controlWrite( dev,
+      USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
+      SET_CONFIGURATION,
+      conf,
+      0,
+      NULL,
+      0);
+
+}
+
+
+// enumerate a device with the control endpoint
+USB_TYPE USBHost::enumerate(USBDeviceConnected * dev)  {
+  uint8_t data[256];
+  uint8_t total_conf_descr_length = 0;
+  USB_TYPE res;
+
+  DBG("data = %p", data);
+
+  if (dev->isEnumerated()) {
+    return USB_TYPE_OK;
+  }
+
+  // first step: get the size of endpoint 0
+  DBG("Get size of EP 0");
+  res = controlRead(  dev,
+      USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
+      GET_DESCRIPTOR,
+      (DEVICE_DESCRIPTOR << 8) | (0),
+      0,
+      data,
+      8);
+
+ if (res != USB_TYPE_OK) {
+    ERR("Control read failed!!");
+    return res;
+  }
+  dev->setSizeControlEndpoint(data[7]);
+  DBG("size control Endpoint: %d", dev->getSizeControlEndpoint());
+
+DBG("Now set addr");
+  // second step: set an address to the device
+  res = controlWrite( dev,
+      USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
+      SET_ADDRESS,
+      dev->getAddress(),
+      0,
+      NULL,
+      0);
+
+  if (res != USB_TYPE_OK) {
+    DBG("SET ADDR FAILED");
+    freeDevice(dev);
+    return res;
+  }
+  dev->activeAddress();
+
+
+  // third step: get the whole device descriptor to see vid, pid
+  res = getDeviceDescriptor(dev, data);
+
+  if (res != USB_TYPE_OK) {
+    DBG("GET DEV DESCR FAILED");
+    return res;
+  }
+  dev->setClass(data[4]);
+  dev->setSubClass(data[5]);
+  dev->setProtocol(data[6]);
+  dev->setVid(data[8] | (data[9] << 8));
+  dev->setPid(data[10] | (data[11] << 8));
+  DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8));
+
+  res = getConfigurationDescriptor(dev, data, &total_conf_descr_length);
+  if (res != USB_TYPE_OK) {
+    return res;
+  }
+
+  // Parse the configuration descriptor
+  parseConfDescr(dev, data, total_conf_descr_length);
+
+
+  // sixth step: set configuration (only 1 supported)
+  res = setConfiguration(dev, 1);
+
+  if (res != USB_TYPE_OK) {
+    DBG("SET CONF FAILED");
+    freeDevice(dev);
+    return res;
+  }
+
+  // Now the device is enumerated!
+  dev->setEnumerated();
+  DBG("device enumerated!!!!");
+
+  // Some devices may require this delay
+  Thread::wait(100);
+
+  return USB_TYPE_OK;
+}
+
+// this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
+void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len)  {
+  uint32_t index = 0;
+  uint32_t len_desc = 0;
+  uint8_t id = 0;
+  int nb_endpoints_used = 0;
+  Endpoint * ep = NULL;
+  uint8_t intf_nb = 0;
+
+  while (index < len) {
+    len_desc = conf_descr[index];
+    id = conf_descr[index+1];
+    switch (id) {
+    case CONFIGURATION_DESCRIPTOR:
+      break;
+    case INTERFACE_DESCRIPTOR:
+      if (intf_nb++ < NB_MAX_INTF) {
+        dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
+        nb_endpoints_used = 0;
+        DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
+      } else {
+        DBG("Drop intf...");
+      }
+      break;
+    case ENDPOINT_DESCRIPTOR:
+      if (intf_nb < NB_MAX_INTF) {
+        if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) {
+          // if the endpoint is isochronous -> skip it (TODO: fix this)
+          if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) {
+            ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03),
+                (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1),
+                conf_descr[index + 4] | (conf_descr[index + 5] << 8),
+                conf_descr[index + 2] & 0x0f);
+            DBG("ADD ENDPOINT %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev);
+            if (ep != NULL && dev != NULL) {
+              addEndpoint(dev, intf_nb - 1, ep);
+            } else {
+              DBG("EP NULL\r\n");
+            }
+            nb_endpoints_used++;
+          } else {
+            DBG("ISO ENDPOINT NOT SUPPORTED");
+          }
+        }
+      }
+      //DBG("ENDPOINT DESCR\r\n");
+      break;
+    case HID_DESCRIPTOR:
+      lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
+      break;
+    default:
+      break;
+    }
+    index += len_desc;
+  }
+}
+
+
+USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking)  {
+  USB_TYPE res;
+
+  if (dev == NULL || ep == NULL) {
+    return USB_TYPE_ERROR;
+  }
+
+  if ((ep->getDir() != IN) || (ep->getType() != BULK_ENDPOINT)) {
+    DBG("wrong dir or bad endpoint type");
+    return USB_TYPE_ERROR;
+  }
+  if (dev->getAddress() != ep->getDeviceAddress()) {
+    DBG("endpoint addr and device addr don't match");
+    return USB_TYPE_ERROR;
+  }
+  addTransfer(ep, buf, len);
+  if (blocking) {
+    unlock();
+    while ((res = control->getState()) == USB_TYPE_PROCESSING);
+    lock();
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+    return USB_TYPE_OK;
+  }
+  return USB_TYPE_PROCESSING;
+}
+
+USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking)  {
+  USB_TYPE res;
+
+  if (dev == NULL || ep == NULL) {
+    return USB_TYPE_ERROR;
+  }
+
+  if ((ep->getDir() != OUT) || (ep->getType() != BULK_ENDPOINT)) {
+    DBG("wrong dir or bad endpoint type");
+    return USB_TYPE_ERROR;
+  }
+  if (dev->getAddress() != ep->getDeviceAddress()) {
+    DBG("endpoint addr and device addr don't match");
+    return USB_TYPE_ERROR;
+  }
+  addTransfer(ep, buf, len);
+  if (blocking) {
+    unlock();
+    while ((res = control->getState()) == USB_TYPE_PROCESSING)
+    {
+      DBG("!!!!!!!!!!!!!wait bulkwrite");
+      Thread::wait(100);
+    }
+    lock();
+    DBG("!!!!!!!!!!!!! bulkwrite finished");
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+    return USB_TYPE_OK;
+  }
+  return USB_TYPE_PROCESSING;
+}
+
+USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking)  {
+  USB_TYPE res;
+
+  if (dev == NULL || ep == NULL) {
+    return USB_TYPE_ERROR;
+  }
+
+  if (ep->getState() != USB_TYPE_IDLE) {
+    return ep->getState();
+  }
+
+  if ((ep->getDir() != OUT) || (ep->getType() != INTERRUPT_ENDPOINT)) {
+    ERR("wrong dir or bad endpoint type: %d, %d", ep->getDir(), ep->getType());
+    return USB_TYPE_ERROR;
+  }
+  if (dev->getAddress() != ep->getDeviceAddress()) {
+    ERR("endpoint addr and device addr don't match");
+    return USB_TYPE_ERROR;
+  }
+  addTransfer(ep, buf, len);
+  if (blocking) {
+    while ((res = ep->getState()) == USB_TYPE_PROCESSING);
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+    return USB_TYPE_OK;
+  }
+  return USB_TYPE_PROCESSING;
+}
+
+USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking)  {
+  USB_TYPE res;
+
+  if (dev == NULL || ep == NULL) {
+    return USB_TYPE_ERROR;
+  }
+
+  if (ep->getState() != USB_TYPE_IDLE) {
+    return ep->getState();
+  }
+
+  if ((ep->getDir() != IN) || (ep->getType() != INTERRUPT_ENDPOINT)) {
+    ERR("wrong dir or bad endpoint type");
+    return USB_TYPE_ERROR;
+  }
+
+  if (dev->getAddress() != ep->getDeviceAddress()) {
+    ERR("endpoint addr and device addr don't match");
+    return USB_TYPE_ERROR;
+  }
+  addTransfer(ep, buf, len);
+  if (blocking) {
+    while ((res = ep->getState()) == USB_TYPE_PROCESSING);
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+    return USB_TYPE_OK;
+  }
+  return USB_TYPE_PROCESSING;
+}
+
+
+USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len)  {
+  int length_transfer = len;
+  //DBG("want to transfer: %d bytes\r\n", length_transfer);
+  USB_TYPE res;
+  control->setSpeed(dev->getSpeed());
+  control->setSize(dev->getSizeControlEndpoint());
+  if (dev->isActiveAddress()) {
+    control->setDeviceAddress(dev->getAddress());
+  } else {
+    control->setDeviceAddress(0);
+  }
+  fillControlBuf(requestType, request, value, index, len);
+ /* DBG("will call transfer: ");
+    for (int i = 0; i < 8; i++) {
+        DBG("%02X ", setupPacket[i]);
+    }*/
+  control->setNextToken(TD_SETUP);
+  addTransfer(control, (uint8_t*)setupPacket, 8);
+  DBG("Now wait for TD to be processed");
+  unlock();
+  DBG("Unlocked");
+  while ((res = control->getState()) == USB_TYPE_PROCESSING);
+  lock();
+  DBG("TD processed with result %d", res);
+  if (res != USB_TYPE_IDLE) {
+    return res;
+  }
+
+  if (length_transfer) {
+    DBG("In data to be transfered...");
+    control->setNextToken(TD_IN);
+    addTransfer(control, (uint8_t *)buf, length_transfer);
+    unlock();
+    while ((res = control->getState()) == USB_TYPE_PROCESSING);
+    lock();
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+  }
+
+  DBG("Transfer NULL packet (OUT)");
+  control->setNextToken(TD_OUT);
+  addTransfer(control, NULL, 0);
+  unlock();
+  while ((res = control->getState()) == USB_TYPE_PROCESSING);
+  lock();
+  if (res != USB_TYPE_IDLE) {
+    return res;
+  }
+  return USB_TYPE_OK;
+}
+
+
+USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len)  {
+  control->setSpeed(dev->getSpeed());
+
+  int length_transfer = len;
+  USB_TYPE res;
+
+  control->setSize(dev->getSizeControlEndpoint());
+  if (dev->isActiveAddress()) {
+    control->setDeviceAddress(dev->getAddress());
+  } else {
+    control->setDeviceAddress(0);
+  }
+  fillControlBuf(requestType, request, value, index, len);
+  /*DBG("will call transfer: ");
+    for (int i = 0; i < 8; i++) {
+        printf("%01X ", setupPacket[i]);
+    }
+    printf("\r\n");*/
+  control->setNextToken(TD_SETUP);
+  addTransfer(control, (uint8_t*)setupPacket, 8);
+  unlock();
+  while ((res = control->getState()) == USB_TYPE_PROCESSING);
+  lock();
+  if (res != USB_TYPE_IDLE) {
+    return res;
+  }
+
+  if (length_transfer) {
+    control->setNextToken(TD_OUT);
+    addTransfer(control, (uint8_t *)buf, length_transfer);
+    unlock();
+    while ((res = control->getState()) == USB_TYPE_PROCESSING);
+    lock();
+    if (res != USB_TYPE_IDLE) {
+      return res;
+    }
+  }
+
+  control->setNextToken(TD_IN);
+  addTransfer(control, NULL, 0);
+  unlock();
+  while ((res = control->getState()) == USB_TYPE_PROCESSING);
+  lock();
+  if (res != USB_TYPE_IDLE) {
+    return res;
+  }
+  return USB_TYPE_OK;
+}
+
+
+void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len)  {
+#ifdef __BIG_ENDIAN
+#error "Must implement BE to LE conv here"
+#endif
+  setupPacket[0] = requestType;
+  setupPacket[1] = request;
+  //We are in LE so it's fine
+  *((uint32_t*)&setupPacket[2]) = value;
+  *((uint32_t*)&setupPacket[4]) = index;
+  *((uint32_t*)&setupPacket[6]) = (uint32_t) len;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,303 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBHOST_H
+#define USBHOST_H
+
+#include "USBHALHost.h"
+#include "USBDeviceConnected.h"
+#include "Endpoint.h"
+
+#define MAX_DEVICE_NB 1
+
+// singleton class
+class USBHost : public USBHALHost {
+public:
+    /*
+    * Static method to create or retrieve the single USBHost instance
+    */
+    static USBHost * getHostInst();
+    
+    USB_TYPE getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf) ;
+    USB_TYPE getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint8_t * len_conf_descr = NULL) ;
+    USB_TYPE setConfiguration(USBDeviceConnected * dev, uint8_t conf) ;
+    USB_TYPE getStringDescriptor(USBDeviceConnected * dev, uint8_t index, uint8_t * buf) ;
+    USB_TYPE getReportDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint8_t len) ;
+
+    /*
+    * Control read: setup stage, data stage and status stage
+    *
+    * @param dev the control read will be done for this device
+    * @param requestType request type
+    * @param request request
+    * @param value value
+    * @param index index
+    * @param buf pointer on a buffer where will be store the data received
+    * @param len length of the transfer
+    *
+    * @returns status of the control read
+    */
+    USB_TYPE controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) ;
+
+    /*
+    * Control write: setup stage, data stage and status stage
+    *
+    * @param dev the control write will be done for this device
+    * @param requestType request type
+    * @param request request
+    * @param value value
+    * @param index index
+    * @param buf pointer on a buffer which will be written
+    * @param len length of the transfer
+    *
+    * @returns status of the control write
+    */
+    USB_TYPE controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) ;
+
+
+    /*
+    * Bulk read
+    *
+    * @param dev the bulk transfer will be done for this device
+    * @param ep endpoint which will be used to read a packet
+    * @param buf pointer on a buffer where will be store the data received
+    * @param len length of the transfer
+    * @param blocking if true, the read is blocking (wait for completion)
+    *
+    * @returns status of the bulk read
+    */
+    USB_TYPE bulkRead(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) ;
+
+    /*
+    * Bulk write
+    *
+    * @param dev the bulk transfer will be done for this device
+    * @param ep endpoint which will be used to write a packet
+    * @param buf pointer on a buffer which will be written
+    * @param len length of the transfer
+    * @param blocking if true, the write is blocking (wait for completion)
+    *
+    * @returns status of the bulk write
+    */
+    USB_TYPE bulkWrite(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) ;
+
+    /*
+    * Interrupt read
+    *
+    * @param dev the bulk transfer will be done for this device
+    * @param ep endpoint which will be used to write a packet
+    * @param buf pointer on a buffer which will be written
+    * @param len length of the transfer
+    * @param blocking if true, the read is blocking (wait for completion)
+    *
+    * @returns status of the interrupt read
+    */
+    USB_TYPE interruptRead(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) ;
+
+    /*
+    * Interrupt write
+    *
+    * @param dev the bulk transfer will be done for this device
+    * @param ep endpoint which will be used to write a packet
+    * @param buf pointer on a buffer which will be written
+    * @param len length of the transfer
+    * @param blocking if true, the write is blocking (wait for completion)
+    *
+    * @returns status of the interrupt write
+    */
+    USB_TYPE interruptWrite(USBDeviceConnected * dev, Endpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true) ;
+
+    /*
+    * Enumerate a device. This method is responsible for:
+    *   - set the address of the device
+    *   - fill a USBDeviceConnected object:
+    *       - add interfaces, endpoints, ...
+    *   - set a configuration
+    *
+    * @param dev device which will be enumerated
+    *
+    * @returns status of the enumeration
+    */
+    USB_TYPE enumerate(USBDeviceConnected * dev) ;
+
+    /*
+    * Get a device
+    *
+    * @param index index of the device which will be returned
+    *
+    * @returns pointer on the "index" device
+    */
+    USBDeviceConnected * getDevice(uint8_t index) ;
+
+    /*
+    * reset port and hub of a specific device
+    *
+    * @param pointer on the device hich will be reseted
+    */
+    void resetDevice(USBDeviceConnected * dev) ;
+
+    /*
+    * If there is a HID device connected, the host stores the length of the report descriptor.
+    * This avoid to the driver to re-ask the configuration descriptor to request the report descriptor
+    *
+    * @returns length of the report descriptor
+    */
+    uint16_t getLengthReportDescr()  {
+        return lenReportDescr;
+    };
+
+    /**
+     *  register a driver into the host associated with a callback function called when the device is disconnected
+     *
+     *  @param dev device
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void))  {
+        int index = findDevice(dev);
+        if ((index != -1) && (mptr != NULL) && (tptr != NULL)) {
+            dev->onDisconnect(intf, tptr, mptr);
+        }
+    }
+
+    /**
+     * register a driver into the host associated with a callback function called when the device is disconnected
+     *
+     * @param dev device
+     * @param fn callback called when the specified device has been disconnected
+     */
+    void registerDriver(USBDeviceConnected * dev, uint8_t intf, void (*fn)(void))  {
+        int index = findDevice(dev);
+        if ((index != -1) && (fn != NULL)) {
+            dev->onDisconnect(intf, fn);
+        }
+    }
+
+
+protected:
+
+    /*
+    * Virtual method called when a device has been connected
+    *
+    * @param hub hub number of the device
+    * @param port port number of the device
+    * @param lowSpeed 1 if low speed, 0 otherwise
+    */
+    virtual void deviceConnected(int hub, int port, bool lowSpeed) ;
+
+    /*
+    * Virtuel method called when a device has been disconnected
+    *
+    * @param hub hub number of the device
+    * @param port port number of the device
+    * @param addr list of the TDs which have been completed to dequeue freed TDs
+    */
+    virtual void deviceDisconnected(int hub, int port, volatile uint32_t addr) ;
+
+    /*
+    * Virtual method called when a transfer has been completed
+    *
+    * @param addr list of the TDs which have been completed
+    */
+    virtual void transferCompleted(volatile uint32_t addr) ;
+
+
+private:
+    // singleton class -> constructor is private
+    USBHost();
+
+    static USBHost * instHost;
+
+    uint8_t  nb_devices;
+    uint16_t  lenReportDescr;
+
+    void fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len) ;
+    void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len) ;
+    void freeDevice(USBDeviceConnected * dev) ;
+    int findDevice(USBDeviceConnected * dev) ;
+
+
+    // endpoints
+    void unqueueEndpoint(Endpoint * ep) ;
+    Endpoint  endpoints[MAX_ENDPOINT];
+    Endpoint* volatile  control;
+
+    Endpoint* volatile  headControlEndpoint;
+    Endpoint* volatile  headBulkEndpoint;
+    Endpoint* volatile  headInterruptEndpoint;
+
+    Endpoint* volatile  tailControlEndpoint;
+    Endpoint* volatile  tailBulkEndpoint;
+    Endpoint* volatile  tailInterruptEndpoint;
+
+    bool controlEndpointAllocated;
+
+
+    // devices connected
+    USBDeviceConnected  devices[MAX_DEVICE_NB];
+    volatile bool  deviceInUse[MAX_DEVICE_NB];
+    volatile bool  deviceReset[MAX_DEVICE_NB];
+    
+    /*
+    * Add a transfer on the TD linked list associated to an ED
+    *
+    * @param ed the transfer is associated to this ed
+    * @param buf pointer on a buffer where will be read/write data to send or receive
+    * @param len transfer length
+    *
+    * @return status of the transfer
+    */
+    USB_TYPE addTransfer(Endpoint * ed, uint8_t * buf, uint32_t len) ;
+    
+    /*
+    * Link the endpoint to the linked list and attach an endpoint this endpoint to a device
+    *
+    * @param dev pointer on a USBDeviceConnected object
+    * @param ep pointer on the Endpoint which will be added
+    *
+    * return true if successful
+    */
+    bool addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, Endpoint * ep) ;
+
+    /*
+    * Create an endpoint descriptor. Warning: the endpoint is not linked.
+    *
+    * @param type endpoint type (CONTROL_ENDPOINT, BULK_ENDPOINT, INTERRUPT_ENDPOINT)
+    * @param dir endpoint direction (no meaning for CONTROL_ENDPOINT)
+    * @param size endpoint max packet size
+    * @param addr endpoint address
+    *
+    * @returns pointer on the Endpoint created
+    */
+    Endpoint * newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) ;
+
+
+    // to store a setup packet
+    uint8_t  setupPacket[8];
+
+
+    /////////////////////////
+    /// FOR DEBUG
+    /////////////////////////
+    void printBulk();
+    void printInt();
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostTypes.h	Thu May 24 16:39:35 2012 +0000
@@ -0,0 +1,191 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USB_INC_H
+#define USB_INC_H
+
+#include "mbed.h"
+
+enum USB_TYPE {
+    USB_TYPE_DISCONNECTED = -10,
+    USB_TYPE_NOTFOUND = -9,
+    USB_TYPE_BADCONFIG = -8,
+    USB_TYPE_FREE = -7,
+    USB_TYPE_IDLE = -6,
+    USB_TYPE_PROCESSING = -5,
+    USB_TYPE_HALTED = -4, //Transfer on an ep is stalled
+    USB_TYPE_BUSY = -3,
+    USB_TYPE_TDFAIL = -2,
+    USB_TYPE_ERROR = -1,
+    USB_TYPE_OK = 0
+};
+
+#define AUDIO_CLASS 0x01
+#define CDC_CLASS   0x02
+#define MSD_CLASS   0x08
+#define HID_CLASS   0x03
+
+
+// From NXP's USBHostLite stack's usbhost_lpc17xx.h 
+// Only the types names have been changed to avoid unecessary typedefs 
+
+
+/*
+**************************************************************************************************************
+*                                                 NXP USB Host Stack
+*
+*                                     (c) Copyright 2008, NXP SemiConductors
+*                                     (c) Copyright 2008, OnChip  Technologies LLC
+*                                                 All Rights Reserved
+*
+*                                                  www.nxp.com
+*                                               www.onchiptech.com
+*
+* File           : usbhost_lpc17xx.h
+* Programmer(s)  : Ravikanth.P
+* Version        :
+*
+**************************************************************************************************************
+*/
+
+
+// ------------------ HcControl Register ---------------------  
+#define  OR_CONTROL_PLE                 0x00000004
+#define  OR_CONTROL_CLE                 0x00000010
+#define  OR_CONTROL_BLE                 0x00000020
+#define  OR_CONTROL_HCFS                0x000000C0
+#define  OR_CONTROL_HC_OPER             0x00000080
+// ----------------- HcCommandStatus Register ----------------- 
+#define  OR_CMD_STATUS_HCR              0x00000001
+#define  OR_CMD_STATUS_CLF              0x00000002
+#define  OR_CMD_STATUS_BLF              0x00000004
+// --------------- HcInterruptStatus Register ----------------- 
+#define  OR_INTR_STATUS_WDH             0x00000002
+#define  OR_INTR_STATUS_RHSC            0x00000040
+#define  OR_INTR_STATUS_UE              0x00000010
+// --------------- HcInterruptEnable Register ----------------- 
+#define  OR_INTR_ENABLE_WDH             0x00000002
+#define  OR_INTR_ENABLE_RHSC            0x00000040
+#define  OR_INTR_ENABLE_MIE             0x80000000
+// ---------------- HcRhDescriptorA Register ------------------ 
+#define  OR_RH_STATUS_LPSC              0x00010000
+#define  OR_RH_STATUS_DRWE              0x00008000
+// -------------- HcRhPortStatus[1:NDP] Register -------------- 
+#define  OR_RH_PORT_CCS                 0x00000001
+#define  OR_RH_PORT_PRS                 0x00000010
+#define  OR_RH_PORT_CSC                 0x00010000
+#define  OR_RH_PORT_PRSC                0x00100000
+#define  OR_RH_PORT_LSDA                0x00000200
+
+
+//
+//**************************************************************************************************************
+//*                                               FRAME INTERVAL
+//**************************************************************************************************************
+//
+
+#define  FI                     0x2EDF           // 12000 bits per frame (-1)
+#define  DEFAULT_FMINTERVAL     ((((6 * (FI - 210)) / 7) << 16) | FI)
+
+//
+//**************************************************************************************************************
+//*                                       ENDPOINT DESCRIPTOR CONTROL FIELDS
+//**************************************************************************************************************
+//
+
+#define  ED_SKIP            (uint32_t) (0x00001000)        // Skip this ep in queue
+
+//
+//**************************************************************************************************************
+//*                                       TRANSFER DESCRIPTOR CONTROL FIELDS
+//**************************************************************************************************************
+//
+
+#define  TD_ROUNDING        (uint32_t) (0x00040000)        // Buffer Rounding                             
+#define  TD_SETUP           (uint32_t)(0)                  // Direction of Setup Packet                   
+#define  TD_IN              (uint32_t)(0x00100000)         // Direction In                                
+#define  TD_OUT             (uint32_t)(0x00080000)         // Direction Out                               
+#define  TD_DELAY_INT(x)    (uint32_t)((x) << 21)          // Delay Interrupt                             
+#define  TD_TOGGLE_0        (uint32_t)(0x02000000)         // Toggle 0                                    
+#define  TD_TOGGLE_1        (uint32_t)(0x03000000)         // Toggle 1                                    
+#define  TD_CC              (uint32_t)(0xF0000000)         // Completion Code                             
+
+//
+//**************************************************************************************************************
+//*                                       USB STANDARD REQUEST DEFINITIONS
+//**************************************************************************************************************
+//
+
+#define  DEVICE_DESCRIPTOR                     (1)
+#define  CONFIGURATION_DESCRIPTOR              (2)
+#define  INTERFACE_DESCRIPTOR                  (4)
+#define  ENDPOINT_DESCRIPTOR                   (5)
+#define  HID_DESCRIPTOR                        (33)
+
+//  ----------- Control RequestType Fields  ----------- 
+#define  USB_DEVICE_TO_HOST         0x80
+#define  USB_HOST_TO_DEVICE         0x00
+#define  USB_REQUEST_TYPE_CLASS     0x20
+#define  USB_RECIPIENT_DEVICE       0x00
+#define  USB_RECIPIENT_INTERFACE    0x01
+
+// -------------- USB Standard Requests  -------------- 
+#define  SET_ADDRESS                 5
+#define  GET_DESCRIPTOR              6
+#define  SET_CONFIGURATION           9
+#define  SET_INTERFACE              11
+
+// -------------- USB Descriptor Length  -------------- 
+#define DEVICE_DESCRIPTOR_LENGTH            0x12
+#define CONFIGURATION_DESCRIPTOR_LENGTH     0x09
+
+
+//
+//**************************************************************************************************************
+//*                                       TYPE DEFINITIONS
+//**************************************************************************************************************
+//
+
+// ----------- HostController EndPoint Descriptor ------------- 
+typedef struct hcEd {               
+    volatile  uint32_t  control;        // Endpoint descriptor control                              
+    volatile  uint32_t  tailTD;         // Physical address of tail in Transfer descriptor list     
+    volatile  uint32_t  headTD;         // Physcial address of head in Transfer descriptor list     
+    volatile  uint32_t  nextED;         // Physical address of next Endpoint descriptor             
+} HCED;
+
+// ------------ HostController Transfer Descriptor ------------ 
+typedef struct hcTd {                       
+    volatile  uint32_t  control;        // Transfer descriptor control                              
+    volatile  uint32_t  currBufPtr;     // Physical address of current buffer pointer               
+    volatile  uint32_t  nextTD;         // Physical pointer to next Transfer Descriptor             
+    volatile  uint32_t  bufEnd;         // Physical address of end of buffer                        
+} HCTD;
+
+// ----------- Host Controller Communication Area ------------  
+typedef struct hcca {                   
+    volatile  uint32_t  IntTable[32];   // Interrupt Table                                          
+    volatile  uint32_t  FrameNumber;    // Frame Number                                             
+    volatile  uint32_t  DoneHead;       // Done Head                                                
+    volatile  uint8_t   Reserved[116];  // Reserved for future use                                  
+    volatile  uint8_t   Unknown[4];     // Unused                                                   
+} HCCA;
+
+
+
+#endif