SDG+USBHost(Mouse) Sample

Dependencies:   Sound_Generator USBHost_custom

Fork of SDG_Mouse_Sample by GR-PEACH_producer_meeting

Information

Japanese version is available in lower part of this page.
このページの後半に日本語版が用意されています.

What is this?

This program is a demonstration that sounds the sound by mouse operation by using USBHost(Mouse) and Sound Generator.

Settings

Close JP3 of GR-PEACH.
/media/uploads/RyoheiHagimoto/sdg-mouse.jpg

Operation

operationeffect
Right clickSounds
Left clickReset to base tone (C)
Moves the mouse to the rightLower the sound
Moves the mouse to the leftHigher the sound
Center cursorAdjust the sensitivity.
Reset the reference value in the click.

Others

The default setting of serial communication (baud rate etc.) in mbed is shown the following link.
Please refer to the link and change the settings of your PC terminal software.
The default value of baud rate in mbed is 9600, and this application uses baud rate 9600.
https://developer.mbed.org/teams/Renesas/wiki/GR-PEACH-Getting-Started#install-the-usb-serial-communication


概要

このプログラムは、USBHost(Mouse) + Sound Generatorで、マウス操作による擬似笛デモです。

設定

GR-PEACHのJP3をショートする必要があります。
/media/uploads/RyoheiHagimoto/sdg-mouse.jpg

操作方法

操作内容
右クリック音出力開始
左クリック基準音(ド)にリセット
マウス右移動高音になります
マウス左移動低音になります
センターカーソル音高低の変化量調整(クリックで基準値にリセット)

Others

mbedのシリアル通信(ボーレート等)のデフォルト設定は以下のリンクに示しています。
リンクを参考に、お使いのPCターミナルソフトの設定を変更して下さい。
mbedでのボーレートのデフォルト値は9600で、このサンプルではボーレート9600を使います。
https://developer.mbed.org/teams/Renesas/wiki/GR-PEACH-Getting-Started#install-the-usb-serial-communication

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Wed Mar 06 16:27:14 2013 +0000
Child:
1:0a457e34fa9e
Commit message:
first commit

Changed in this revision

FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
USBHost/IUSBEnumerator.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/USBEndpoint.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBEndpoint.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/USBHostConf.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
USBHost/dbg.h Show annotated file Show diff for this revision Revisions of this file
USBHostHID/USBHostKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostHID/USBHostKeyboard.h Show annotated file Show diff for this revision Revisions of this file
USBHostHID/USBHostMouse.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostHID/USBHostMouse.h Show annotated file Show diff for this revision Revisions of this file
USBHostHub/USBHostHub.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostHub/USBHostHub.h Show annotated file Show diff for this revision Revisions of this file
USBHostMSD/USBHostMSD.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostMSD/USBHostMSD.h Show annotated file Show diff for this revision Revisions of this file
USBHostSerial/MtxCircBuffer.h Show annotated file Show diff for this revision Revisions of this file
USBHostSerial/USBHostSerial.cpp Show annotated file Show diff for this revision Revisions of this file
USBHostSerial/USBHostSerial.h Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/FATFileSystem/#b6669c987c8e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/IUSBEnumerator.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,38 @@
+/* Copyright (c) 2010-2012 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 IUSBENUMERATOR_H_
+#define IUSBENUMERATOR_H_
+
+#include "stdint.h"
+#include "USBEndpoint.h"
+
+/*
+Generic interface to implement for "smart" USB enumeration
+*/
+
+class IUSBEnumerator
+{
+public:
+    virtual void setVidPid(uint16_t vid, uint16_t pid) = 0;
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used
+};
+
+#endif /*IUSBENUMERATOR_H_*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBDeviceConnected.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,124 @@
+/* Copyright (c) 2010-2012 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"
+#include "dbg.h"
+
+USBDeviceConnected::USBDeviceConnected() {
+    init();
+}
+
+void USBDeviceConnected::init() {
+    hub_nb = 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;
+    strcpy(name, "Unknown");
+    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;
+        }
+    }
+    hub_parent = NULL;
+    hub = 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, USBEndpoint * 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_) {
+    USB_DBG("init dev: %p", this);
+    init();
+    hub_nb = hub_;
+    port = port_;
+    speed = lowSpeed_;
+}
+
+void USBDeviceConnected::disconnect() {
+    for(int i = 0; i < nb_interf; i++) {
+        intf[i].detach.call();
+    }
+    init();
+}
+
+
+USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) {
+    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)) {
+            if(index) {
+                index--;
+            } else {
+                return intf[intf_nb].ep[i];
+            }
+        }
+    }
+    return NULL;
+}
+
+USBEndpoint * 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	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,188 @@
+/* Copyright (c) 2010-2012 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 "USBEndpoint.h"
+#include "USBHostConf.h"
+
+class USBHostHub;
+
+typedef struct {
+    bool in_use;
+    uint8_t nb_endpoint;
+    uint8_t intf_class;
+    uint8_t intf_subclass;
+    uint8_t intf_protocol;
+    USBEndpoint * ep[MAX_ENDPOINT_PER_INTERFACE];
+    FunctionPointer detach;
+} INTERFACE; 
+
+class USBDeviceConnected
+{
+public:
+
+    /**
+    * Constructor
+    */
+    USBDeviceConnected();
+
+    /**
+    * Attach an USBEndpoint to this device
+    *
+    * @param ep pointeur on the USBEndpoint which will be attached
+    * @returns true if successful, false otherwise
+    */
+    bool addEndpoint(uint8_t intf_nb, USBEndpoint * ep);
+
+    /**
+    * Retrieve an USBEndpoint by its TYPE and DIRECTION
+    *
+    * @param intf_nb the interface on which to lookup the USBEndpoint
+    * @param type type of the USBEndpoint looked for
+    * @param direction of the USBEndpoint looked for
+    * @param index the index of the USBEndpoint whitin the interface
+    * @returns pointer on the USBEndpoint if found, NULL otherwise
+    */
+    USBEndpoint * getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index = 0);
+
+    /**
+    * Retrieve an USBEndpoint by its index
+    *
+    * @param index index of the USBEndpoint
+    * @returns pointer on the USBEndpoint if found, NULL otherwise
+    */
+    USBEndpoint * getEndpoint(uint8_t intf_nb, uint8_t index);
+
+    /**
+    * Add a new interface to this device
+    *
+    * @param intf_nb interface number
+    * @param intf_class interface class
+    * @param intf_subclass interface subclass
+    * @param intf_ptotocol interface protocol
+    * @returns true if successful, false otherwise
+    */
+    bool addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol);
+
+    /**
+    * Get the number of interfaces attached to this USB device
+    *
+    * @returns number of interfaces
+    */
+    uint8_t getNbInterface() {
+        return nb_interf;
+    };
+
+    /**
+    * Get a specific interface
+    *
+    * @param index index of the interface to be fetched
+    * @returns interface
+    */
+    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>
+    inline 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
+     */
+    inline 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);
+    inline void setAddress(uint8_t addr_) { addr = addr_; };
+    inline void setVid(uint16_t vid_) { vid = vid_; };
+    inline void setPid(uint16_t pid_) { pid = pid_; };
+    inline void setClass(uint8_t device_class_) { device_class = device_class_; };
+    inline void setSubClass(uint8_t device_subclass_) { device_subclass = device_subclass_; };
+    inline void setProtocol(uint8_t pr) { proto = pr; };
+    inline void setSizeControlEndpoint(uint32_t size) { sizeControlEndpoint = size; };
+    inline void activeAddress(bool active) { activeAddr = active; };
+    inline void setEnumerated() { enumerated = true; };
+    inline void setHubParent(USBHostHub * hub) { hub_parent = hub; };
+    inline void setName(const char * name_) { strcpy(name, name_); };
+
+    //getters
+    inline uint8_t     getPort() { return port; };
+    inline uint8_t     getHub() { return hub_nb; };
+    inline uint8_t     getAddress() { return addr; };
+    inline uint16_t    getVid() { return vid; };
+    inline uint16_t    getPid() { return pid; };
+    inline uint8_t     getClass() { return device_class; };
+    inline uint8_t     getSubClass() { return device_subclass; };
+    inline uint8_t     getProtocol() { return proto; };
+    inline bool        getSpeed() { return speed; };
+    inline uint32_t    getSizeControlEndpoint() { return sizeControlEndpoint; };
+    inline bool        isActiveAddress() { return activeAddr; };
+    inline bool        isEnumerated() { return enumerated; };
+    inline USBHostHub * getHubParent() { return hub_parent; };
+    inline const char * getName() { return name; };
+    
+    // in case this device is a hub
+    USBHostHub * hub;
+
+private:
+    USBHostHub * hub_parent;
+
+    INTERFACE intf[MAX_INTF];
+    uint32_t sizeControlEndpoint;
+    uint8_t hub_nb;
+    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;
+    volatile bool activeAddr;
+    volatile bool enumerated;
+    uint8_t nb_interf;
+
+    char name[10];
+
+    void init();
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBEndpoint.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,163 @@
+/* Copyright (c) 2010-2012 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 "dbg.h"
+#include "USBEndpoint.h"
+
+void USBEndpoint::init(HCED * hced_, ENDPOINT_TYPE type_, ENDPOINT_DIRECTION dir_, uint32_t size, uint8_t ep_number, HCTD* td_list_[2])
+{
+    hced = hced_;
+    type = type_;
+    dir = dir_;
+    setup = (type == CONTROL_ENDPOINT) ? true : false;
+
+    //TDs have been allocated by the host
+    memcpy((HCTD**)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));
+    
+    td_list[0]->ep = this;
+    td_list[1]->ep = this;
+
+    hced->control = 0;
+    //Empty queue
+    hced->tailTD = td_list[0];
+    hced->headTD = td_list[0];
+    hced->nextED = 0;
+
+    address = (ep_number & 0x7F) | ((dir - 1) << 7);
+
+    hced->control = ((ep_number & 0x7F) << 7)                         // Endpoint address
+                    | (type != CONTROL_ENDPOINT ? ( dir << 11) : 0 )  // direction : Out = 1, 2 = In
+                    | ((size & 0x3ff) << 16);                         // MaxPkt Size
+
+    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 USBEndpoint::setSize(uint32_t size)
+{
+    hced->control &= ~(0x3ff << 16);
+    hced->control |= (size << 16);
+}
+
+
+void USBEndpoint::setDeviceAddress(uint8_t addr)
+{
+    hced->control &= ~(0x7f);
+    hced->control |= (addr & 0x7F);
+}
+
+void USBEndpoint::setSpeed(uint8_t speed)
+{
+    hced->control &= ~(1 << 13);
+    hced->control |= (speed << 13);
+}
+
+//Only for control Eps
+void USBEndpoint::setNextToken(uint32_t token)
+{
+    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;
+    }
+}
+
+struct {
+    USB_TYPE type;
+    const char * str;
+} static type_string[] = {
+/*0*/   {USB_TYPE_OK, "USB_TYPE_OK"},
+        {USB_TYPE_CRC_ERROR, "USB_TYPE_CRC_ERROR"},
+        {USB_TYPE_BIT_STUFFING_ERROR, "USB_TYPE_BIT_STUFFING_ERROR"},
+        {USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR, "USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR"},
+        {USB_TYPE_STALL_ERROR, "USB_TYPE_STALL_ERROR"},
+/*5*/   {USB_TYPE_DEVICE_NOT_RESPONDING_ERROR, "USB_TYPE_DEVICE_NOT_RESPONDING_ERROR"},
+        {USB_TYPE_PID_CHECK_FAILURE_ERROR, "USB_TYPE_PID_CHECK_FAILURE_ERROR"},
+        {USB_TYPE_UNEXPECTED_PID_ERROR, "USB_TYPE_UNEXPECTED_PID_ERROR"},
+        {USB_TYPE_DATA_OVERRUN_ERROR, "USB_TYPE_DATA_OVERRUN_ERROR"},
+        {USB_TYPE_DATA_UNDERRUN_ERROR, "USB_TYPE_DATA_UNDERRUN_ERROR"},
+/*10*/  {USB_TYPE_ERROR, "USB_TYPE_ERROR"},
+        {USB_TYPE_ERROR, "USB_TYPE_ERROR"},
+        {USB_TYPE_BUFFER_OVERRUN_ERROR, "USB_TYPE_BUFFER_OVERRUN_ERROR"},
+        {USB_TYPE_BUFFER_UNDERRUN_ERROR, "USB_TYPE_BUFFER_UNDERRUN_ERROR"},
+        {USB_TYPE_DISCONNECTED, "USB_TYPE_DISCONNECTED"},
+/*15*/  {USB_TYPE_FREE, "USB_TYPE_FREE"},
+        {USB_TYPE_IDLE, "USB_TYPE_IDLE"},
+        {USB_TYPE_PROCESSING, "USB_TYPE_PROCESSING"},
+        {USB_TYPE_ERROR, "USB_TYPE_ERROR"}
+};
+
+void USBEndpoint::setState(uint8_t st) {
+    if (st > 18)
+        return;
+    state = type_string[st].type;
+}
+
+
+const char * USBEndpoint::getStateString() {
+    return type_string[state].str;
+}
+
+void USBEndpoint::queueTransfer()
+{
+    transfer_len = (uint32_t)td_current->bufEnd - (uint32_t)td_current->currBufPtr + 1;
+    transferred = transfer_len;
+    buf_start = (uint8_t *)td_current->currBufPtr;
+
+    //Now add this free TD at this end of the queue
+    state = USB_TYPE_PROCESSING;
+    td_current->nextTD = (uint32_t)td_next;
+    hced->tailTD = td_next;
+}
+
+void USBEndpoint::unqueueTransfer(volatile HCTD * td)
+{
+    td->control=0;
+    td->currBufPtr=0;
+    td->bufEnd=0;
+    td->nextTD=0;
+    hced->headTD = (HCTD *)((uint32_t)hced->tailTD | ((uint32_t)hced->headTD & 0x2)); //Carry bit
+    td_current = td_next;
+    td_next = td;
+}
+
+void USBEndpoint::queueEndpoint(USBEndpoint * ed)
+{
+    nextEp = ed;
+    hced->nextED = (ed == NULL) ? 0 : (uint32_t)ed->getHCED();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBEndpoint.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,164 @@
+/* Copyright (c) 2010-2012 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 USBENDPOINT_H
+#define USBENDPOINT_H
+
+#include "FunctionPointer.h"
+#include "USBHostTypes.h"
+
+class USBDeviceConnected;
+
+class USBEndpoint
+{
+public:
+    /**
+    * Constructor
+    */
+    USBEndpoint() {
+        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
+    * @param td_list array of two allocated transfer descriptors
+    */
+    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(USBEndpoint * endpoint);
+
+
+    /**
+    * Queue a transfer on the endpoint
+    */
+    void queueTransfer();
+
+    /**
+    * Unqueue a transfer from the endpoint
+    *
+    * @param td hctd which will be unqueued
+    */
+    void unqueueTransfer(volatile HCTD * td);
+
+    /**
+     *  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>
+    inline 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
+     */
+    inline void attach(void (*fn)(void)) {
+        if(fn != NULL) {
+            rx.attach(fn);
+        }
+    }
+
+    /**
+    * Call the handler associted to the end of a transfer
+    */
+    inline void call() {
+        rx.call();
+    };
+
+
+    // setters
+    inline void setState(USB_TYPE st) { state = st; }
+    void setState(uint8_t st);
+    void setDeviceAddress(uint8_t addr);
+    inline void setLengthTransferred(int len) { transferred = len; };
+    void setSpeed(uint8_t speed);
+    void setSize(uint32_t size);
+    inline void setDir(ENDPOINT_DIRECTION d) { dir = d; }
+
+    // getters
+    const char *                getStateString();
+    inline USB_TYPE             getState() { return state; }
+    inline ENDPOINT_TYPE        getType() { return type; };
+    inline uint8_t              getDeviceAddress() { return hced->control & 0x7f; };
+    inline int                  getLengthTransferred() { return transferred; }
+    inline uint8_t *            getBufStart() { return buf_start; }
+    inline uint8_t              getAddress(){ return address; };
+    inline uint32_t             getSize() { return (hced->control >> 16) & 0x3ff; };
+    inline volatile HCTD *      getHeadTD() { return (volatile HCTD*) ((uint32_t)hced->headTD & ~0xF); };
+    inline volatile HCTD**      getTDList() { return td_list; };
+    inline volatile HCED *      getHCED() { return hced; };
+    inline ENDPOINT_DIRECTION   getDir() { return dir; }
+    inline volatile HCTD *      getProcessedTD() { return td_current; };
+    inline volatile HCTD*       getNextTD() { return td_current; };
+    inline bool                 isSetup() { return setup; }
+    inline USBEndpoint *        nextEndpoint() { return (USBEndpoint*)nextEp; };
+    
+    USBDeviceConnected * dev;
+
+private:
+    ENDPOINT_TYPE type;
+    volatile USB_TYPE state;
+    ENDPOINT_DIRECTION dir;
+    bool setup;
+
+    uint8_t address;
+
+    int transfer_len;
+    int transferred;
+    uint8_t * buf_start;
+
+    FunctionPointer rx;
+
+    USBEndpoint* nextEp;
+
+    // USBEndpoint descriptor
+    volatile HCED * hced;
+
+    volatile HCTD * td_list[2];
+    volatile HCTD * td_current;
+    volatile HCTD * td_next;
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,325 @@
+/* Copyright (c) 2010-2012 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 "mbed.h"
+#include "USBHALHost.h"
+#include "dbg.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 sizeof(HCCA)
+#define ED_SIZE sizeof(HCED)
+#define TD_SIZE sizeof(HCTD)
+
+#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("AHBSRAM1"),aligned));  //256 bytes aligned!
+
+USBHALHost * USBHALHost::instHost;
+
+USBHALHost::USBHALHost() {
+    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() {
+    NVIC_DisableIRQ(USB_IRQn);
+    
+    //Cut power
+    LPC_SC->PCONP &= ~(1UL<<31);
+    wait_ms(100);
+
+    // 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));
+
+    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 100 ms before apply reset
+    wait_ms(100);
+
+    // software reset
+    LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
+    
+    // Write Fm Interval and Largest Data Packet Counter
+    LPC_USB->HcFmInterval    = DEFAULT_FMINTERVAL;
+    LPC_USB->HcPeriodicStart = FI * 90 / 100;
+
+    // Put HC in operational state
+    LPC_USB->HcControl  = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
+    // Set Global Power
+    LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
+
+    LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
+    
+    // Clear Interrrupt Status
+    LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
+
+    LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
+
+    // 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) {
+        //Device connected
+        wait_ms(100);
+        USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1);
+        deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
+    }
+}
+
+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::enableList(ENDPOINT_TYPE type) {
+    switch(type) {
+        case CONTROL_ENDPOINT:
+            LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
+            LPC_USB->HcControl |= OR_CONTROL_CLE;
+            break;
+        case ISOCHRONOUS_ENDPOINT:
+            break;
+        case BULK_ENDPOINT:
+            LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
+            LPC_USB->HcControl |= OR_CONTROL_BLE;
+            break;
+        case INTERRUPT_ENDPOINT:
+            LPC_USB->HcControl |= OR_CONTROL_PLE;
+            break;
+    }
+}
+
+
+bool USBHALHost::disableList(ENDPOINT_TYPE type) {
+    switch(type) {
+        case CONTROL_ENDPOINT:
+            if(LPC_USB->HcControl & OR_CONTROL_CLE) {
+                LPC_USB->HcControl &= ~OR_CONTROL_CLE;
+                return true;
+            }
+            return false;
+        case ISOCHRONOUS_ENDPOINT:
+            return false;
+        case BULK_ENDPOINT:
+            if(LPC_USB->HcControl & OR_CONTROL_BLE){
+                LPC_USB->HcControl &= ~OR_CONTROL_BLE;
+                return true;
+            }
+            return false;
+        case INTERRUPT_ENDPOINT:
+            if(LPC_USB->HcControl & OR_CONTROL_PLE) {
+                LPC_USB->HcControl &= ~OR_CONTROL_PLE;
+                return true;
+            }
+            return false;
+    }
+    return false;
+}
+
+
+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::resetRootHub() {
+    // Initiate port reset
+    LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; 
+    
+    while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
+    
+    // ...and clear port reset signal
+    LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
+}
+
+
+void USBHALHost::_usbisr(void) {
+    if (instHost) {
+        instHost->UsbIrqhandler();
+    }
+}
+
+void USBHALHost::UsbIrqhandler() {
+    if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
+    {
+        
+        uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
+
+        // Root hub status change interrupt
+        if (int_status & OR_INTR_STATUS_RHSC) { 
+            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 {
+
+                    //Root device connected
+                    if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { 
+                        
+                        // wait 100ms to avoid bounce
+                        wait_ms(100);
+                        
+                        //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
+                        deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA); 
+                    } 
+                    
+                    //Root device disconnected
+                    else { 
+                        
+                        if (!(int_status & OR_INTR_STATUS_WDH)) {
+                            usb_hcca->DoneHead = 0;
+                        }
+                        
+                        // wait 100ms to avoid bounce
+                        wait_ms(100);
+                        
+                        deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
+                        
+                        if (int_status & OR_INTR_STATUS_WDH) {
+                            usb_hcca->DoneHead = 0;
+                            LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
+                        }
+                    }
+                }
+                LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
+            }
+            if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) {
+                LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
+            }
+            LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
+        }
+
+        // Writeback Done Head interrupt
+        if (int_status & OR_INTR_STATUS_WDH) {
+            transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
+            LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,167 @@
+/* Copyright (c) 2010-2012 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 "USBHostTypes.h"
+#include "USBHostConf.h"
+
+class USBHostHub;
+
+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 the root hub
+    */
+    void resetRootHub();
+    
+    /**
+    * 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 List for the specified endpoint type
+    */
+    void enableList(ENDPOINT_TYPE type);
+    
+    /**
+    * Disable List for the specified endpoint type
+    */
+    bool disableList(ENDPOINT_TYPE type);
+
+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
+    * @param hub_parent reference to the hub where the device is connected (NULL if the hub parent is the root hub)
+    */
+    virtual void deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent = NULL) {};
+    
+    /**
+    * Virtual method called when a device has been disconnected
+    *
+    * @param hub hub number of the device
+    * @param port port number of the device
+    * @param hub_parent reference to the hub where the device is connected (NULL if the hub parent is the root hub)
+    * @param addr list of the TDs which have been completed to dequeue freed TDs
+    */
+    virtual void deviceDisconnected(int hub, int port, USBHostHub * hub_parent, 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();
+
+    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];
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,1098 @@
+/* Copyright (c) 2010-2012 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 "USBHost.h"
+#include "USBHostHub.h"
+
+USBHost * USBHost::instHost = NULL;
+
+#define DEVICE_CONNECTED_EVENT      (1 << 0)
+#define DEVICE_DISCONNECTED_EVENT   (1 << 1)
+#define TD_PROCESSED_EVENT          (1 << 2)
+
+#define MAX_TRY_ENUMERATE_HUB       3
+
+#define MIN(a, b) ((a > b) ? b : a)
+
+DigitalOut l4(LED4);
+
+/**
+* How interrupts are processed:
+*    - new device connected:
+*       a message is queued
+*/
+void USBHost::usb_process() {
+    
+    bool controlListState;
+    bool bulkListState;
+    bool interruptListState;
+    USBEndpoint * ep;
+    uint8_t i, j, res, timeout_set_addr = 10;
+    uint8_t buf[8];
+    bool too_many_hub;
+    int idx;
+
+#if DEBUG_TRANSFER
+    uint8_t * buf_transfer;
+#endif
+        
+#if MAX_HUB_NB
+    uint8_t k;
+#endif
+    
+    while(1) {
+        osEvent evt = queue_usb_event.get();
+        
+        if (evt.status == osEventMessage) {
+            
+            l4 = !l4;
+            message_t * usb_msg = (message_t*)evt.value.p;
+            
+            switch (usb_msg->event_id) {
+                
+                // a new device has been connected
+                case DEVICE_CONNECTED_EVENT:
+                    too_many_hub = false;
+                    buf[4] = 0;
+                    
+                    for (i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+                        if (!deviceInUse[i]) {
+                            USB_DBG_EVENT("new device connected: %p\r\n", &devices[i]);
+                            devices[i].init(usb_msg->hub, usb_msg->port, usb_msg->lowSpeed);
+                            deviceReset[i] = false;
+                            break;
+                        }
+                    }
+                    
+                    if (i == MAX_DEVICE_CONNECTED) {
+                        USB_ERR("Too many device connected!!\r\n");
+                        usb_mutex.unlock();
+                        continue;
+                    }
+                    
+                    if (!controlEndpointAllocated) {
+                        control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00);
+                        addEndpoint(NULL, 0, (USBEndpoint*)control);
+                        controlEndpointAllocated = true;
+                    }
+                    
+#if MAX_HUB_NB
+                    if (usb_msg->hub_parent)
+                        devices[i].setHubParent((USBHostHub *)(usb_msg->hub_parent));
+#endif
+                    
+                    resetDevice(&devices[i]);
+                    
+                    for (j = 0; j < timeout_set_addr; j++) {
+                        // set size of control endpoint
+                        devices[i].setSizeControlEndpoint(8);
+                        
+                        devices[i].activeAddress(false);
+                        
+                        // get first 8 bit of device descriptor
+                        // and check if we deal with a hub
+                        USB_DBG("usb_thread read device descriptor on dev: %p\r\n", &devices[i]);
+                        res = getDeviceDescriptor(&devices[i], buf, 8);
+                    
+                        if (res != USB_TYPE_OK) {
+                            USB_ERR("usb_thread could not read dev descr");
+                            continue;
+                        }
+                    
+                        // set size of control endpoint
+                        devices[i].setSizeControlEndpoint(buf[7]);
+                        
+                        // second step: set an address to the device
+                        res = setAddress(&devices[i], devices[i].getAddress());
+                    
+                        if (res != USB_TYPE_OK) {
+                            USB_ERR("SET ADDR FAILED");
+                            continue;
+                        }
+                        devices[i].activeAddress(true);
+                        USB_DBG("Address of %p: %d", &devices[i], devices[i].getAddress());
+                        
+                        // try to read again the device descriptor to check if the device
+                        // answers to its new address
+                        res = getDeviceDescriptor(&devices[i], buf, 8);
+                    
+                        if (res == USB_TYPE_OK) {
+                            break;
+                        }
+                        
+                        wait_ms(100);
+                    }
+                    
+                    USB_INFO("New device connected: %p [hub: %d - port: %d]", &devices[i], usb_msg->hub, usb_msg->port);
+                    
+#if MAX_HUB_NB
+                    if (buf[4] == HUB_CLASS) {
+                        for (k = 0; k < MAX_HUB_NB; k++) {
+                            if (hub_in_use[k] == false) {
+                                for (uint8_t j = 0; j < MAX_TRY_ENUMERATE_HUB; j++) {
+                                    if (hubs[k].connect(&devices[i])) {
+                                        devices[i].hub = &hubs[k];
+                                        hub_in_use[k] = true;
+                                        break;
+                                    }
+                                }
+                                if (hub_in_use[k] == true)
+                                    break;
+                            }
+                        }
+                        
+                        if (k == MAX_HUB_NB) {
+                            USB_ERR("Too many hubs connected!!\r\n");
+                            too_many_hub = true;
+                        }
+                    }
+                    
+                    if (usb_msg->hub_parent)
+                        ((USBHostHub *)(usb_msg->hub_parent))->deviceConnected(&devices[i]);
+#endif
+                    
+                    if ((i < MAX_DEVICE_CONNECTED) && !too_many_hub) {
+                        deviceInUse[i] = true;
+                    }
+                    
+                    break;
+                    
+                // a device has been disconnected
+                case DEVICE_DISCONNECTED_EVENT:
+                    
+                    usb_mutex.lock();
+                
+                    controlListState = disableList(CONTROL_ENDPOINT);
+                    bulkListState = disableList(BULK_ENDPOINT);
+                    interruptListState = disableList(INTERRUPT_ENDPOINT);
+                
+                    idx = findDevice(usb_msg->hub, usb_msg->port, (USBHostHub *)(usb_msg->hub_parent));
+                    if (idx != -1) {
+                        freeDevice((USBDeviceConnected*)&devices[idx]);
+                    }
+                    
+                    if (controlListState) enableList(CONTROL_ENDPOINT);
+                    if (bulkListState) enableList(BULK_ENDPOINT);
+                    if (interruptListState) enableList(INTERRUPT_ENDPOINT);
+                    
+                    usb_mutex.unlock();
+                    
+                    break;
+                    
+                // a td has been processed
+                // call callback on the ed associated to the td
+                // we are not in ISR -> users can use printf in their callback method
+                case TD_PROCESSED_EVENT:
+                    ep = (USBEndpoint *) ((HCTD *)usb_msg->td_addr)->ep;
+                    ep->setState(usb_msg->td_state);
+                    if (ep->getState() == USB_TYPE_IDLE) {
+                        USB_DBG_EVENT("call callback on td %p [ep: %p state: %s - dev: %p - %s]", usb_msg->td_addr, ep, ep->getStateString(), ep->dev, ep->dev->getName());
+#if DEBUG_TRANSFER
+                        if (ep->getDir() == IN) {
+                            buf_transfer = ep->getBufStart();
+                            printf("READ SUCCESS [%d bytes transferred] on ep: [%p - addr: %02X]: ", ep->getLengthTransferred(), ep, ep->getAddress());
+                            for (int i = 0; i < ep->getLengthTransferred(); i++)
+                                printf("%02X ", buf_transfer[i]);
+                            printf("\r\n\r\n");
+                        }
+#endif
+                        ep->call();
+                    } else {
+                        idx = findDevice(ep->dev);
+                        if (idx != -1) {
+                            if (deviceInUse[idx])
+                                USB_WARN("td %p processed but not in idle state: %s [dev: %p - %s]", usb_msg->td_addr, ep->getStateString(), ep->dev, ep->dev->getName());
+                        }
+                    }
+                    break;
+            }
+            
+            mpool_usb_event.free(usb_msg);
+        }
+    }
+}
+
+/* static */void USBHost::usb_process_static(void const * arg) {
+    ((USBHost *)arg)->usb_process();
+}
+
+USBHost::USBHost() : usbThread(USBHost::usb_process_static, (void *)this, osPriorityNormal, USB_THREAD_STACK)
+{
+    headControlEndpoint = NULL;
+    headBulkEndpoint = NULL;
+    headInterruptEndpoint = NULL;
+    tailControlEndpoint = NULL;
+    tailBulkEndpoint = NULL;
+    tailInterruptEndpoint = NULL;
+
+    lenReportDescr = 0;
+
+    controlEndpointAllocated = false;
+
+    for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        deviceInUse[i] = false;
+        devices[i].setAddress(i + 1);
+        deviceReset[i] = false;
+        deviceAttachedDriver[i] = false;
+    }
+    
+#if MAX_HUB_NB
+    for (uint8_t i = 0; i < MAX_HUB_NB; i++) {
+        hubs[i].setHost(this);
+        hub_in_use[i] = false;
+    }
+#endif
+}
+
+
+void USBHost::transferCompleted(volatile uint32_t addr)
+{
+    uint8_t state;
+
+    if(addr == NULL)
+        return;
+
+    volatile HCTD* tdList = NULL;
+
+    //First we must reverse the list order and dequeue each TD
+    do {
+        volatile HCTD* td = (volatile HCTD*)addr;
+        addr = td->nextTD; //Dequeue from physical list
+        td->nextTD = (uint32_t)tdList; //Enqueue into reversed list
+        tdList = td;
+    } while(addr);
+
+    while(tdList != NULL) {
+        volatile HCTD* td = tdList;
+        tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below
+        if (td->ep != NULL) {
+            USBEndpoint * ep = (USBEndpoint *)(td->ep);
+            
+            if (((HCTD *)td)->control >> 28) {
+                state = ((HCTD *)td)->control >> 28;
+            } else {
+                if (td->currBufPtr)
+                    ep->setLengthTransferred((uint32_t)td->currBufPtr - (uint32_t)ep->getBufStart());
+                state = 16 /*USB_TYPE_IDLE*/;
+            }
+            
+            ep->unqueueTransfer(td);
+            
+            if (ep->getType() != CONTROL_ENDPOINT) {
+                // callback on the processed td will be called from the usb_thread (not in ISR)
+                message_t * usb_msg = mpool_usb_event.alloc();
+                usb_msg->event_id = TD_PROCESSED_EVENT;
+                usb_msg->td_addr = (void *)td;
+                usb_msg->td_state = state;
+                queue_usb_event.put(usb_msg);
+            } else {
+                ep->setState(state);
+            }
+        }
+    }
+}
+
+USBHost * USBHost::getHostInst()
+{
+    if (instHost == NULL) {
+        instHost = new USBHost();
+        instHost->init();
+    }
+    return instHost;
+}
+
+
+/*
+ * Called when a device has been connected
+ * Called in ISR!!!! (no printf)
+ */
+/* virtual */ void USBHost::deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent)
+{
+    // be sure that the new device connected is not already connected...
+    int idx = findDevice(hub, port, hub_parent);
+    if (idx != -1) {
+        if (deviceInUse[idx])
+            return;
+    }
+    
+    message_t * usb_msg = mpool_usb_event.alloc();
+    usb_msg->event_id = DEVICE_CONNECTED_EVENT;
+    usb_msg->hub = hub;
+    usb_msg->port = port;
+    usb_msg->lowSpeed = lowSpeed;
+    usb_msg->hub_parent = hub_parent;
+    queue_usb_event.put(usb_msg);
+}
+
+/*
+ * Called when a device has been disconnected
+ * Called in ISR!!!! (no printf)
+ */
+/* virtual */ void USBHost::deviceDisconnected(int hub, int port, USBHostHub * hub_parent, volatile uint32_t addr)
+{
+    // be sure that the device disconnected is connected...
+    int idx = findDevice(hub, port, hub_parent);
+    if (idx != -1) {
+        if (!deviceInUse[idx])
+            return;
+    } else {
+        return;
+    }
+    
+    message_t * usb_msg = mpool_usb_event.alloc();
+    usb_msg->event_id = DEVICE_DISCONNECTED_EVENT;
+    usb_msg->hub = hub;
+    usb_msg->port = port;
+    usb_msg->hub_parent = hub_parent;
+    queue_usb_event.put(usb_msg);
+}
+
+void USBHost::freeDevice(USBDeviceConnected * dev)
+{
+    USBEndpoint * ep = NULL;
+    HCED * ed = NULL;
+    
+#if MAX_HUB_NB
+    if (dev->getClass() == HUB_CLASS) {
+        if (dev->hub == NULL) {
+            USB_ERR("HUB NULL!!!!!\r\n");
+        } else {
+            dev->hub->hubDisconnected();
+            for (uint8_t i = 0; i < MAX_HUB_NB; i++) {
+                if (dev->hub == &hubs[i]) {
+                    hub_in_use[i] = false;
+                    break;
+                }
+            }
+        }
+    }
+    
+    // notify hub parent that this device has been disconnected
+    if (dev->getHubParent())
+        dev->getHubParent()->deviceDisconnected(dev);
+    
+#endif
+    
+    int idx = findDevice(dev);
+    if (idx != -1) {
+        deviceInUse[idx] = false;
+        deviceReset[idx] = false;
+        deviceAttachedDriver[idx] = false;
+
+        for (int j = 0; j < dev->getNbInterface(); j++) {
+            USB_DBG("FREE INTF %d on dev: %p, %p, nb_endpot: %d, %s", j, (void *)dev->getInterface(j), dev, dev->getInterface(j)->nb_endpoint, dev->getName());
+            for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) {
+                if ((ep = dev->getEndpoint(j, i)) != NULL) {
+                    ed = (HCED *)ep->getHCED();
+                    ed->control |= (1 << 13); //sKip bit
+                    unqueueEndpoint(ep);
+
+                    freeTD((volatile uint8_t*)ep->getTDList()[0]);
+                    freeTD((volatile uint8_t*)ep->getTDList()[1]);
+
+                    freeED((uint8_t *)ep->getHCED());
+                }
+                printList(BULK_ENDPOINT);
+                printList(INTERRUPT_ENDPOINT);
+            }
+        }
+        USB_INFO("Device disconnected [%p - %s - hub: %d - port: %d]", dev, dev->getName(), dev->getHub(), dev->getPort());
+        dev->disconnect();
+    }
+}
+
+
+void USBHost::unqueueEndpoint(USBEndpoint * ep)
+{
+    USBEndpoint * prec = NULL;
+    USBEndpoint * current = NULL;
+
+    for (int i = 0; i < 2; i++) {
+        current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)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();
+                    } else if (current == headInterruptEndpoint) {
+                        updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED());
+                        headInterruptEndpoint = current->nextEndpoint();
+                    }
+                }
+                // here we are dequeuing the queue of ed
+                // we need to update the tail pointer
+                else {
+                    prec->queueEndpoint(NULL);
+                    if (current == headBulkEndpoint) {
+                        updateBulkHeadED(0);
+                        headBulkEndpoint = current->nextEndpoint();
+                    } else if (current == headInterruptEndpoint) {
+                        updateInterruptHeadED(0);
+                        headInterruptEndpoint = current->nextEndpoint();
+                    }
+                    
+                    // modify tail
+                    switch (current->getType()) {
+                        case BULK_ENDPOINT:
+                            tailBulkEndpoint = prec;
+                            break;
+                        case INTERRUPT_ENDPOINT:
+                            tailInterruptEndpoint = prec;
+                            break;
+                    }
+                }
+                current->setState(USB_TYPE_FREE);
+                return;
+            }
+            prec = current;
+            current = current->nextEndpoint();
+        }
+    }
+}
+
+
+USBDeviceConnected * USBHost::getDevice(uint8_t index)
+{
+    if ((index >= MAX_DEVICE_CONNECTED) || (!deviceInUse[index]) || (deviceAttachedDriver[index])) {
+        return NULL;
+    }
+    return (USBDeviceConnected*)&devices[index];
+}
+
+// create an USBEndpoint descriptor. the USBEndpoint is not linked
+USBEndpoint * 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 USBEndpoint
+    for (i = 0; i < MAX_ENDPOINT; i++) {
+        if (endpoints[i].getState() == USB_TYPE_FREE) {
+            endpoints[i].init(ed, type, dir, size, addr, td_list);
+            USB_DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d", &endpoints[i], type, dir, size, addr);
+            return &endpoints[i];
+        }
+    }
+    USB_ERR("could not allocate more endpoints!!!!");
+    return NULL;
+}
+
+
+USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev)
+{
+    int index = findDevice(dev);
+    if (index != -1) {
+        USB_DBG("Resetting hub %d, port %d\n", dev->getHub(), dev->getPort());
+        wait_ms(50);
+        if (dev->getHub() == 0) {
+            resetRootHub();
+        }
+#if MAX_HUB_NB
+        else {
+            dev->getHubParent()->portReset(dev->getPort());
+        }
+#endif
+        wait_ms(100);
+        deviceReset[index] = true;
+        return USB_TYPE_OK;
+    }
+    if (deviceReset[index] && !deviceAttachedDriver[index])
+        return USB_TYPE_OK;
+    
+    return USB_TYPE_ERROR;
+}
+
+// link the USBEndpoint to the linked list and attach an USBEndpoint to a device
+bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep)
+{
+
+    if (ep == NULL) {
+        return false;
+    }
+
+    HCED * prevEd;
+
+    // set device address in the USBEndpoint descriptor
+    if (dev == NULL) {
+        ep->setDeviceAddress(0);
+    } else {
+        ep->setDeviceAddress(dev->getAddress());
+    }
+
+    if ((dev != NULL) && dev->getSpeed()) {
+        ep->setSpeed(dev->getSpeed());
+    }
+
+    // queue the new USBEndpoint on the ED list
+    switch (ep->getType()) {
+
+        case CONTROL_ENDPOINT:
+            prevEd = ( HCED*) controlHeadED();
+            if (!prevEd) {
+                updateControlHeadED((uint32_t) ep->getHCED());
+                USB_DBG("First control USBEndpoint: %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());
+                USB_DBG("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
+                headBulkEndpoint = ep;
+                tailBulkEndpoint = ep;
+                break;
+            }
+            USB_DBG("Queue BULK Ed %p after %p\r\n",ep->getHCED(), prevEd);
+            tailBulkEndpoint->queueEndpoint(ep);
+            tailBulkEndpoint = ep;
+            break;
+
+        case INTERRUPT_ENDPOINT:
+            prevEd = ( HCED*) interruptHeadED();
+            if (!prevEd) {
+                updateInterruptHeadED((uint32_t) ep->getHCED());
+                USB_DBG("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
+                headInterruptEndpoint = ep;
+                tailInterruptEndpoint = ep;
+                break;
+            }
+            USB_DBG("Queue INTERRUPT Ed %p after %p\r\n",ep->getHCED(), prevEd);
+            tailInterruptEndpoint->queueEndpoint(ep);
+            tailInterruptEndpoint = ep;
+            break;
+        default:
+            return false;
+    }
+    
+    ep->dev = dev;
+    dev->addEndpoint(intf_nb, ep);
+
+    return true;
+}
+
+
+int USBHost::findDevice(USBDeviceConnected * dev)
+{
+    for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if (dev == &devices[i]) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int USBHost::findDevice(uint8_t hub, uint8_t port, USBHostHub * hub_parent)
+{
+    for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if (devices[i].getHub() == hub && devices[i].getPort() == port) {
+            if (hub_parent != NULL) {
+                if (hub_parent == devices[i].getHubParent())
+                    return i;
+            } else {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
+void USBHost::printList(ENDPOINT_TYPE type)
+{
+#if DEBUG_EP_STATE
+    HCED * hced;
+    switch(type) {
+        case CONTROL_ENDPOINT:
+            hced = (HCED *)controlHeadED();
+            break;
+        case BULK_ENDPOINT:
+            hced = (HCED *)bulkHeadED();
+            break;
+        case INTERRUPT_ENDPOINT:
+            hced = (HCED *)interruptHeadED();
+            break;
+    }
+    HCTD * hctd = NULL;
+    const char * type_str = (type == BULK_ENDPOINT) ? "BULK" :
+                            ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" :
+                            ((type == CONTROL_ENDPOINT) ? "CONTROL" : "ISOCHRONOUS"));
+    printf("State of %s:\r\n", type_str);
+    while (hced != NULL) {
+        uint8_t dir = ((hced->control & (3 << 11)) >> 11);
+        printf("hced: %p [ADDR: %d, DIR: %s, EP_NB: 0x%X]\r\n", hced,
+                                                   hced->control & 0x7f,
+                                                   (dir == 1) ? "OUT" : ((dir == 0) ? "FROM_TD":"IN"),
+                                                    (hced->control & (0xf << 7)) >> 7);
+        hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0xf));
+        while (hctd != (hced->tailTD)) {
+            printf("\thctd: %p [DIR: %s]\r\n", hctd, ((hctd->control & (3 << 19)) >> 19) == 1 ? "OUT" : "IN");
+            hctd = (HCTD *)((uint32_t)(hctd->nextTD));
+        }
+        printf("\thctd: %p\r\n", hctd);
+        hced = (HCED *)((uint32_t)(hced->nextED));
+    }
+    printf("\r\n\r\n");
+#endif
+}
+
+
+// add a transfer on the TD linked list
+USB_TYPE USBHost::addTransfer(USBEndpoint * 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;
+    }
+
+    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;
+    }
+
+    td->control      = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC);
+    td->currBufPtr   = buf;
+    td->bufEnd       = (buf + (len - 1));
+
+    ENDPOINT_TYPE type = ed->getType();
+
+    disableList(type);
+    ed->queueTransfer();
+    printList(type);
+    enableList(type);
+
+    return USB_TYPE_PROCESSING;
+}
+
+
+
+USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_dev_descr)
+{
+    USB_TYPE t = controlRead(  dev,
+                         USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
+                         GET_DESCRIPTOR,
+                         (DEVICE_DESCRIPTOR << 8) | (0),
+                         0, buf, MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf));
+    if (len_dev_descr)
+        *len_dev_descr = MIN(DEVICE_DESCRIPTOR_LENGTH, max_len_buf);
+    
+    return t;
+}
+
+USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr)
+{
+    USB_TYPE res;
+    uint16_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) {
+        USB_ERR("GET CONF 1 DESCR FAILED");
+        return res;
+    }
+    total_conf_descr_length = buf[2] | (buf[3] << 8);
+    total_conf_descr_length = MIN(max_len_buf, total_conf_descr_length);
+    
+    if (len_conf_descr)
+        *len_conf_descr = total_conf_descr_length;
+    
+    USB_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::setAddress(USBDeviceConnected * dev, uint8_t address) {
+    return controlWrite(    dev,
+                            USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
+                            SET_ADDRESS,
+                            address,
+                            0, NULL, 0);
+    
+}
+
+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 USBEndpoint
+USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
+{
+    uint16_t total_conf_descr_length = 0;
+    USB_TYPE res;
+    
+    uint8_t index = findDevice(dev);
+
+    if (dev->isEnumerated() && deviceAttachedDriver[index]) {
+        return USB_TYPE_OK;
+    }
+    
+    // third step: get the whole device descriptor to see vid, pid
+    res = getDeviceDescriptor(dev, data, DEVICE_DESCRIPTOR_LENGTH);
+
+    if ((res != USB_TYPE_OK) && (res != USB_TYPE_DEVICE_NOT_RESPONDING_ERROR)) {
+        USB_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));
+    USB_DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8));
+
+    pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) );
+
+    res = getConfigurationDescriptor(dev, data, 400, &total_conf_descr_length);
+    if (res != USB_TYPE_OK) {
+        return res;
+    }
+
+#if DEBUG
+    USB_DBG("CONFIGURATION DESCRIPTOR:\r\n");
+    for (int i = 0; i < total_conf_descr_length; i++)
+        printf("%02X ", data[i]);
+    printf("\r\n\r\n");
+#endif
+
+    // Parse the configuration descriptor
+    parseConfDescr(dev, data, total_conf_descr_length, pEnumerator);
+
+
+    // sixth step: set configuration (only 1 supported)
+    res = setConfiguration(dev, 1);
+
+    if (res != USB_TYPE_OK) {
+        USB_DBG("SET CONF FAILED");
+        return res;
+    }
+
+    // Now the device is enumerated!
+    dev->setEnumerated();
+    USB_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, IUSBEnumerator* pEnumerator)
+{
+    uint32_t index = 0;
+    uint32_t len_desc = 0;
+    uint8_t id = 0;
+    int nb_endpoints_used = 0;
+    USBEndpoint * ep = NULL;
+    uint8_t intf_nb = 0;
+    bool parsing_intf = false;
+
+    while (index < len) {
+        len_desc = conf_descr[index];
+        id = conf_descr[index+1];
+        switch (id) {
+            case CONFIGURATION_DESCRIPTOR:
+                break;
+            case INTERFACE_DESCRIPTOR:
+                if(pEnumerator->parseInterface(intf_nb, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
+                    if (intf_nb++ <= MAX_INTF) {
+                        dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
+                        nb_endpoints_used = 0;
+                        USB_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 {
+                        USB_DBG("Drop intf...");
+                    }
+                    parsing_intf = true;
+                } else {
+                    parsing_intf = false;
+                }
+                break;
+            case ENDPOINT_DESCRIPTOR:
+                if (parsing_intf && (intf_nb <= MAX_INTF) ) {
+                    if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) {
+                        if( pEnumerator->useEndpoint(intf_nb - 1, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) {
+                            // if the USBEndpoint 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);
+                                USB_DBG("ADD USBEndpoint %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 {
+                                    USB_DBG("EP NULL");
+                                }
+                                nb_endpoints_used++;
+                            } else {
+                                USB_DBG("ISO USBEndpoint NOT SUPPORTED");
+                            }
+                        }
+                    }
+                }
+                break;
+            case HID_DESCRIPTOR:
+                lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
+                break;
+            default:
+                break;
+        }
+        index += len_desc;
+    }
+}
+
+
+USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
+{
+    return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, true);
+}
+
+USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
+{
+    return generalTransfer(dev, ep, buf, len, blocking, BULK_ENDPOINT, false);
+}
+
+USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
+{
+    return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, true);
+}
+
+USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking)
+{
+    return generalTransfer(dev, ep, buf, len, blocking, INTERRUPT_ENDPOINT, false);
+}
+
+USB_TYPE USBHost::generalTransfer(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking, ENDPOINT_TYPE type, bool write) {
+
+#if DEBUG_TRANSFER
+    const char * type_str = (type == BULK_ENDPOINT) ? "BULK" : ((type == INTERRUPT_ENDPOINT) ? "INTERRUPT" : "ISOCHRONOUS");
+    USB_DBG_TRANSFER("----- %s %s [dev: %p - %s - hub: %d - port: %d - addr: %d]------", type_str, (write) ? "WRITE" : "READ", dev, dev->getName(), dev->getHub(), dev->getPort(), dev->getAddress());
+#endif
+
+    USB_TYPE res;
+    ENDPOINT_DIRECTION dir = (write) ? OUT : IN;
+
+    if (dev == NULL) {
+        USB_ERR("dev NULL");
+        return USB_TYPE_ERROR;
+    }
+
+    if (ep == NULL) {
+        USB_ERR("ep NULL");
+        return USB_TYPE_ERROR;
+    }
+
+    if (ep->getState() != USB_TYPE_IDLE) {
+        USB_WARN("[ep: %p - dev: %p] NOT IDLE: %s", ep, ep->dev, ep->getStateString());
+        return ep->getState();
+    }
+
+    if ((ep->getDir() != dir) || (ep->getType() != type)) {
+        USB_ERR("[ep: %p - dev: %p] wrong dir or bad USBEndpoint type", ep, ep->dev);
+        return USB_TYPE_ERROR;
+    }
+
+    if (dev->getAddress() != ep->getDeviceAddress()) {
+        USB_ERR("[ep: %p - dev: %p] USBEndpoint addr and device addr don't match", ep, ep->dev);
+        return USB_TYPE_ERROR;
+    }
+    
+
+
+#if DEBUG_TRANSFER
+    if (write) {
+        USB_DBG_TRANSFER("%s WRITE buffer", type_str);
+        for (int i = 0; i < ep->getLengthTransferred(); i++)
+            printf("%02X ", buf[i]);
+        printf("\r\n\r\n");
+    }
+#endif
+    usb_mutex.lock();
+    addTransfer(ep, buf, len);
+    usb_mutex.unlock();
+
+    if (blocking) {
+
+        while((res = ep->getState()) == USB_TYPE_PROCESSING) {
+            Thread::wait(1);
+        }
+
+        USB_DBG_TRANSFER("%s TRANSFER res: %s", type_str, ep->getStateString());
+
+        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) {
+    return controlTransfer(dev, requestType, request, value, index, buf, len, false);
+}
+
+USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
+    return controlTransfer(dev, requestType, request, value, index, buf, len, true);
+}
+
+
+USB_TYPE USBHost::controlTransfer(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len, bool write)
+{
+    USB_DBG_TRANSFER("----- CONTROL %s [dev: %p - %s - hub: %d - port: %d] ------", (write) ? "WRITE" : "READ", dev, dev->getName(), dev->getHub(), dev->getPort());
+
+    int length_transfer = len;
+    USB_TYPE res;
+    uint32_t token;
+
+    usb_mutex.lock();
+    control->setSpeed(dev->getSpeed());
+    control->setSize(dev->getSizeControlEndpoint());
+    if (dev->isActiveAddress()) {
+        control->setDeviceAddress(dev->getAddress());
+    } else {
+        control->setDeviceAddress(0);
+    }
+    
+    USB_DBG_TRANSFER("Control transfer on device: %d\r\n", control->getDeviceAddress());
+    fillControlBuf(requestType, request, value, index, len);
+
+#if DEBUG_TRANSFER
+    USB_DBG_TRANSFER("SETUP PACKET: ");
+    for (int i = 0; i < 8; i++)
+        printf("%01X ", setupPacket[i]);
+    printf("\r\n");
+#endif
+
+    control->setNextToken(TD_SETUP);
+    addTransfer(control, (uint8_t*)setupPacket, 8);
+
+    while((res = control->getState()) == USB_TYPE_PROCESSING) {
+        Thread::wait(1);
+    }
+
+    USB_DBG_TRANSFER("CONTROL setup stage %s", control->getStateString());
+
+    if (res != USB_TYPE_IDLE) {
+        usb_mutex.unlock();
+        return res;
+    }
+
+    if (length_transfer) {
+        token = (write) ? TD_OUT : TD_IN;
+        control->setNextToken(token);
+        addTransfer(control, (uint8_t *)buf, length_transfer);
+
+        while((res = control->getState()) == USB_TYPE_PROCESSING) {
+            Thread::wait(1);
+        }
+
+#if DEBUG_TRANSFER
+        USB_DBG_TRANSFER("CONTROL %s stage %s", (write) ? "WRITE" : "READ", control->getStateString());
+        if (write) {
+            USB_DBG_TRANSFER("CONTROL WRITE buffer");
+            for (int i = 0; i < control->getLengthTransferred(); i++)
+                printf("%02X ", buf[i]);
+            printf("\r\n\r\n");
+        } else {
+            USB_DBG_TRANSFER("CONTROL READ SUCCESS [%d bytes transferred]", control->getLengthTransferred());
+            for (int i = 0; i < control->getLengthTransferred(); i++)
+                printf("%02X ", buf[i]);
+            printf("\r\n\r\n");
+        }
+#endif
+
+        if (res != USB_TYPE_IDLE) {
+            usb_mutex.unlock();
+            return res;
+        }
+    }
+
+    token = (write) ? TD_IN : TD_OUT;
+    control->setNextToken(token);
+    addTransfer(control, NULL, 0);
+
+    while((res = control->getState()) == USB_TYPE_PROCESSING) {
+        Thread::wait(1);
+    }
+
+    USB_DBG_TRANSFER("CONTROL ack stage %s", control->getStateString());
+    usb_mutex.unlock();
+
+    if (res != USB_TYPE_IDLE)
+        return res;
+
+    return USB_TYPE_OK;
+}
+
+
+void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_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
+    *((uint16_t*)&setupPacket[2]) = value;
+    *((uint16_t*)&setupPacket[4]) = index;
+    *((uint16_t*)&setupPacket[6]) = (uint32_t) len;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,377 @@
+/* Copyright (c) 2010-2012 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 "IUSBEnumerator.h"
+#include "USBHostConf.h"
+#include "rtos.h"
+#include "dbg.h"
+#include "USBHostHub.h"
+
+// singleton class
+class USBHost : public USBHALHost {
+public:
+    /**
+    * Static method to create or retrieve the single USBHost instance
+    */
+    static USBHost * getHostInst();
+    
+    /**
+    * 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 USBEndpoint 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, USBEndpoint * 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 USBEndpoint 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, USBEndpoint * 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 USBEndpoint 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, USBEndpoint * 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 USBEndpoint 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, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking = true);
+
+    /**
+    * Enumerate a device.
+    *
+    * @param dev device which will be enumerated
+    *
+    * @returns status of the enumeration
+    */
+    USB_TYPE enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator);
+
+    /**
+    * 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 a specific device
+    *
+    * @param dev device which will be resetted
+    */
+    USB_TYPE 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
+    */
+    inline 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>
+    inline void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void)) {
+        int index = findDevice(dev);
+        if ((index != -1) && (mptr != NULL) && (tptr != NULL)) {
+            USB_DBG("register driver for dev: %p", dev);
+            deviceAttachedDriver[index] = true;
+            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
+     */
+    inline void registerDriver(USBDeviceConnected * dev, uint8_t intf, void (*fn)(void)) {
+        int index = findDevice(dev);
+        if ((index != -1) && (fn != NULL)) {
+            USB_DBG("register driver for dev: %p", dev);
+            deviceAttachedDriver[index] = true;
+            dev->onDisconnect(intf, fn);
+        }
+    }
+    
+    /**
+    * 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
+    * @param hub_parent reference on the parent hub
+    */
+    virtual void deviceConnected(int hub, int port, bool lowSpeed, USBHostHub * hub_parent = NULL);
+
+    /**
+    * 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, USBHostHub * hub_parent, volatile uint32_t addr);
+    
+    /**
+    * Free a specific device
+    *
+    * @param dev device to be freed
+    */
+    void freeDevice(USBDeviceConnected * dev);
+
+protected:
+
+    /**
+    * 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;
+    uint16_t  lenReportDescr;
+
+    // endpoints
+    void unqueueEndpoint(USBEndpoint * ep) ;
+    USBEndpoint  endpoints[MAX_ENDPOINT];
+    USBEndpoint* volatile  control;
+
+    USBEndpoint* volatile  headControlEndpoint;
+    USBEndpoint* volatile  headBulkEndpoint;
+    USBEndpoint* volatile  headInterruptEndpoint;
+
+    USBEndpoint* volatile  tailControlEndpoint;
+    USBEndpoint* volatile  tailBulkEndpoint;
+    USBEndpoint* volatile  tailInterruptEndpoint;
+
+    bool controlEndpointAllocated;
+
+    // devices connected
+    USBDeviceConnected devices[MAX_DEVICE_CONNECTED];
+    volatile bool  deviceInUse[MAX_DEVICE_CONNECTED];
+    volatile bool  deviceAttachedDriver[MAX_DEVICE_CONNECTED];
+    volatile bool  deviceReset[MAX_DEVICE_CONNECTED];
+    
+#if MAX_HUB_NB
+    USBHostHub hubs[MAX_HUB_NB];
+    bool hub_in_use[MAX_HUB_NB];
+#endif
+
+    // to store a setup packet
+    uint8_t  setupPacket[8];
+    
+    typedef struct {
+        uint8_t event_id;
+        void * td_addr;
+        uint8_t hub;
+        uint8_t port;
+        uint8_t lowSpeed;
+        uint8_t td_state;
+        void * hub_parent;
+    } message_t;
+    
+    Thread usbThread;
+    void usb_process();
+    static void usb_process_static(void const * arg);
+    MemoryPool<message_t, 10> mpool_usb_event;
+    Queue<message_t, 10> queue_usb_event;
+    Mutex usb_mutex;
+    
+    // buffer for conf descriptor
+    uint8_t data[400];
+    
+    /**
+    * 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(USBEndpoint * ed, uint8_t * buf, uint32_t len) ;
+    
+    /**
+    * Link the USBEndpoint to the linked list and attach an USBEndpoint this USBEndpoint to a device
+    *
+    * @param dev pointer on a USBDeviceConnected object
+    * @param ep pointer on the USBEndpoint which will be added
+    *
+    * return true if successful
+    */
+    bool addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep) ;
+
+    /**
+    * Create an USBEndpoint descriptor. Warning: the USBEndpoint is not linked.
+    *
+    * @param type USBEndpoint type (CONTROL_ENDPOINT, BULK_ENDPOINT, INTERRUPT_ENDPOINT)
+    * @param dir USBEndpoint direction (no meaning for CONTROL_ENDPOINT)
+    * @param size USBEndpoint max packet size
+    * @param addr USBEndpoint address
+    *
+    * @returns pointer on the USBEndpoint created
+    */
+    USBEndpoint * newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) ;
+    
+    /**
+    * Request the device descriptor
+    *
+    * @param dev request the device descriptor on this device
+    * @param buf buffer to store the device descriptor
+    * @param max_len_buf maximum size of buf
+    * @param len_dev_descr pointer to store the length of the packet transferred
+    */
+    USB_TYPE getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_dev_descr = NULL);
+
+    /**
+    * Request the configuration descriptor
+    *
+    * @param dev request the configuration descriptor on this device
+    * @param buf buffer to store the configuration descriptor
+    * @param max_len_buf maximum size of buf
+    * @param len_conf_descr pointer to store the length of the packet transferred
+    */
+    USB_TYPE getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t max_len_buf, uint16_t * len_conf_descr = NULL);
+    
+    /**
+    * Set the address of a specific device
+    *
+    * @param dev device to set the address
+    * @param address address
+    */
+    USB_TYPE setAddress(USBDeviceConnected * dev, uint8_t address);
+
+    /**
+    * Set the configuration of a device
+    *
+    * @param dev device on which the specified configuration will be activated
+    * @param conf configuration number to activate (usually 1)
+    */
+    USB_TYPE setConfiguration(USBDeviceConnected * dev, uint8_t conf);
+    
+    USB_TYPE controlTransfer(   USBDeviceConnected * dev,
+                                uint8_t requestType,
+                                uint8_t request,
+                                uint32_t value,
+                                uint32_t index,
+                                uint8_t * buf,
+                                uint32_t len,
+                                bool write);
+
+    USB_TYPE generalTransfer(   USBDeviceConnected * dev,
+                                USBEndpoint * ep,
+                                uint8_t * buf,
+                                uint32_t len,
+                                bool blocking,
+                                ENDPOINT_TYPE type,
+                                bool write) ;
+                                
+    void fillControlBuf(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index, int len) ;
+    void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) ;
+    int findDevice(USBDeviceConnected * dev) ;
+    int findDevice(uint8_t hub, uint8_t port, USBHostHub * hub_parent = NULL) ;
+
+    /////////////////////////
+    /// FOR DEBUG
+    /////////////////////////
+    void printList(ENDPOINT_TYPE type);
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostConf.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,66 @@
+#ifndef USBHOST_CONF_H
+#define USBHOST_CONF_H
+
+/*
+* Maximum number of devices that can be connected
+* to the usb host
+*/
+#define MAX_DEVICE_CONNECTED        10
+
+/*
+* Maximum of Hub connected to the usb host
+*/
+#define MAX_HUB_NB                  5
+
+/*
+* Maximum number of ports on a USB hub
+*/
+#define MAX_HUB_PORT                4
+
+/*
+* Enable USBHostMSD
+*/
+#define USBHOST_MSD                 1
+
+/*
+* Enable USBHostKeyboard
+*/
+#define USBHOST_KEYBOARD            1
+
+/*
+* Enable USBHostMouse
+*/
+#define USBHOST_MOUSE               1
+
+/*
+* Enable USBHostSerial
+*/
+#define USBHOST_SERIAL              1
+
+/*
+* Maximum number of interfaces of a usb device
+*/
+#define MAX_INTF                    2
+
+/*
+* Maximum number of endpoints on each interface
+*/
+#define MAX_ENDPOINT_PER_INTERFACE  3
+
+/*
+* Maximum number of endpoint descriptors that can be allocated
+*/
+#define MAX_ENDPOINT                (MAX_DEVICE_CONNECTED * MAX_INTF * MAX_ENDPOINT_PER_INTERFACE)
+
+/*
+* Maximum number of transfer descriptors that can be allocated
+*/
+#define MAX_TD                      (MAX_ENDPOINT*2)
+
+/*
+* usb_thread stack size
+*/
+#define USB_THREAD_STACK            (128*4 + MAX_HUB_NB*128*4)
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostTypes.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,228 @@
+/* Copyright (c) 2010-2012 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_OK = 0,
+
+    // completion code
+    USB_TYPE_CRC_ERROR = 1,
+    USB_TYPE_BIT_STUFFING_ERROR = 2,
+    USB_TYPE_DATA_TOGGLE_MISMATCH_ERROR = 3,
+    USB_TYPE_STALL_ERROR = 4,
+    USB_TYPE_DEVICE_NOT_RESPONDING_ERROR = 5,
+    USB_TYPE_PID_CHECK_FAILURE_ERROR = 6,
+    USB_TYPE_UNEXPECTED_PID_ERROR = 7,
+    USB_TYPE_DATA_OVERRUN_ERROR = 8,
+    USB_TYPE_DATA_UNDERRUN_ERROR = 9,
+    USB_TYPE_RESERVED = 9,
+    USB_TYPE_RESERVED_ = 10,
+    USB_TYPE_BUFFER_OVERRUN_ERROR = 12,
+    USB_TYPE_BUFFER_UNDERRUN_ERROR = 13,
+
+    // general usb state
+    USB_TYPE_DISCONNECTED = 14,
+    USB_TYPE_FREE = 15,
+    USB_TYPE_IDLE = 16,
+    USB_TYPE_PROCESSING = 17,
+
+    USB_TYPE_ERROR = 18,
+};
+
+
+enum ENDPOINT_DIRECTION {
+    OUT = 1,
+    IN
+};
+
+enum ENDPOINT_TYPE {
+    CONTROL_ENDPOINT = 0,
+    ISOCHRONOUS_ENDPOINT,
+    BULK_ENDPOINT,
+    INTERRUPT_ENDPOINT
+};
+
+#define AUDIO_CLASS     0x01
+#define CDC_CLASS       0x02
+#define HID_CLASS       0x03
+#define MSD_CLASS       0x08
+#define HUB_CLASS       0x09
+#define SERIAL_CLASS    0x0A
+
+// ------------------ 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
+
+#define  FI                     0x2EDF           // 12000 bits per frame (-1)
+#define  DEFAULT_FMINTERVAL     ((((6 * (FI - 210)) / 7) << 16) | FI)
+
+#define  ED_SKIP            (uint32_t) (0x00001000)        // Skip this ep in queue
+
+#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                             
+
+#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_REQUEST_TYPE_STANDARD  0x00
+#define  USB_RECIPIENT_DEVICE       0x00
+#define  USB_RECIPIENT_INTERFACE    0x01
+#define  USB_RECIPIENT_ENDPOINT     0x02
+
+// -------------- USB Standard Requests  -------------- 
+#define  SET_ADDRESS                0x05
+#define  GET_DESCRIPTOR             0x06
+#define  SET_CONFIGURATION          0x09
+#define  SET_INTERFACE              0x0b
+#define  CLEAR_FEATURE              0x01
+
+// -------------- USB Descriptor Length  -------------- 
+#define DEVICE_DESCRIPTOR_LENGTH            0x12
+#define CONFIGURATION_DESCRIPTOR_LENGTH     0x09
+
+// ------------ HostController Transfer Descriptor ------------
+typedef __packed struct hcTd {
+    __IO  uint32_t  control;        // Transfer descriptor control
+    __IO  uint8_t *  currBufPtr;    // Physical address of current buffer pointer
+    __IO  uint32_t  nextTD;         // Physical pointer to next Transfer Descriptor
+    __IO  uint8_t *  bufEnd;        // Physical address of end of buffer
+    void * ep;                      // ep address where a td is linked in
+    uint32_t dummy[3];              // padding
+} HCTD;
+
+// ----------- HostController EndPoint Descriptor ------------- 
+typedef __packed struct hcEd {
+    __IO  uint32_t  control;        // Endpoint descriptor control
+    __IO  HCTD *  tailTD;           // Physical address of tail in Transfer descriptor list
+    __IO  HCTD *  headTD;           // Physcial address of head in Transfer descriptor list
+    __IO  uint32_t  nextED;         // Physical address of next Endpoint descriptor
+} HCED;
+
+
+// ----------- Host Controller Communication Area ------------  
+typedef __packed struct hcca {
+    __IO  uint32_t  IntTable[32];   // Interrupt Table
+    __IO  uint32_t  FrameNumber;    // Frame Number
+    __IO  uint32_t  DoneHead;       // Done Head
+    volatile  uint8_t   Reserved[116];  // Reserved for future use                                  
+    volatile  uint8_t   Unknown[4];     // Unused                                                   
+} HCCA;
+
+typedef __packed struct {
+    uint8_t bLength;            
+    uint8_t bDescriptorType;    
+    uint16_t bcdUSB;            
+    uint8_t bDeviceClass;       
+    uint8_t bDeviceSubClass;    
+    uint8_t bDeviceProtocol;    
+    uint8_t bMaxPacketSize;     
+    uint16_t idVendor;          
+    uint16_t idProduct;         
+    uint16_t bcdDevice;         
+    uint8_t iManufacturer;      
+    uint8_t iProduct;           
+    uint8_t iSerialNumber;      
+    uint8_t bNumConfigurations; 
+} DeviceDescriptor;
+
+typedef __packed struct {
+    uint8_t bLength;               
+    uint8_t bDescriptorType;       
+    uint16_t wTotalLength;         
+    uint8_t bNumInterfaces;        
+    uint8_t bConfigurationValue;   
+    uint8_t iConfiguration;        
+    uint8_t bmAttributes;          
+    uint8_t bMaxPower;             
+} ConfigurationDescriptor; 
+
+typedef struct {
+    uint8_t bLength;                 
+    uint8_t bDescriptorType;   
+    uint8_t bInterfaceNumber;  
+    uint8_t bAlternateSetting; 
+    uint8_t bNumEndpoints;     
+    uint8_t bInterfaceClass;   
+    uint8_t bInterfaceSubClass;
+    uint8_t bInterfaceProtocol;
+    uint8_t iInterface;        
+} InterfaceDescriptor; 
+
+typedef struct {
+    uint8_t bLength;          
+    uint8_t bDescriptorType;  
+    uint8_t bEndpointAddress; 
+    uint8_t bmAttributes;     
+    uint16_t wMaxPacketSize;  
+    uint8_t bInterval;        
+} EndpointDescriptor;
+
+typedef struct {
+    uint8_t bDescLength;      
+    uint8_t bDescriptorType;  
+    uint8_t bNbrPorts;        
+    uint16_t wHubCharacteristics;
+    uint8_t bPwrOn2PwrGood;   
+    uint8_t bHubContrCurrent; 
+    uint8_t DeviceRemovable;  
+    uint8_t PortPweCtrlMak;   
+} HubDescriptor;              
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/dbg.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,35 @@
+#ifndef USB_DEBUG_H
+#define USB_DEBUG_H
+
+//Debug is disabled by default
+#define DEBUG 0
+#define DEBUG_TRANSFER 0
+#define DEBUG_EP_STATE 0
+#define DEBUG_EVENT 0
+
+#if (DEBUG)
+#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_DBG(x, ...)
+#endif
+
+#if (DEBUG_TRANSFER)
+#define USB_DBG_TRANSFER(x, ...) std::printf("[USB_TRANSFER: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_DBG_TRANSFER(x, ...)
+#endif
+
+#if (DEBUG_EVENT)
+#define USB_DBG_EVENT(x, ...) std::printf("[USB_EVENT: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_DBG_EVENT(x, ...)
+#endif
+
+#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]"x"\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostKeyboard.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,189 @@
+/* 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 "USBHostKeyboard.h"
+
+#if USBHOST_KEYBOARD
+
+static uint8_t keymap[4][0x39] = { 
+    { 0, 0, 0, 0, 'a', 'b' /*0x05*/,
+      'c', 'd', 'e', 'f', 'g' /*0x0a*/,
+      'h', 'i', 'j', 'k', 'l'/*0x0f*/,
+      'm', 'n', 'o', 'p', 'q'/*0x14*/,
+      'r', 's', 't', 'u', 'v'/*0x19*/,
+      'w', 'x', 'y', 'z', '1'/*0x1E*/,
+      '2', '3', '4', '5', '6'/*0x23*/,
+      '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/
+      0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/
+      '=', '[', ']', '\\', '#', /*0x32*/
+      ';', '\'', 0, ',', '.', /*0x37*/
+      '/'},
+
+    /* CTRL MODIFIER */
+    { 0, 0, 0, 0, 0, 0 /*0x05*/,
+      0, 0, 0, 0, 0 /*0x0a*/,
+      0, 0, 0, 0, 0/*0x0f*/,
+      0, 0, 0, 0, 0/*0x14*/,
+      0, 0, 0, 0, 0/*0x19*/,
+      0, 0, 0, 0, 0/*0x1E*/,
+      0, 0, 0, 0, 0/*0x23*/,
+      0, 0, 0, 0, 0 /*enter*/, /*0x28*/
+      0, 0, 0, 0, 0, /*0x2d*/
+      0, 0, 0, 0, 0, /*0x32*/
+      0, 0, 0, 0, 0, /*0x37*/
+      0},
+
+    /* SHIFT MODIFIER */
+    { 0, 0, 0, 0, 'A', 'B' /*0x05*/,
+      'C', 'D', 'E', 'F', 'G' /*0x0a*/,
+      'H', 'I', 'J', 'K', 'L'/*0x0f*/,
+      'M', 'N', 'O', 'P', 'Q'/*0x14*/,
+      'R', 'S', 'T', 'U', 'V'/*0x19*/,
+      'W', 'X', 'Y', 'Z', '!'/*0x1E*/,
+      '@', '#', '$', '%', '^'/*0x23*/,
+      '&', '*', '(', ')', 0, /*0x28*/
+      0, 0, 0, 0, 0, /*0x2d*/
+      '+', '{', '}', '|', '~', /*0x32*/
+      ':', '"', 0, '<', '>', /*0x37*/
+      '?'},
+
+    /* ALT MODIFIER */
+    { 0, 0, 0, 0, 0, 0 /*0x05*/,
+      0, 0, 0, 0, 0 /*0x0a*/,
+      0, 0, 0, 0, 0/*0x0f*/,
+      0, 0, 0, 0, 0/*0x14*/,
+      0, 0, 0, 0, 0/*0x19*/,
+      0, 0, 0, 0, 0/*0x1E*/,
+      0, 0, 0, 0, 0/*0x23*/,
+      0, 0, 0, 0, 0 /*enter*/, /*0x28*/
+      0, 0, 0, 0, 0, /*0x2d*/
+      0, 0, 0, 0, 0, /*0x32*/
+      0, 0, 0, 0, 0, /*0x37*/
+      0}
+
+};
+
+
+USBHostKeyboard::USBHostKeyboard() {
+    host = USBHost::getHostInst();
+    init();
+}
+
+
+void USBHostKeyboard::init() {
+    dev = NULL;
+    int_in = NULL;
+    report_id = 0;
+    onKey = NULL;
+    onKeyCode = NULL;
+    dev_connected = false;
+    keyboard_intf = -1;
+    keyboard_device_found = false;
+}
+
+bool USBHostKeyboard::connected() {
+    return dev_connected;
+}
+
+
+bool USBHostKeyboard::connect() {
+    
+    U8 i;
+    
+    if (dev_connected) {
+        return true;
+    }
+    
+    for (i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+
+            if (host->enumerate(dev, this))
+                break;
+            
+            if (keyboard_device_found) {
+                int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN);
+                
+                if (!int_in)
+                    break;
+                
+                USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+                dev->setName("Keyboard");
+                host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init);
+                
+                int_in->attach(this, &USBHostKeyboard::rxHandler);
+                host->interruptRead(dev, int_in, report, int_in->getSize(), false);
+                
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostKeyboard::rxHandler() {
+    int len = int_in->getLengthTransferred();
+    int index = (len == 9) ? 1 : 0;
+    int len_listen = int_in->getSize();
+    uint8_t key = 0;
+    if (len == 8 || len == 9) {
+        uint8_t modifier = (report[index] == 4) ? 3 : report[index];
+        len_listen = len;
+        key = keymap[modifier][report[index + 2]];
+        if (key && onKey) {
+            (*onKey)(key);
+        }
+        if (onKeyCode) {
+            (*onKeyCode)(report[index + 2], modifier);
+        }
+    }
+    if (dev != NULL)
+        host->interruptRead(dev, int_in, report, len_listen, false);
+}
+
+/*virtual*/ void USBHostKeyboard::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for keyboard driver
+}
+
+/*virtual*/ bool USBHostKeyboard::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    if ((keyboard_intf == -1) &&
+        (intf_class == HID_CLASS) &&
+        (intf_subclass == 0x01) &&
+        (intf_protocol == 0x01)) {
+        keyboard_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostKeyboard::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == keyboard_intf) {
+        if (type == INTERRUPT_ENDPOINT && dir == IN) {
+            keyboard_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostKeyboard.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,102 @@
+/* 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 USBHOSTKEYBOARD_H
+#define USBHOSTKEYBOARD_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_KEYBOARD
+
+#include "USBHost.h"
+
+class USBHostKeyboard : public IUSBEnumerator {
+public:
+    
+    /**
+    * Constructor
+    */
+    USBHostKeyboard();
+
+    /**
+     * Try to connect a keyboard device
+     *
+     * * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
+    * Check if a keyboard is connected
+    *
+    * @returns true if a keyboard is connected
+    */
+    bool connected();
+
+    /**
+     * Attach a callback called when a keyboard event is received
+     *
+     * @param fptr function pointer
+     */
+    inline void attach(void (*ptr)(uint8_t key)) {
+        if (ptr != NULL) {
+            onKey = ptr;
+        }
+    }
+
+    /**
+     * Attach a callback called when a keyboard event is received
+     *
+     * @param fptr function pointer
+     */
+    inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) {
+        if (ptr != NULL) {
+            onKeyCode = ptr;
+        }
+    }
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+    USBHost * host;
+    USBDeviceConnected * dev;
+    USBEndpoint * int_in;
+    uint8_t report[9];
+    int keyboard_intf;
+    bool keyboard_device_found;
+    
+    bool dev_connected;
+
+    void rxHandler();
+
+    void (*onKey)(uint8_t key);
+    void (*onKeyCode)(uint8_t key, uint8_t modifier);
+
+    int report_id;
+    
+    void init();
+
+};
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostMouse.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,117 @@
+/* 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 "USBHostMouse.h"
+
+#if USBHOST_MOUSE
+
+USBHostMouse::USBHostMouse() {
+    host = USBHost::getHostInst();
+    init();
+}
+
+void USBHostMouse::init() {
+    dev = NULL;
+    int_in = NULL;
+    onUpdate = NULL;
+    report_id = 0;
+    dev_connected = false;
+    mouse_device_found = false;
+    mouse_intf = -1;
+}
+
+bool USBHostMouse::connected() {
+    return dev_connected;
+}
+
+bool USBHostMouse::connect() {
+    
+    U8 i;
+    
+    if (dev_connected) {
+        return true;
+    }
+    
+    for (i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+
+            if(host->enumerate(dev, this))
+                break;
+            
+            if (mouse_device_found) {
+                
+                int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN);
+                if (!int_in)
+                    break;
+                
+                USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+                dev->setName("Mouse");
+                host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init);
+                
+                int_in->attach(this, &USBHostMouse::rxHandler);
+                host->interruptRead(dev, int_in, report, int_in->getSize(), false);
+                
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostMouse::rxHandler() {
+    int len_listen = int_in->getSize();
+    int len = int_in->getLengthTransferred();
+    if (onUpdate) {
+        (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]);
+    }
+    if (dev != NULL)
+        host->interruptRead(dev, int_in, report, len_listen, false);
+}
+
+/*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for mouse driver
+}
+
+/*virtual*/ bool USBHostMouse::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    if ((mouse_intf == -1) &&
+        (intf_class == HID_CLASS) &&
+        (intf_subclass == 0x01) &&
+        (intf_protocol == 0x02)) {
+        mouse_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostMouse::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == mouse_intf) {
+        if (type == INTERRUPT_ENDPOINT && dir == IN) {
+            mouse_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostMouse.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,86 @@
+/* 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 USBHOSTMOUSE_H
+#define USBHOSTMOUSE_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_MOUSE
+
+#include "USBHost.h"
+
+class USBHostMouse : public IUSBEnumerator {
+public:
+
+    /**
+    * Constructor
+    */
+    USBHostMouse();
+
+    /**
+     * Try to connect a mouse device
+     *
+     * * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
+    * Check if a mouse is connected
+    *
+    * @returns true if a mouse is connected
+    */
+    bool connected();
+
+    /**
+     * Attach a callback called when a mouse event is received
+     *
+     * @param fptr function pointer
+     */
+    inline void attach(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) {
+        if (ptr != NULL) {
+            onUpdate = ptr;
+        }
+    }
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+    USBHost * host;
+    USBDeviceConnected * dev;
+    USBEndpoint * int_in;
+    uint8_t report[4];
+    
+    bool dev_connected;
+    bool mouse_device_found;
+    int mouse_intf;
+
+    void rxHandler();
+    void (*onUpdate)(uint8_t buttons, int8_t x, int8_t y, int8_t z);
+    int report_id;
+    void init();
+};
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHub/USBHostHub.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,275 @@
+/* Copyright (c) 2010-2012 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 "USBHostHub.h"
+
+#if MAX_HUB_NB
+
+#include "USBHost.h"
+#include "dbg.h"
+
+#define GET_STATUS 0x00
+#define CLEAR_FEATURE 0x01
+#define GET_STATE 0x02
+#define SET_FEATURE 0x03
+#define GET_DESCRIPTOR 0x06
+
+#define PORT_CONNECTION_FEATURE     (0x00)
+#define PORT_ENABLE_FEATURE         (0x01)
+#define PORT_RESET_FEATURE          (0x04)
+#define PORT_POWER_FEATURE          (0x08)
+
+#define C_PORT_CONNECTION_FEATURE     (16)
+#define C_PORT_ENABLE_FEATURE         (17)
+#define C_PORT_RESET_FEATURE          (20)
+
+#define PORT_CONNECTION   (1 << 0)
+#define PORT_ENABLE       (1 << 1)
+#define PORT_SUSPEND      (1 << 2)
+#define PORT_OVER_CURRENT (1 << 3)
+#define PORT_RESET        (1 << 4)
+#define PORT_POWER        (1 << 8)
+#define PORT_LOW_SPEED    (1 << 9)
+
+#define C_PORT_CONNECTION   (1 << 16)
+#define C_PORT_ENABLE       (1 << 17)
+#define C_PORT_SUSPEND      (1 << 18)
+#define C_PORT_OVER_CURRENT (1 << 19)
+#define C_PORT_RESET        (1 << 20)
+
+USBHostHub::USBHostHub() {
+    host = NULL;
+    init();
+}
+
+void USBHostHub::init() {
+    dev_connected = false;
+    dev = NULL;
+    int_in = NULL;
+    dev_connected = false;
+    hub_intf = -1;
+    hub_device_found = false;
+    nb_port = 0;
+    hub_characteristics = 0;
+    
+    for (int i = 0; i < MAX_HUB_PORT; i++) {
+        device_children[i] = NULL;
+    }
+}
+
+void USBHostHub::setHost(USBHost * host_) {
+    host = host_;
+}
+
+bool USBHostHub::connected()
+{
+    return dev_connected;
+}
+
+bool USBHostHub::connect(USBDeviceConnected * dev)
+{   
+    if (dev_connected) {
+        return true;
+    }
+    
+    if(host->enumerate(dev, this)) {
+        init();
+        return false;
+    }
+    
+    if (hub_device_found) {
+        this->dev = dev;
+    
+        int_in = dev->getEndpoint(hub_intf, INTERRUPT_ENDPOINT, IN);
+        
+        if (!int_in) {
+            init();
+            return false;
+        }
+        
+        USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+        dev->setName("Hub");
+        host->registerDriver(dev, hub_intf, this, &USBHostHub::disconnect);
+        
+        int_in->attach(this, &USBHostHub::rxHandler);
+        
+        // get HUB descriptor
+        host->controlRead(  dev, 
+                            USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
+                            GET_DESCRIPTOR,
+                            0x29 << 8, 0, buf, sizeof(HubDescriptor));
+        nb_port = buf[2];
+        hub_characteristics = buf[3];
+        
+        USB_DBG("Hub has %d port", nb_port);
+        
+        for (uint8_t j = 1; j <= nb_port; j++) {
+            setPortFeature(PORT_POWER_FEATURE, j);
+        }
+        wait_ms(buf[5]*2);
+        
+        host->interruptRead(dev, int_in, buf, 1, false);
+        dev_connected = true;
+        return true;
+    }
+    
+    return false;
+}
+
+void USBHostHub::disconnect() {
+    init();
+}
+
+/*virtual*/ void USBHostHub::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for MSD driver
+}
+
+/*virtual*/ bool USBHostHub::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    if ((hub_intf == -1) &&
+        (intf_class == HUB_CLASS) &&
+        (intf_subclass == 0) &&
+        (intf_protocol == 0)) {
+        hub_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostHub::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == hub_intf) {
+        if ((type == INTERRUPT_ENDPOINT) && (dir == IN)) {
+            hub_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+void USBHostHub::deviceConnected(USBDeviceConnected * dev) {
+    device_children[dev->getPort() - 1] = dev;
+}
+
+void USBHostHub::deviceDisconnected(USBDeviceConnected * dev) {
+    device_children[dev->getPort() - 1] = NULL;
+}
+
+void USBHostHub::hubDisconnected() {
+    for (uint8_t i = 0; i < MAX_HUB_PORT; i++) {
+        if (device_children[i] != NULL) {
+            host->freeDevice(device_children[i]);
+        }
+    }
+}
+
+void USBHostHub::rxHandler() {
+    uint32_t status;
+    if (int_in) {
+        if (int_in->getState() == USB_TYPE_IDLE) {
+            for (int port = 1; port <= nb_port; port++) {
+                status = getPortStatus(port);
+                USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status);
+                
+                // if connection status has changed
+                if (status & C_PORT_CONNECTION) {
+                    if (status & PORT_CONNECTION) {
+                        USB_DBG("[hub handler hub: %d - port: %d] new device connected", dev->getHub(), port);
+                        host->deviceConnected(dev->getHub() + 1, port, status & PORT_LOW_SPEED, this);
+                    } else {
+                        USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port);
+                        host->deviceDisconnected(dev->getHub() + 1, port, this, NULL);
+                    }
+                    
+                    clearPortFeature(C_PORT_CONNECTION_FEATURE, port);
+                }
+                
+                if (status & C_PORT_RESET) {
+                    clearPortFeature(C_PORT_RESET_FEATURE, port);
+                }
+                
+                if (status & C_PORT_ENABLE) {
+                    clearPortFeature(C_PORT_ENABLE_FEATURE, port);
+                }
+                
+                if ((status & PORT_OVER_CURRENT)) {
+                    USB_ERR("OVER CURRENT DETECTED\r\n");
+                    clearPortFeature(PORT_OVER_CURRENT, port);
+                    host->deviceDisconnected(dev->getHub() + 1, port, this, NULL);
+                }
+            }
+        }
+        host->interruptRead(dev, int_in, buf, 1, false);
+    }
+}
+
+void USBHostHub::portReset(uint8_t port) {
+    // reset port
+    uint32_t status;
+    USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this)
+    setPortFeature(PORT_RESET_FEATURE, port);
+    while(1) {
+        status = getPortStatus(port);
+        if (status & (PORT_ENABLE | PORT_RESET))
+            break;
+        if (status & PORT_OVER_CURRENT) {
+            USB_ERR("OVER CURRENT DETECTED\r\n");
+            clearPortFeature(PORT_OVER_CURRENT, port);
+            host->deviceDisconnected(dev->getHub() + 1, port, this, NULL);
+            break;
+        }
+        Thread::wait(10);
+    }
+}
+
+void USBHostHub::setPortFeature(uint32_t feature, uint8_t port) {
+    host->controlWrite( dev,
+                        USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
+                        SET_FEATURE,
+                        feature,
+                        port,
+                        NULL,
+                        0);
+}
+
+void USBHostHub::clearPortFeature(uint32_t feature, uint8_t port) {
+    host->controlWrite( dev,
+                        USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
+                        CLEAR_FEATURE,
+                        feature,
+                        port,
+                        NULL,
+                        0);
+}
+
+uint32_t USBHostHub::getPortStatus(uint8_t port) {
+    uint32_t st;
+    host->controlRead(  dev,
+                        USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE | USB_RECIPIENT_ENDPOINT,
+                        GET_STATUS,
+                        0,
+                        port,
+                        (uint8_t *)&st,
+                        4);
+    return st;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHub/USBHostHub.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,128 @@
+/* Copyright (c) 2010-2012 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 USBHOSTHUB_H
+#define USBHOSTHUB_H
+
+#include "USBHostConf.h"
+
+#if MAX_HUB_NB
+
+#include "USBHostTypes.h"
+#include "IUSBEnumerator.h"
+
+class USBHost;
+class USBDeviceConnected;
+class USBEndpoint;
+
+/** 
+ * A class to use a USB Hub
+ */
+class USBHostHub : public IUSBEnumerator {
+public:
+    /**
+    * Constructor
+    */
+    USBHostHub();
+
+    /**
+    * Check if a USB Hub is connected
+    *
+    * @return true if a serial device is connected
+    */
+    bool connected();
+
+    /**
+     * Try to connect device
+     *
+     * @param dev device to connect
+     * @return true if connection was successful
+     */
+    bool connect(USBDeviceConnected * dev);
+    
+    /**
+    * Automatically called by USBHost when a device
+    * has been enumerated by usb_thread
+    *
+    * @param dev device connected
+    */
+    void deviceConnected(USBDeviceConnected * dev);
+    
+    /**
+    * Automatically called by USBHost when a device
+    * has been disconnected from this hub
+    *
+    * @param dev device connected
+    */
+    void deviceDisconnected(USBDeviceConnected * dev);
+    
+    /**
+    * Rest a specific port
+    *
+    * @param port port number
+    */
+    void portReset(uint8_t port);
+    
+    /*
+    * Called by USBHost to set the instance of USBHost
+    *
+    * @param host host instance
+    */
+    void setHost(USBHost * host);
+    
+    /**
+    * Called by USBhost when a hub has been disconnected
+    */
+    void hubDisconnected();
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+    USBHost * host;
+    USBDeviceConnected * dev;
+    bool dev_connected;
+    USBEndpoint * int_in;
+    uint8_t nb_port;
+    uint8_t hub_characteristics;
+
+    void rxHandler();
+
+    uint8_t buf[sizeof(HubDescriptor)];
+
+    int hub_intf;
+    bool hub_device_found;
+
+    void setPortFeature(uint32_t feature, uint8_t port);
+    void clearPortFeature(uint32_t feature, uint8_t port);
+    uint32_t getPortStatus(uint8_t port);
+
+    USBDeviceConnected * device_children[MAX_HUB_PORT];
+    
+    void init();
+    void disconnect();
+
+};
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostMSD/USBHostMSD.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,311 @@
+/* Copyright (c) 2010-2012 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 "USBHostMSD.h"
+
+#if USBHOST_MSD
+
+#include "dbg.h"
+
+#define CBW_SIGNATURE   0x43425355
+#define CSW_SIGNATURE   0x53425355
+
+#define DEVICE_TO_HOST  0x80
+#define HOST_TO_DEVICE  0x00
+
+#define GET_MAX_LUN     (0xFE)
+
+USBHostMSD::USBHostMSD(const char * rootdir) : FATFileSystem(rootdir)
+{
+    host = USBHost::getHostInst();
+    init();
+}
+
+void USBHostMSD::init() {
+    dev_connected = false;
+    dev = NULL;
+    bulk_in = NULL;
+    bulk_out = NULL;
+    dev_connected = false;
+    blockSize = 0;
+    blockCount = 0;
+    msd_intf = -1;
+    msd_device_found = false;
+    disk_init = false;
+    dev_connected = false;
+}
+
+
+bool USBHostMSD::connected()
+{
+    return dev_connected;
+}
+
+bool USBHostMSD::connect()
+{
+    U8 i;
+
+    if (dev_connected) {
+        return true;
+    }
+
+    for (i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+            
+            if(host->enumerate(dev, this))
+                break;
+
+            if (msd_device_found) {
+                bulk_in = dev->getEndpoint(msd_intf, BULK_ENDPOINT, IN);
+                bulk_out = dev->getEndpoint(msd_intf, BULK_ENDPOINT, OUT);
+                
+                if (!bulk_in || !bulk_out)
+                    break;
+                
+                USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+                dev->setName("MSD");
+                host->registerDriver(dev, msd_intf, this, &USBHostMSD::init);
+
+                dev_connected = true;
+                return true;
+            }
+        } //if()
+    } //for()
+    return false;
+}
+
+/*virtual*/ void USBHostMSD::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for MSD driver
+}
+
+/*virtual*/ bool USBHostMSD::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    if ((msd_intf == -1) &&
+        (intf_class == MSD_CLASS) &&
+        (intf_subclass == 0x06) &&
+        (intf_protocol == 0x50)) {
+        msd_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostMSD::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == msd_intf) {
+        if (type == BULK_ENDPOINT) {
+            msd_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+int USBHostMSD::testUnitReady() {
+    return SCSITransfer(NULL, 6, DEVICE_TO_HOST, 0, 0);
+}
+
+int USBHostMSD::readCapacity() {
+    uint8_t cmd[10] = {0x25,0,0,0,0,0,0,0,0,0};
+    uint8_t result[8];
+    int status = SCSITransfer(cmd, 10, DEVICE_TO_HOST, result, 8);
+    if (status == 0) {
+        blockCount = (result[0] << 24) | (result[1] << 16) | (result[2] << 8) | result[3];
+        blockSize = (result[4] << 24) | (result[5] << 16) | (result[6] << 8) | result[7];
+        USB_INFO("MSD [dev: %p] - blockCount: %lld, blockSize: %d\r\n", dev, blockCount, blockSize);
+    }
+    return status;
+}
+
+
+int USBHostMSD::SCSIRequestSense() {
+    uint8_t cmd[5] = {0x03,0,0,0,0x13};
+    uint8_t result[19];
+    int status = SCSITransfer(cmd, 5, DEVICE_TO_HOST, result, 19);
+    return status;
+}
+
+
+int USBHostMSD::inquiry(uint8_t lun, uint8_t page_code) {
+    uint8_t evpd = (page_code == 0) ? 0 : 1;
+    uint8_t cmd[6] = {0x12, (lun << 5) | evpd, page_code, 0, 36, 0};
+    uint8_t result[36];
+    int status = SCSITransfer(cmd, 6, DEVICE_TO_HOST, result, 36);
+    if (status == 0) {
+        char vid_pid[9];
+        memcpy(vid_pid, &result[8], 8);
+        vid_pid[8] = 0;
+        USB_INFO("MSD [dev: %p] - Vendor ID: %s", dev, vid_pid);
+
+        memcpy(vid_pid, &result[16], 8);
+        USB_INFO("MSD [dev: %p] - Produc ID: %s", dev, vid_pid);
+
+        memcpy(vid_pid, &result[32], 4);
+        vid_pid[4] = 0;
+        USB_INFO("MSD [dev: %p] - Product rev: %s", dev, vid_pid);
+    }
+    return status;
+}
+
+int USBHostMSD::checkResult(uint8_t res, USBEndpoint * ep) {
+    // if ep stalled: send clear feature
+    if (res == USB_TYPE_STALL_ERROR) {
+        res = host->controlWrite(   dev,
+                                    USB_RECIPIENT_ENDPOINT | USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_STANDARD,
+                                    CLEAR_FEATURE,
+                                    0,
+                                    ep->getAddress(),
+                                    NULL,
+                                    0);
+        // set state to IDLE if clear feature successful
+        if (res == USB_TYPE_OK) {
+            ep->setState(USB_TYPE_IDLE);
+        }
+    }
+
+    if (res != USB_TYPE_OK)
+        return -1;
+
+    return 0;
+}
+
+
+int USBHostMSD::SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len) {
+
+    int res = 0;
+
+    cbw.Signature = CBW_SIGNATURE;
+    cbw.Tag = 0;
+    cbw.DataLength = transfer_len;
+    cbw.Flags = flags;
+    cbw.LUN = 0;
+    cbw.CBLength = cmd_len;
+    memset(cbw.CB,0,sizeof(cbw.CB));
+    if (cmd) {
+        memcpy(cbw.CB,cmd,cmd_len);
+    }
+
+    // send the cbw
+    res = host->bulkWrite(dev, bulk_out,(uint8_t *)&cbw, 31);
+    if (checkResult(res, bulk_out))
+        return -1;
+
+    // data stage if needed
+    if (data) {
+        if (flags == HOST_TO_DEVICE) {
+
+            res = host->bulkWrite(dev, bulk_out, data, transfer_len);
+            if (checkResult(res, bulk_out))
+                return -1;
+
+        } else if (flags == DEVICE_TO_HOST) {
+
+            res = host->bulkRead(dev, bulk_in, data, transfer_len);
+            if (checkResult(res, bulk_in))
+                return -1;
+        }
+    }
+
+    // status stage
+    csw.Signature = 0;
+    res = host->bulkRead(dev, bulk_in,(uint8_t *)&csw, 13);
+    if (checkResult(res, bulk_in))
+        return -1;
+
+    if (csw.Signature != CSW_SIGNATURE) {
+        return -1;
+    }
+
+    // ModeSense?
+    if ((csw.Status == 1) && (cmd[0] != 0x03))
+        return SCSIRequestSense();
+
+    USB_DBG("recv csw: status: %d", csw.Status);
+    return csw.Status;
+}
+
+
+int USBHostMSD::dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction) {
+    uint8_t cmd[10];
+    memset(cmd,0,10);
+    cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
+
+    cmd[2] = (block >> 24) & 0xff;
+    cmd[3] = (block >> 16) & 0xff;
+    cmd[4] = (block >> 8) & 0xff;
+    cmd[5] =  block & 0xff;
+
+    cmd[7] = (nbBlock >> 8) & 0xff;
+    cmd[8] = nbBlock & 0xff;
+
+    return SCSITransfer(cmd, 10, direction, buf, blockSize*nbBlock);
+}
+
+
+int USBHostMSD::disk_initialize() {
+    USB_DBG("FILESYSTEM: init");
+    U8 i, timeout = 10;
+    
+    for (i = 0; i < timeout; i++) {
+        if (!testUnitReady())
+            break;
+    }
+    
+    if (i == timeout) {
+        disk_init = false;
+        return -1;
+    }
+    inquiry(0, 0);
+    disk_init = 1;
+    return readCapacity();
+}
+
+int USBHostMSD::disk_write(const uint8_t *buffer, uint64_t block_number) {
+    USB_DBG("FILESYSTEM: write block: %lld", block_number);
+    if (!disk_init) {
+        disk_initialize();
+    }
+    if (!disk_init)
+        return -1;
+    return dataTransfer((uint8_t *)buffer, block_number, 1, HOST_TO_DEVICE);
+}
+
+int USBHostMSD::disk_read(uint8_t * buffer, uint64_t block_number) {
+    USB_DBG("FILESYSTEM: read block %lld", block_number);
+    if (!disk_init) {
+        disk_initialize();
+    }
+    if (!disk_init)
+        return -1;
+    return dataTransfer((uint8_t *)buffer, block_number, 1, DEVICE_TO_HOST);
+}
+
+uint64_t USBHostMSD::disk_sectors() {
+    USB_DBG("FILESYSTEM: sectors");
+    if (!disk_init) {
+        disk_initialize();
+    }
+    if (!disk_init)
+        return 0;
+    return blockCount;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostMSD/USBHostMSD.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,121 @@
+/* Copyright (c) 2010-2012 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 USBHOSTMSD_H
+#define USBHOSTMSD_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_MSD
+
+#include "USBHost.h"
+#include "FATFileSystem.h"
+
+/** 
+ * A class to use a USB stick
+ */
+ 
+class USBHostMSD : public IUSBEnumerator, public FATFileSystem {
+public:
+    /**
+    * Constructor
+    *
+    * @param rootdir mount name
+    */
+    USBHostMSD(const char * rootdir);
+
+    /**
+    * Check if a MSD device is connected
+    *
+    * @return true if a MSD device is connected
+    */
+    bool connected();
+
+    /*
+     * Try to connect to a MSD device
+     *
+     * * @return true if connection was successful
+     */
+    bool connect();
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+    // From FATFileSystem
+    virtual int disk_initialize();
+    virtual int disk_status() {return 0;};
+    virtual int disk_read(uint8_t * buffer, uint64_t sector);
+    virtual int disk_write(const uint8_t * buffer, uint64_t sector);
+    virtual int disk_sync() {return 0;};
+    virtual uint64_t disk_sectors();
+
+private:
+    USBHost * host;
+    USBDeviceConnected * dev;
+    bool dev_connected;
+    USBEndpoint * bulk_in;
+    USBEndpoint * bulk_out;
+
+    // Bulk-only CBW
+    typedef __packed struct {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataLength;
+        uint8_t  Flags;
+        uint8_t  LUN;
+        uint8_t  CBLength;
+        uint8_t  CB[16];
+    } CBW;
+
+    // Bulk-only CSW
+    typedef __packed struct {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataResidue;
+        uint8_t  Status;
+    } CSW;
+
+    CBW cbw;
+    CSW csw;
+
+    int SCSITransfer(uint8_t * cmd, uint8_t cmd_len, int flags, uint8_t * data, uint32_t transfer_len);
+    int testUnitReady();
+    int readCapacity();
+    int inquiry(uint8_t lun, uint8_t page_code);
+    int SCSIRequestSense();
+    int dataTransfer(uint8_t * buf, uint32_t block, uint8_t nbBlock, int direction);
+    int checkResult(uint8_t res, USBEndpoint * ep);
+
+    int blockSize;
+    uint64_t blockCount;
+
+    int msd_intf;
+    bool msd_device_found;
+    bool disk_init;
+    
+    void init();
+
+};
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostSerial/MtxCircBuffer.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,88 @@
+/* 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 MTXCIRCBUFFER_H
+#define MTXCIRCBUFFER_H
+
+#include "stdint.h"
+#include "rtos.h"
+
+//Mutex protected circular buffer
+template<typename T, int size>
+class MtxCircBuffer {
+public:
+    
+    MtxCircBuffer() {
+        write = 0;
+        read = 0;
+    }
+
+    bool isFull() {
+        mtx.lock();
+        bool r = (((write + 1) % size) == read);
+        mtx.unlock();
+        return r;
+    }
+
+    bool isEmpty() {
+        mtx.lock();
+        bool r = (read == write);
+        mtx.unlock();
+        return r;
+    }
+
+    void queue(T k) {
+        mtx.lock();
+        while (((write + 1) % size) == read) {
+            mtx.unlock();
+            Thread::wait(10);
+            mtx.lock();
+        }
+        buf[write++] = k;
+        write %= size;
+        mtx.unlock();
+    }
+
+    uint16_t available() {
+        mtx.lock();
+        uint16_t a = (write >= read) ? (write - read) : (size - read + write);
+        mtx.unlock();
+        return a;
+    }
+
+    bool dequeue(T * c) {
+        mtx.lock();
+        bool empty = (read == write);
+        if (!empty) {
+            *c = buf[read++];
+            read %= size;
+        }
+        mtx.unlock();
+        return (!empty);
+    }
+
+private:
+    volatile uint16_t write;
+    volatile uint16_t read;
+    volatile T buf[size];
+    Mutex mtx;
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostSerial/USBHostSerial.cpp	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,160 @@
+/* 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 "USBHostSerial.h"
+
+#if USBHOST_SERIAL
+
+#include "dbg.h"
+
+USBHostSerial::USBHostSerial(): circ_buf() {
+    host = USBHost::getHostInst();
+    size_bulk_in = 0;
+    size_bulk_out = 0;
+    init();
+}
+
+void USBHostSerial::init() {
+    dev = NULL;
+    bulk_in = NULL;
+    bulk_out = NULL;
+    dev_connected = false;
+    serial_intf = -1;
+    serial_device_found = false;
+}
+
+bool USBHostSerial::connected()
+{
+    return dev_connected;
+}
+
+bool USBHostSerial::connect() {
+
+    if (dev_connected) {
+        return true;
+    }
+    for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+
+            if(host->enumerate(dev, this))
+                break;
+            
+            if (serial_device_found) {
+                bulk_in = dev->getEndpoint(serial_intf, BULK_ENDPOINT, IN);
+                bulk_out = dev->getEndpoint(serial_intf, BULK_ENDPOINT, OUT);
+                
+                if (!bulk_in || !bulk_out)
+                    break;
+                
+                USB_INFO("New Serial device: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+                dev->setName("Serial");
+                host->registerDriver(dev, serial_intf, this, &USBHostSerial::init);
+                
+                size_bulk_in = bulk_in->getSize();
+                size_bulk_out = bulk_out->getSize();
+                
+                bulk_in->attach(this, &USBHostSerial::rxHandler);
+                bulk_out->attach(this, &USBHostSerial::txHandler);
+                
+                host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostSerial::rxHandler() {
+    if (bulk_in) {
+        int len = bulk_in->getLengthTransferred();
+        if (bulk_in->getState() == USB_TYPE_IDLE) {
+            for (int i = 0; i < len; i++) {
+                circ_buf.queue(buf[i]);
+            }
+            rx.call();
+        }
+        host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
+    }
+}
+
+void USBHostSerial::txHandler() {
+    if (bulk_out) {
+        if (bulk_out->getState() == USB_TYPE_IDLE) {
+            tx.call();
+        }
+    }
+}
+
+int USBHostSerial::_putc(int c) {
+    if (bulk_out) {
+        if (host->bulkWrite(dev, bulk_out, (uint8_t *)&c, 1) == USB_TYPE_OK) {
+            return 1;
+        }
+    }
+    return -1;
+}
+
+
+int USBHostSerial::_getc() {
+    uint8_t c = 0;
+    while ((bulk_in != NULL) && (circ_buf.isEmpty()));
+    if (bulk_in == NULL) {
+        return -1;
+    }
+    circ_buf.dequeue(&c);
+    return c;
+}
+
+
+uint8_t USBHostSerial::available() {
+    return circ_buf.available();
+}
+
+/*virtual*/ void USBHostSerial::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for MSD driver
+}
+
+/*virtual*/ bool USBHostSerial::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+    if ((serial_intf == -1) &&
+        (intf_class == SERIAL_CLASS) &&
+        (intf_subclass == 0x00) &&
+        (intf_protocol == 0x00)) {
+        serial_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostSerial::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == serial_intf) {
+        if (type == BULK_ENDPOINT) {
+            serial_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostSerial/USBHostSerial.h	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,134 @@
+/* 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 USBHOSTSERIAL_H
+#define USBHOSTSERIAL_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_SERIAL
+
+#include "USBHost.h"
+#include "Stream.h"
+#include "MtxCircBuffer.h"
+
+class USBHostSerial : public IUSBEnumerator, public Stream {
+public:
+    /**
+    * Constructor
+    */
+    USBHostSerial();
+
+    enum IrqType {
+        RxIrq,
+        TxIrq
+    };
+
+    /**
+    * Check if a virtual serial port is connected
+    *
+    * @returns true if a serial device is connected
+    */
+    bool connected();
+    
+    /**
+     * Try to connect a serial device
+     *
+     * * @return true if connection was successful
+     */
+    bool connect();
+    
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    uint8_t available(); 
+
+    /**
+     *  Attach a member function to call when a packet is received.
+     *
+     *  @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>
+    inline void attach(T* tptr, void (T::*mptr)(void), IrqType irq = RxIrq) {
+        if ((mptr != NULL) && (tptr != NULL)) {
+            if (irq == RxIrq) {
+                rx.attach(tptr, mptr);
+            } else {
+                tx.attach(tptr, mptr);
+            }
+        }
+    }
+
+    /**
+     * Attach a callback called when a packet is received
+     *
+     * @param fptr function pointer
+     */
+    inline void attach(void (*fn)(void), IrqType irq = RxIrq) {
+        if (fn != NULL) {
+            if (irq == RxIrq) {
+                rx.attach(fn);
+            } else {
+                tx.attach(fn);
+            }
+        }
+    }
+
+
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+    virtual int _getc();
+    virtual int _putc(int c);
+    
+private:
+    USBHost * host;
+    USBDeviceConnected * dev;
+    USBEndpoint * bulk_in;
+    USBEndpoint * bulk_out;
+    uint32_t size_bulk_in;
+    uint32_t size_bulk_out;
+
+    bool dev_connected;
+
+    void init();
+
+    MtxCircBuffer<uint8_t, 64> circ_buf;
+
+    uint8_t buf[64];
+
+    void rxHandler();
+    void txHandler();
+    FunctionPointer rx;
+    FunctionPointer tx;
+
+    int serial_intf;
+    bool serial_device_found;
+
+};
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Mar 06 16:27:14 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed-rtos/#53e6cccd8782