This example demonstrates the reading of the USB Gamepad in the Nucleo.

Dependencies:   mbed

Intro

This example demonstrates the reading of the USB Gamepad in the Nucleo.

Parts

STM32 Nucleo F446RE
USB Connector
LED 2pcs
Register 470 ohm 2pcs
Breadboard
Wires

Wiring diagram

/media/uploads/beaglescout007/nucleo_ex04_usbpad.png This circuit diagram was created by fritzing.

/media/uploads/beaglescout007/usbcon.jpg

USB con.Nucleo
GNDGND
+PA_12
-PA_11
5V5V

https://youtu.be/EYIukjwJSew

Original Library

Files at this revision

API Documentation at this revision

Comitter:
beaglescout007
Date:
Tue Mar 15 11:39:04 2016 +0000
Commit message:
Release

Changed in this revision

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.h 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/USBHALHost2_F401RE.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHALHost_F401RE.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHALHost_F401RE.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/USBHostGamepad.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHostGamepad.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHostHub.cpp 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
USBHost/mydebug.h Show annotated file Show diff for this revision Revisions of this file
USBHost/mymap.h Show annotated file Show diff for this revision Revisions of this file
USBHost/myvector.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b5f79b4f741d USBHost/IUSBEnumerator.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/IUSBEnumerator.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,37 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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_*/
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBDeviceConnected.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBDeviceConnected.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,90 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBDeviceConnected.h"
+#include "dbg.h"
+
+USBDeviceConnected::USBDeviceConnected() {
+    init();
+}
+
+void USBDeviceConnected::init() {
+    port = 0;
+    vid = 0;
+    pid = 0;
+    nb_interf = 0;
+    enumerated = false;
+    device_class = 0;
+    device_subclass = 0;
+    proto = 0;
+    lowSpeed = false;
+    hub_parent = NULL;
+}
+
+bool USBDeviceConnected::addInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) {
+    USB_DBG("intf_nb=%d", intf_nb);
+    if (intf.count(intf_nb) > 0) {
+        return false;
+    }
+    intf[intf_nb] = new INTERFACE(intf_class, intf_subclass, intf_protocol);
+    return true;
+}
+
+bool USBDeviceConnected::addEndpoint(uint8_t intf_nb, USBEndpoint * ept) {
+    if (intf.count(intf_nb) > 0) {
+        intf[intf_nb]->ep.push_back(ept);
+        return true;
+    }
+    return false;
+}
+
+void USBDeviceConnected::init(USBDeviceConnected* parent, uint8_t port_, bool lowSpeed_) {
+    USB_DBG("init dev: %p", this);
+    init();
+    hub_parent = parent;
+    port = port_;
+    lowSpeed = lowSpeed_;
+}
+
+void USBDeviceConnected::disconnect() {
+    //for(int i = 0; i < MAX_INTF; i++) {
+    //    intf[i].detach.call();
+    //}
+    //init();
+}
+
+
+USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint8_t index) {
+    USB_DBG("intf_nb=%d", intf_nb);
+    USB_TEST_ASSERT(intf.count(intf_nb) > 0);
+    INTERFACE* inter = intf[intf_nb];
+    for (int i = 0; i < inter->ep.size(); i++) {
+        if ((inter->ep[i]->getType() == type) && (inter->ep[i]->getDir() == dir)) {
+            if(index) {
+                index--;
+            } else {
+                return inter->ep[i];
+            }
+        }
+    }
+    return NULL;
+}
+
+USBEndpoint * USBDeviceConnected::getEndpoint(uint8_t intf_nb, uint8_t index) {
+    USB_TEST_ASSERT(intf.count(intf_nb) > 0);
+    return intf[intf_nb]->ep[index];
+}
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBDeviceConnected.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBDeviceConnected.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,134 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "USBEndpoint.h"
+#include "USBHostConf.h"
+#include "myvector.h"
+#include "mymap.h"
+
+class USBEndpoint;
+
+struct INTERFACE {
+    INTERFACE(uint8_t _class, uint8_t _subclass, uint8_t _protocol) {
+        intf_class = _class;
+        intf_subclass = _subclass;
+        intf_protocol = _protocol;
+    }
+    uint8_t intf_class;
+    uint8_t intf_subclass;
+    uint8_t intf_protocol;
+    myvector<USBEndpoint*>ep; 
+}; 
+
+/**
+* USBDeviceConnected class
+*/
+class USBDeviceConnected {
+public:
+
+    /**
+    * Constructor
+    */
+    USBDeviceConnected();
+
+    /**
+    * Attach an USBEndpoint to this device
+    *
+    * @param intf_nb interface number
+    * @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 dir 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 intf_nb interface number
+    * @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_protocol 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);
+
+    /**
+    * Disconnect the device by calling a callback function registered by a driver
+    */
+    void disconnect();
+
+    void init(USBDeviceConnected* parent, uint8_t _port, bool _lowSpeed);
+    void setAddress(uint8_t addr_) { addr = addr_; };
+    void setVid(uint16_t vid_) { vid = vid_; };
+    void setPid(uint16_t pid_) { pid = pid_; };
+    void setClass(uint8_t device_class_) { device_class = device_class_; }
+    void setSubClass(uint8_t device_subclass_) { device_subclass = device_subclass_; };
+    void setProtocol(uint8_t pr) { proto = pr; };
+    void setEnumerated() { enumerated = true; };
+    void setNbIntf(uint8_t nb_intf) {nb_interf = nb_intf; };
+    void setSpeed(bool _lowSpeed) { lowSpeed = _lowSpeed; }
+    void setName(const char * name_, uint8_t intf_nb) { return; };
+    void setEpCtl(USBEndpoint* ep) { ep_ctl = ep; }
+
+    static int getNewAddress() {
+        static int addr = 1;
+        return addr++;
+    }
+    uint8_t getAddress() { return addr; };
+    uint16_t getVid() { return vid; };
+    uint16_t getPid() { return pid; };
+    uint8_t getClass() { return device_class; };
+    bool getSpeed() { return lowSpeed; }
+    bool isEnumerated() { return enumerated; };
+    USBEndpoint* getEpCtl() { return ep_ctl; }
+
+private:
+    USBDeviceConnected* hub_parent;
+    mymap<int,INTERFACE*>intf;
+    uint8_t port;
+    uint16_t vid;
+    uint16_t pid;
+    uint8_t addr;
+    uint8_t device_class;
+    uint8_t device_subclass;
+    uint8_t proto;
+    bool lowSpeed;
+    bool enumerated;
+    uint8_t nb_interf;
+    USBEndpoint* ep_ctl;
+    void init();
+};
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBEndpoint.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBEndpoint.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,168 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#pragma once
+#include "FunctionPointer.h"
+#include "USBHostTypes.h"
+#include "USBDeviceConnected.h"
+
+class USBDeviceConnected;
+
+/**
+* USBEndpoint class
+*/
+class USBEndpoint {
+public:
+    /**
+    * Constructor
+    */
+    USBEndpoint(USBDeviceConnected* _dev) {
+        init(CONTROL_ENDPOINT, IN, 8, 0);
+        dev = _dev;
+        pData = NULL;
+    }
+
+    /**
+    * Initialize an endpoint
+    *
+    * @param type endpoint type
+    * @param dir endpoint direction
+    * @param size endpoint size
+    * @param ep_number endpoint number
+    */
+    void init(ENDPOINT_TYPE _type, ENDPOINT_DIRECTION _dir, uint32_t size, uint8_t ep_number) {
+        setState(USB_TYPE_FREE);
+        setType(_type);
+        dir = _dir;
+        MaxPacketSize = size;
+        address = ep_number;
+        data01_toggle = DATA0;
+    }
+
+    void ohci_init(uint8_t frameCount, uint8_t queueLimit) {
+        ohci.frameCount = frameCount;
+        ohci.queueLimit = queueLimit;
+    }
+
+    /**
+     *  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 (*fptr)(void)) {
+        if(fptr != NULL) {
+            rx.attach(fptr);
+        }
+    }
+
+    /**
+    * Call the handler associted to the end of a transfer
+    */
+    inline void call() {
+        rx.call();
+    };
+
+    void setType(ENDPOINT_TYPE _type) { type = _type; }
+    void setState(USB_TYPE st) { state = st; }
+    void setDevice(USBDeviceConnected* _dev) { dev = _dev; }
+    void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; }
+    void setLengthTransferred(int len) { transferred = len; };
+    void setAddress(int addr) { address = addr; }
+    void setSize(int size) { MaxPacketSize = size; }
+    void setData01(uint8_t data01) { data01_toggle = data01; }
+    void setNextEndpoint(USBEndpoint* ep) { nextEp = ep; };
+    template<class T>
+    void setHALData(T data) { pData = data; }
+
+    USBDeviceConnected* getDevice() { return dev; }
+    ENDPOINT_TYPE getType() { return type; };
+    USB_TYPE getState() { return state; }
+    int getLengthTransferred() { return transferred; }
+    uint8_t *getBufStart() { return buf_start; }
+    int getBufSize() { return buf_size; }
+    uint8_t getAddress(){ return address; };
+    int getSize() { return MaxPacketSize; }
+    ENDPOINT_DIRECTION getDir() { return dir; }
+    uint8_t getData01() { return data01_toggle; }
+    void toggleData01() {
+        data01_toggle = (data01_toggle == DATA0) ? DATA1 : DATA0;
+    }
+    USBEndpoint* nextEndpoint() { return nextEp; };
+    template<class T>
+    T getHALData() { return reinterpret_cast<T>(pData); }
+
+    struct {
+        uint8_t queueLimit;
+        uint8_t frameCount; // 1-8
+    } ohci;
+private:
+    USBEndpoint(){}
+    ENDPOINT_TYPE type;
+    USB_TYPE state;
+    ENDPOINT_DIRECTION dir;
+    USBDeviceConnected* dev;
+    uint8_t data01_toggle; // DATA0,DATA1
+    uint8_t address;
+    int transferred;
+    uint8_t * buf_start;
+    int buf_size;
+    FunctionPointer rx;
+    int MaxPacketSize;
+    USBEndpoint* nextEp;
+    void* pData;
+};
+
+class EndpointQueue {
+public:
+    EndpointQueue():head(NULL),tail(NULL) {}
+    void push(USBEndpoint* ep) {
+        if (head) {
+            tail->setNextEndpoint(ep);
+        } else {
+            head = ep;
+        }
+        tail = ep;
+        ep->setNextEndpoint(NULL);
+    }
+    USBEndpoint* pop() {
+        USBEndpoint* ep = head;
+        if (ep) {
+            head = ep->nextEndpoint();
+        }
+        return ep;
+    }
+    bool empty() { return head == NULL; }
+
+private:
+    USBEndpoint* head;
+    USBEndpoint* tail;
+};
+
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,35 @@
+#include "mbed.h"
+
+struct SETUP_PACKET {
+    uint8_t bmRequestType;
+    uint8_t bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+    SETUP_PACKET(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) {
+        bmRequestType = RequestType;
+        bRequest = Request;
+        wValue = Value;
+        wIndex = Index;
+        wLength = Length;
+    }
+};
+
+#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)
+#include "USBHALHost_F401RE.h"
+#elif defined(TARGET_KL46Z)||defined(TARGET_KL25Z)||defined(TARGET_K64F)
+#include "USBHALHost_KL46Z.h"
+#elif defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
+#include "USBHALHost_LPC4088.h"
+#else
+#error "target error"
+#endif
+
+#ifndef  CTASSERT
+template <bool>struct CtAssert;
+template <>struct CtAssert<true> {};
+#define CTASSERT(A) CtAssert<A>();
+#endif // CTASSERT
+
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost2_F401RE.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost2_F401RE.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,540 @@
+#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)
+#include "USBHALHost.h"
+
+// usbh_conf.c
+HCD_HandleTypeDef hhcd_USB_OTG_FS;
+
+static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd);
+
+// stm32f4xx_it.c
+extern "C" {
+void OTG_FS_IRQHandler(void)
+{
+  HAL_NVIC_ClearPendingIRQ(OTG_FS_IRQn);
+  HAL_HCD_IRQHandler(&hhcd_USB_OTG_FS);
+}
+}
+
+// stm32f4xx_hal_hcd.c
+static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
+static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); 
+static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
+static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
+
+/**
+  * @brief  This function handles HCD interrupt request.
+  * @param  hhcd: HCD handle
+  * @retval none
+  */
+static void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+  uint32_t i = 0 , interrupt = 0;
+  
+  /* ensure that we are in device mode */
+  if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
+  {
+    /* avoid spurious interrupt */
+    if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) 
+    {
+      return;
+    }
+    
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
+    {
+     /* incorrect mode, acknowledge the interrupt */
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
+    }
+    
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
+    {
+     /* incorrect mode, acknowledge the interrupt */
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
+    }
+
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
+    {
+     /* incorrect mode, acknowledge the interrupt */
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
+    }   
+    
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
+    {
+     /* incorrect mode, acknowledge the interrupt */
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
+    }     
+    
+    /* Handle Host Disconnect Interrupts */
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
+    {
+      
+      /* Cleanup HPRT */
+      USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
+        USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
+       
+      /* Handle Host Port Interrupts */
+      HAL_HCD_Disconnect_Callback(hhcd);
+       USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
+    }
+    
+    /* Handle Host Port Interrupts */
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
+    {
+      HCD_Port_IRQHandler (hhcd);
+    }
+    
+    /* Handle Host SOF Interrupts */
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
+    {
+      HAL_HCD_SOF_Callback(hhcd);
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
+    }
+          
+    /* Handle Host channel Interrupts */
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
+    {
+      
+      interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
+      for (i = 0; i < hhcd->Init.Host_channels ; i++)
+      {
+        if (interrupt & (1 << i))
+        {
+          if ((USBx_HC(i)->HCCHAR) &  USB_OTG_HCCHAR_EPDIR)
+          {
+            HCD_HC_IN_IRQHandler (hhcd, i);
+          }
+          else
+          {
+            HCD_HC_OUT_IRQHandler (hhcd, i);
+          }
+        }
+      }
+      __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
+    } 
+    
+        /* Handle Rx Queue Level Interrupts */
+    if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL))
+    {
+      USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+      
+      HCD_RXQLVL_IRQHandler (hhcd);
+      
+      USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+    }
+    
+  }
+}
+/**
+  * @brief  This function handles Host Channel IN interrupt requests.
+  * @param  hhcd: HCD handle
+  * @param  chnum : Channel number
+  *         This parameter can be a value from 1 to 15
+  * @retval none
+  */
+static void HCD_HC_IN_IRQHandler   (HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+    
+  if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
+  {
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+  }  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
+  {
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
+  }
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)  
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+    hhcd->hc[chnum].state = HC_STALL;
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);    
+    USB_HC_Halt(hhcd->Instance, chnum);    
+  }
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+    USB_HC_Halt(hhcd->Instance, chnum);  
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);    
+    hhcd->hc[chnum].state = HC_DATATGLERR;
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
+  }    
+  
+  if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);  
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
+  }
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
+  {
+    
+    if (hhcd->Init.dma_enable)
+    {
+      hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \
+                               (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
+    }
+    
+    hhcd->hc[chnum].state = HC_XFRC;
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
+    
+    
+    if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)||
+        (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
+    {
+      __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+      USB_HC_Halt(hhcd->Instance, chnum); 
+      __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+      
+    }
+    else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
+    {
+      USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+      __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+      USB_HC_Halt(hhcd->Instance, chnum); 
+      __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+    }
+    else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC)
+    {
+      USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+      hhcd->hc[chnum].urb_state = URB_DONE; 
+      HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
+    }
+    hhcd->hc[chnum].toggle_in ^= 1;
+    
+  }
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
+  {
+    __HAL_HCD_MASK_HALT_HC_INT(chnum); 
+    
+    if(hhcd->hc[chnum].state == HC_XFRC)
+    {
+      hhcd->hc[chnum].urb_state  = URB_DONE;      
+    }
+
+    else if (hhcd->hc[chnum].state == HC_NAK)
+    {
+      hhcd->hc[chnum].urb_state  = URB_DONE;
+    }
+    
+    else if (hhcd->hc[chnum].state == HC_STALL) 
+    {
+      hhcd->hc[chnum].urb_state  = URB_STALL;
+    }   
+    
+    else if (hhcd->hc[chnum].state == HC_XACTERR)
+    {
+        hhcd->hc[chnum].urb_state = URB_NOTREADY;
+    }
+
+    else if (hhcd->hc[chnum].state == HC_DATATGLERR)
+    {
+        hhcd->hc[chnum].urb_state = URB_ERROR;
+    }
+
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
+    HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
+  }  
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+     hhcd->hc[chnum].state = HC_XACTERR;
+     USB_HC_Halt(hhcd->Instance, chnum);     
+     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
+  }
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
+  {  
+    if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
+    {
+      __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+      USB_HC_Halt(hhcd->Instance, chnum);  
+    }
+    else if (hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)
+    {
+      /* re-activate the channel  */
+      USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS;         
+      USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+   
+    }
+    
+    else if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)
+    {
+      __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+      USB_HC_Halt(hhcd->Instance, chnum); 
+    }
+
+    hhcd->hc[chnum].state = HC_NAK;
+     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+  }
+}
+
+/**
+  * @brief  This function handles Host Channel OUT interrupt requests.
+  * @param  hhcd: HCD handle
+  * @param  chnum : Channel number
+  *         This parameter can be a value from 1 to 15
+  * @retval none
+  */
+static void HCD_HC_OUT_IRQHandler  (HCD_HandleTypeDef *hhcd, uint8_t chnum)
+{
+  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
+  
+  if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_AHBERR)
+  {
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+  }  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_ACK)
+  {
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
+    
+    if( hhcd->hc[chnum].do_ping == 1)
+    {
+      hhcd->hc[chnum].state = HC_NYET;     
+      __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+      USB_HC_Halt(hhcd->Instance, chnum); 
+      hhcd->hc[chnum].urb_state  = URB_NOTREADY;
+    }
+  }
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NYET)
+  {
+    hhcd->hc[chnum].state = HC_NYET;
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);      
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
+    
+  }  
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_FRMOR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);  
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
+  }
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_XFRC)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+    USB_HC_Halt(hhcd->Instance, chnum);   
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
+    hhcd->hc[chnum].state = HC_XFRC;
+
+  }  
+
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_STALL)  
+  {
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);  
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum);
+    USB_HC_Halt(hhcd->Instance, chnum);   
+    hhcd->hc[chnum].state = HC_STALL;    
+  }
+
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_NAK)
+  {  
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);   
+    hhcd->hc[chnum].state = HC_NAK;
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+  }
+
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_TXERR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);      
+    hhcd->hc[chnum].state = HC_XACTERR;  
+     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
+  }
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_DTERR)
+  {
+    __HAL_HCD_UNMASK_HALT_HC_INT(chnum); 
+    USB_HC_Halt(hhcd->Instance, chnum);      
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);    
+    hhcd->hc[chnum].state = HC_DATATGLERR;
+  }
+  
+  
+  else if ((USBx_HC(chnum)->HCINT) &  USB_OTG_HCINT_CHH)
+  {
+    __HAL_HCD_MASK_HALT_HC_INT(chnum); 
+    
+    if(hhcd->hc[chnum].state == HC_XFRC)
+    {
+      hhcd->hc[chnum].urb_state  = URB_DONE;
+      if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)
+      {
+        hhcd->hc[chnum].toggle_out ^= 1; 
+      }      
+    }
+    else if (hhcd->hc[chnum].state == HC_NAK) 
+    {
+      hhcd->hc[chnum].urb_state  = URB_NOTREADY;
+    }  
+    
+    else if (hhcd->hc[chnum].state == HC_NYET) 
+    {
+      hhcd->hc[chnum].urb_state  = URB_NOTREADY;
+      hhcd->hc[chnum].do_ping = 0;
+    }   
+    
+    else if (hhcd->hc[chnum].state == HC_STALL) 
+    {
+      hhcd->hc[chnum].urb_state  = URB_STALL;
+    } 
+    
+    else if(hhcd->hc[chnum].state == HC_XACTERR)
+    {
+      hhcd->hc[chnum].urb_state = URB_NOTREADY;
+    }
+    
+    else if (hhcd->hc[chnum].state == HC_DATATGLERR)
+    {
+      hhcd->hc[chnum].urb_state = URB_ERROR;
+    }
+
+    __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
+    HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);  
+  }
+} 
+
+/**
+  * @brief  This function handles Rx Queue Level interrupt requests.
+  * @param  hhcd: HCD handle
+  * @retval none
+  */
+static void HCD_RXQLVL_IRQHandler  (HCD_HandleTypeDef *hhcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;  
+  uint8_t                       channelnum =0;  
+  uint32_t                      pktsts;
+  uint32_t                      pktcnt; 
+  uint32_t                      temp = 0;
+  
+  temp = hhcd->Instance->GRXSTSP ;
+  channelnum = temp &  USB_OTG_GRXSTSP_EPNUM;  
+  pktsts = (temp &  USB_OTG_GRXSTSP_PKTSTS) >> 17;
+  pktcnt = (temp &  USB_OTG_GRXSTSP_BCNT) >> 4;
+    
+  switch (pktsts)
+  {
+  case GRXSTS_PKTSTS_IN:
+    /* Read the data into the host buffer. */
+    if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void  *)0))
+    {  
+      
+      USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt);
+     
+      /*manage multiple Xfer */
+      hhcd->hc[channelnum].xfer_buff += pktcnt;           
+      hhcd->hc[channelnum].xfer_count  += pktcnt;
+        
+      if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0)
+      {
+        /* re-activate the channel when more packets are expected */
+        USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; 
+        USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+        hhcd->hc[channelnum].toggle_in ^= 1;
+      }
+    }
+    break;
+
+  case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
+    break;
+  case GRXSTS_PKTSTS_IN_XFER_COMP:
+  case GRXSTS_PKTSTS_CH_HALTED:
+  default:
+    break;
+  }
+}
+
+/**
+  * @brief  This function handles Host Port interrupt requests.
+  * @param  hhcd: HCD handle
+  * @retval none
+  */
+static void HCD_Port_IRQHandler  (HCD_HandleTypeDef *hhcd)
+{
+  USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;  
+  __IO uint32_t hprt0, hprt0_dup;
+  
+  /* Handle Host Port Interrupts */
+  hprt0 = USBx_HPRT0;
+  hprt0_dup = USBx_HPRT0;
+  
+  hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
+                 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
+  
+  /* Check wether Port Connect Detected */
+  if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
+  {  
+    if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
+    {
+      USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
+      HAL_HCD_Connect_Callback(hhcd);
+    }
+    hprt0_dup  |= USB_OTG_HPRT_PCDET;
+    
+  }
+  
+  /* Check whether Port Enable Changed */
+  if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
+  {
+    hprt0_dup |= USB_OTG_HPRT_PENCHNG;
+    
+    if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
+    {    
+      if(hhcd->Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
+      {
+        if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
+        {
+          USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ );
+        }
+        else
+        {
+          USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ );
+        }
+      }
+      else
+      {
+        if(hhcd->Init.speed == HCD_SPEED_FULL)
+        {
+          USBx_HOST->HFIR = (uint32_t)60000;
+        }
+      }
+      HAL_HCD_Connect_Callback(hhcd);
+      
+      if(hhcd->Init.speed == HCD_SPEED_HIGH)
+      {
+        USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); 
+      }
+    }
+    else
+    {
+      /* Cleanup HPRT */
+      USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\
+        USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG );
+      
+      USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); 
+    }    
+  }
+  
+  /* Check For an overcurrent */
+  if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
+  {
+    hprt0_dup |= USB_OTG_HPRT_POCCHNG;
+  }
+
+  /* Clear Port Interrupts */
+  USBx_HPRT0 = hprt0_dup;
+}
+
+#endif
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost_F401RE.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost_F401RE.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,534 @@
+#if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)
+#include "USBHALHost.h"
+#include <algorithm>
+
+#ifdef _USB_DBG
+extern RawSerial pc;
+//RawSerial pc(USBTX,USBRX);
+#include "mydebug.h"
+#define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0);
+#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)
+
+#else
+#define USB_DBG(...) while(0)
+#define USB_DBG_HEX(A,B) while(0)
+#endif
+
+#undef USB_TEST_ASSERT
+void usb_test_assert_internal(const char *expr, const char *file, int line);
+#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
+
+#define USB_TRACE1(A) while(0)
+
+#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
+
+__IO bool attach_done = false;
+
+void delay_ms(uint32_t t)
+{
+    HAL_Delay(t);
+}
+
+// usbh_conf.c
+extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
+
+void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
+{
+  GPIO_InitTypeDef GPIO_InitStruct;
+  if(hhcd->Instance==USB_OTG_FS)
+  {
+    /* Peripheral clock enable */
+    __USB_OTG_FS_CLK_ENABLE();
+  
+    /**USB_OTG_FS GPIO Configuration    
+    PA11     ------> USB_OTG_FS_DM
+    PA12     ------> USB_OTG_FS_DP 
+    */
+    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /* Peripheral interrupt init*/
+    /* Sets the priority grouping field */
+    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
+    HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
+    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
+  }
+}
+
+// stm32f4xx_it.c
+extern "C" {
+void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
+{
+    USB_TRACE1(hhcd);
+    attach_done = true;
+}
+
+} // extern "C"
+
+USBHALHost* USBHALHost::instHost;
+
+USBHALHost::USBHALHost() {
+    instHost = this;
+}
+
+void USBHALHost::init() {
+    hhcd_USB_OTG_FS.Instance = USB_OTG_FS;
+    hhcd_USB_OTG_FS.Init.Host_channels = 8;
+    hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;
+    hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;
+    hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
+    hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
+    hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE;
+    hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
+    hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE;
+
+    HAL_HCD_Init(&hhcd_USB_OTG_FS);
+    HAL_HCD_Start(&hhcd_USB_OTG_FS);
+
+    bool lowSpeed = wait_attach();
+    delay_ms(200);
+    HAL_HCD_ResetPort(&hhcd_USB_OTG_FS);
+    delay_ms(100); // Wait for 100 ms after Reset
+    addDevice(NULL, 0, lowSpeed);
+}
+
+bool USBHALHost::wait_attach() {
+    Timer t;
+    t.reset();
+    t.start();
+    while(!attach_done) {
+        if (t.read_ms() > 5*1000) {
+            t.reset();
+            USB_INFO("Please attach USB device.");
+        }
+    }
+    wait_ms(100);
+    return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW;
+}
+
+int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
+    const uint8_t ep_addr = 0x00;
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(ep_addr, 
+        dev->getAddress(),
+        dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
+        EP_TYPE_CTRL, ep->getSize());
+
+    setup->wLength = wLength;
+    hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
+    while(hc.GetURBState() == URB_IDLE);
+
+    switch(hc.GetURBState()) {
+        case URB_DONE:
+            LastStatus = ACK;
+            break;
+        default:
+            LastStatus = 0xff;
+            break;
+    }
+    ep->setData01(DATA1);
+    return 8;
+}
+
+int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
+    switch(ep->getType()) {
+        case CONTROL_ENDPOINT:
+            return token_ctl_in(ep, data, size, retryLimit);
+        case INTERRUPT_ENDPOINT:
+            return token_int_in(ep, data, size);
+        case BULK_ENDPOINT:
+            return token_blk_in(ep, data, size, retryLimit);
+    }
+    return -1;
+}
+
+int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
+    const uint8_t ep_addr = 0x80;
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(ep_addr, 
+        dev->getAddress(),
+        dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
+        EP_TYPE_CTRL, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    hc.SubmitRequest(data, size);
+    while(hc.GetURBState() == URB_IDLE);
+
+    switch(hc.GetURBState()) {
+        case URB_DONE:
+            LastStatus = ACK;
+            break;
+        default:
+            LastStatus = 0xff;
+            return -1;
+    }
+    ep->toggleData01();
+    return hc.GetXferCount();
+}
+
+int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) {
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(
+        ep->getAddress(),
+        dev->getAddress(),
+        dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
+        EP_TYPE_INTR, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    hc.SubmitRequest(data, size);
+    while(hc.GetURBState() == URB_IDLE);
+    switch(hc.GetURBState()) {
+        case URB_DONE:
+            switch(hc.GetState()) {
+                case HC_XFRC:
+                    LastStatus = ep->getData01();
+                    ep->toggleData01();
+                    return hc.GetXferCount();
+                case HC_NAK:
+                    LastStatus = NAK;
+                    return -1;
+            }
+            break;
+    }
+    LastStatus = STALL;
+    return -1;
+}
+
+int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(
+        ep->getAddress(),
+        dev->getAddress(),
+        HCD_SPEED_FULL,
+        EP_TYPE_BULK, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    int retry = 0;
+    do {
+        hc.SubmitRequest(data, size);
+        while(hc.GetURBState() == URB_IDLE);
+
+        switch(hc.GetURBState()) {
+            case URB_DONE:
+                switch(hc.GetState()) {
+                    case HC_XFRC:
+                        LastStatus = ep->getData01();
+                        ep->toggleData01();
+                        return hc.GetXferCount();
+                    case HC_NAK:
+                        LastStatus = NAK;
+                        if (retryLimit > 0) {
+                            delay_ms(1 + 10 * retry);
+                        }
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case URB_STALL:
+                LastStatus = STALL;
+                return -1;
+            default:
+                LastStatus = STALL;
+                delay_ms(500 + 100 * retry);
+                break;
+        }
+    }while(retry++ < retryLimit);
+    return -1;
+}
+
+int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
+    switch(ep->getType()) {
+        case CONTROL_ENDPOINT:
+            return token_ctl_out(ep, data, size, retryLimit);
+        case INTERRUPT_ENDPOINT:
+            return token_int_out(ep, data, size);
+        case BULK_ENDPOINT:
+            return token_blk_out(ep, data, size, retryLimit);
+    }
+    return -1;
+}
+
+int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
+    const uint8_t ep_addr = 0x00;
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(ep_addr, 
+        dev->getAddress(),
+        dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
+        EP_TYPE_CTRL, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    do {
+        hc.SubmitRequest((uint8_t*)data, size);
+        while(hc.GetURBState() == URB_IDLE);
+
+        switch(hc.GetURBState()) {
+            case URB_DONE:
+                LastStatus = ACK;
+                ep->toggleData01();
+                return size;
+
+            default:
+                break;
+        }
+        delay_ms(1);
+    }while(retryLimit-- > 0); 
+    return -1;
+}
+
+int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) {
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(
+        ep->getAddress(),
+        dev->getAddress(),
+        dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
+        EP_TYPE_INTR, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    hc.SubmitRequest((uint8_t*)data, size);
+    while(hc.GetURBState() == URB_IDLE);
+    if (hc.GetURBState() != URB_DONE) {
+        return -1;
+    }
+    ep->toggleData01();
+    return size;
+}
+
+int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
+    HC hc;
+    USBDeviceConnected* dev = ep->getDevice();
+    hc.Init(
+        ep->getAddress(), dev->getAddress(),
+        HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());
+
+    hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
+
+    int retry = 0;
+    do {
+        hc.SubmitRequest((uint8_t*)data, size);
+        while(hc.GetURBState() == URB_IDLE);
+
+        switch(hc.GetURBState()) {
+            case URB_DONE:
+                switch(hc.GetState()) {
+                    case HC_XFRC: // ACK
+                        LastStatus = ep->getData01();
+                        ep->toggleData01();
+                        return size;
+                    default:
+                        break;
+                }
+                break;
+            case URB_NOTREADY: // HC_NAK
+                LastStatus = NAK;
+                delay_ms(100 * retry);
+                break;
+            default:
+                LastStatus = STALL;
+                return -1;
+        }
+    } while(retry++ < retryLimit);
+    return -1;
+}
+
+int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
+    HC* hc = ep->getHALData<HC*>();
+    if (hc == NULL) {
+        hc = new HC;
+        ep->setHALData<HC*>(hc);
+        USBDeviceConnected* dev = ep->getDevice();
+        hc->Init(
+            ep->getAddress(), dev->getAddress(),
+            HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
+    }
+    hc->SubmitRequest(data, size);
+    while(hc->GetURBState() == URB_IDLE);
+    return hc->GetXferCount();
+}
+
+int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) {
+    if (total == 0) {
+        return token_in(ep);
+    }
+    int retryLimit = block ? 10 : 0;
+    int read_len = 0;
+    for(int n = 0; read_len < total; n++) {
+        int size = std::min((int)total-read_len, ep->getSize());
+        int result = token_in(ep, data+read_len, size, retryLimit);
+        if (result < 0) {
+            if (block) {
+                return -1;
+            }
+            if (LastStatus == NAK) {
+                if (n == 0) {
+                    return -1;
+                }
+                break;
+            }
+            return result;
+        }
+        read_len += result;
+        if (result < ep->getSize()) {
+            break;
+        }
+    }
+    return read_len;
+}
+
+int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) {
+    if (total == 0) {
+        return token_out(ep);
+    }
+    int write_len = 0;
+    for(int n = 0; write_len < total; n++) {
+        int size = std::min((int)total-write_len, ep->getSize());
+        int result = token_out(ep, data+write_len, size);
+        if (result < 0) {
+            if (LastStatus == NAK) {
+                if (n == 0) {
+                    return -1;
+                }
+                break;
+            }
+            USB_DBG("token_out result=%d %02x", result, LastStatus);
+            return result;
+        }
+        write_len += result;
+        if (result < ep->getSize()) {
+            break;
+        }
+    }
+    return write_len;
+}
+void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
+    USB_TRACE1(size);
+    USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING);
+    ep->setBuffer(data, size);
+    ep->setState(USB_TYPE_PROCESSING);
+}
+
+USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
+    USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING);
+    uint8_t* buf = ep->getBufStart();
+    int size = ep->getBufSize();
+    int result = multi_token_in(ep, buf, size, false);
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_PROCESSING;
+    }
+    ep->setLengthTransferred(result);
+    ep->setState(USB_TYPE_IDLE);
+    return USB_TYPE_OK;
+
+}
+
+void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
+    USB_TEST_ASSERT(toggle == 1);
+    ep->setData01(toggle == 0 ? DATA0 : DATA1);
+}
+
+uint8_t HC::slot = 0x00;
+
+HC::HC() {
+    static const int start = 1;
+    uint8_t mask = (1<<start);
+    for(int i = start; i < 8; i++, mask <<= 1) {
+        if (!(slot & mask)) {
+            slot |= mask;
+            _ch = i;
+            return;
+        }
+    }
+    _ch = 0; // ERROR!!!
+}
+
+HC::HC(int ch) {
+    _ch = ch;
+    slot |= (1<<_ch);
+}
+
+HC::~HC() {
+    slot &= ~(1<<_ch);
+}
+
+HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) {
+    _ep_addr = epnum;
+    _ep_type = ep_type;
+    return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch,
+                           epnum, dev_address, speed, ep_type, mps);
+}
+
+HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) {
+    uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
+    if (_ep_type == EP_TYPE_CTRL) {
+        HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch];
+        if (setup) {
+            hc->data_pid = HC_PID_SETUP;
+            hc->toggle_out = 0;
+        } else {
+            if (direction == DIR_IN) {
+                if (hc->toggle_in == 0) {
+                    hc->data_pid = HC_PID_DATA0;
+                } else {
+                    hc->data_pid = HC_PID_DATA1;
+                }
+            } else { // OUT
+                if (hc->toggle_out == 0) {
+                    hc->data_pid = HC_PID_DATA0;
+                } else {
+                    hc->data_pid = HC_PID_DATA1;
+                }
+            }
+        }
+        hc->xfer_buff = pbuff;
+        hc->xfer_len  = length;
+        hc->urb_state = URB_IDLE;
+        hc->xfer_count = 0;
+        hc->ch_num = _ch;
+        hc->state = HC_IDLE;
+  
+        return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0);
+    }
+    return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch,
+                                    direction, _ep_type, 0, pbuff, length, 0);
+}
+
+HCD_URBStateTypeDef HC::GetURBState() {
+    return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch);
+}
+
+HCD_HCStateTypeDef HC::GetState() {
+    return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch);
+}
+
+uint32_t HC::GetXferCount() {
+    return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch);
+}
+
+void HC::SetToggle(uint8_t toggle) {
+    if (_ep_addr & 0x80) { // IN
+        hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle;
+    } else { // OUT
+        hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle;
+    }
+}
+
+#endif
+
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHALHost_F401RE.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHALHost_F401RE.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,59 @@
+#pragma once
+#include "mbed.h"
+#include "USBHostTypes.h"
+#include "USBEndpoint.h"
+
+class HC {
+    static const uint8_t DIR_IN  = 1;
+    static const uint8_t DIR_OUT = 0;
+
+public:
+    HC();
+    HC(int ch);
+    ~HC();
+    HAL_StatusTypeDef Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps);
+    HAL_StatusTypeDef SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup = false);
+    HCD_URBStateTypeDef GetURBState();
+    HCD_HCStateTypeDef GetState();
+    uint32_t GetXferCount();
+    void SetToggle(uint8_t toggle);
+
+    static uint8_t slot;
+
+private:
+    int _ch;
+    uint8_t _ep_addr;
+    uint8_t _ep_type;
+};
+
+class USBHALHost {
+public:
+    uint8_t LastStatus;
+    uint8_t prev_LastStatus;
+
+protected:
+    USBHALHost();
+    void init();
+    virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0;
+    int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0);
+    int token_iso_in(USBEndpoint* ep, uint8_t* data, int size);
+    int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, size_t total = 0, bool block = true);
+    int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, size_t total = 0);
+    void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size);
+    USB_TYPE multi_token_inNB_result(USBEndpoint* ep);
+    void setToggle(USBEndpoint* ep, uint8_t toggle);
+
+private:
+    int token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0, int retryLimit = 10);
+    int token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0, int retryLimit = 10);
+    int token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit);
+    int token_int_in(USBEndpoint* ep, uint8_t* data, int size);
+    int token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit);
+    int token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit);
+    int token_int_out(USBEndpoint* ep, const uint8_t* data, int size);
+    int token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit);
+    bool wait_attach();
+    static USBHALHost * instHost;
+};
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHost.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,352 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBHost.h"
+
+#define USB_TRACE1(A) while(0)
+#undef USB_TEST_ASSERT
+void usb_test_assert_internal(const char *expr, const char *file, int line);
+#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
+
+USBHost* USBHost::inst = NULL;
+
+USBHost* USBHost::getHostInst() {
+    if (inst == NULL) {
+        inst = new USBHost();
+        inst->init();
+    }
+    return inst;
+}
+
+void USBHost::poll()
+{
+    if (inst) {
+        inst->task();
+    }
+}
+
+USBHost::USBHost() {
+}
+
+/* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) {
+    USBDeviceConnected* dev = new USBDeviceConnected;
+    USBEndpoint* ep = new USBEndpoint(dev);
+    dev->init(0, port, lowSpeed);
+    dev->setAddress(0);
+    dev->setEpCtl(ep);
+    uint8_t desc[18];
+    wait_ms(100);
+
+    int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    if (rc != USB_TYPE_OK) {
+        USB_ERR("ADD DEVICE FAILD");
+    }
+    USB_DBG_HEX(desc, 8);
+    DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
+    ep->setSize(dev_desc->bMaxPacketSize);
+
+    int new_addr = USBDeviceConnected::getNewAddress();
+    rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    dev->setAddress(new_addr);
+    wait_ms(100);
+
+    rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    USB_DBG_HEX(desc, sizeof(desc));
+
+    dev->setVid(dev_desc->idVendor);
+    dev->setPid(dev_desc->idProduct);
+    dev->setClass(dev_desc->bDeviceClass);
+    USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d",
+        parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
+        dev->getAddress());
+
+    DeviceLists.push_back(dev);
+
+    if (dev->getClass() == HUB_CLASS) {
+        const int config = 1;
+        int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
+        USB_TEST_ASSERT(rc == USB_TYPE_OK);
+        wait_ms(100);
+        Hub(dev);
+    }
+    return true;
+}
+
+// enumerate a device with the control USBEndpoint
+USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
+{
+    if (dev->getClass() == HUB_CLASS) { // skip hub class
+        return USB_TYPE_OK;
+    }
+    uint8_t desc[18];
+    USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    USB_DBG_HEX(desc, sizeof(desc));
+    if (rc != USB_TYPE_OK) {
+        return rc;
+    }
+    DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
+    dev->setClass(dev_desc->bDeviceClass);
+    pEnumerator->setVidPid(dev->getVid(), dev->getPid());
+
+    rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    USB_DBG_HEX(desc, 4);
+
+    int TotalLength = desc[2]|desc[3]<<8;
+    uint8_t* buf = new uint8_t[TotalLength];
+    rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    //USB_DBG_HEX(buf, TotalLength);
+
+    // Parse the configuration descriptor
+    parseConfDescr(dev, buf, TotalLength, pEnumerator);
+    delete[] buf;
+    // only set configuration if not enumerated before
+    if (!dev->isEnumerated()) {
+        USB_DBG("Set configuration 1 on dev: %p", dev);
+        // sixth step: set configuration (only 1 supported)
+        int config = 1;
+        USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
+        if (res != USB_TYPE_OK) {
+            USB_ERR("SET CONF FAILED");
+            return res;
+        }
+        // Some devices may require this delay
+        wait_ms(100);
+        dev->setEnumerated();
+        // Now the device is enumerated!
+        USB_DBG("dev %p is enumerated", dev);
+    }
+    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;
+    USBEndpoint * ep = NULL;
+    uint8_t intf_nb = 0;
+    bool parsing_intf = false;
+    uint8_t current_intf = 0;
+    EndpointDescriptor* ep_desc;
+
+    while (index < len) {
+        len_desc = conf_descr[index];
+        id = conf_descr[index+1];
+        USB_DBG_HEX(conf_descr+index, len_desc);
+        switch (id) {
+            case CONFIGURATION_DESCRIPTOR:
+                USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
+                dev->setNbIntf(conf_descr[4]);
+                break;
+            case INTERFACE_DESCRIPTOR:
+                if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
+                    intf_nb++;
+                    current_intf = conf_descr[index + 2];
+                    dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
+                    USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
+                    parsing_intf = true;
+                } else {
+                    parsing_intf = false;
+                }
+                break;
+            case ENDPOINT_DESCRIPTOR:
+                ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
+                if (parsing_intf && (intf_nb <= MAX_INTF) ) {
+                    ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
+                    ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
+                    if(pEnumerator->useEndpoint(current_intf, type, dir)) {
+                        ep = new USBEndpoint(dev);
+                        ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress);
+                        USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
+                        dev->addEndpoint(current_intf, ep);
+                    }
+                }
+                break;
+            case HID_DESCRIPTOR:
+                //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
+                break;
+            default:
+                break;
+        }
+        index += len_desc;
+    }
+}
+
+USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
+    USBEndpoint* ep = dev->getEpCtl();
+    SETUP_PACKET setup(requestType, request, value, index, len);
+
+    int result = token_setup(ep, &setup, len); // setup stage
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+
+    int read_len = multi_token_in(ep, buf, len); // data stage
+    USB_TRACE1(read_len);
+    if (read_len < 0) {
+        return USB_TYPE_ERROR;
+    }
+
+    setToggle(ep, 1); // DATA1
+    result = multi_token_out(ep); // status stage
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(read_len);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
+    USBEndpoint* ep = dev->getEpCtl();
+    SETUP_PACKET setup(requestType, request, value, index, len);
+
+    int result = token_setup(ep, &setup, len); // setup stage
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    int write_len = 0;
+    if (buf != NULL) {
+        write_len = multi_token_out(ep, buf, len); // data stage
+        USB_TRACE1(write_len);
+        if (write_len < 0) {
+            return USB_TYPE_ERROR;
+        }
+    }
+
+    setToggle(ep, 1); // DATA1
+    result = multi_token_in(ep); // status stage
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(write_len);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
+    if (blocking == false) {
+        ep->setBuffer(buf, len);
+        ep_queue.push(ep);
+        multi_token_inNB(ep, buf, len);
+        return USB_TYPE_PROCESSING;
+    }
+    int result = multi_token_in(ep, buf, len);
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(result);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
+    USB_TEST_ASSERT(blocking);
+    int result = multi_token_out(ep, buf, len);
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(result);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
+    if (blocking == false) {
+        ep->setBuffer(buf, len);
+        ep_queue.push(ep);
+        multi_token_inNB(ep, buf, len);
+        return USB_TYPE_PROCESSING;
+    }
+    int result = multi_token_in(ep, buf, len);
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(result);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
+    USB_TEST_ASSERT(blocking);
+    int result = multi_token_out(ep, buf, len);
+    USB_TRACE1(result);
+    if (result < 0) {
+        return USB_TYPE_ERROR;
+    }
+    ep->setLengthTransferred(result);
+    return USB_TYPE_OK;
+}
+
+USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
+    USB_TEST_ASSERT(blocking);
+    isochronousReadNB(ep, buf, len);
+    return USB_TYPE_OK;
+}
+
+int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) {
+    USB_TRACE1(size);
+    if (ep->getState() != USB_TYPE_PROCESSING) {
+        ep->setState(USB_TYPE_PROCESSING);
+        ep->setBuffer(data, size);
+        multi_token_inNB(ep, data, size);
+    }
+    if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) {
+        return ep->getLengthTransferred();
+    }
+    return -1;
+}
+
+int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) {
+    USB_TRACE1(size);
+    return interruptReadNB(ep, data, size);
+}
+
+int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) {
+    USB_TRACE1(size);
+    int result = token_iso_in(ep, data, size);
+    if (result >= 0) {
+         ep->setLengthTransferred(result);
+    }
+    return result;
+}
+
+void USBHost::task() {
+    USBEndpoint* ep = ep_queue.pop();
+    if (ep) {
+        USB_TEST_ASSERT(ep->getDir() == IN);
+        if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) {
+            ep->call();
+        } else {
+            ep_queue.push(ep);
+        }
+    }
+}
+
+void usb_test_assert_internal(const char *expr, const char *file, int line){
+    error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr);
+}
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHost.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,195 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include "mbed.h"
+#include "USBHALHost.h"
+#include "USBDeviceConnected.h"
+#include "IUSBEnumerator.h"
+#include "USBHostConf.h"
+#include "dbg.h"
+#include "myvector.h"
+
+/**
+* USBHost class
+*   This class is a singleton. All drivers have a reference on the static USBHost instance
+*/
+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 interrupt 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 interrupt 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);
+
+    /**
+    * Isochronous read
+    *
+    * @param dev the isochronous 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 isochronousRead(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) {
+        return index < DeviceLists.size() ? DeviceLists[index] : NULL;
+    }
+
+    /**
+     *  register a driver into the host associated with a callback function called when the device is disconnected
+     *
+     *  @param dev device
+     *  @param intf interface number
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void registerDriver(USBDeviceConnected * dev, uint8_t intf, T* tptr, void (T::*mptr)(void)) {
+    }
+
+    // KL46Z-USBHost extensions
+    int interruptReadNB(USBEndpoint* ep, uint8_t* data, int size);
+    int bulkReadNB(USBEndpoint*ep, uint8_t* data, int size);
+    int isochronousReadNB(USBEndpoint*ep, uint8_t* data, int size);
+
+    /**
+     * non-blocking processing
+     */
+    static void poll();
+
+private:
+    USBHost();
+    static USBHost* inst;
+    virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed);
+    void root_enumeration(USBDeviceConnected* dev);
+    void parseConfDescr(USBDeviceConnected* dev, uint8_t* conf_descr, uint32_t len, IUSBEnumerator* pEnumerator);
+    myvector<USBDeviceConnected*>DeviceLists;
+    void task();
+    EndpointQueue ep_queue;
+
+    // USB HUB
+    bool Hub(USBDeviceConnected* dev);
+    int SetPortPower(USBDeviceConnected* dev, int port);
+    int ClearPortPower(USBDeviceConnected* dev, int port);
+    int PortReset(USBDeviceConnected* dev, int port);
+    int SetPortFeature(USBDeviceConnected* dev, int feature, int index);
+    int ClearPortFeature(USBDeviceConnected* dev, int feature, int index);
+    int SetPortReset(USBDeviceConnected* dev, int port);
+    int GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status);
+};
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostConf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostConf.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,72 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBHOST_CONF_H
+#define USBHOST_CONF_H
+
+/*
+* Maximum number of devices that can be connected
+* to the usb host
+*/
+#define MAX_DEVICE_CONNECTED        5
+
+/*
+* Maximum of Hub connected to the usb host
+*/
+#define MAX_HUB_NB                  1
+
+/*
+* Maximum number of ports on a USB hub
+*/
+#define MAX_HUB_PORT                4
+
+/*
+* Enable USBHostMSD
+*/
+#define USBHOST_MSD                 0
+
+/*
+* Enable USBHostKeyboard
+*/
+#define USBHOST_KEYBOARD            0
+
+/*
+* Enable USBHostMouse
+*/
+#define USBHOST_MOUSE               0
+
+/*
+* Enable USBHostSerial or USBHostMultiSerial (if set > 1)
+*/
+#define USBHOST_SERIAL              0
+
+/*
+* Enable USB3Gmodule
+*/
+#define USBHOST_3GMODULE            0 
+
+/*
+* Maximum number of interfaces of a usb device
+*/
+#define MAX_INTF                    4
+
+/*
+* usb_thread stack size
+*/
+#define USB_THREAD_STACK            (256*4 + MAX_HUB_NB*256*4)
+
+#endif
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostGamepad.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostGamepad.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,119 @@
+/*
+ * mbed USBHost Gamepad driver sample
+ * Copyright (c) 2014 Yuuichi Akagawa
+ *
+ * modified from mbed USBHostMouse
+ *
+ * mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "USBHostGamepad.h"
+//#if USBHOST_GAMEPAD
+
+USBHostGamepad::USBHostGamepad() {
+    host = USBHost::getHostInst();
+    init();
+}
+
+void USBHostGamepad::init() {
+    dev = NULL;
+    int_in = NULL;
+    dev_connected = false;
+    gamepad_device_found = false;
+    gamepad_intf = -1;
+}
+
+bool USBHostGamepad::connected() {
+    return dev_connected;
+}
+
+bool USBHostGamepad::connect() {
+    if (dev_connected) {
+        return true;
+    }
+
+    for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+
+            if(host->enumerate(dev, this))
+                break;
+
+            if (gamepad_device_found) {
+
+                int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN);
+                if (!int_in)
+                    break;
+
+                USB_INFO("New Gamepad/Joystick device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf);
+#if DEBUG > 3
+                //Parse HID Report Descriptor
+                parseHidDescr();
+#endif
+                dev->setName("Gamepad", gamepad_intf);
+                host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init);
+
+                int_in->attach(this, &USBHostGamepad::rxHandler);
+                rxSize = int_in->getSize();
+                if (rxSize > sizeof(report))
+                    rxSize = sizeof(report);
+                host->interruptRead(dev, int_in, report, rxSize, false);
+
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+void USBHostGamepad::rxHandler() {
+    if (dev)
+        host->interruptRead(dev, int_in, report, rxSize, false);
+        
+    /* modified 2016 Racoon */
+        
+}
+
+/*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid)
+{
+    // we don't check VID/PID for gamepad driver
+}
+
+/*virtual*/ bool USBHostGamepad::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 ((gamepad_intf == -1) &&
+        (intf_class == HID_CLASS) &&
+        (intf_subclass == 0x00) &&
+        (intf_protocol == 0x00)) {
+        gamepad_intf = intf_nb;
+        return true;
+    }
+    return false;
+}
+
+/*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    if (intf_nb == gamepad_intf) {
+        if (type == INTERRUPT_ENDPOINT && dir == IN) {
+            gamepad_device_found = true;
+            return true;
+        }
+    }
+    return false;
+}
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostGamepad.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostGamepad.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,90 @@
+/* 
+ * modified from
+ * mbed USBHost Gamepad driver sample
+ * Copyright (c) 2014 Yuuichi Akagawa
+ *
+ * modified from mbed USBHostMouse
+ *
+ * Copyright (c) 2014 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 USBHOSTGAMEPAD_H
+#define USBHOSTGAMEPAD_H
+
+#include "USBHostConf.h"
+
+//#if USBHOST_GAMEPAD
+
+#include "USBHost.h"
+//HID Class Request
+#define HID_GET_REPORT                                 0x01
+#define HID_GET_IDLE                                   0x02
+#define HID_GET_PROTOCOL                               0x03
+#define HID_GET_DESCRIPTOR                             0x06
+#define HID_SET_REPORT                                 0x09
+#define HID_SET_IDLE                                   0x0a
+#define HID_SET_PROTOCOL                               0x0b
+
+/** 
+ * A class to communicate a USB MIDI device
+ */
+class USBHostGamepad : public IUSBEnumerator {
+public:
+    /**
+     * Constructor
+     */
+    USBHostGamepad();
+
+    /**
+     * Try to connect a gamepad device
+     *
+     * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
+    * Check if a gamepad is connected
+    *
+    * @returns true if a gamepad is connected
+    */
+    bool connected();
+
+    uint8_t report[8]; /* modified 2016 Racoon */
+    int rxSize;
+        
+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;
+
+    bool dev_connected;
+    bool gamepad_device_found;
+    int gamepad_intf;
+
+    void rxHandler();
+    void init();
+};
+
+#endif
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostHub.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostHub.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,113 @@
+#include "USBHost.h"
+
+#define PORT_CONNECTION   0
+#define PORT_ENABLE       1
+#define PORT_SUSPEND      2
+#define PORT_OVER_CURRENT 3
+#define PORT_RESET        4
+#define PORT_POWER        8
+#define PORT_LOW_SPEED    9
+
+#define C_PORT_CONNECTION   16
+#define C_PORT_ENABLE       17
+#define C_PORT_SUSPEND      18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET        20
+
+bool USBHost::Hub(USBDeviceConnected* dev) {
+    USB_INFO("New HUB: VID:%04x PID:%04x [dev: %p]", dev->getVid(), dev->getPid(), dev);
+    HubDescriptor hubdesc;
+    // get HUB descriptor
+    int rc = controlRead(dev, 
+                        USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS,
+                        GET_DESCRIPTOR,
+                        0x29 << 8, 0, reinterpret_cast<uint8_t*>(&hubdesc), 
+                        sizeof(HubDescriptor));
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    if (rc != USB_TYPE_OK) {
+        return false;
+    }
+    USB_DBG_HEX((uint8_t*)&hubdesc, sizeof(hubdesc));
+
+    uint32_t status;
+    rc = controlRead( dev,
+                      0xa0, 0, 0, 0, reinterpret_cast<uint8_t*>(&status), 4);
+    USB_TEST_ASSERT(rc == USB_TYPE_OK);
+    if (rc != USB_TYPE_OK) {
+        return false;
+    }
+    USB_DBG("HUB STATUS: %08X\n", status);
+
+    for(int i = 1; i <= hubdesc.bNbrPorts; i++) {
+        SetPortPower(dev, i); // power on
+        wait_ms(hubdesc.bPwrOn2PwrGood*2);
+        uint32_t status;
+        GetPortStatus(dev, i, &status);
+        USB_DBG("port: %d status: %08X\n", i, status);
+        if (status & 0x010000) { // Connect Status Change, has changed
+            USB_TEST_ASSERT(status & 0x000001);
+            ClearPortFeature(dev, C_PORT_CONNECTION, i);
+            int lowSpeed = 0;
+            if (status & 0x0200) {
+                lowSpeed = 1;
+            }
+            PortReset(dev, i);
+            if (!addDevice(dev, i, lowSpeed)) {
+                ClearPortPower(dev, i); // power off
+            }
+        } else {
+            ClearPortPower(dev, i); // power off
+        }
+    }
+    return false;
+}
+
+
+int USBHost::SetPortPower(USBDeviceConnected* dev, int port)
+{
+    return SetPortFeature(dev, PORT_POWER, port);
+}
+
+int USBHost::ClearPortPower(USBDeviceConnected* dev, int port)
+{
+    return ClearPortFeature(dev, PORT_POWER, port);
+}
+
+int USBHost::SetPortFeature(USBDeviceConnected* dev, int feature, int index)
+{
+    return controlWrite(dev, 0x23, SET_FEATURE,feature,index,0,0);
+}
+
+int USBHost::ClearPortFeature(USBDeviceConnected* dev, int feature, int index)
+{
+    return controlWrite(dev, 0x23, CLEAR_FEATURE,feature,index,0,0);
+}
+
+int USBHost::SetPortReset(USBDeviceConnected* dev, int port)
+{
+    return SetPortFeature(dev, PORT_RESET, port);
+}
+
+int USBHost::GetPortStatus(USBDeviceConnected* dev, int port, uint32_t* status)
+{
+    return controlRead(dev, 0xa3, GET_STATUS, 0, port, (uint8_t*)status, 4);
+}
+
+int USBHost::PortReset(USBDeviceConnected* dev, int port)
+{
+    USB_DBG("%p port=%d\n", this, port);
+    USB_TEST_ASSERT(port >= 1);
+    SetPortReset(dev, port);
+    // wait reset
+    for(int i = 0; i < 100; i++) {
+        uint32_t status;    
+        GetPortStatus(dev, port, &status);
+        USB_DBG("RESET port: %d status: %08X\n", port, status);
+        if (status & 0x100000) { // Reset change , Reset complete
+            return USB_TYPE_OK;
+        }
+        wait_ms(5);
+     }
+     return USB_TYPE_ERROR;
+}
+
diff -r 000000000000 -r b5f79b4f741d USBHost/USBHostTypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHostTypes.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,168 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USB_INC_H
+#define USB_INC_H
+
+#include "mbed.h"
+#include "toolchain.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
+
+#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  GET_STATUS                 0x00
+#define  SET_FEATURE                0x03
+#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
+
+// PID
+#define DATA0 0x03
+#define DATA1 0x0b
+#define ACK   0x02
+#define STALL 0x0e
+#define NAK   0x0a
+
+#pragma pack(push,1)
+typedef 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; 
+} PACKED DeviceDescriptor;
+
+typedef 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;             
+} PACKED 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;              
+#pragma pack(pop)
+
+#endif
+
diff -r 000000000000 -r b5f79b4f741d USBHost/dbg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/dbg.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,91 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USB_DEBUG_H
+#define USB_DEBUG_H
+
+//Debug is disabled by default
+#ifndef DEBUG
+//#define DEBUG 3 /*INFO,ERR,WARN*/
+#define DEBUG 0
+#endif
+#ifndef DEBUG2
+#define DEBUG2 0
+#endif
+#define DEBUG_TRANSFER 0
+#define DEBUG_EP_STATE 0
+#define DEBUG_EVENT 0
+
+#if (DEBUG > 3)
+#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
+//#define USB_DBG(x, ...) std::printf("[USB_DBG: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#define USB_DBG_HEX(A,B) debug_hex(A,B)
+extern void debug_hex(uint8_t* buf, int size);
+#define USB_DBG_ERRSTAT() report.print_errstat();
+#else
+#define USB_DBG(x, ...)
+#define USB_DBG_HEX(A,B) while(0)
+#define USB_DBG_ERRSTAT() while(0)
+#endif
+
+#if (DEBUG2 > 3)
+#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");} while(0);
+#else
+#define USB_DBG2(...)  while(0);
+#endif
+
+#if (DEBUG > 2)
+#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\r\n");}while(0);
+//#define USB_INFO(x, ...) std::printf("[USB_INFO: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_INFO(x, ...)
+#endif
+
+#if (DEBUG > 1)
+#define USB_WARN(x, ...) std::printf("[USB_WARNING: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_WARN(x, ...)
+#endif
+
+#if (DEBUG > 0)
+#define USB_ERR(x, ...) std::printf("[USB_ERR: %s:%d]" x "\r\n", __FILE__, __LINE__, ##__VA_ARGS__);
+#else
+#define USB_ERR(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
+
+#ifdef _USB_TEST
+#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
+#else
+#define USB_TEST_ASSERT(A) while(0)
+#define USB_TEST_ASSERT_FALSE(A) while(0)
+#endif
+
+#endif
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/mydebug.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/mydebug.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,14 @@
+#pragma once
+template<class SERIAL_T>
+void debug_hex(SERIAL_T& pc, const uint8_t* buf, int size)
+{
+    for(int i = 0; i < size; i++) {
+        pc.printf("%02x ", buf[i]);
+        if (i%16 == 15) {
+            pc.puts("\n");
+        }
+    }
+    pc.puts("\n");
+}
+
+
diff -r 000000000000 -r b5f79b4f741d USBHost/mymap.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/mymap.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,66 @@
+#pragma once
+
+template<class K,class T>
+class mymap {
+    struct mypair {
+        K first;
+        T second;
+    };
+public:
+    mymap() {
+        m_size = 0;
+    }
+    T& operator[](const K& key) {
+        int it;
+        if (count(key) == 0) {
+            it = insert(key, 0);
+        } else {
+            it = find(key);
+        }
+        return m_buf[it].second;
+    }
+    bool empty() { return m_size == 0 ? true : false; }
+    int size() { return m_size; }
+    void clear() { m_size = 0; }
+    int count(K key) {
+        for(int i = 0; i < m_size; i++) {
+            if (m_buf[i].first == key) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+private:
+    int find(K key) {
+        for(int i = 0; i < m_size; i++) {
+            if (m_buf[i].first == key) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    int insert(K key, T value) {
+        int it = find(key);
+        if (it != -1) {
+            m_buf[it].second = value;
+            return it;
+        }
+        mypair* new_buf = new mypair[m_size+1];
+        if (m_size > 0) {
+            for(int i = 0; i < m_size; i++) {
+                new_buf[i] = m_buf[i];
+            }
+            delete[] m_buf;
+        }
+        m_buf = new_buf;
+        it = m_size++;
+        m_buf[it].first = key;
+        m_buf[it].second = value;
+        return it;
+    }
+
+    int m_size;
+    mypair *m_buf;
+};
+
diff -r 000000000000 -r b5f79b4f741d USBHost/myvector.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/myvector.h	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,35 @@
+#pragma once
+
+template<class T>
+class myvector {
+public:
+    myvector() {
+        m_size = 0;
+        m_buf = NULL;
+    }
+    ~myvector() {
+        if (m_buf) {
+            delete[] m_buf;
+        }
+    }
+    void push_back(T v) {
+        T* new_buf = new T[m_size+1];
+        if (m_size > 0) {
+            for(int i = 0; i < m_size; i++) {
+                new_buf[i] = m_buf[i];
+            }
+            delete[] m_buf;
+        }
+        m_buf = new_buf;
+        m_buf[m_size++] = v;
+    }
+    T& operator[](const int index) {
+        return m_buf[index];
+    }
+    int size() { return m_size; }
+
+private:
+    int m_size;
+    T *m_buf;
+};
+
diff -r 000000000000 -r b5f79b4f741d main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,29 @@
+#include "mbed.h"
+#include "USBHostGamepad.h"
+
+USBHostGamepad *pad;
+
+// LED
+DigitalOut red(PB_5);
+DigitalOut yellow(PA_10);
+
+int main()
+{    
+    // USB Gmaepad Initialize
+    pad = new USBHostGamepad();
+    if (!pad->connect()) {
+        printf("USB Gamepad not found.\r\n");
+        while(1);
+    }
+    
+    while(1)
+    {
+        USBHost::poll();
+        
+        red = pad->report[4] & 0x20;
+        yellow = pad->report[4] & 0x40;
+        
+        printf("%02x %02x %02x %02x %02x %02x %02x %02x\r\n", pad->report[0],pad->report[1],pad->report[2],pad->report[3],pad->report[4],pad->report[5],pad->report[6],pad->report[7]);
+        wait_ms(16);
+    }
+}
diff -r 000000000000 -r b5f79b4f741d mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Mar 15 11:39:04 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb
\ No newline at end of file