USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

Legacy Warning

This is an mbed 2 library. To learn more about mbed OS 5, visit the docs.

Pull requests against this repository are no longer supported. Please raise against mbed OS 5 as documented above.

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Thu Aug 13 15:46:06 2015 +0100
Parent:
58:f3cad7e6984e
Child:
60:0e6b3f44926e
Child:
65:1031882d3481
Child:
66:7662d9ed5011
Commit message:
Synchronized with git revision 376d6a73e345b728a788041adb166b08cd8d2b95

Full URL: https://github.com/mbedmicro/mbed/commit/376d6a73e345b728a788041adb166b08cd8d2b95/

Silicon Labs - Add support for USBDevice

Changed in this revision

USBDevice/TARGET_Silicon_Labs/inc/em_usb.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/inc/em_usbd.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/inc/em_usbh.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/inc/em_usbhal.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/inc/em_usbtypes.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/inc/usbconfig.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/src/em_usbd.c Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/src/em_usbdep.c Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/src/em_usbdint.c Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/src/em_usbhal.c Show annotated file Show diff for this revision Revisions of this file
USBDevice/TARGET_Silicon_Labs/src/em_usbtimer.c Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBEndpoints.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBEndpoints_EFM32.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHAL_EFM32.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/em_usb.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,999 @@
+/***************************************************************************//**
+ * @file em_usb.h
+ * @brief USB protocol stack library API for EFM32.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __EM_USB_H
+#define __EM_USB_H
+
+#include "em_device.h"
+#include "em_assert.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "usbconfig.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+
+#include <string.h>
+#include <stddef.h>
+#include "em_common.h"
+#include "em_int.h"
+
+#if defined( USB_USE_PRINTF )
+#include <stdio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __CC_ARM
+#pragma anon_unions
+#endif
+
+/***************************************************************************//**
+ * @addtogroup USB
+ * @brief USB HOST and DEVICE protocol stacks.
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup USB_COMMON
+ * @brief Common parts for both HOST and DEVICE USB stacks, see @ref usb_device
+ *        and @ref usb_host pages for device and host library documentation.
+ * @{
+ ******************************************************************************/
+
+#define SILABS_USB_VID          0x10C4          /**< Silicon Labs Vendor ID, supplied by USB-IF.       */
+
+/* SETUP request, direction of data stage */
+#define USB_SETUP_DIR_OUT       0               /**< Setup request data stage OUT direction value.     */
+#define USB_SETUP_DIR_IN        1               /**< Setup request data stage IN direction value.      */
+#define USB_SETUP_DIR_MASK      0x80            /**< Setup request data stage direction mask.          */
+#define USB_SETUP_DIR_D2H       0x80            /**< Setup request data stage IN direction mask.       */
+#define USB_SETUP_DIR_H2D       0x00            /**< Setup request data stage OUT direction mask.      */
+
+/* SETUP request type */
+#define USB_SETUP_TYPE_STANDARD       0         /**< Standard setup request value.                     */
+#define USB_SETUP_TYPE_CLASS          1         /**< Class setup request value.                        */
+#define USB_SETUP_TYPE_VENDOR         2         /**< Vendor setup request value.                       */
+#define USB_SETUP_TYPE_STANDARD_MASK  0x00      /**< Standard setup request mask.                      */
+#define USB_SETUP_TYPE_CLASS_MASK     0x20      /**< Class setup request mask.                         */
+#define USB_SETUP_TYPE_VENDOR_MASK    0x40      /**< Vendor setup request mask.                        */
+
+/* SETUP request recipient */
+#define USB_SETUP_RECIPIENT_DEVICE    0         /**< Setup request device recipient value.             */
+#define USB_SETUP_RECIPIENT_INTERFACE 1         /**< Setup request interface recipient value.          */
+#define USB_SETUP_RECIPIENT_ENDPOINT  2         /**< Setup request endpoint recipient value.           */
+#define USB_SETUP_RECIPIENT_OTHER     3         /**< Setup request other recipient value.              */
+
+/* SETUP standard request codes for Full Speed devices */
+#define GET_STATUS                0             /**< Standard setup request GET_STATUS.                */
+#define CLEAR_FEATURE             1             /**< Standard setup request CLEAR_FEATURE.             */
+#define SET_FEATURE               3             /**< Standard setup request SET_FEATURE.               */
+#define SET_ADDRESS               5             /**< Standard setup request SET_ADDRESS.               */
+#define GET_DESCRIPTOR            6             /**< Standard setup request GET_DESCRIPTOR.            */
+#define SET_DESCRIPTOR            7             /**< Standard setup request SET_DESCRIPTOR.            */
+#define GET_CONFIGURATION         8             /**< Standard setup request GET_CONFIGURATION.         */
+#define SET_CONFIGURATION         9             /**< Standard setup request SET_CONFIGURATION.         */
+#define GET_INTERFACE             10            /**< Standard setup request GET_INTERFACE.             */
+#define SET_INTERFACE             11            /**< Standard setup request SET_INTERFACE.             */
+#define SYNCH_FRAME               12            /**< Standard setup request SYNCH_FRAME.               */
+
+/* SETUP class request codes */
+#define USB_HID_GET_REPORT        0x01          /**< HID class setup request GET_REPORT.               */
+#define USB_HID_GET_IDLE          0x02          /**< HID class setup request GET_IDLE.                 */
+#define USB_HID_SET_REPORT        0x09          /**< HID class setup request SET_REPORT.               */
+#define USB_HID_SET_IDLE          0x0A          /**< HID class setup request SET_IDLE.                 */
+#define USB_HID_SET_PROTOCOL      0x0B          /**< HID class setup request SET_PROTOCOL.             */
+#define USB_CDC_SETLINECODING     0x20          /**< CDC class setup request SET_LINE_CODING.          */
+#define USB_CDC_GETLINECODING     0x21          /**< CDC class setup request GET_LINE_CODING.          */
+#define USB_CDC_SETCTRLLINESTATE  0x22          /**< CDC class setup request SET_CONTROL_LINE_STATE.   */
+#define USB_MSD_BOTRESET          0xFF          /**< MSD class setup request Bulk only transfer reset. */
+#define USB_MSD_GETMAXLUN         0xFE          /**< MSD class setup request Get Max LUN.              */
+#define USB_AUDIO_GET_CUR         0x81          /**< Audio class setup request GET_CUR.                */
+#define USB_AUDIO_SET_CUR         0x01          /**< Audio class setup request SET_CUR.                */
+#define USB_AUDIO_GET_CUR         0x81          /**< Audio class setup request GET_CUR.                */
+#define USB_AUDIO_SET_MIN         0x02          /**< Audio class setup request SET_MIN.                */
+#define USB_AUDIO_GET_MIN         0x82          /**< Audio class setup request GET_MIN.                */
+#define USB_AUDIO_SET_MAX         0x03          /**< Audio class setup request SET_MAX.                */
+#define USB_AUDIO_GET_MAX         0x83          /**< Audio class setup request GET_MAX.                */
+#define USB_AUDIO_SET_RES         0x04          /**< Audio class setup request SET_RES.                */
+#define USB_AUDIO_GET_RES         0x84          /**< Audio class setup request GET_RES.                */
+#define USB_AUDIO_SET_MEM         0x05          /**< Audio class setup request SET_MEM.                */
+#define USB_AUDIO_GET_MEM         0x85          /**< Audio class setup request GET_MEM.                */
+#define USB_AUDIO_GET_STAT        0xFF          /**< Audio class setup request GET_STAT.               */
+
+/* SETUP command GET/SET_DESCRIPTOR decriptor types */
+#define USB_DEVICE_DESCRIPTOR             1     /**< DEVICE descriptor value.                          */
+#define USB_CONFIG_DESCRIPTOR             2     /**< CONFIGURATION descriptor value.                   */
+#define USB_STRING_DESCRIPTOR             3     /**< STRING descriptor value.                          */
+#define USB_MAX_STRING_DESCRIPTOR_CHARS   126   /**< Maximum STRING descriptor bString length.         */
+#define USB_INTERFACE_DESCRIPTOR          4     /**< INTERFACE descriptor value.                       */
+#define USB_ENDPOINT_DESCRIPTOR           5     /**< ENDPOINT descriptor value.                        */
+#define USB_DEVICE_QUALIFIER_DESCRIPTOR   6     /**< DEVICE_QUALIFIER descriptor value.                */
+#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR 7     /**< OTHER_SPEED_CONFIGURATION descriptor value.       */
+#define USB_INTERFACE_POWER_DESCRIPTOR    8     /**< INTERFACE_POWER descriptor value.                 */
+#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR 11 /**< INTERFACE_ASSOCIATION descriptor value.           */
+#define USB_HID_DESCRIPTOR                0x21  /**< HID descriptor value.                             */
+#define USB_SMARTCARD_DESCRIPTOR          0x21  /**< Smartcard usb-ccid-specific Descriptor Type.      */
+#define USB_HID_REPORT_DESCRIPTOR         0x22  /**< HID REPORT descriptor value.                      */
+#define USB_CS_INTERFACE_DESCRIPTOR       0x24  /**< Audio Class-specific interface Descriptor Type.   */
+#define USB_CS_ENDPOINT_DESCRIPTOR        0x25  /**< Audio Class-specific endpoint Descriptor Type.    */
+#define USB_HUB_DESCRIPTOR                0x29  /**< HUB descriptor value.                             */
+#define USB_CA_HEADER_DESCRIPTOR          1     /**< Audio Class-Specific AC Interface Header descriptor.*/
+#define USB_CA_INPUT_TERMINAL_DESCRIPTOR  2     /**< Audio Class-Specific AC Interface Input Terminal desc. */
+#define USB_CA_OUTPUT_TERMINAL_DESCRIPTOR 3     /**< Audio Class-Specific AC Interface Output Terminal desc.*/
+#define USB_CA_MIXER_UNIT_DESCRIPTOR      4     /**< Audio Class-Specific AC Interface Mixer descriptor.*/
+#define USB_CA_SELECTOR_UNIT_DESCRIPTOR   5     /**< Audio Class-Specific AC Interface Selector desc.  */
+#define USB_CA_FEATURE_UNIT_DESCRIPTOR    6     /**< Audio Class-Specific AC Interface Feature desc.   */
+#define USB_CA_PROCESSING_UNIT_DESCRIPTOR 7     /**< Audio Class-Specific AC Interface Processing desc.*/
+#define USB_CA_EXTENSION_UNIT_DESCRIPTOR  8     /**< Audio Class-Specific AC Interface Extension desc. */
+#define USB_CA_EP_GENERAL_DESCRIPTOR      1     /**< Audio Class-Specific general descriptor subtype code.*/
+#define USB_CA_AS_GENERAL_DESCRIPTOR      1     /**< Audio Class-Specific AS Interface General descriptor.*/
+#define USB_CA_FORMAT_TYPE_DESCRIPTOR     2     /**< Audio Class-Specific AS Interface Format Type desc. */
+
+#define USB_DEVICE_DESCSIZE               18    /**< Device descriptor size.                           */
+#define USB_CONFIG_DESCSIZE               9     /**< Configuration descriptor size.                    */
+#define USB_INTERFACE_DESCSIZE            9     /**< Interface descriptor size.                        */
+#define USB_ENDPOINT_DESCSIZE             7     /**< Endpoint descriptor size.                         */
+#define USB_DEVICE_QUALIFIER_DESCSIZE     10    /**< Device qualifier descriptor size.                 */
+#define USB_OTHER_SPEED_CONFIG_DESCSIZE   9     /**< Device other speed configuration descriptor size. */
+#define USB_INTERFACE_ASSOCIATION_DESCSIZE 8    /**< INTERFACE_ASSOCIATION descriptor size.            */
+#define USB_HID_DESCSIZE                  9     /**< HID descriptor size.                              */
+#define USB_SMARTCARD_DESCSIZE            54    /**< CCID descriptor size.                             */
+#define USB_CDC_HEADER_FND_DESCSIZE       5     /**< CDC Header functional descriptor size.            */
+#define USB_CDC_CALLMNG_FND_DESCSIZE      5     /**< CDC Call Management functional descriptor size.   */
+#define USB_CDC_ACM_FND_DESCSIZE          4     /**< CDC Abstract Control Management functional descriptor size.*/
+#define USB_CA_INPUT_TERMINAL_DESCSIZE    12    /**< Audio Input Terminal descriptor size.             */
+#define USB_CA_OUTPUT_TERMINAL_DESCSIZE   9     /**< Audio Output Terminal descriptor size.            */
+#define USB_CA_EP_GENERAL_DESCSIZE        7     /**< Audio Class-Specific general descriptor subtype size.*/
+#define USB_CA_AS_GENERAL_DESCSIZE        7     /**< Audio Class-Specific AS Interface General desc size.*/
+#define USB_CA_STD_AS_ENDPOINT_DESCSZIE   9     /**< Audio-class standard audio stream descriptor size.*/
+
+/* Misc. USB definitions */
+#define USB_LS_CTRL_EP_MAXSIZE  8               /**< The max size of low speed control endpoints.      */
+#define USB_LS_INTR_EP_MAXSIZE  8               /**< The max size of low speed interrupt endpoints.    */
+#define USB_FS_CTRL_EP_MAXSIZE  64              /**< The max size of full speed control endpoints.     */
+#define USB_FS_INTR_EP_MAXSIZE  64              /**< The max size of full speed interrupt endpoints.   */
+#define USB_FS_BULK_EP_MAXSIZE  64              /**< The max size of full speed bulk endpoints.        */
+#define USB_FS_ISOC_EP_MAXSIZE  1023            /**< The max size of full speed isochronous endpoints. */
+#define USB_EPTYPE_CTRL         0               /**< Endpoint type control.                            */
+#define USB_EPTYPE_ISOC         1               /**< Endpoint type isochron.                           */
+#define USB_EPTYPE_BULK         2               /**< Endpoint type bulk.                               */
+#define USB_EPTYPE_INTR         3               /**< Endpoint type interrupt.                          */
+#define USB_EPSYNC_NO           (0 << 2)        /**< Endpoint synchronization type, none.              */
+#define USB_EPSYNC_ASYNC        (1 << 2)        /**< Endpoint synchronization type, asynchronous.      */
+#define USB_EPSYNC_ADAPTIVE     (2 << 2)        /**< Endpoint synchronization type, adaptive.          */
+#define USB_EPSYNC_SYNC         (3 << 2)        /**< Endpoint synchronization type, synchronous.       */
+#define USB_EP_DIR_IN           0x80            /**< Endpoint direction mask.                          */
+#define USB_SETUP_PKT_SIZE      8               /**< Setup request packet size.                        */
+#define USB_EPNUM_MASK          0x0F            /**< Endpoint number mask.                             */
+#define USB_LANGID_ENUS         0x0409          /**< English-United States language id.                */
+#define USB_MAX_DEVICE_ADDRESS  127             /**< Maximum allowable device address.                 */
+
+#define CONFIG_DESC_BM_REMOTEWAKEUP 0x20        /**< Configuration descriptor attribute macro.         */
+#define CONFIG_DESC_BM_SELFPOWERED  0x40        /**< Configuration descriptor attribute macro.         */
+#define CONFIG_DESC_BM_RESERVED_D7  0x80        /**< Configuration descriptor attribute macro.         */
+#define CONFIG_DESC_BM_TRANSFERTYPE 0x03        /**< Configuration descriptor transfer type bitmask.   */
+#define CONFIG_DESC_MAXPOWER_mA(x)  (((x)+1)/2) /**< Configuration descriptor power macro.             */
+
+#define DEVICE_IS_SELFPOWERED       0x0001      /**< Standard request GET_STATUS bitmask.              */
+#define REMOTE_WAKEUP_ENABLED       0x0002      /**< Standard request GET_STATUS bitmask.              */
+#define USB_FEATURE_ENDPOINT_HALT         0     /**< Standard request CLEAR/SET_FEATURE bitmask.       */
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP  1     /**< Standard request CLEAR/SET_FEATURE bitmask.       */
+
+#define HUB_FEATURE_PORT_RESET            4     /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
+#define HUB_FEATURE_PORT_POWER            8     /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
+#define HUB_FEATURE_C_PORT_CONNECTION     16    /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
+#define HUB_FEATURE_C_PORT_RESET          20    /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
+#define HUB_FEATURE_PORT_INDICATOR        22    /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
+
+#define USB_CLASS_CDC                     2     /**< CDC device/interface class code.                    */
+#define USB_CLASS_CDC_DATA                0x0A  /**< CDC Data interface class code.                      */
+#define USB_CLASS_CDC_ACM                 2     /**< CDC Abstract Control Model interface subclass code. */
+#define USB_CLASS_CDC_HFN                 0     /**< CDC class Header Functional Descriptor subtype.     */
+#define USB_CLASS_CDC_CMNGFN              1     /**< CDC class Call Management Functional Descriptor subtype.*/
+#define USB_CLASS_CDC_ACMFN               2     /**< CDC class Abstract Control Management Functional Descriptor subtype.*/
+#define USB_CLASS_CDC_UNIONFN             6     /**< CDC class Union Functional Descriptor subtype.      */
+
+#define USB_CLASS_HID                     3     /**< HID device/interface class code.                    */
+#define USB_CLASS_HID_KEYBOARD            1     /**< HID keyboard interface protocol code.               */
+#define USB_CLASS_HID_MOUSE               2     /**< HID mouse interface protocol code.                  */
+
+#define USB_CLASS_HUB                     9     /**< HUB device/interface class code.                    */
+
+#define USB_CLASS_MSD                     8     /**< MSD device/interface class code.                    */
+#define USB_CLASS_MSD_BOT_TRANSPORT       0x50  /**< MSD Bulk Only Transport protocol.                   */
+#define USB_CLASS_MSD_SCSI_CMDSET         6     /**< MSD Subclass SCSI transparent command set.          */
+#define USB_CLASS_MSD_CSW_CMDPASSED       0     /**< MSD BOT Command status wrapper command passed code. */
+#define USB_CLASS_MSD_CSW_CMDFAILED       1     /**< MSD BOT Command status wrapper command failed code. */
+#define USB_CLASS_MSD_CSW_PHASEERROR      2     /**< MSD BOT Command status wrapper cmd phase error code.*/
+
+#define USB_CLASS_AUDIO                   1     /**< Audio interface class code.                         */
+#define USB_CLASS_AUDIO_CONTROL           1     /**< Audio subclass code for control interface.          */
+#define USB_CLASS_AUDIO_STREAMING         2     /**< Audio subclass code for streaming interface.        */
+#define USB_CLASS_AUDIO_MIDISTREAMING     3     /**< Audio subclass code for midi streaming interface.   */
+
+/*** Triplet for the device descriptor of a composite device using IAD descriptors. ***/
+#define USB_CLASS_MISCELLANEOUS           0xEF  /**< MISCELLANEOUS device class code.                    */
+#define USB_CLASS_MISC_COMMON_SUBCLASS    2     /**< MISCELLANEOUS Common sub class code.                */
+#define USB_CLASS_MISC_IAD_PROTOCOL       1     /**< MISCELLANEOUS Interface Association Descriptor protocol code. */
+
+#define PORT_FULL_SPEED                   1     /**< Full speed return value for USBH_GetPortSpeed(). */
+#define PORT_LOW_SPEED                    2     /**< Low speed return value for USBH_GetPortSpeed().  */
+
+#if defined( __GNUC__  )                  /* GCC compilers */
+#if defined( __CHAR16_TYPE__ )
+typedef __CHAR16_TYPE__ char16_t;
+#else
+typedef unsigned short char16_t;
+#endif
+
+#elif defined( __ICCARM__ )               /* IAR compiler */
+#include <uchar.h>
+
+#elif defined( __CC_ARM )                 /* MDK-ARM compiler */
+typedef unsigned short char16_t;
+#endif
+
+/** Macro for creating USB compliant UTF-16LE UNICODE string descriptors.
+ *  @n Example: STATIC_CONST_STRING_DESC( iManufacturer, 'E','n','e','r','g','y',' ','M','i','c','r','o',' ','A','S' );
+ *  @note The size of the resulting struct will be two byte larger than a USB string
+ *        descriptor. This is to accommodate a terminating null char for the string.
+ *        The value assigned to the 'len' member does not take this into account
+ *        and is therefore correct usb wise.
+ */
+#define STATIC_CONST_STRING_DESC( _name, ... )                  \
+EFM32_PACK_START( 1 )                                           \
+typedef struct                                                  \
+{                                                               \
+  uint8_t  len;                                                 \
+  uint8_t  type;                                                \
+  char16_t name[ 1 + sizeof( (char16_t[]){__VA_ARGS__} ) / 2];  \
+} __attribute__ ((packed)) _##_name;                            \
+EFM32_PACK_END()                                                \
+EFM32_ALIGN( 4 )                                                \
+EFM32_PACK_START( 1 )                                           \
+static const _##_name _name __attribute__ ((aligned(4)))=       \
+{                                                               \
+  .len  = sizeof( _##_name ) - 2,                               \
+  .type = USB_STRING_DESCRIPTOR,                                \
+  .name = {__VA_ARGS__},                                        \
+  .name[ ( ( sizeof( _##_name ) - 2 ) / 2 ) - 1 ] = '\0'        \
+}                                                               \
+EFM32_PACK_END()
+
+/** Macro for creating USB compliant language string descriptors.
+ *  @n Example: STATIC_CONST_STRING_DESC_LANGID( langID, 0x04, 0x09 );
+ */
+#define STATIC_CONST_STRING_DESC_LANGID( _name, x, y )      \
+EFM32_PACK_START( 1 )                                       \
+typedef struct                                              \
+{                                                           \
+  uint8_t len;                                              \
+  uint8_t type;                                             \
+  uint8_t name[ 2 ];                                        \
+} __attribute__ ((packed)) _##_name;                        \
+EFM32_PACK_END()                                            \
+EFM32_ALIGN( 4 )                                            \
+EFM32_PACK_START( 1 )                                       \
+static const _##_name _name __attribute__ ((aligned(4)))=   \
+{                                                           \
+  .len = 4,                                                 \
+  .type = USB_STRING_DESCRIPTOR,                            \
+  .name = { y, x }                                          \
+}                                                           \
+EFM32_PACK_END()
+
+/** Macro for creating WORD (4 byte) aligned uint8_t array with size which
+ *  is a multiple of WORD size.
+ *  @n Example: @n UBUF( rxBuffer, 37 );  =>  uint8_t rxBuffer[ 40 ];
+ */
+#if !defined(__GNUC__)
+#define        UBUF( x, y ) EFM32_ALIGN( 4 )        uint8_t x[((y)+3)&~3]
+#define STATIC_UBUF( x, y ) EFM32_ALIGN( 4 ) static uint8_t x[((y)+3)&~3]
+#else
+#define        UBUF( x, y ) uint8_t x[((y)+3)&~3] __attribute__ ((aligned(4)))
+
+/** Macro for creating WORD (4 byte) aligned static uint8_t arrays with size which
+ *  is a multiple of WORD size.
+ *  @n Example: @n STATIC_UBUF( rxBuffer, 37 );  =>  static uint8_t rxBuffer[ 40 ];
+ */
+#define STATIC_UBUF( x, y ) static uint8_t x[((y)+3)&~3] __attribute__ ((aligned(4)))
+#endif
+
+
+/** @brief USB transfer status enumerator. */
+typedef enum
+{
+  /* NOTE: Please keep in sync with table errMsg[] in em_usbhal.c */
+  USB_STATUS_OK              = 0,               /**< No errors detected.                               */
+  USB_STATUS_REQ_ERR         = -1,              /**< Setup request error.                              */
+  USB_STATUS_EP_BUSY         = -2,              /**< Endpoint is busy.                                 */
+  USB_STATUS_REQ_UNHANDLED   = -3,              /**< Setup request not handled.                        */
+  USB_STATUS_ILLEGAL         = -4,              /**< Illegal operation attempted.                      */
+  USB_STATUS_EP_STALLED      = -5,              /**< Endpoint is stalled.                              */
+  USB_STATUS_EP_ABORTED      = -6,              /**< Endpoint transfer was aborted.                    */
+  USB_STATUS_EP_ERROR        = -7,              /**< Endpoint transfer error.                          */
+  USB_STATUS_EP_NAK          = -8,              /**< Endpoint NAK'ed transfer request.                 */
+  USB_STATUS_DEVICE_UNCONFIGURED = -9,          /**< Device is unconfigured.                           */
+  USB_STATUS_DEVICE_SUSPENDED    = -10,         /**< Device is suspended.                              */
+  USB_STATUS_DEVICE_RESET    = -11,             /**< Device is/was reset.                              */
+  USB_STATUS_TIMEOUT         = -12,             /**< Transfer timeout.                                 */
+  USB_STATUS_DEVICE_REMOVED  = -13,             /**< Device was removed.                               */
+  USB_STATUS_HC_BUSY         = -14,             /**< Host channel is busy.                             */
+  USB_STATUS_DEVICE_MALFUNCTION = -15,          /**< Malfunctioning device attached.                   */
+  USB_STATUS_PORT_OVERCURRENT = -16,            /**< VBUS shortcircuit/overcurrent failure.            */
+} USB_Status_TypeDef;
+/** @} (end addtogroup USB_COMMON) */
+
+
+#if defined( USB_DEVICE )
+/***************************************************************************//**
+ * @addtogroup USB_DEVICE
+ * @brief USB DEVICE protocol stack, see @ref usb_device page for detailed documentation.
+ * @{
+ ******************************************************************************/
+
+#define USB_PWRSAVE_MODE_OFF       0 /**< No energy saving mode selected.                       */
+#define USB_PWRSAVE_MODE_ONSUSPEND 1 /**< Enter USB power-save mode on suspend.                 */
+#define USB_PWRSAVE_MODE_ONVBUSOFF 2 /**< Enter USB power-save mode when not attached to host.  */
+#define USB_PWRSAVE_MODE_ENTEREM2  4 /**< Enter EM2 while in power-save mode.                   */
+
+#define USB_USBC_32kHz_CLK_LFXO    0 /**< Use 32kHz LFXO clock while in powersave mode.         */
+#define USB_USBC_32kHz_CLK_LFRCO   1 /**< Use 32kHz LFRCO clock while in powersave mode.        */
+
+/** @brief USB device state enumerator. */
+typedef enum
+{
+  USBD_STATE_NONE       = 0,                    /**< Device state is undefined/unknown.                */
+  USBD_STATE_ATTACHED   = 1,                    /**< Device state is ATTACHED.                         */
+  USBD_STATE_POWERED    = 2,                    /**< Device state is POWERED.                          */
+  USBD_STATE_DEFAULT    = 3,                    /**< Device state is DEFAULT.                          */
+  USBD_STATE_ADDRESSED  = 4,                    /**< Device state is ADDRESSED.                        */
+  USBD_STATE_CONFIGURED = 5,                    /**< Device state is CONFIGURED.                       */
+  USBD_STATE_SUSPENDED  = 6,                    /**< Device state is SUSPENDED.                        */
+  USBD_STATE_LASTMARKER = 7,                    /**< Device state enum end marker.                     */
+} USBD_State_TypeDef;
+/** @} (end addtogroup USB_DEVICE) */
+#endif /* defined( USB_DEVICE ) */
+
+/** @addtogroup USB_COMMON
+ *  @{*/
+
+/** @brief USB Setup request package. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  union
+  {
+    struct
+    {
+      union
+      {
+        struct
+        {
+          uint8_t Recipient : 5;                /**< Request recipient (device, interface, endpoint or other).*/
+          uint8_t Type      : 2;                /**< Request type (standard, class or vendor).         */
+          uint8_t Direction : 1;                /**< Transfer direction of SETUP data phase.           */
+        };
+        uint8_t bmRequestType;                  /**< Request characteristics.                          */
+      };
+      uint8_t   bRequest;                       /**< Request code.                                     */
+      uint16_t  wValue;                         /**< Varies according to request.                      */
+      uint16_t  wIndex;                         /**< Index or offset, varies according to request.     */
+      uint16_t  wLength;                        /**< Number of bytes to transfer if there is a data stage.*/
+    };
+  uint32_t  dw[2];
+  };
+} __attribute__ ((packed)) USB_Setup_TypeDef;
+EFM32_PACK_END()
+
+
+/** @brief USB Device Descriptor. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  uint8_t  bLength;                             /**< Size of this descriptor in bytes                  */
+  uint8_t  bDescriptorType;                     /**< Constant DEVICE Descriptor Type                   */
+  uint16_t bcdUSB;                              /**< USB Specification Release Number in Binary-Coded
+                                                     Decimal                                           */
+  uint8_t  bDeviceClass;                        /**< Class code (assigned by the USB-IF)               */
+  uint8_t  bDeviceSubClass;                     /**< Subclass code (assigned by the USB-IF)            */
+  uint8_t  bDeviceProtocol;                     /**< Protocol code (assigned by the USB-IF)            */
+  uint8_t  bMaxPacketSize0;                     /**< Maximum packet size for endpoint zero             */
+  uint16_t idVendor;                            /**< Vendor ID (assigned by the USB-IF)                */
+  uint16_t idProduct;                           /**< Product ID (assigned by the manufacturer)         */
+  uint16_t bcdDevice;                           /**< Device release number in binary-coded decimal     */
+  uint8_t  iManufacturer;                       /**< Index of string descriptor describing manufacturer*/
+  uint8_t  iProduct;                            /**< Index of string descriptor describing product     */
+  uint8_t  iSerialNumber;                       /**< Index of string descriptor describing the device
+                                                     serialnumber                                      */
+  uint8_t  bNumConfigurations;                  /**< Number of possible configurations                 */
+} __attribute__ ((packed)) USB_DeviceDescriptor_TypeDef;
+EFM32_PACK_END()
+
+
+/** @brief USB Configuration Descriptor. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  uint8_t  bLength;                             /**< Size of this descriptor in bytes                  */
+  uint8_t  bDescriptorType;                     /**< Constant CONFIGURATION Descriptor Type            */
+  uint16_t wTotalLength;                        /**< Total length of data returned for this
+                                                     configuration. Includes the combined length of all
+                                                     descriptors (configuration, interface, endpoint,
+                                                     and class- or vendor-specific) returned for this
+                                                     configuration.                                    */
+  uint8_t  bNumInterfaces;                      /**< Number of interfaces supported by this
+                                                     configuration                                     */
+  uint8_t  bConfigurationValue;                 /**< Value to use as an argument to the
+                                                     SetConfiguration request to select this
+                                                     configuration.                                    */
+  uint8_t  iConfiguration;                      /**< Index of string descriptor describing this
+                                                     configuration.                                    */
+  uint8_t  bmAttributes;                        /**< Configuration characteristics.
+                                                     @n D7: Reserved (set to one)
+                                                     @n D6: Self-powered
+                                                     @n D5: Remote Wakeup
+                                                     @n D4...0: Reserved (reset to zero)               */
+  uint8_t  bMaxPower;                           /**< Maximum power consumption of the USB device, unit
+                                                     is 2mA per LSB                                    */
+} __attribute__ ((packed)) USB_ConfigurationDescriptor_TypeDef;
+EFM32_PACK_END()
+
+
+/** @brief USB Interface Descriptor. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  uint8_t bLength;                              /**< Size of this descriptor in bytes.                 */
+  uint8_t bDescriptorType;                      /**< Constant INTERFACE Descriptor Type.               */
+  uint8_t bInterfaceNumber;                     /**< Number of this interface. Zero-based value
+                                                     identifying the index in the array of concurrent
+                                                     interfaces supported by this configuration.       */
+  uint8_t bAlternateSetting;                    /**< Value used to select this alternate setting for
+                                                     the interface identified in the prior field.      */
+  uint8_t bNumEndpoints;                        /**< Number of endpoints used by this interface
+                                                     (excluding endpoint zero). If this value is zero,
+                                                     this interface only uses the Default Control Pipe.*/
+  uint8_t bInterfaceClass;                      /**< Class code (assigned by the USB-IF). A value
+                                                     of zero is reserved for future standardization. If
+                                                     this field is set to FFH, the interface class is
+                                                     vendor-specific. All other values are reserved for
+                                                     assignment by the USB-IF.                         */
+  uint8_t bInterfaceSubClass;                   /**< Subclass code (assigned by the USB-IF). These codes
+                                                     are qualified by the value of the bInterfaceClass
+                                                     field. If the bInterfaceClass field is reset to
+                                                     zero, this field must also be reset to zero. If
+                                                     the bInterfaceClass field is not set to FFH, all
+                                                     values are reserved forassignment by the USB-IF.  */
+  uint8_t bInterfaceProtocol;                   /**< Protocol code (assigned by the USB). These codes
+                                                     are qualified by the value of the bInterfaceClass
+                                                     and the bInterfaceSubClass fields. If an interface
+                                                     supports class-specific requests, this code
+                                                     identifies the protocols that the device uses as
+                                                     defined by the specification of the device class.
+                                                     If this field is reset to zero, the device does
+                                                     not use a class-specific protocol on this
+                                                     interface. If this field is set to FFH, the device
+                                                     uses a vendor-specific protocol for this interface*/
+  uint8_t iInterface;                           /**< Index of string descriptor describing this
+                                                     interface.                                        */
+} __attribute__ ((packed)) USB_InterfaceDescriptor_TypeDef;
+EFM32_PACK_END()
+
+
+/** @brief USB Endpoint Descriptor. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  uint8_t   bLength;                            /**< Size of this descriptor in bytes                  */
+  uint8_t   bDescriptorType;                    /**< Constant ENDPOINT Descriptor Type                 */
+  uint8_t   bEndpointAddress;                   /**< The address of the endpoint                       */
+  uint8_t   bmAttributes;                       /**< This field describes the endpoint attributes      */
+  uint16_t  wMaxPacketSize;                     /**< Maximum packet size for the endpoint              */
+  uint8_t   bInterval;                          /**< Interval for polling EP for data transfers        */
+} __attribute__ ((packed)) USB_EndpointDescriptor_TypeDef;
+EFM32_PACK_END()
+
+
+/** @brief USB String Descriptor. */
+EFM32_PACK_START( 1 )
+typedef struct
+{
+  uint8_t len;                                  /**< Size of this descriptor in bytes.                 */
+  uint8_t type;                                 /**< Constant STRING Descriptor Type.                  */
+  char16_t name[];                              /**< The string encoded with UTF-16LE UNICODE charset. */
+} __attribute__ ((packed)) USB_StringDescriptor_TypeDef;
+EFM32_PACK_END()
+
+/** @} (end addtogroup USB_COMMON) */
+
+/*** -------------------- Serial port debug configuration ---------------- ***/
+
+#if defined( DOXY_DOC_ONLY )
+/** @addtogroup USB_COMMON
+ *  @{*/
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit a single char on the debug serial port.
+ *
+ * @note
+ *   This function is enabled with \#define DEBUG_USB_API when configuring the
+ *   protocol stack in "usbconfig.h".
+ *   This is convenient when debugging code, no need to remove use of this
+ *   function when debugging has completed.
+ *
+ * @param[in] c
+ *   Char to transmit.
+ *
+ * @return
+ *   The char transmitted.
+ ******************************************************************************/
+int  USB_PUTCHAR( char c );
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit a zero terminated string on the debug serial port.
+ *
+ * @note
+ *   This function is enabled with \#define DEBUG_USB_API when configuring the
+ *   protocol stack in "usbconfig.h".
+ *   This is convenient when debugging code, no need to remove use of this
+ *   function when debugging has completed.
+ *
+ * @param[in] p
+ *   Pointer to string to transmit.
+ ******************************************************************************/
+void USB_PUTS( const char *p );
+
+/***************************************************************************//**
+ * @brief
+ *   Transmit "printf" formated data on the debug serial port.
+ *
+ * @note
+ *   This function is enabled with \#define USB_USE_PRINTF when configuring the
+ *   protocol stack in "usbconfig.h".
+ *   This is convenient when debugging code, no need to remove use of this
+ *   function when debugging has completed.
+ *
+ * @param[in] format
+ *   Format string (as in printf). No floating point format support.
+ ******************************************************************************/
+int  USB_PRINTF( const char *format, ... );
+
+/** @} (end addtogroup USB_COMMON) */
+#endif /* defined( DOXY_DOC_ONLY ) */
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/* Hardware constraint, do not change. */
+#define MAX_NUM_HOSTCHANNELS  14
+
+/* The DMA engine use one FIFO ram word for each host channel. */
+#define MAX_HOST_FIFO_SIZE_INWORDS (512-MAX_NUM_HOSTCHANNELS)/*Unit is 4 bytes*/
+
+#if defined ( USER_PUTCHAR )
+  void USB_Puts( const char *p );
+  #define USB_PUTS( s )            USB_Puts( s )
+  #define USB_PUTCHAR( c )         USER_PUTCHAR( c )
+#else
+  #define USB_PUTS( s )
+  #define USB_PUTCHAR( c )
+#endif
+
+#if defined( USB_USE_PRINTF )
+  /* Use a printf which don't support floating point formatting */
+  #if defined(__ICCARM__) || defined (__CC_ARM) || defined (__CROSSWORKS_ARM)
+    #define USB_PRINTF                  printf
+  #else
+    #define USB_PRINTF                  iprintf
+  #endif
+#else
+  #define USB_PRINTF(...)
+#endif /* defined( USB_USE_PRINTF ) */
+
+#if defined( DEBUG_USB_API )
+  #define DEBUG_USB_API_PUTS( s )       USB_PUTS( s )
+  #define DEBUG_USB_API_PUTCHAR( c )    USB_PUTCHAR( c )
+#else
+  #define DEBUG_USB_API_PUTS( s )
+  #define DEBUG_USB_API_PUTCHAR( c )
+#endif /* defined( DEBUG_USB_API ) */
+
+/** @endcond */
+
+/*** -------------------- Common API definitions ------------------------- ***/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#if defined( USB_HOST )
+  #if defined( NUM_APP_TIMERS )
+    #define NUM_QTIMERS ( NUM_HC_USED + 2 + NUM_APP_TIMERS + 1 )
+  #else
+    #define NUM_QTIMERS ( NUM_HC_USED + 2 + 1 )
+  #endif
+  /* + 2 for default ctrl. host ch. 0 & 1, + 1 for host port timer  */
+#else
+  #if defined( NUM_APP_TIMERS )
+    #define NUM_QTIMERS ( NUM_APP_TIMERS )
+  #else
+    #define NUM_QTIMERS 0
+  #endif
+#endif /* defined( USB_HOST ) */
+/** @endcond */
+
+/** @addtogroup USB_COMMON
+ *  @{*/
+
+/***************************************************************************//**
+ * @brief
+ *  USB transfer callback function.
+ *
+ * @details
+ *  The callback function is called when a transfer has completed. An application
+ *  should check the status, xferred and optionally the remaining parameters
+ *  before deciding if the transfer is usable. In the case where the transfer
+ *  is part of a control request data stage, the callback function should
+ *  return an appropriate @ref USB_Status_TypeDef status.
+ *
+ * @param[in] status
+ *   The transfer status. See @ref USB_Status_TypeDef.
+ *
+ * @param[in] xferred
+ *   Number of bytes actually transferred.
+ *
+ * @param[in] remaining
+ *   Number of bytes not transferred.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+typedef int  (*USB_XferCompleteCb_TypeDef)( USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining );
+
+/***************************************************************************//**
+ * @brief
+ *  USBTIMER callback function.
+ *
+ * @details
+ *  The callback function is called when an USBTIMER has expired. The callback
+ *  is done with interrupts disabled.
+ ******************************************************************************/
+typedef void (*USBTIMER_Callback_TypeDef)(  void );
+
+char *USB_GetErrorMsgString(            int error );
+
+#if defined( USB_USE_PRINTF )
+  void USB_PrintErrorMsgString(         char *pre, int error );
+#else
+  #define USB_PrintErrorMsgString(      pre, error )
+#endif
+
+void  USBTIMER_DelayMs(                 uint32_t msec );
+void  USBTIMER_DelayUs(                 uint32_t usec );
+void  USBTIMER_Init(                    void );
+
+#if ( NUM_QTIMERS > 0 )
+  void  USBTIMER_Start(                 uint32_t id, uint32_t timeout, USBTIMER_Callback_TypeDef callback );
+  void  USBTIMER_Stop(                  uint32_t id );
+#endif /* ( NUM_QTIMERS > 0 ) */
+/** @} (end addtogroup USB_COMMON) */
+
+#if defined( USB_DEVICE )
+/** @addtogroup USB_DEVICE
+ *  @{*/
+/*** -------------------- DEVICE mode API definitions -------------------- ***/
+
+/***************************************************************************//**
+ * @brief
+ *  USB Reset callback function.
+ * @details
+ *  Called whenever USB reset signalling is detected on the USB port.
+ ******************************************************************************/
+typedef void (*USBD_UsbResetCb_TypeDef)( void );
+
+/***************************************************************************//**
+ * @brief
+ *  USB Start Of Frame (SOF) interrupt callback function.
+ *
+ * @details
+ *  Called at each SOF interrupt (if enabled),
+ *
+ * @param[in] sofNr
+ *   Current frame number. The value rolls over to 0 after 16383 (0x3FFF).
+ ******************************************************************************/
+typedef void (*USBD_SofIntCb_TypeDef)( uint16_t sofNr );
+
+/***************************************************************************//**
+ * @brief
+ *  USB State change callback function.
+ *
+ * @details
+ *  Called whenever the device change state.
+ *
+ * @param[in] oldState
+ *   The device USB state just leaved. See @ref USBD_State_TypeDef.
+ *
+ * @param[in] newState
+ *   New (the current) USB device state. See @ref USBD_State_TypeDef.
+ ******************************************************************************/
+typedef void (*USBD_DeviceStateChangeCb_TypeDef)( USBD_State_TypeDef oldState, USBD_State_TypeDef newState );
+
+/***************************************************************************//**
+ * @brief
+ *  USB power mode callback function.
+ *
+ * @details
+ *  Called whenever the device stack needs to query if the device is currently
+ *  self- or bus-powered. Typically when host has issued an @ref GET_STATUS
+ *  setup command.
+ *
+ * @return
+ *  True if self-powered, false otherwise.
+ ******************************************************************************/
+typedef bool (*USBD_IsSelfPoweredCb_TypeDef)( void );
+
+/***************************************************************************//**
+ * @brief
+ *  USB setup request callback function.
+ *
+ * @details
+ *  Called on each setup request received from host. This gives the application a
+ *  possibility to extend or override standard requests, and to implement class
+ *  or vendor specific requests. Return @ref USB_STATUS_OK if the request is
+ *  handled, return @ref USB_STATUS_REQ_ERR if it is an illegal request or
+ *  return @ref USB_STATUS_REQ_UNHANDLED to pass the request on to the default
+ *  request handler.
+ *
+ * @param[in] setup
+ *  Pointer to an USB setup packet. See @ref USB_Setup_TypeDef.
+ *
+ * @return
+ *  An appropriate status/error code. See @ref USB_Status_TypeDef.
+ ******************************************************************************/
+typedef int  (*USBD_SetupCmdCb_TypeDef)( const USB_Setup_TypeDef *setup );
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+struct USBD_Callbacks_TypeDef;
+typedef struct USBD_Callbacks_TypeDef const *USBD_Callbacks_TypeDef_Pointer;
+/** @endcond */
+
+
+/** @brief USB Device stack initialization structure.
+ *  @details This structure is passed to @ref USBD_Init() when starting up
+ *  the device.                                                             */
+typedef struct
+{
+  const USB_DeviceDescriptor_TypeDef      *deviceDescriptor;      /**< Pointer to a device descriptor.                */
+  const uint8_t                           *configDescriptor;      /**< Pointer to a configuration descriptor.         */
+  const void * const                      *stringDescriptors;     /**< Pointer to an array of string descriptor pointers.*/
+  const uint8_t                           numberOfStrings;        /**< Number of strings in string descriptor array.  */
+  const uint8_t                           *bufferingMultiplier;   /**< Pointer to an array defining the size of the
+                                                                       endpoint buffers. The size is given in
+                                                                       multiples of endpoint size. Generally a value
+                                                                       of 1 (single) or 2 (double) buffering should be
+                                                                       used.                                          */
+  USBD_Callbacks_TypeDef_Pointer          callbacks;              /**< Pointer to struct with callbacks
+                                                                       (@ref USBD_Callbacks_TypeDef). These callbacks
+                                                                       are used by the device stack to signal events
+                                                                       to or query the application.                   */
+  const uint32_t                          reserved;               /**< Reserved for future use.                       */
+} USBD_Init_TypeDef;
+
+
+/** @brief USB Device stack callback structure.
+ *  @details Callback functions used by the device stack to signal events or
+ *  query status to/from the application. See @ref USBD_Init_TypeDef. Assign
+ *  members to NULL if your application don't need a specific callback. */
+typedef struct USBD_Callbacks_TypeDef
+{
+  const USBD_UsbResetCb_TypeDef           usbReset;               /**< Called whenever USB reset signalling is detected
+                                                                       on the USB port.                                */
+  const USBD_DeviceStateChangeCb_TypeDef  usbStateChange;         /**< Called whenever the device change state.        */
+  const USBD_SetupCmdCb_TypeDef           setupCmd;               /**< Called on each setup request received from host.*/
+  const USBD_IsSelfPoweredCb_TypeDef      isSelfPowered;          /**< Called whenever the device stack needs to query
+                                                                       if the device is currently self- or bus-powered.
+                                                                       Applies to devices which can operate in both modes.*/
+  const USBD_SofIntCb_TypeDef             sofInt;                 /**< Called at each SOF interrupt. If NULL, the device
+                                                                       stack will not enable the SOF interrupt.        */
+} USBD_Callbacks_TypeDef;
+
+
+/*** -------------------- DEVICE mode API -------------------------------- ***/
+
+void                USBD_AbortAllTransfers( void );
+int                 USBD_AbortTransfer(     int epAddr );
+void                USBD_Connect(           void );
+void                USBD_Disconnect(        void );
+bool                USBD_EpIsBusy(          int epAddr );
+USBD_State_TypeDef  USBD_GetUsbState(       void );
+const char *        USBD_GetUsbStateName(   USBD_State_TypeDef state );
+int                 USBD_Init(              const USBD_Init_TypeDef *p );
+int                 USBD_Read(              int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback );
+int                 USBD_RemoteWakeup(      void );
+bool                USBD_SafeToEnterEM2(    void );
+int                 USBD_StallEp(           int epAddr );
+void                USBD_Stop(              void );
+int                 USBD_UnStallEp(         int epAddr );
+int                 USBD_Write(             int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback );
+
+#ifdef __MBED__
+int                 USBD_SetAddress(        uint8_t addr );
+int                 USBD_AddEndpoint(       int epAddr, int transferType, int maxPacketSize, int bufferMult );
+int                 USBD_EpIsStalled(       int epAddr );
+void                USBD_StallEp0(          void );
+#endif
+
+/** @} (end addtogroup USB_DEVICE) */
+#endif /* defined( USB_DEVICE ) */
+
+
+#if defined( USB_HOST )
+/***************************************************************************//**
+ * @addtogroup USB_HOST
+ * @brief USB HOST protocol stack, see @ref usb_host page for detailed documentation.
+ * @{
+ ******************************************************************************/
+/*** -------------------- HOST mode API definitions ---------------------- ***/
+
+#define USB_VBUSOVRCUR_PORT_NONE     -1       /**< No overcurrent flag functionality.                   */
+#define USB_VBUSOVRCUR_POLARITY_LOW  0        /**< Overcurrent flag pin polarity is low.                */
+#define USB_VBUSOVRCUR_POLARITY_HIGH 1        /**< Overcurrent flag pin polarity is high.               */
+
+/** USB HOST endpoint status enumerator. */
+typedef enum
+{
+  H_EP_IDLE             = 0,                      /**< The endpoint is idle.                            */
+  H_EP_SETUP            = 1,                      /**< The endpoint is in SETUP stage.                  */
+  H_EP_DATA_IN          = 2,                      /**< The endpoint is in DATA IN stage.                */
+  H_EP_DATA_OUT         = 3,                      /**< The endpoint is in DATA OUT stage.               */
+  H_EP_STATUS_IN        = 4,                      /**< The endpoint is in STATUS IN stage.              */
+  H_EP_STATUS_OUT       = 5,                      /**< The endpoint is in STATUS OUT stage.             */
+} USBH_EpState_TypeDef;
+
+
+/** @brief USB HOST endpoint status data.
+ *  @details A host application should not manipulate the contents of
+ * this struct.                                                             */
+typedef struct
+{
+  USB_Setup_TypeDef               setup;          /**< A SETUP package.                                 */
+  uint8_t                         setupErrCnt;    /**< Error counter for SETUP transfers.               */
+  USB_EndpointDescriptor_TypeDef  epDesc;         /**< Endpoint descriptor.                             */
+  struct USBH_Device_TypeDef      *parentDevice;  /**< The device the endpoint belongs to.              */
+  uint8_t                         type;           /**< Endpoint type.                                   */
+  uint16_t                        packetSize;     /**< Packet size, current transfer.                   */
+  uint8_t                         hcOut;          /**< Host channel number assigned for OUT transfers.  */
+  uint8_t                         hcIn;           /**< Host channel number assigned for IN transfers.   */
+  bool                            in;             /**< Endpoint direction.                              */
+  uint8_t                         toggle;         /**< Endpoint data toggle.                            */
+  USBH_EpState_TypeDef            state;          /**< Endpoint state.                                  */
+  uint8_t                         addr;           /**< Endpoint address.                                */
+  uint8_t                         *buf;           /**< Transfer buffer.                                 */
+  volatile bool                   xferCompleted;  /**< Transfer completion flag.                        */
+  USB_Status_TypeDef              xferStatus;     /**< Transfer status.                                 */
+  USB_XferCompleteCb_TypeDef      xferCompleteCb; /**< Transfer completion callback function.           */
+  uint32_t                        xferred;        /**< Number of bytes transferred.                     */
+  uint32_t                        remaining;      /**< Number of bytes remaining.                       */
+  uint32_t                        timeout;        /**< Transfer timeout.                                */
+} USBH_Ep_TypeDef;
+
+
+/** @brief USB HOST device definition.
+ *  @details A host application should not manipulate the contents of
+ *  this struct.                                                            */
+typedef struct USBH_Device_TypeDef
+{
+  USB_DeviceDescriptor_TypeDef          devDesc;  /**< The device device descriptor.                    */
+  USB_ConfigurationDescriptor_TypeDef   confDesc; /**< The device configuration descriptor.             */
+  USB_InterfaceDescriptor_TypeDef       itfDesc;  /**< The device interface descriptor.                 */
+  USBH_Ep_TypeDef                       ep0;      /**< Endpoint 0 status data.                          */
+  USBH_Ep_TypeDef                       *ep;      /**< Array of endpoint status data.                   */
+  int                                   numEp;    /**< Number of endpoints.                             */
+  uint8_t                               addr;     /**< The device address.                              */
+  uint8_t                               speed;    /**< The device speed (low or full speed).            */
+} USBH_Device_TypeDef;
+
+
+/** @brief USB Host stack initialization structure.
+ *  @details This structure is passed to @ref USBH_Init() when starting up the
+ *  device. Max accumulated FIFO size is 2K bytes.                          */
+typedef struct
+{
+  uint32_t                  rxFifoSize;     /**< Number of FIFO bytes set aside for IN endpoints.            */
+  uint32_t                  nptxFifoSize;   /**< Number of FIFO bytes set aside for OUT CTRL/BULK endoints.  */
+  uint32_t                  ptxFifoSize;    /**< Number of FIFO bytes set aside for OUT INTR/ISO endoints.   */
+  uint32_t                  reserved;       /**< Reserved for future use.                                    */
+} USBH_Init_TypeDef;
+
+
+/** Default @ref USBH_Init_TypeDef values, provides reasonable Tx/Rx FIFO
+ *  partitioning.                                                         */
+/* In DMA mode the total available FIFO space is smaller.       */
+/* The DMA controller use one FIFO word pr. channel for status. */
+/* The unit in the table is byte.                               */
+#define USBH_INIT_DEFAULT                                                    \
+{                                                                            \
+  MAX_HOST_FIFO_SIZE_INWORDS * 2,/* 1024 bytes Rx FIFO size.             */  \
+  MAX_HOST_FIFO_SIZE_INWORDS,    /* 512 bytes non-periodic Tx FIFO size. */  \
+  MAX_HOST_FIFO_SIZE_INWORDS,    /* 512 bytes periodic Tx FIFO size.     */  \
+  0                              /* Reserved.                            */  \
+}
+
+/*** -------------------- HOST mode API ---------------------------------- ***/
+
+int     USBH_AssignHostChannel(            USBH_Ep_TypeDef *ep, uint8_t hcnum );
+int     USBH_ControlMsg(                   USBH_Ep_TypeDef *ep, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, void *data, int timeout, USB_XferCompleteCb_TypeDef callback );
+int     USBH_ControlMsgB(                  USBH_Ep_TypeDef *ep, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, void *data, int timeout );
+bool    USBH_DeviceConnected(              void );
+int     USBH_GetConfigurationDescriptorB(  USBH_Device_TypeDef *device, void *buf, int len, uint8_t configIndex );
+int     USBH_GetDeviceDescriptorB(         USBH_Device_TypeDef *device, void *buf, int len );
+uint8_t USBH_GetPortSpeed(                 void );
+int     USBH_GetStringB(                   USBH_Device_TypeDef *device, uint8_t *buf, int bufLen, uint8_t stringIndex, uint16_t langID );
+int     USBH_Init(                         const USBH_Init_TypeDef *p );
+int     USBH_InitDeviceData(               USBH_Device_TypeDef *device, const uint8_t *buf, USBH_Ep_TypeDef *ep, int numEp, uint8_t deviceSpeed );
+int     USBH_PortReset(                    void );
+int     USBH_PortResume(                   void );
+void    USBH_PortSuspend(                  void );
+void    USBH_PrintString(                  const char *pre, const USB_StringDescriptor_TypeDef *s, const char *post );
+
+#if defined( USB_USE_PRINTF )
+int     USBH_PrintConfigurationDescriptor( const USB_ConfigurationDescriptor_TypeDef *config, int maxLen );
+int     USBH_PrintDeviceDescriptor(        const USB_DeviceDescriptor_TypeDef *device );
+int     USBH_PrintEndpointDescriptor(      const USB_EndpointDescriptor_TypeDef *endpoint );
+int     USBH_PrintInterfaceDescriptor(     const USB_InterfaceDescriptor_TypeDef *interface );
+#else
+#define USBH_PrintConfigurationDescriptor( config, maxLen )
+#define USBH_PrintDeviceDescriptor(        device )
+#define USBH_PrintEndpointDescriptor(      endpoint )
+#define USBH_PrintInterfaceDescriptor(     interface )
+#endif /* defined( USB_USE_PRINTF ) */
+
+int                                  USBH_QueryDeviceB(                uint8_t *buf, size_t bufsize, uint8_t deviceSpeed );
+USB_ConfigurationDescriptor_TypeDef* USBH_QGetConfigurationDescriptor( const uint8_t *buf, int configIndex );
+USB_DeviceDescriptor_TypeDef*        USBH_QGetDeviceDescriptor(        const uint8_t *buf );
+USB_EndpointDescriptor_TypeDef*      USBH_QGetEndpointDescriptor(      const uint8_t *buf, int configIndex, int interfaceIndex, int endpointIndex );
+USB_InterfaceDescriptor_TypeDef*     USBH_QGetInterfaceDescriptor(     const uint8_t *buf, int configIndex, int interfaceIndex );
+
+int     USBH_Read(                         USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout, USB_XferCompleteCb_TypeDef callback );
+int     USBH_ReadB(                        USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout );
+int     USBH_SetAddressB(                  USBH_Device_TypeDef *device, uint8_t deviceAddress );
+int     USBH_SetAltInterfaceB(             USBH_Device_TypeDef *device, uint8_t interfaceIndex, uint8_t alternateSetting );
+int     USBH_SetConfigurationB(            USBH_Device_TypeDef *device, uint8_t configValue );
+int     USBH_StallEpB(                     USBH_Ep_TypeDef *ep );
+void    USBH_Stop(                         void );
+int     USBH_UnStallEpB(                   USBH_Ep_TypeDef *ep );
+int     USBH_WaitForDeviceConnectionB(     uint8_t *buf, int timeoutInSeconds );
+int     USBH_Write(                        USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout, USB_XferCompleteCb_TypeDef callback );
+int     USBH_WriteB(                       USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout );
+
+/** @} (end addtogroup USB_HOST) */
+#endif /* defined( USB_HOST ) */
+/** @} (end addtogroup USB) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/em_usbd.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,206 @@
+/***************************************************************************//**
+ * @file em_usbd.h
+ * @brief USB protocol stack library API for EFM32.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __EM_USBD_H
+#define __EM_USBD_H
+
+#include "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#if defined( DEBUG_USB_API )
+#define DEBUG_TRACE_ABORT( x )                                  \
+{                                                               \
+  if ( x == USB_STATUS_EP_STALLED )                             \
+  {  DEBUG_USB_API_PUTS( "\nEP cb(), EP stalled" );           } \
+  else if ( x == USB_STATUS_EP_ABORTED )                        \
+  {  DEBUG_USB_API_PUTS( "\nEP cb(), EP aborted" );           } \
+  else if ( x == USB_STATUS_DEVICE_UNCONFIGURED )               \
+  {  DEBUG_USB_API_PUTS( "\nEP cb(), device unconfigured" );  } \
+  else if ( x == USB_STATUS_DEVICE_SUSPENDED )                  \
+  {  DEBUG_USB_API_PUTS( "\nEP cb(), device suspended" );     } \
+  else /* ( x == USB_STATUS_DEVICE_RESET ) */                   \
+  {  DEBUG_USB_API_PUTS( "\nEP cb(), device reset" );         } \
+}
+#else
+#define DEBUG_TRACE_ABORT( x )
+#endif
+
+extern USBD_Device_TypeDef *dev;
+extern volatile bool USBD_poweredDown;
+
+__STATIC_INLINE void USBD_ArmEp0( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE void USBD_ArmEpN( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE void USBD_AbortEp( USBD_Ep_TypeDef *ep );
+
+void USBD_SetUsbState( USBD_State_TypeDef newState );
+
+int  USBDCH9_SetupCmd( USBD_Device_TypeDef *device );
+
+void USBDEP_Ep0Handler( USBD_Device_TypeDef *device );
+void USBDEP_EpHandler( uint8_t epAddr );
+
+__STATIC_INLINE void USBD_ActivateAllEps( bool forceIdle )
+{
+  int i;
+
+  for ( i = 1; i <= NUM_EP_USED; i++ )
+  {
+    USBDHAL_ActivateEp( &dev->ep[ i ], forceIdle );
+  }
+}
+
+__STATIC_INLINE void USBD_ArmEp( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->num == 0 )
+  {
+    USBD_ArmEp0( ep );
+  }
+  else
+  {
+    USBD_ArmEpN( ep );
+  }
+}
+
+__STATIC_INLINE void USBD_ArmEp0( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->in )
+  {
+    if ( ep->remaining == 0 )       /* Zero Length Packet? */
+    {
+      ep->zlp = 1;
+    }
+
+    USBDHAL_SetEp0InDmaPtr( ep->buf );
+    USBDHAL_StartEp0In( EFM32_MIN( ep->remaining, ep->packetSize ),
+                        dev->ep0MpsCode );
+  }
+  else
+  {
+    USBDHAL_SetEp0OutDmaPtr( ep->buf );
+    USBDHAL_StartEp0Out( ep->packetSize, dev->ep0MpsCode );
+  }
+}
+
+__STATIC_INLINE void USBD_ArmEpN( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->in )
+  {
+    USBDHAL_StartEpIn( ep );
+  }
+  else
+  {
+    USBDHAL_StartEpOut( ep );
+  }
+}
+
+__STATIC_INLINE void USBD_DeactivateAllEps( USB_Status_TypeDef reason )
+{
+  int i;
+  USBD_Ep_TypeDef *ep;
+
+  for ( i = 1; i <= NUM_EP_USED; i++ )
+  {
+    ep = &dev->ep[ i ];
+
+    if ( ep->state == D_EP_IDLE )
+    {
+      USBDHAL_DeactivateEp( ep );
+    }
+  }
+
+  USBDHAL_AbortAllTransfers( reason );
+}
+
+__STATIC_INLINE USBD_Ep_TypeDef *USBD_GetEpFromAddr( uint8_t epAddr )
+{
+  int epIndex;
+  USBD_Ep_TypeDef *ep = NULL;
+
+  if ( epAddr & USB_SETUP_DIR_MASK )
+  {
+    epIndex = dev->inEpAddr2EpIndex[ epAddr & USB_EPNUM_MASK ];
+  }
+  else
+  {
+    epIndex = dev->outEpAddr2EpIndex[ epAddr & USB_EPNUM_MASK ];
+  }
+
+  if ( epIndex )
+  {
+    ep = &dev->ep[ epIndex ];
+  }
+  else if ( ( epAddr & USB_EPNUM_MASK ) == 0 )
+  {
+    ep = &dev->ep[ 0 ];
+  }
+
+  return ep;
+}
+
+__STATIC_INLINE void USBD_ReArmEp0( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->in )
+  {
+    USBDHAL_StartEp0In( EFM32_MIN( ep->remaining, ep->packetSize ),
+                        dev->ep0MpsCode );
+  }
+  else
+  {
+    USBDHAL_StartEp0Out( ep->packetSize, dev->ep0MpsCode );
+  }
+}
+
+__STATIC_INLINE void USBD_AbortEp( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->state == D_EP_IDLE )
+  {
+    return;
+  }
+
+  if ( ep->in )
+  {
+    USBDHAL_AbortEpIn( ep );
+  }
+  else
+  {
+    USBDHAL_AbortEpOut( ep );
+  }
+}
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_DEVICE ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USBD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/em_usbh.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,75 @@
+/***************************************************************************//**
+ * @file em_usbh.h
+ * @brief USB protocol stack library API for EFM32.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __EM_USBH_H
+#define __EM_USBH_H
+
+#include "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_HOST )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+extern USBH_Hc_TypeDef                  hcs[];
+extern int                              USBH_attachRetryCount;
+extern const USBH_AttachTiming_TypeDef  USBH_attachTiming[];
+extern USBH_Init_TypeDef                USBH_initData;
+extern volatile USBH_PortState_TypeDef  USBH_portStatus;
+
+USB_Status_TypeDef USBH_CtlSendSetup(   USBH_Ep_TypeDef *ep );
+USB_Status_TypeDef USBH_CtlSendData(    USBH_Ep_TypeDef *ep, uint16_t length );
+USB_Status_TypeDef USBH_CtlReceiveData( USBH_Ep_TypeDef *ep, uint16_t length );
+
+#if defined( USB_RAW_API )
+int USBH_CtlRxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount );
+int USBH_CtlTxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount );
+#endif
+
+void USBHEP_EpHandler(     USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
+void USBHEP_CtrlEpHandler( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
+void USBHEP_TransferDone(  USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
+
+__STATIC_INLINE uint16_t USBH_GetFrameNum( void )
+{
+  return USBHHAL_GetFrameNum();
+}
+
+__STATIC_INLINE bool USBH_FrameNumIsEven( void )
+{
+  return ( USBHHAL_GetFrameNum() & 1 ) == 0;
+}
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USBH_H      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/em_usbhal.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,757 @@
+/***************************************************************************//**
+ * @file em_usbhal.h
+ * @brief USB protocol stack library, low level USB peripheral access.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __EM_USBHAL_H
+#define __EM_USBHAL_H
+
+#include "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#define USB_PID_DATA0         0
+#define USB_PID_DATA2         1
+#define USB_PID_DATA1         2
+#define USB_PID_SETUP         3
+
+#define HPRT_F_SPEED          ( 1 << _USB_HPRT_PRTSPD_SHIFT )
+#define HPRT_L_SPEED          ( 2 << _USB_HPRT_PRTSPD_SHIFT )
+#define HCFG_PHYCLK_48MHZ     1
+#define HCFG_PHYCLK_6MHZ      2
+
+#define DOEP0_XFERSIZE_PKTCNT_MASK ( _USB_DOEP0TSIZ_XFERSIZE_MASK | \
+                                     _USB_DOEP0TSIZ_PKTCNT_MASK   )
+#define DOEP_XFERSIZE_PKTCNT_MASK  ( _USB_DOEP_TSIZ_XFERSIZE_MASK | \
+                                     _USB_DOEP_TSIZ_PKTCNT_MASK   )
+
+#define DIEP0_XFERSIZE_PKTCNT_MASK ( _USB_DIEP0TSIZ_XFERSIZE_MASK | \
+                                     _USB_DIEP0TSIZ_PKTCNT_MASK   )
+#define DIEP_XFERSIZE_PKTCNT_MASK  ( _USB_DIEP_TSIZ_XFERSIZE_MASK | \
+                                     _USB_DIEP_TSIZ_PKTCNT_MASK   | \
+                                     _USB_DIEP_TSIZ_MC_MASK       )
+
+#define DIEPCTL_EPTYPE_CONTROL (0 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_ISOC    (1 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_BULK    (2 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+#define DIEPCTL_EPTYPE_INTR    (3 << _USB_DIEP_CTL_EPTYPE_SHIFT )
+
+#define DOEPCTL_EPTYPE_CONTROL (0 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_ISOC    (1 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_BULK    (2 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+#define DOEPCTL_EPTYPE_INTR    (3 << _USB_DOEP_CTL_EPTYPE_SHIFT )
+
+#define HCCHAR_EPTYPE_CTRL     (0 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_ISOC     (1 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_BULK     (2 << _USB_HC_CHAR_EPTYPE_SHIFT )
+#define HCCHAR_EPTYPE_INTR     (3 << _USB_HC_CHAR_EPTYPE_SHIFT )
+
+#define GRXSTSP_PKTSTS_DEVICE_GOTNAK          ( 1 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_DATAOUTRECEIVED ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_DATAOUTCOMPLETE ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_SETUPCOMPLETE   ( 4 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_DEVICE_SETUPRECEIVED   ( 6 << _USB_GRXSTSP_PKTSTS_SHIFT )
+
+#define GRXSTSP_PKTSTS_HOST_DATAINRECEIVED  ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_DATAINCOMPLETE  ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_DATATOGGLEERROR ( 5 << _USB_GRXSTSP_PKTSTS_SHIFT )
+#define GRXSTSP_PKTSTS_HOST_CHANNELHALTED   ( 7 << _USB_GRXSTSP_PKTSTS_SHIFT )
+
+#define DCTL_WO_BITMASK \
+          ( _USB_DCTL_CGOUTNAK_MASK  | _USB_DCTL_SGOUTNAK_MASK   | \
+            _USB_DCTL_CGNPINNAK_MASK | _USB_DCTL_SGNPINNAK_MASK  )
+#define GUSBCFG_WO_BITMASK ( USB_GUSBCFG_CORRUPTTXPKT )
+#define DEPCTL_WO_BITMASK \
+          ( USB_DIEP_CTL_CNAK       | USB_DIEP_CTL_SNAK        | \
+            USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF  )
+
+#define HPRT_WC_MASK ( USB_HPRT_PRTCONNDET | USB_HPRT_PRTENA | \
+                       USB_HPRT_PRTENCHNG  | USB_HPRT_PRTOVRCURRCHNG )
+
+typedef __IO uint32_t USB_FIFO_TypeDef[ 0x1000 / sizeof( uint32_t ) ];
+typedef __IO uint32_t USB_DIEPTXF_TypeDef;
+
+#define USB_DINEPS       ((USB_DIEP_TypeDef    *) &USB->DIEP0CTL )
+#define USB_DOUTEPS      ((USB_DOEP_TypeDef    *) &USB->DOEP0CTL )
+#define USB_FIFOS        ((USB_FIFO_TypeDef    *) &USB->FIFO0D   )
+#define USB_DIEPTXFS     ((USB_DIEPTXF_TypeDef *) &USB->DIEPTXF1 )
+
+void USBHAL_CoreReset( void );
+
+#if defined( USB_DEVICE )
+void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason );
+USB_Status_TypeDef USBDHAL_CoreInit( const uint32_t totalRxFifoSize,
+                                     const uint32_t totalTxFifoSize );
+void USBDHAL_Connect( void );
+void USBDHAL_Disconnect( void );
+void USBDHAL_AbortAllEps( void );
+void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep );
+void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep );
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
+                                   USBD_Ep_TypeDef *ep, uint16_t *halt );
+__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep );
+__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep );
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+USB_Status_TypeDef USBHHAL_CoreInit( const uint32_t rxFifoSize,
+                                     const uint32_t nptxFifoSize,
+                                     const uint32_t ptxFifoSize );
+void USBHHAL_HCHalt(  int hcnum, uint32_t hcchar );
+void USBHHAL_HCInit(  int hcnum );
+void USBHHAL_HCStart( int hcnum );
+#endif /* defined( USB_HOST ) */
+
+__STATIC_INLINE void USBHAL_DisableGlobalInt( void )
+{
+  USB->GAHBCFG &= ~USB_GAHBCFG_GLBLINTRMSK;
+}
+
+__STATIC_INLINE void USBHAL_DisablePhyPins( void )
+{
+  USB->ROUTE = _USB_ROUTE_RESETVALUE;
+}
+
+__STATIC_INLINE void USBHAL_DisableUsbInt( void )
+{
+  USB->IEN = _USB_IEN_RESETVALUE;
+}
+
+__STATIC_INLINE void USBHAL_EnableGlobalInt( void )
+{
+  USB->GAHBCFG |= USB_GAHBCFG_GLBLINTRMSK;
+}
+
+__STATIC_INLINE void USBHAL_FlushRxFifo( void )
+{
+  USB->GRSTCTL = USB_GRSTCTL_RXFFLSH;
+  while ( USB->GRSTCTL & USB_GRSTCTL_RXFFLSH ) {}
+}
+
+__STATIC_INLINE void USBHAL_FlushTxFifo( uint8_t fifoNum )
+{
+  USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | ( fifoNum << _USB_GRSTCTL_TXFNUM_SHIFT );
+  while ( USB->GRSTCTL & USB_GRSTCTL_TXFFLSH ) {}
+}
+
+__STATIC_INLINE uint32_t USBHAL_GetCoreInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->GINTSTS;
+  retVal &= USB->GINTMSK;
+
+  return retVal;
+}
+
+__STATIC_INLINE bool USBHAL_VbusIsOn( void )
+{
+  return ( USB->STATUS & USB_STATUS_VREGOS ) != 0;
+}
+
+#if defined( USB_DEVICE )
+__STATIC_INLINE void USBDHAL_ActivateEp( USBD_Ep_TypeDef *ep, bool forceIdle )
+{
+#define DIEP_MPS_EPTYPE_TXFNUM_MASK ( _USB_DIEP_CTL_MPS_MASK    | \
+                                      _USB_DIEP_CTL_EPTYPE_MASK | \
+                                      _USB_DIEP_CTL_TXFNUM_MASK )
+#define DOEP_MPS_EPTYPE_MASK        ( _USB_DOEP_CTL_MPS_MASK    | \
+                                      _USB_DOEP_CTL_EPTYPE_MASK )
+  uint32_t daintmask, depctl;
+
+  if ( forceIdle )
+    ep->state = D_EP_IDLE;
+
+  if ( ep->in )
+  {
+    daintmask = ep->mask;
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+
+    if ( !( depctl & USB_DIEP_CTL_USBACTEP ) )
+    {
+      depctl = ( depctl                                     &
+                 ~( DIEP_MPS_EPTYPE_TXFNUM_MASK          |
+                    USB_DIEP_CTL_STALL                     )  ) |
+               ( ep->packetSize << _USB_DIEP_CTL_MPS_SHIFT    ) |
+               ( ep->type       << _USB_DIEP_CTL_EPTYPE_SHIFT ) |
+               ( ep->txFifoNum  << _USB_DIEP_CTL_TXFNUM_SHIFT ) |
+               USB_DIEP_CTL_SETD0PIDEF                          |
+               USB_DIEP_CTL_USBACTEP                            |
+               USB_DIEP_CTL_SNAK;
+    }
+    else
+    {
+      depctl |= USB_DIEP_CTL_SETD0PIDEF;
+    }
+    USB_DINEPS[ ep->num ].CTL = depctl;
+  }
+  else
+  {
+    daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+
+    if ( !( depctl & USB_DOEP_CTL_USBACTEP ) )
+    {
+      depctl = ( depctl                                     &
+                 ~( DOEP_MPS_EPTYPE_MASK                 |
+                    USB_DOEP_CTL_STALL                     )  ) |
+               ( ep->packetSize << _USB_DOEP_CTL_MPS_SHIFT    ) |
+               ( ep->type       << _USB_DOEP_CTL_EPTYPE_SHIFT ) |
+               USB_DOEP_CTL_SETD0PIDEF                          |
+               USB_DOEP_CTL_USBACTEP                            |
+               USB_DOEP_CTL_SNAK;
+    }
+    else
+    {
+      depctl |= USB_DOEP_CTL_SETD0PIDEF;
+    }
+    USB_DOUTEPS[ ep->num ].CTL = depctl;
+  }
+
+  /* Enable interrupt for this EP */
+  USB->DAINTMSK |= daintmask;
+
+#undef DIEP_MPS_EPTYPE_TXFNUM_MASK
+#undef DOEP_MPS_EPTYPE_MASK
+}
+
+__STATIC_INLINE void USBDHAL_ClearRemoteWakeup( void )
+{
+  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
+}
+
+__STATIC_INLINE void USBDHAL_DeactivateEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t daintmask;
+
+  if ( ep->in )
+  {
+    USB_DINEPS[ ep->num ].CTL = 0;
+    daintmask = ep->mask;
+  }
+  else
+  {
+    USB_DOUTEPS[ ep->num ].CTL = 0;
+    daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
+  }
+
+  /* Disable interrupt for this EP */
+  USB->DAINTMSK &= ~daintmask;
+}
+
+__STATIC_INLINE void USBDHAL_EnableInts( USBD_Device_TypeDef *dev )
+{
+  uint32_t mask;
+
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  /* Clear pending interrupts */
+  USB->GINTSTS = 0xFFFFFFFF;
+
+  mask = USB_GINTMSK_USBSUSPMSK     |
+         USB_GINTMSK_USBRSTMSK      |
+         USB_GINTMSK_ENUMDONEMSK    |
+         USB_GINTMSK_IEPINTMSK      |
+         USB_GINTMSK_OEPINTMSK      |
+         USB_GINTMSK_WKUPINTMSK;
+
+  if ( dev->callbacks->sofInt )
+  {
+    mask |= USB_GINTMSK_SOFMSK;
+  }
+
+  USB->GINTMSK = mask;
+}
+
+__STATIC_INLINE void USBDHAL_EnableUsbResetAndSuspendInt( void )
+{
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  USB->GINTMSK = USB_GINTMSK_USBRSTMSK | USB_GINTMSK_USBSUSPMSK;
+}
+
+__STATIC_INLINE void USBDHAL_Ep0Activate( uint32_t ep0mps )
+{
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGNPINNAK;
+
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE bool USBDHAL_EpIsStalled( USBD_Ep_TypeDef *ep )
+{
+  bool retVal = false;
+  uint16_t stallStatus;
+
+  if ( USBDHAL_GetStallStatusEp( ep, &stallStatus ) == USB_STATUS_OK )
+  {
+    retVal = stallStatus & 1 ? true : false;
+  }
+  return retVal;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetAllInEpInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->DAINT;
+  retVal &= USB->DAINTMSK;
+  return retVal & 0xFFFF;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetAllOutEpInts( void )
+{
+  uint32_t retVal;
+
+  retVal  = USB->DAINT;
+  retVal &= USB->DAINTMSK;
+  return retVal >> 16;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep )
+{
+  uint32_t retVal, msk;
+
+  msk    = USB->DIEPMSK;
+  retVal = USB_DINEPS[ ep->num ].INT;
+
+  return retVal & msk;
+}
+
+__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep )
+{
+  uint32_t retVal;
+
+  retVal  = USB_DOUTEPS[ ep->num ].INT;
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  retVal &= USB->DOEPMSK | USB_DOEP0INT_STUPPKTRCVD;
+#else
+  retVal &= USB->DOEPMSK;
+#endif
+
+  return retVal;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
+                                   USBD_Ep_TypeDef *ep, uint16_t *halt )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      *halt = depctl & USB_DIEP_CTL_STALL ? 1 : 0;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DOEPCTL_EPTYPE_INTR ) || ( eptype == DOEPCTL_EPTYPE_BULK ))
+    {
+      *halt = depctl & USB_DOEP_CTL_STALL ? 1 : 0;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+
+__STATIC_INLINE void USBDHAL_ReenableEp0Setup( USBD_Device_TypeDef *dev )
+
+{
+  USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+}
+
+__STATIC_INLINE void USBDHAL_SetAddr( uint8_t addr )
+{
+  USB->DCFG = ( USB->DCFG                    &
+                ~_USB_DCFG_DEVADDR_MASK        ) |
+              (addr << _USB_DCFG_DEVADDR_SHIFT );
+}
+
+__STATIC_INLINE void USBDHAL_SetEp0InDmaPtr( uint8_t* addr )
+{
+  USB->DIEP0DMAADDR = (uint32_t)addr;
+}
+
+__STATIC_INLINE void USBDHAL_SetEp0OutDmaPtr( uint8_t* addr )
+{
+  USB->DOEP0DMAADDR = (uint32_t)addr;
+}
+
+__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->in )
+  {
+    USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL   &
+                                  ~DEPCTL_WO_BITMASK            ) |
+                                USB_DIEP_CTL_SNAK                 |
+                                USB_DIEP_CTL_EPDIS;
+  }
+  else
+  {
+    USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL   &
+                                   ~DEPCTL_WO_BITMASK             ) |
+                                 USB_DOEP_CTL_EPENA;
+
+    USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL   &
+                                   ~DEPCTL_WO_BITMASK             ) |
+                                 USB_DOEP_CTL_SNAK                  |
+                                 USB_DOEP_CTL_EPDIS;
+  }
+}
+
+__STATIC_INLINE void USBDHAL_SetRemoteWakeup( void )
+{
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_RMTWKUPSIG;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_StallEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if ( eptype != DIEPCTL_EPTYPE_ISOC )
+    {
+      if ( depctl & USB_DIEP_CTL_EPENA )
+      {
+        depctl |= USB_DIEP_CTL_EPDIS;
+      }
+      USB_DINEPS[ ep->num ].CTL = depctl | USB_DIEP_CTL_STALL;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if ( eptype != DIEPCTL_EPTYPE_ISOC )
+    {
+      USB_DOUTEPS[ ep->num ].CTL = depctl | USB_DOEP_CTL_STALL;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0In( uint32_t len, uint32_t ep0mps )
+{
+  USB->DIEP0TSIZ = ( len << _USB_DIEP0TSIZ_XFERSIZE_SHIFT   ) |
+                   ( 1   << _USB_DIEP0TSIZ_PKTCNT_SHIFT     );
+
+  USB->DIEP0CTL = ( USB->DIEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DIEP0CTL_CNAK | USB_DIEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0Out( uint32_t len, uint32_t ep0mps )
+{
+  USB->DOEP0TSIZ = ( len << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
+                   ( 1   << _USB_DOEP0TSIZ_PKTCNT_SHIFT   );
+
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | ep0mps;
+}
+
+__STATIC_INLINE void USBDHAL_StartEp0Setup( USBD_Device_TypeDef *dev )
+{
+  dev->ep[ 0 ].in = false;
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  USB->DOEP0TSIZ = ( 8*3 << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
+                   ( 1   << _USB_DOEP0TSIZ_PKTCNT_SHIFT   ) |
+                   ( 3   << _USB_DOEP0TSIZ_SUPCNT_SHIFT   );
+#else
+  USB->DOEP0TSIZ = 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+#endif
+
+  dev->setup = dev->setupPkt;
+  USB->DOEP0DMAADDR = (uint32_t)dev->setup;
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+#else
+  USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
+                  | USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
+                  | dev->ep0MpsCode;
+#endif
+}
+
+__STATIC_INLINE void USBDHAL_StartEpIn( USBD_Ep_TypeDef *ep )
+{
+  uint32_t pktcnt, xfersize;
+
+  if ( ep->remaining == 0 )     /* ZLP ? */
+  {
+    pktcnt = 1;
+    xfersize = 0;
+  }
+  else
+  {
+    pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
+    xfersize = ep->remaining;
+  }
+
+  USB_DINEPS[ ep->num ].TSIZ =
+                ( USB_DINEPS[ ep->num ].TSIZ                &
+                  ~DIEP_XFERSIZE_PKTCNT_MASK                  ) |
+                ( xfersize << _USB_DIEP_TSIZ_XFERSIZE_SHIFT   ) |
+                ( pktcnt   << _USB_DIEP_TSIZ_PKTCNT_SHIFT     );
+
+  USB_DINEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
+  USB_DINEPS[ ep->num ].CTL =
+                  ( USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK ) |
+                  USB_DIEP_CTL_CNAK                                  |
+                  USB_DIEP_CTL_EPENA;
+}
+
+__STATIC_INLINE void USBDHAL_StartEpOut( USBD_Ep_TypeDef *ep )
+{
+  uint32_t pktcnt, xfersize;
+
+  if ( ep->remaining == 0 )     /* ZLP ? */
+  {
+    pktcnt = 1;
+    xfersize = ep->packetSize;
+  }
+  else
+  {
+    pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
+    xfersize = pktcnt * ep->packetSize;
+  }
+
+  USB_DOUTEPS[ ep->num ].TSIZ =
+                  ( USB_DOUTEPS[ ep->num ].TSIZ               &
+                    ~DOEP_XFERSIZE_PKTCNT_MASK                  ) |
+                  ( xfersize << _USB_DOEP_TSIZ_XFERSIZE_SHIFT   ) |
+                  ( pktcnt   << _USB_DOEP_TSIZ_PKTCNT_SHIFT     );
+
+  ep->hwXferSize = xfersize;
+  USB_DOUTEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
+  USB_DOUTEPS[ ep->num ].CTL =
+                          ( USB_DOUTEPS[ ep->num ].CTL  &
+                            ~DEPCTL_WO_BITMASK             ) |
+                          USB_DOEP_CTL_CNAK                  |
+                          USB_DOEP_CTL_EPENA;
+}
+
+__STATIC_INLINE USB_Status_TypeDef USBDHAL_UnStallEp( USBD_Ep_TypeDef *ep )
+{
+  uint32_t depctl, eptype;
+  USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
+
+  if ( ep->in == true )
+  {
+    depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      depctl |=  USB_DIEP_CTL_SETD0PIDEF;
+      depctl &= ~USB_DIEP_CTL_STALL;
+      USB_DINEPS[ ep->num ].CTL = depctl;
+      retVal = USB_STATUS_OK;
+    }
+  }
+  else
+  {
+    depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
+    eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
+
+    if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
+    {
+      depctl |=  USB_DOEP_CTL_SETD0PIDEF;
+      depctl &= ~USB_DOEP_CTL_STALL;
+      USB_DOUTEPS[ ep->num ].CTL = depctl;
+      retVal = USB_STATUS_OK;
+    }
+  }
+
+  return retVal;
+}
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+__STATIC_INLINE void USBHHAL_HCActivate( int hcnum, uint32_t hcchar, bool intep )
+{
+  uint32_t oddframe;
+
+  if ( intep )
+  {
+    oddframe = USB->HFNUM & 1;
+
+    USB->HC[ hcnum ].CHAR =
+                    ( hcchar &
+                      ~( USB_HC_CHAR_CHDIS | _USB_HC_CHAR_ODDFRM_MASK ) ) |
+
+                    /* Schedule INT transfers to start in next frame. */
+                    ( oddframe & 1 ? 0 : USB_HC_CHAR_ODDFRM             ) |
+
+                    USB_HC_CHAR_CHENA;
+  }
+  else
+  {
+    USB->HC[ hcnum ].CHAR = ( hcchar & ~USB_HC_CHAR_CHDIS ) |
+                              USB_HC_CHAR_CHENA;
+  }
+}
+
+__STATIC_INLINE bool USBHHAL_InitializedAndPowered( void )
+{
+  if ( ( USB->ROUTE & USB_ROUTE_PHYPEN ) &&
+       ( USB->HPRT  & USB_HPRT_PRTPWR  )    )
+    return true;
+  return false;
+}
+
+__STATIC_INLINE void USBHHAL_EnableInts( void )
+{
+  /* Disable all interrupts. */
+  USB->GINTMSK = 0;
+
+  /* Clear pending OTG interrupts */
+  USB->GOTGINT = 0xFFFFFFFF;
+
+  /* Clear pending interrupts */
+  USB->GINTSTS = 0xFFFFFFFF;
+
+  USB->GINTMSK = USB_GINTMSK_PRTINTMSK     |
+                 USB_GINTMSK_HCHINTMSK     |
+                 USB_GINTMSK_DISCONNINTMSK;
+}
+
+__STATIC_INLINE uint16_t USBHHAL_GetFrameNum( void )
+{
+  return USB->HFNUM;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHcChar( uint8_t hcnum )
+{
+  return USB->HC[ hcnum ].CHAR;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHcInts( uint8_t hcnum )
+{
+  uint32_t retVal;
+
+  retVal  = USB->HC[ hcnum ].INT;
+  return retVal;
+}
+
+__STATIC_INLINE uint32_t USBHHAL_GetHostChannelInts( void )
+{
+  return USB->HAINT;
+}
+
+__STATIC_INLINE uint8_t USBHHAL_GetPortSpeed( void )
+{
+  return ( USB->HPRT & _USB_HPRT_PRTSPD_MASK ) >> _USB_HPRT_PRTSPD_SHIFT;
+}
+
+__STATIC_INLINE void USBHHAL_PortReset( bool on )
+{
+  if ( on )
+  {
+    DEBUG_USB_INT_LO_PUTCHAR( '+' );
+    USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTRST;
+  }
+  else
+  {
+    DEBUG_USB_INT_LO_PUTCHAR( '-' );
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTRST );
+  }
+}
+
+__STATIC_INLINE void USBHHAL_PortResume( bool on )
+{
+  if ( on )
+  {
+    USB->HPRT = ( USB->HPRT & ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP ) ) |
+                USB_HPRT_PRTRES;
+  }
+  else
+  {
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP | USB_HPRT_PRTRES );
+  }
+}
+
+__STATIC_INLINE void USBHHAL_PortSuspend( void )
+{
+  USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTSUSP;
+}
+
+__STATIC_INLINE void USBHHAL_VbusOn( bool on )
+{
+  if ( on )
+  {
+    USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTPWR;
+    DEBUG_USB_INT_LO_PUTCHAR( '/' );
+  }
+  else
+  {
+    USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTPWR );
+    DEBUG_USB_INT_LO_PUTCHAR( '\\' );
+  }
+}
+#endif /* defined( USB_HOST ) */
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USBHAL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/em_usbtypes.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,230 @@
+/***************************************************************************//**
+ * @file em_usbtypes.h
+ * @brief USB protocol stack library, internal type definitions.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __EM_USBTYPES_H
+#define __EM_USBTYPES_H
+
+#include "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/* Limits imposed by the USB peripheral */
+#define NP_RX_QUE_DEPTH       8
+#define HP_RX_QUE_DEPTH       8
+#define MAX_XFER_LEN          524287L         /* 2^19 - 1 bytes             */
+#define MAX_PACKETS_PR_XFER   1023            /* 2^10 - 1 packets           */
+#if defined( _USB_DIEPTXF6_MASK )
+  #define MAX_NUM_TX_FIFOS      6             /* In addition to EP0 Tx FIFO */
+  #define MAX_NUM_IN_EPS        6             /* In addition to EP0         */
+  #define MAX_NUM_OUT_EPS       6             /* In addition to EP0         */
+  #define MAX_DEVICE_FIFO_SIZE_INWORDS 512U
+#else
+  #define MAX_NUM_TX_FIFOS      3             /* In addition to EP0 Tx FIFO */
+  #define MAX_NUM_IN_EPS        3             /* In addition to EP0         */
+  #define MAX_NUM_OUT_EPS       3             /* In addition to EP0         */
+  #define MAX_DEVICE_FIFO_SIZE_INWORDS 384U
+#endif
+#define MIN_EP_FIFO_SIZE_INWORDS  16U         /* Unit is words (32bit)      */
+#define MIN_EP_FIFO_SIZE_INBYTES  64U         /* Unit is bytes (8bit)       */
+
+/* For MCU's without USB host capability. */
+#if !defined( USB_ROUTE_VBUSENPEN )
+#define USB_VBUS_SWITCH_NOT_PRESENT
+#endif
+
+/* Limit imposed by the USB standard */
+#define MAX_USB_EP_NUM      15
+
+#if defined( USB_DEVICE )
+  /* Check power saving modes. */
+  #ifndef USB_PWRSAVE_MODE
+    /* Default powersave-mode is OFF. */
+    #define USB_PWRSAVE_MODE  USB_PWRSAVE_MODE_OFF
+  #else
+    #if ( USB_PWRSAVE_MODE                                               &  \
+          ~( USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF |      \
+             USB_PWRSAVE_MODE_ENTEREM2                                 )    )
+      #error "Illegal USB powersave mode."
+    #endif
+  #endif /* ifndef USB_PWRSAVE_MODE */
+
+  /* Check power saving low frequency clock selection. */
+  #ifndef USB_USBC_32kHz_CLK
+    /* Default clock source is LFXO. */
+    #define USB_USBC_32kHz_CLK USB_USBC_32kHz_CLK_LFXO
+  #else
+    #if ( ( USB_USBC_32kHz_CLK != USB_USBC_32kHz_CLK_LFXO  ) &&  \
+          ( USB_USBC_32kHz_CLK != USB_USBC_32kHz_CLK_LFRCO )     )
+      #error "Illegal USB 32kHz powersave clock selection."
+    #endif
+  #endif /* ifndef USB_USBC_32kHz_CLK */
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+  /* Check VBUS overcurrent definitions. */
+  #ifndef USB_VBUSOVRCUR_PORT
+    #define USB_VBUSOVRCUR_PORT       gpioPortE
+    #define USB_VBUSOVRCUR_PIN        2
+    #define USB_VBUSOVRCUR_POLARITY   USB_VBUSOVRCUR_POLARITY_LOW
+  #endif
+#endif
+
+/* Developer mode debugging macro's */
+#if defined( DEBUG_USB_INT_LO )
+  #define DEBUG_USB_INT_LO_PUTS( s )    USB_PUTS( s )
+  #define DEBUG_USB_INT_LO_PUTCHAR( c ) USB_PUTCHAR( c )
+#else
+  #define DEBUG_USB_INT_LO_PUTS( s )
+  #define DEBUG_USB_INT_LO_PUTCHAR( c )
+#endif /* defined( DEBUG_USB_INT_LO ) */
+
+#if defined( DEBUG_USB_INT_HI )
+  #define DEBUG_USB_INT_HI_PUTS( s )    USB_PUTS( s )
+  #define DEBUG_USB_INT_HI_PUTCHAR( c ) USB_PUTCHAR( c )
+#else
+  #define DEBUG_USB_INT_HI_PUTS( s )
+  #define DEBUG_USB_INT_HI_PUTCHAR( c )
+#endif /* defined( DEBUG_USB_INT_HI ) */
+
+#if defined( USB_HOST )
+  #if defined( NUM_APP_TIMERS )
+    #define HOSTPORT_TIMER_INDEX  (NUM_APP_TIMERS)
+  #else
+    #define HOSTPORT_TIMER_INDEX  (0)
+  #endif
+  #define HOSTCH_TIMER_INDEX      (HOSTPORT_TIMER_INDEX + 1 )
+#endif
+
+/* Macros for selecting a hardware timer. */
+#define USB_TIMER0 0
+#define USB_TIMER1 1
+#define USB_TIMER2 2
+#define USB_TIMER3 3
+
+#if defined( USB_HOST )
+#define HCS_NAK       0x01
+#define HCS_STALL     0x02
+#define HCS_XACT      0x04
+#define HCS_TGLERR    0x08
+#define HCS_BABBLE    0x10
+#define HCS_TIMEOUT   0x20
+#define HCS_COMPLETED 0x40
+#define HCS_RETRY     0x80
+#endif
+
+#if defined( USB_DEVICE )
+typedef enum
+{
+  D_EP_IDLE          = 0,
+  D_EP_TRANSMITTING  = 1,
+  D_EP_RECEIVING     = 2,
+  D_EP0_IN_STATUS    = 3,
+  D_EP0_OUT_STATUS   = 4
+} USBD_EpState_TypeDef;
+
+typedef struct
+{
+  bool                        in;
+  uint8_t                     zlp;
+  uint8_t                     num;
+  uint8_t                     addr;
+  uint8_t                     type;
+  uint8_t                     txFifoNum;
+  uint8_t                     *buf;
+  uint16_t                    packetSize;
+  uint16_t                    mask;
+  uint32_t                    remaining;
+  uint32_t                    xferred;
+  uint32_t                    hwXferSize;
+  uint32_t                    fifoSize;
+  USBD_EpState_TypeDef        state;
+  USB_XferCompleteCb_TypeDef  xferCompleteCb;
+} USBD_Ep_TypeDef;
+
+typedef struct
+{
+  USB_Setup_TypeDef                     *setup;
+  USB_Setup_TypeDef                     setupPkt[3];
+  uint8_t                               configurationValue; /* Must be DWORD aligned */
+  bool                                  remoteWakeupEnabled;
+  uint8_t                               numberOfStrings;
+  uint8_t                               numberOfInterfaces;
+  USBD_State_TypeDef                    state;
+  USBD_State_TypeDef                    savedState;
+  USBD_State_TypeDef                    lastState;
+  const USB_DeviceDescriptor_TypeDef    *deviceDescriptor;
+  const USB_ConfigurationDescriptor_TypeDef *configDescriptor;
+  const void * const                    *stringDescriptors;
+  const USBD_Callbacks_TypeDef          *callbacks;
+  USBD_Ep_TypeDef                       ep[ NUM_EP_USED + 1 ];
+  uint8_t                               inEpAddr2EpIndex[  MAX_USB_EP_NUM + 1 ];
+  uint8_t                               outEpAddr2EpIndex[ MAX_USB_EP_NUM + 1 ];
+  uint32_t                              ep0MpsCode;
+} USBD_Device_TypeDef;
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+typedef enum
+{
+  H_PORT_DISCONNECTED         = 0,
+  H_PORT_CONNECTED_DEBOUNCING = 1,
+  H_PORT_CONNECTED_RESETTING  = 2,
+  H_PORT_CONNECTED            = 3,
+  H_PORT_OVERCURRENT          = 4
+} USBH_PortState_TypeDef;
+
+typedef struct
+{
+  int   debounceTime;
+  int   resetTime;
+} USBH_AttachTiming_TypeDef;
+
+typedef struct
+{
+  uint8_t                 *buf;
+  int                     errorCnt;
+  uint32_t                remaining;
+  uint32_t                xferred;
+  uint32_t                hwXferSize;
+  uint8_t                 status;
+  bool                    idle;
+  USBH_Ep_TypeDef         *ep;
+} USBH_Hc_TypeDef;
+#endif /* defined( USB_HOST ) */
+
+/** @endcond */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
+#endif /* __EM_USBTYPES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/inc/usbconfig.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,88 @@
+/***************************************************************************//**
+ * @file usbconfig.h
+ * @brief USB protocol stack library, application supplied configuration options.
+ * @version 3.20.12
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 __USBCONFIG_H
+#define __USBCONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Compile stack for device mode. */
+#define USB_DEVICE
+
+/* Maximum number of endpoint used, EP0 excluded. If you change this, you must
+   also change USBEndpoints_EFM32.h to match. */
+#define NUM_EP_USED 6
+
+/* Power management modes. The following can be or'd toghether. See comments in
+   em_usbd.c under "Energy-saving modes" for more details.
+
+   USB_PWRSAVE_MODE_ONSUSPEND  Set USB peripheral in low power mode on suspend
+
+   USB_PWRSAVE_MODE_ONVBUSOFF  Set USB peripheral in low power mode when not
+   attached to a host. While this mode assumes that the internal voltage regulator
+   is used and that the VREGI pin of the chip is connected to VBUS it should
+   be safe to use given that VREGOSEN is always enabled. If you disable VREGOSEN
+   you must turn this off.
+
+   USB_PWRSAVE_MODE_ENTEREM2  Enter EM2 when USB peripheral is in low power mode.
+   On Mbed this allows the sleep() and deepsleep() calls to enter EM2, but
+   does not automatically enter any sleep states. Entering EM1 is always allowed.
+
+   Note for Happy Gecko, errata USB_E111: Entering EM2 when both the system clock
+   (HFCLK) and the USB core clock (USBCCLK) is running on USHFRCO will result in
+   a lock-up.
+*/
+#define USB_PWRSAVE_MODE  (USB_PWRSAVE_MODE_ONSUSPEND|USB_PWRSAVE_MODE_ONVBUSOFF|USB_PWRSAVE_MODE_ENTEREM2)
+
+/* Use dynamic memory to allocate rx/tx buffers in the HAL. Saves memory
+   as buffers are only allocated for used endpoints. The system malloc
+   must return memory that is aligned by 4.
+
+   Note: if you disable this, using isochronous endpoints with packet
+   sizes that are larger than the maximum for other EP types (64) will
+   not work. */
+#define USB_USE_DYNAMIC_MEMORY
+
+/* When the USB peripheral is set in low power mode, it must be clocked by a 32kHz
+   clock. Both LFXO and LFRCO can be used, but only LFXO guarantee USB specification
+   compliance. */
+#define USB_USBC_32kHz_CLK   USB_USBC_32kHz_CLK_LFXO
+
+/* Uncomment to get some debugging information. Default value for USER_PUTCHAR
+   should work for SiLabs Gecko boards. Printf requires a working retarget
+   implementation for write(). */
+//#define DEBUG_USB_API
+//#define USB_USE_PRINTF
+//#define USER_PUTCHAR   ITM_SendChar
+//#define DEBUG_USB_INT_HI
+//#define DEBUG_USB_INT_LO
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __USBCONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/src/em_usbd.c	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,1438 @@
+/**************************************************************************//**
+ * @file em_usbd.c
+ * @brief USB protocol stack library, device API.
+ * @version 3.20.14
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE )
+
+#include "em_cmu.h"
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#include "em_usbd.h"
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+static USBD_Device_TypeDef device;
+USBD_Device_TypeDef *dev = &device;
+
+static uint32_t totalRxFifoSize = 0, totalTxFifoSize = 0;
+static int numEps = 0;
+static int txFifoNum = 1;
+
+static void USBD_ResetEndpoints(void);
+extern USB_Status_TypeDef USBDHAL_ReconfigureFifos( uint32_t totalRxFifoSize,
+                                                    uint32_t totalTxFifoSize );
+#ifndef __MBED__
+static const char *stateNames[] =
+{
+  [ USBD_STATE_NONE       ] = "NONE      ",
+  [ USBD_STATE_ATTACHED   ] = "ATTACHED  ",
+  [ USBD_STATE_POWERED    ] = "POWERED   ",
+  [ USBD_STATE_DEFAULT    ] = "DEFAULT   ",
+  [ USBD_STATE_ADDRESSED  ] = "ADDRESSED ",
+  [ USBD_STATE_CONFIGURED ] = "CONFIGURED",
+  [ USBD_STATE_SUSPENDED  ] = "SUSPENDED ",
+  [ USBD_STATE_LASTMARKER ] = "UNDEFINED "
+};
+#endif
+
+/** @endcond */
+
+/***************************************************************************//**
+ * @brief
+ *   Abort all pending transfers.
+ *
+ * @details
+ *   Aborts transfers for all endpoints currently in use. Pending
+ *   transfers on the default endpoint (EP0) are not aborted.
+ ******************************************************************************/
+void USBD_AbortAllTransfers( void )
+{
+  INT_Disable();
+  USBDHAL_AbortAllTransfers( USB_STATUS_EP_ABORTED );
+  INT_Enable();
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Abort a pending transfer on a specific endpoint.
+ *
+ * @param[in] epAddr
+ *   The address of the endpoint to abort.
+ ******************************************************************************/
+int USBD_AbortTransfer( int epAddr )
+{
+  USB_XferCompleteCb_TypeDef callback;
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( ep->num == 0 )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  INT_Disable();
+  if ( ep->state == D_EP_IDLE )
+  {
+    INT_Enable();
+    return USB_STATUS_OK;
+  }
+
+  USBD_AbortEp( ep );
+
+  ep->state = D_EP_IDLE;
+  if ( ep->xferCompleteCb )
+  {
+    callback = ep->xferCompleteCb;
+    ep->xferCompleteCb = NULL;
+
+    if ( ( dev->lastState == USBD_STATE_CONFIGURED ) &&
+         ( dev->state     == USBD_STATE_ADDRESSED  )    )
+    {
+      USBDHAL_DeactivateEp( ep );
+    }
+
+    DEBUG_TRACE_ABORT( USB_STATUS_EP_ABORTED );
+    callback( USB_STATUS_EP_ABORTED, ep->xferred, ep->remaining );
+  }
+
+  INT_Enable();
+  return USB_STATUS_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Start USB device operation.
+ *
+ * @details
+ *   Device operation is started by connecting a pullup resistor on the
+ *   appropriate USB data line.
+ ******************************************************************************/
+void USBD_Connect( void )
+{
+  INT_Disable();
+  USBDHAL_Connect();
+  INT_Enable();
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Stop USB device operation.
+ *
+ * @details
+ *   Device operation is stopped by disconnecting the pullup resistor from the
+ *   appropriate USB data line. Often referred to as a "soft" disconnect.
+ ******************************************************************************/
+void USBD_Disconnect( void )
+{
+  INT_Disable();
+  USBDHAL_Disconnect();
+  INT_Enable();
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Check if an endpoint is busy doing a transfer.
+ *
+ * @param[in] epAddr
+ *   The address of the endpoint to check.
+ *
+ * @return
+ *   True if endpoint is busy, false otherwise.
+ ******************************************************************************/
+bool USBD_EpIsBusy( int epAddr )
+{
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_EpIsBusy(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( ep->state == D_EP_IDLE )
+    return false;
+
+  return true;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Get current USB device state.
+ *
+ * @return
+ *   Device USB state. See @ref USBD_State_TypeDef.
+ ******************************************************************************/
+USBD_State_TypeDef USBD_GetUsbState( void )
+{
+  return dev->state;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Get a string naming a device USB state.
+ *
+ * @param[in] state
+ *   Device USB state. See @ref USBD_State_TypeDef.
+ *
+ * @return
+ *   State name string pointer.
+ ******************************************************************************/
+const char *USBD_GetUsbStateName( USBD_State_TypeDef state )
+{
+  if ( state > USBD_STATE_LASTMARKER )
+    state = USBD_STATE_LASTMARKER;
+
+#ifndef __MBED__
+  return stateNames[ state ];
+#else
+  return NULL;
+#endif
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Initializes USB device hardware and internal protocol stack data structures,
+ *   then connects the data-line (D+ or D-) pullup resistor to signal host that
+ *   enumeration can begin.
+ *
+ * @note
+ *   You may later use @ref USBD_Disconnect() and @ref USBD_Connect() to force
+ *   reenumeration.
+ *
+ * @param[in] p
+ *   Pointer to device initialization struct. See @ref USBD_Init_TypeDef.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_Init( const USBD_Init_TypeDef *p )
+{
+  USBD_Ep_TypeDef *ep;
+
+#if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN )
+  /* Devices supporting crystal-less USB can use HFRCO or HFXO as core clock. */
+  /* All other devices must use HFXO as core clock.                           */
+  if ( CMU_ClockSelectGet( cmuClock_HF ) != cmuSelect_HFXO )
+  {
+    CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
+  }
+#endif
+
+#if !defined( CMU_OSCENCMD_USHFRCOEN )
+#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
+  CMU_OscillatorEnable(cmuOsc_LFXO, true, false);
+#else
+  CMU_OscillatorEnable(cmuOsc_LFRCO, true, false);
+#endif
+
+#else
+  CMU_ClockEnable(cmuClock_CORELE, true);
+  /* LFC clock is needed to detect USB suspend when LEMIDLE is activated. */
+#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
+  CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFXO);
+#else
+  CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFRCO);
+#endif
+  CMU_ClockEnable(cmuClock_USBLE, true);
+#endif
+
+  USBTIMER_Init();
+
+  memset( dev, 0, sizeof( USBD_Device_TypeDef ) );
+
+  dev->setup                = dev->setupPkt;
+  dev->state                = USBD_STATE_LASTMARKER;
+  dev->savedState           = USBD_STATE_NONE;
+  dev->lastState            = USBD_STATE_NONE;
+  dev->callbacks            = p->callbacks;
+  dev->remoteWakeupEnabled  = false;
+
+  /* Initialize EP0 */
+
+  ep                 = &dev->ep[ 0 ];
+  ep->in             = false;
+  ep->buf            = NULL;
+  ep->num            = 0;
+  ep->mask           = 1;
+  ep->addr           = 0;
+  ep->type           = USB_EPTYPE_CTRL;
+  ep->txFifoNum      = 0;
+
+  /* FIXME! */
+  ep->packetSize     = 64;
+  dev->ep0MpsCode = _USB_DOEP0CTL_MPS_64B;
+
+  ep->remaining      = 0;
+  ep->xferred        = 0;
+  ep->state          = D_EP_IDLE;
+  ep->xferCompleteCb = NULL;
+  ep->fifoSize       = ep->packetSize / 4;
+
+  totalTxFifoSize = ep->fifoSize * p->bufferingMultiplier[ 0 ];
+  totalRxFifoSize = (ep->fifoSize + 1) * p->bufferingMultiplier[ 0 ];
+
+  /* Rx-FIFO size: SETUP packets : 4*n + 6    n=#CTRL EP's
+   *               GOTNAK        : 1
+   *               Status info   : 2*n        n=#OUT EP's (EP0 included) in HW
+   */
+  totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) );
+
+  INT_Disable();
+
+  /* Enable USB clock */
+  CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC;
+
+#if defined( CMU_OSCENCMD_USHFRCOEN )
+  CMU->USHFRCOCONF = CMU_USHFRCOCONF_BAND_48MHZ;
+  CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_USHFRCO );
+
+  /* Enable USHFRCO Clock Recovery mode. */
+  CMU->USBCRCTRL |= CMU_USBCRCTRL_EN;
+
+  /* Turn on Low Energy Mode (LEM) features. */
+  USB->CTRL = USB_CTRL_LEMOSCCTRL_GATE
+              | USB_CTRL_LEMIDLEEN
+              | USB_CTRL_LEMPHYCTRL;
+#else
+  CMU_ClockSelectSet( cmuClock_USBC, cmuSelect_HFCLK );
+#endif
+
+  USBHAL_DisableGlobalInt();
+
+  if ( USBDHAL_CoreInit( totalRxFifoSize, totalTxFifoSize ) == USB_STATUS_OK )
+  {
+    USBDHAL_EnableUsbResetAndSuspendInt();
+    USBHAL_EnableGlobalInt();
+    NVIC_ClearPendingIRQ( USB_IRQn );
+    NVIC_EnableIRQ( USB_IRQn );
+  }
+  else
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Init(), FIFO setup error" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
+  if ( USBHAL_VbusIsOn() )
+  {
+    USBD_SetUsbState( USBD_STATE_POWERED );
+  }
+  else
+#endif
+  {
+    USBD_SetUsbState( USBD_STATE_NONE );
+  }
+
+  INT_Enable();
+  return USB_STATUS_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Start a read (OUT) transfer on an endpoint.
+ *
+ * @note
+ *   The transfer buffer length must be a multiple of 4 bytes in length and
+ *   WORD (4 byte) aligned. When allocating the buffer, round buffer length up.
+ *   If it is possible that the host will send more data than your device
+ *   expects, round buffer size up to the next multiple of maxpacket size.
+ *
+ * @param[in] epAddr
+ *   Endpoint address.
+ *
+ * @param[in] data
+ *   Pointer to transfer data buffer.
+ *
+ * @param[in] byteCount
+ *   Transfer length.
+ *
+ * @param[in] callback
+ *   Function to be called on transfer completion. Supply NULL if no callback
+ *   is needed. See @ref USB_XferCompleteCb_TypeDef.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_Read( int epAddr, void *data, int byteCount,
+               USB_XferCompleteCb_TypeDef callback )
+{
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  USB_PRINTF("USBD: Read addr %x, data %p, size %d, cb 0x%lx\n",
+             epAddr, data, byteCount, (uint32_t)callback);
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( (   byteCount > MAX_XFER_LEN                           ) ||
+       ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER )    )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal transfer size" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( (uint32_t)data & 3 )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Misaligned data buffer" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  INT_Disable();
+  if ( USBDHAL_EpIsStalled( ep ) )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is halted" );
+    return USB_STATUS_EP_STALLED;
+  }
+
+  if ( ep->state != D_EP_IDLE )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is busy" );
+    return USB_STATUS_EP_BUSY;
+  }
+
+  if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Device not configured" );
+    return USB_STATUS_DEVICE_UNCONFIGURED;
+  }
+
+  ep->buf       = (uint8_t*)data;
+  ep->remaining = byteCount;
+  ep->xferred   = 0;
+
+  if ( ep->num == 0 )
+  {
+    ep->in = false;
+  }
+  else if ( ep->in != false )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal EP direction" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  ep->state          = D_EP_RECEIVING;
+  ep->xferCompleteCb = callback;
+
+  USBD_ArmEp( ep );
+  INT_Enable();
+  return USB_STATUS_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Perform a remote wakeup signalling sequence.
+ *
+ * @note
+ *   It is the responsibility of the application to ensure that remote wakeup
+ *   is not attempted before the device has been suspended for at least 5
+ *   miliseconds. This function should not be called from within an interrupt
+ *   handler.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_RemoteWakeup( void )
+{
+  INT_Disable();
+
+  if ( ( dev->state != USBD_STATE_SUSPENDED ) ||
+       ( dev->remoteWakeupEnabled == false  )    )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_RemoteWakeup(), Illegal remote wakeup" );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  USBDHAL_SetRemoteWakeup();
+  INT_Enable();
+  USBTIMER_DelayMs( 10 );
+  INT_Disable();
+  USBDHAL_ClearRemoteWakeup();
+  INT_Enable();
+  return USB_STATUS_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Check if it is ok to enter energy mode EM2.
+ *
+ * @note
+ *   Before entering EM2 both the USB hardware and the USB stack must be in a
+ *   certain state, this function checks if all conditions for entering EM2
+ *   is met.
+ *   Refer to the @ref usb_device_powersave section for more information.
+ *
+ * @return
+ *   True if ok to enter EM2, false otherwise.
+ ******************************************************************************/
+bool USBD_SafeToEnterEM2( void )
+{
+#if ( USB_PWRSAVE_MODE )
+  return USBD_poweredDown ? true : false;
+#else
+  return false;
+#endif
+}
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+void USBD_SetUsbState( USBD_State_TypeDef newState )
+{
+  USBD_State_TypeDef currentState;
+
+  currentState = dev->state;
+  if ( newState == USBD_STATE_SUSPENDED )
+  {
+    dev->savedState = currentState;
+  }
+
+  dev->lastState = dev->state;
+  dev->state = newState;
+
+  if ( ( dev->callbacks->usbStateChange ) &&
+       ( currentState != newState       )    )
+  {
+    /* When we transition to a state "lower" than CONFIGURED
+     * we must reset the endpoint data
+     */
+    if ( (dev->lastState == USBD_STATE_CONFIGURED ||
+          dev->lastState == USBD_STATE_SUSPENDED ) &&
+         dev->state < USBD_STATE_CONFIGURED )
+    {
+      USBD_ResetEndpoints();
+    }
+
+    dev->callbacks->usbStateChange( currentState, newState );
+  }
+}
+
+/** @endcond */
+
+/***************************************************************************//**
+ * @brief
+ *   Set an endpoint in the stalled (halted) state.
+ *
+ * @param[in] epAddr
+ *   The address of the endpoint to stall.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_StallEp( int epAddr )
+{
+  USB_Status_TypeDef retVal;
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_StallEp(), Illegal request" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( ep->num == 0 )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_StallEp(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  INT_Disable();
+  retVal = USBDHAL_StallEp( ep );
+  INT_Enable();
+
+  if ( retVal != USB_STATUS_OK )
+  {
+    retVal = USB_STATUS_ILLEGAL;
+  }
+
+  return retVal;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Stop USB device stack operation.
+ *
+ * @details
+ *   The data-line pullup resistor is turned off, USB interrupts are disabled,
+ *   and finally the USB pins are disabled.
+ ******************************************************************************/
+void USBD_Stop( void )
+{
+  USBD_Disconnect();
+  NVIC_DisableIRQ( USB_IRQn );
+  USBHAL_DisableGlobalInt();
+  USBHAL_DisableUsbInt();
+  USBHAL_DisablePhyPins();
+  USBD_SetUsbState( USBD_STATE_NONE );
+  /* Turn off USB clocks. */
+  CMU->HFCORECLKEN0 &= ~(CMU_HFCORECLKEN0_USB | CMU_HFCORECLKEN0_USBC);
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Reset stall state on a stalled (halted) endpoint.
+ *
+ * @param[in] epAddr
+ *   The address of the endpoint to un-stall.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_UnStallEp( int epAddr )
+{
+  USB_Status_TypeDef retVal;
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal request" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( ep->num == 0 )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  INT_Disable();
+  retVal = USBDHAL_UnStallEp( ep );
+  INT_Enable();
+
+  if ( retVal != USB_STATUS_OK )
+  {
+    retVal = USB_STATUS_ILLEGAL;
+  }
+
+  return retVal;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Start a write (IN) transfer on an endpoint.
+ *
+ * @param[in] epAddr
+ *   Endpoint address.
+ *
+ * @param[in] data
+ *   Pointer to transfer data buffer. This buffer must be WORD (4 byte) aligned.
+ *
+ * @param[in] byteCount
+ *   Transfer length.
+ *
+ * @param[in] callback
+ *   Function to be called on transfer completion. Supply NULL if no callback
+ *   is needed. See @ref USB_XferCompleteCb_TypeDef.
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_Write( int epAddr, void *data, int byteCount,
+                USB_XferCompleteCb_TypeDef callback )
+{
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  USB_PRINTF("USBD: Write addr %x, data %p, size %d, cb 0x%lx\n",
+             epAddr, data, byteCount, (uint32_t)callback);
+
+  if ( ep == NULL )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal endpoint" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( (   byteCount > MAX_XFER_LEN                           ) ||
+       ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER )    )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal transfer size" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  if ( (uint32_t)data & 3 )
+  {
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Misaligned data buffer" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  INT_Disable();
+  if ( USBDHAL_EpIsStalled( ep ) )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is halted" );
+    return USB_STATUS_EP_STALLED;
+  }
+
+  if ( ep->state != D_EP_IDLE )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is busy" );
+    return USB_STATUS_EP_BUSY;
+  }
+
+  if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Device not configured" );
+    return USB_STATUS_DEVICE_UNCONFIGURED;
+  }
+
+  ep->buf       = (uint8_t*)data;
+  ep->remaining = byteCount;
+  ep->xferred   = 0;
+
+  if ( ep->num == 0 )
+  {
+    ep->in = true;
+  }
+  else if ( ep->in != true )
+  {
+    INT_Enable();
+    DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal EP direction" );
+    EFM_ASSERT( false );
+    return USB_STATUS_ILLEGAL;
+  }
+
+  ep->state          = D_EP_TRANSMITTING;
+  ep->xferCompleteCb = callback;
+
+  USBD_ArmEp( ep );
+  INT_Enable();
+  return USB_STATUS_OK;
+}
+
+int USBD_SetAddress(uint8_t addr)
+{
+  int retVal = USB_STATUS_REQ_ERR;
+
+  if ( dev->state == USBD_STATE_DEFAULT )
+  {
+    if ( addr != 0 )
+    {
+      USBD_SetUsbState( USBD_STATE_ADDRESSED );
+    }
+    USBDHAL_SetAddr( addr );
+    retVal = USB_STATUS_OK;
+  }
+  else if ( dev->state == USBD_STATE_ADDRESSED )
+  {
+    if ( addr == 0 )
+    {
+      USBD_SetUsbState( USBD_STATE_DEFAULT );
+    }
+    USBDHAL_SetAddr( addr );
+    retVal = USB_STATUS_OK;
+  }
+
+  return retVal;
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Query the stall state of an endpoint
+ *
+ * @param[in] epAddr
+ *   The address of the endpoint to query.
+ *
+ * @return
+ *   True if endpoint is stalled, false otherwise
+ ******************************************************************************/
+int USBD_EpIsStalled(int epAddr)
+{
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if( !ep )
+  {
+    return false;
+  }
+
+  return USBDHAL_EpIsStalled(ep);
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Reset (remove) all client endpoints
+ *
+ * @details
+ *   Removes client endpoints, and resets the RX/TX fifos. No endpoints
+ *   other than EP0 can be used until added with @ref USBD_AddEndpoint.
+ ******************************************************************************/
+static void USBD_ResetEndpoints(void)
+{
+  USBD_Ep_TypeDef *ep = &dev->ep[0];
+
+  numEps = 0;
+  txFifoNum = 1;
+
+  totalTxFifoSize  = ep->fifoSize * 1;
+  totalRxFifoSize  = (ep->fifoSize + 1) * 1;
+  totalRxFifoSize += 10 + 1 + ( 2 * (MAX_NUM_OUT_EPS + 1) );
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Add a new endpoint
+ *
+ * @param[in] epAddr
+ *   Endpoint address
+ *
+ * @param[in] transferType
+ *   Endpoint type, one of @ref USB_EPTYPE_BULK, @ref USB_EPTYPE_INTR or
+ *   @ref USB_EPTYPE_ISOC.
+ *
+ * @param[in] maxPacketSize
+ *   Maximum packet size of the new endpoint, in bytes
+ *
+ * @param[in] bufferMult
+ *   FIFO buffer size multiplier
+ *
+ * @return
+ *   @ref USB_STATUS_OK on success, else an appropriate error code.
+ ******************************************************************************/
+int USBD_AddEndpoint(int epAddr, int transferType,
+                     int maxPacketSize, int bufferMult)
+{
+  USBD_Ep_TypeDef *ep;
+
+  numEps++;
+
+  ep                 = &dev->ep[ numEps ];
+  ep->in             = ( epAddr & USB_SETUP_DIR_MASK ) != 0;
+  ep->buf            = NULL;
+  ep->addr           = epAddr;
+  ep->num            = ep->addr & USB_EPNUM_MASK;
+  ep->mask           = 1 << ep->num;
+  ep->type           = transferType;
+  ep->packetSize     = maxPacketSize;
+  ep->remaining      = 0;
+  ep->xferred        = 0;
+  ep->state          = D_EP_IDLE;
+  ep->xferCompleteCb = NULL;
+
+  if ( ep->in )
+  {
+    ep->txFifoNum = txFifoNum++;
+    ep->fifoSize = ( ( ep->packetSize + 3 ) / 4 ) * bufferMult;
+    dev->inEpAddr2EpIndex[ ep->num ] = numEps;
+    totalTxFifoSize += ep->fifoSize;
+
+    if ( ep->num > MAX_NUM_IN_EPS )
+    {
+      DEBUG_USB_API_PUTS( "\nUSBD_AddEndpoint(), Illegal IN EP address" );
+      EFM_ASSERT( false );
+      return USB_STATUS_ILLEGAL;
+    }
+  }
+  else
+  {
+    ep->fifoSize = ( ( ( ep->packetSize + 3 ) / 4 ) + 1 ) * bufferMult;
+    dev->outEpAddr2EpIndex[ ep->num ] = numEps;
+    totalRxFifoSize += ep->fifoSize;
+
+    if ( ep->num > MAX_NUM_OUT_EPS )
+    {
+      DEBUG_USB_API_PUTS( "\nUSBD_AddEndpoint(), Illegal OUT EP address" );
+      EFM_ASSERT( false );
+      return USB_STATUS_ILLEGAL;
+    }
+  }
+
+  USB_PRINTF("USBD: Added endpoint %d to slot %d, in %d, addr 0x%x, type %d, ps %d, fifo %ld (total tx %ld, rx %ld)\n",
+             ep->num, numEps, ep->in, ep->addr, ep->type, ep->packetSize, ep->fifoSize,
+             totalTxFifoSize, totalRxFifoSize);
+
+  INT_Disable();
+#if defined( CMU_OSCENCMD_USHFRCOEN )
+  /* Happy Gecko workaround: disable LEM GATE mode if using ISOC endpoints. */
+  if ( transferType == USB_EPTYPE_ISOC )
+  {
+      USB->CTRL = (USB->CTRL & ~_USB_CTRL_LEMOSCCTRL_MASK) | USB_CTRL_LEMOSCCTRL_NONE;
+  }
+#endif
+
+  int ret = USBDHAL_ReconfigureFifos(totalRxFifoSize, totalTxFifoSize);
+  INT_Enable();
+
+  if( ret != USB_STATUS_OK ) {
+    return ret;
+  }
+
+  USBDHAL_ActivateEp(ep, false);
+
+  return USB_STATUS_OK;
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Set an endpoint0 in the stalled (halted) state.
+ *
+ * @details
+ *   Temporarily stalls endpoint 0. Used to signal a failure to respond to
+ *   the host's setup packet.
+ ******************************************************************************/
+void USBD_StallEp0()
+{
+    int const epAddr = 0;
+    USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+    ep->in = true;
+    USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
+    ep->in = false; /* OUT for next SETUP */
+    USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
+#if !defined( USB_DOEP0INT_STUPPKTRCVD )
+    USBDHAL_ReenableEp0Setup( dev ); /* Prepare for next SETUP pkt. */
+#else
+    USBDHAL_StartEp0Setup( dev );
+#endif
+    ep->state = D_EP_IDLE;
+}
+
+/******** THE REST OF THE FILE IS DOCUMENTATION ONLY !**********************//**
+ * @{
+
+@page usb_device USB device stack library
+
+  The source files for the USB device stack resides in the usb directory
+  and follows the naming convention: em_usbd<em>nnn</em>.c/h.
+
+  @li @ref usb_device_intro
+  @li @ref usb_device_api
+  @li @ref usb_device_conf
+  @li @ref usb_device_powersave
+  @li @ref usb_device_example1
+
+
+@n @section usb_device_intro Introduction
+
+  The USB device protocol stack provides an API which makes it possible to
+  create USB devices with a minimum of effort. The device stack supports control,
+  bulk and interrupt transfers.
+
+  The stack is highly configurable to suit various needs, it does also contain
+  useful debugging features together with several demonstration projects to
+  get you started fast.
+
+  We recommend that you read through this documentation, then proceed to build
+  and test a few example projects before you start designing your own device.
+
+@n @section usb_device_api The device stack API
+
+  This section contains brief descriptions of the functions in the API. You will
+  find detailed information on input and output parameters and return values by
+  clicking on the hyperlinked function names. It is also a good idea to study
+  the code in the USB demonstration projects.
+
+  Your application code must include one header file: @em em_usb.h.
+
+  All functions defined in the API can be called from within interrupt handlers.
+
+  The USB stack use a hardware timer to keep track of time. TIMER0 is the
+  default choice, refer to @ref usb_device_conf for other possibilities.
+  Your application must not use the selected timer.
+
+  <b>Pitfalls:</b>@n
+    The USB peripheral will fill your receive buffers in quantities of WORD's
+    (4 bytes). Transmit and receive buffers must be WORD aligned, in
+    addition when allocating storage for receive buffers, round size up to
+    next WORD boundary. If it is possible that the host will send more data
+    than your device expects, round buffer size up to the next multiple of
+    maxpacket size for the relevant endpoint to avoid data corruption.
+
+    Transmit buffers passed to @htmlonly USBD_Write() @endhtmlonly must be
+    statically allocated because @htmlonly USBD_Write() @endhtmlonly only
+    initiates the transfer. When the host decide to actually perform the
+    transfer, your data must be available.
+
+  @n @ref USBD_Init() @n
+    This function is called to register your device and all its properties with
+    the device stack. The application must fill in a @ref USBD_Init_TypeDef
+    structure prior to calling. Refer to @ref DeviceInitCallbacks for the
+    optional callback functions defined within this structure. When this
+    function has been called your device is ready to be enumerated by the USB
+    host.
+
+  @ref USBD_Read(), @ref USBD_Write() @n
+    These functions initiate data transfers.
+    @n @htmlonly USBD_Read() @endhtmlonly initiate a transfer of data @em
+    from host @em to device (an @em OUT transfer in USB terminology).
+    @n @htmlonly USBD_Write() @endhtmlonly initiate a transfer of data @em from
+    device @em to host (an @em IN transfer).
+
+    When the USB host actually performs the transfer, your application will be
+    notified by means of a callback function which you provide (optionally).
+    Refer to @ref TransferCallback for details of the callback functionality.
+
+  @ref USBD_AbortTransfer(), @ref USBD_AbortAllTransfers() @n
+    These functions terminate transfers that are initiated, but has not yet
+    taken place. If a transfer is initiated with @htmlonly USBD_Read()
+    or USBD_Write(), @endhtmlonly but the USB host never actually peform
+    the transfers, these functions will deactivate the transfer setup to make
+    the USB device endpoint hardware ready for new (and potentially) different
+    transfers.
+
+  @ref USBD_Connect(), @ref USBD_Disconnect() @n
+    These functions turns the data-line (D+ or D-) pullup on or off. They can be
+    used to force reenumeration. It's good practice to delay at least one second
+    between @htmlonly USBD_Disconnect() and USBD_Connect() @endhtmlonly
+    to allow the USB host to unload the currently active device driver.
+
+  @ref USBD_EpIsBusy() @n
+    Check if an endpoint is busy.
+
+  @ref USBD_StallEp(), @ref USBD_UnStallEp() @n
+    These functions stalls or un-stalls an endpoint. This functionality may not
+    be needed by your application, but the USB device stack use them in response
+    to standard setup commands SET_FEATURE and CLEAR_FEATURE. They may be useful
+    when implementing some USB classes, e.g. a mass storage device use them
+    extensively.
+
+  @ref USBD_RemoteWakeup() @n
+    Used in SUSPENDED state (see @ref USB_Status_TypeDef) to signal resume to
+    host. It's the applications responsibility to adhere to the USB standard
+    which states that a device can not signal resume before it has been
+    SUSPENDED for at least 5 ms. The function will also check the configuration
+    descriptor defined by the application to see if it is legal for the device
+    to signal resume.
+
+  @ref USBD_GetUsbState() @n
+    Returns the device USB state (see @ref USBD_State_TypeDef). Refer to
+    Figure 9-1. "Device State Diagram" in the USB revision 2.0 specification.
+
+  @ref USBD_GetUsbStateName() @n
+    Returns a text string naming a given USB device state.
+
+  @ref USBD_SafeToEnterEM2() @n
+    Check if it is ok to enter energy mode EM2. Refer to the
+    @ref usb_device_powersave section for more information.
+
+  @n @anchor TransferCallback <b>The transfer complete callback function:</b> @n
+    @n USB_XferCompleteCb_TypeDef() is called when a transfer completes. It is
+    called with three parameters, the status of the transfer, the number of
+    bytes transferred and the number of bytes remaining. It may not always be
+    needed to have a callback on transfer completion, but you should keep in
+    mind that a transfer may be aborted when you least expect it. A transfer
+    will be aborted if host stalls the endpoint, if host resets your device, if
+    host unconfigures your device or if you unplug your device cable and the
+    device is selfpowered.
+    @htmlonly USB_XferCompleteCb_TypeDef() @endhtmlonly is also called if your
+    application use @htmlonly USBD_AbortTransfer() or USBD_AbortAllTransfers()
+    @endhtmlonly calls.
+    @note This callback is called from within an interrupt handler with
+          interrupts disabled.
+
+  @n @anchor DeviceInitCallbacks <b>Optional callbacks passed to the stack via
+    the @ref USBD_Init() function:</b> @n
+    @n These callbacks are all optional, and it is up to the application
+    programmer to decide if the application needs the functionality they
+    provide.
+    @note These callbacks are all called from within an interrupt handler
+          with interrupts disabled.
+
+  USBD_UsbResetCb_TypeDef() is called each time reset signalling is sensed on
+    the USB wire.
+
+  @n USBD_SofIntCb_TypeDef() is called with framenumber as a parameter on
+    each SOF interrupt.
+
+  @n USBD_DeviceStateChangeCb_TypeDef() is called whenever the device state
+    change. Useful for detecting e.g. SUSPENDED state change in order to reduce
+    current consumption of buspowered devices. The USB HID keyboard example
+    project has a good example on how to use this callback.
+
+  @n USBD_IsSelfPoweredCb_TypeDef() is called by the device stack when host
+    queries the device with a standard setup GET_STATUS command to check if the
+    device is currently selfpowered or buspowered. This feature is only
+    applicable on selfpowered devices which also works when only buspower is
+    available.
+
+  @n USBD_SetupCmdCb_TypeDef() is called each time a setup command is
+    received from host. Use this callback to override or extend the default
+    handling of standard setup commands, and to implement class or vendor
+    specific setup commands. The USB HID keyboard example project has a good
+    example on how to use this callback.
+
+  @n <b>Utility functions:</b> @n
+    @n    USB_PUTCHAR() Transmit a single char on the debug serial port.
+    @n @n USB_PUTS() Transmit a zero terminated string on the debug serial port.
+    @n @n USB_PRINTF() Transmit "printf" formated data on the debug serial port.
+    @n @n USB_GetErrorMsgString() Return an error message string for a given
+          error code.
+    @n @n USB_PrintErrorMsgString() Format and print a text string given an
+          error code, prepends an optional user supplied leader string.
+    @n @n USBTIMER_DelayMs() Active wait millisecond delay function. Can also be
+          used inside interrupt handlers.
+    @n @n USBTIMER_DelayUs() Active wait microsecond delay function. Can also be
+          used inside interrupt handlers.
+    @n @n USBTIMER_Init() Initialize the timer system. Called by @htmlonly
+          USBD_Init(), @endhtmlonly but your application must call it again to
+          reinitialize whenever you change the HFPERCLK frequency.
+    @n @n USBTIMER_Start() Start a timer. You can configure the USB device stack
+          to provide any number of timers. The timers have 1 ms resolution, your
+          application is notified of timeout by means of a callback.
+    @n @n USBTIMER_Stop() Stop a timer.
+
+@n @section usb_device_conf Configuring the device stack
+
+  Your application must provide a header file named @em usbconfig.h. This file
+  must contain the following \#define's:@n @n
+  @verbatim
+#define USB_DEVICE       // Compile the stack for device mode.
+#define NUM_EP_USED n    // Your application use 'n' endpoints in
+                         // addition to endpoint 0. @endverbatim
+
+  @n @em usbconfig.h may define the following items: @n @n
+  @verbatim
+#define NUM_APP_TIMERS n // Your application needs 'n' timers
+
+#define DEBUG_USB_API    // Turn on API debug diagnostics.
+
+// Some utility functions in the API needs printf. These
+// functions have "print" in their name. This macro enables
+// these functions.
+#define USB_USE_PRINTF   // Enable utility print functions.
+
+// Define a function for transmitting a single char on the serial port.
+extern int RETARGET_WriteChar(char c);
+#define USER_PUTCHAR  RETARGET_WriteChar
+
+#define USB_TIMER USB_TIMERn  // Select which hardware timer the USB stack
+                              // is allowed to use. Valid values are n=0,1,2...
+                              // corresponding to TIMER0, TIMER1, ...
+                              // If not specified, TIMER0 is used
+
+#define USB_VBUS_SWITCH_NOT_PRESENT  // Hardware does not have a VBUS switch
+
+#define USB_CORECLK_HFRCO   // Devices supporting crystal-less USB can use
+                            // HFRCO as core clock, default is HFXO
+@endverbatim
+
+  @n You are strongly encouraged to start application development with DEBUG_USB_API
+  turned on. When DEBUG_USB_API is turned on and USER_PUTCHAR is defined, useful
+  debugging information will be output on the development kit serial port.
+  Compiling with the DEBUG_EFM_USER flag will also enable all asserts
+  in both @em emlib and in the USB stack. If asserts are enabled and
+  USER_PUTCHAR defined, assert texts will be output on the serial port.
+
+  You application must include @em retargetserial.c if DEBUG_USB_API is defined
+  and @em retargetio.c if USB_USE_PRINTF is defined.
+  These files reside in the @em drivers
+  directory in the software package for your development board. Refer to
+  @ref usb_device_powersave for energy-saving mode configurations.
+
+@n @section usb_device_powersave Energy-saving modes
+
+  The device stack provides two energy saving levels. The first level is to
+  set the USB peripheral in energy saving mode, the next level is to enter
+  Energy Mode 2 (EM2). These energy saving modes can be applied when the device
+  is suspended by the USB host, or when when the device is not connected to a
+  USB host.
+  In addition to this an application can use energy modes EM1 and EM2. There
+  are no restrictions on when EM1 can be entered, EM2 can only be entered
+  when the USB device is suspended or detached from host.
+
+  Energy-saving modes are selected with a \#define in @em usbconfig.h, default
+  selection is to not use any energy saving modes.@n @n
+  @verbatim
+#define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ENTEREM2)@endverbatim
+
+  There are three flags available, the flags can be or'ed together as shown above.
+
+  <b>\#define USB_PWRSAVE_MODE_ONSUSPEND</b>@n Set USB peripheral in low power
+  mode on suspend.
+
+  <b>\#define USB_PWRSAVE_MODE_ONVBUSOFF</b>@n Set USB peripheral in low power
+  mode when not attached to a host. This mode assumes that the internal voltage
+  regulator is used and that the VREGI pin of the chip is connected to VBUS.
+  This option can not be used with bus-powered devices.
+
+  <b>\#define USB_PWRSAVE_MODE_ENTEREM2</b>@n Enter EM2 when USB peripheral is
+  in low power mode.
+
+  When the USB peripheral is set in low power mode, it must be clocked by a 32kHz
+  clock. Both LFXO and LFRCO can be used, but only LFXO guarantee USB specification
+  compliance. Selection is done with a \#define in @em usbconfig.h.@n @n
+  @verbatim
+#define USB_USBC_32kHz_CLK   USB_USBC_32kHz_CLK_LFXO @endverbatim
+  Two flags are available, <b>USB_USBC_32kHz_CLK_LFXO</b> and
+  <b>USB_USBC_32kHz_CLK_LFRCO</b>. <b>USB_USBC_32kHz_CLK_LFXO</b> is selected
+  by default.
+
+  The USB HID keyboard and Mass Storage device example projects demonstrate
+  different energy-saving modes.
+
+  <b>Example 1:</b>
+  Leave all energy saving to the stack, the device enters EM2 on suspend and
+  when detached from host. @n
+  @verbatim
+In usbconfig.h:
+
+#define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF | USB_PWRSAVE_MODE_ENTEREM2)
+  @endverbatim
+
+  @n <b>Example 2:</b>
+  Let the stack control energy saving in the USB periheral but let your
+  application control energy modes EM1 and EM2. @n
+  @verbatim
+In usbconfig.h:
+
+#define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF)
+
+In application code:
+
+if ( USBD_SafeToEnterEM2() )
+  EMU_EnterEM2(true);
+else
+  EMU_EnterEM1(); @endverbatim
+
+@n @section usb_device_example1 Vendor unique device example application
+
+  This example represents the most simple USB device imaginable. It's purpose
+  is to turn user LED's on or off under control of vendor unique setup commands.
+  The device will rely on @em libusb device driver on the host, a host
+  application @em EFM32-LedApp.exe is bundled with the example.
+
+  The main() is really simple ! @n @n
+  @verbatim
+#include "em_usb.h"
+
+#include "descriptors.h"
+
+int main( void )
+{
+  BSP_Init(BSP_INIT_DEFAULT); // Initialize DK board register access
+  CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
+  BSP_LedsSet(0);             // Turn off all LED's
+
+  ConsoleDebugInit();         // Initialize UART for debug diagnostics
+
+  USB_PUTS( "\nEFM32 USB LED Vendor Unique Device example\n" );
+
+  USBD_Init( &initstruct );   // GO !
+
+  //When using a debugger it is pratical to uncomment the following three
+  //lines to force host to re-enumerate the device.
+
+  //USBD_Disconnect();
+  //USBTIMER_DelayMs( 1000 );
+  //USBD_Connect();
+
+  for (;;) {}
+} @endverbatim
+
+  @n Configure the device stack in <em>usbconfig.h</em>: @n @n
+  @verbatim
+#define USB_DEVICE                        // Compile stack for device mode.
+
+// **************************************************************************
+**                                                                         **
+** Specify number of endpoints used (in addition to EP0).                  **
+**                                                                         **
+*****************************************************************************
+#define NUM_EP_USED 0                     // EP0 is the only endpoint used.
+
+// **************************************************************************
+**                                                                         **
+** Configure serial port debug output.                                     **
+**                                                                         **
+*****************************************************************************
+// Prototype a function for transmitting a single char on the serial port.
+extern int RETARGET_WriteChar(char c);
+#define USER_PUTCHAR RETARGET_WriteChar
+
+// Enable debug diagnostics from API functions (illegal input params etc.)
+#define DEBUG_USB_API @endverbatim
+
+  @n Define device properties and fill in USB initstruct in
+  <em>descriptors.h</em>: @n @n
+  @verbatim
+EFM32_ALIGN(4)
+static const USB_DeviceDescriptor_TypeDef deviceDesc __attribute__ ((aligned(4))) =
+{
+  .bLength            = USB_DEVICE_DESCSIZE,
+  .bDescriptorType    = USB_DEVICE_DESCRIPTOR,
+  .bcdUSB             = 0x0200,
+  .bDeviceClass       = 0xFF,
+  .bDeviceSubClass    = 0,
+  .bDeviceProtocol    = 0,
+  .bMaxPacketSize0    = USB_FS_CTRL_EP_MAXSIZE,
+  .idVendor           = 0x10C4,
+  .idProduct          = 0x0001,
+  .bcdDevice          = 0x0000,
+  .iManufacturer      = 1,
+  .iProduct           = 2,
+  .iSerialNumber      = 3,
+  .bNumConfigurations = 1
+};
+
+EFM32_ALIGN(4)
+static const uint8_t configDesc[] __attribute__ ((aligned(4)))=
+{
+  // *** Configuration descriptor ***
+  USB_CONFIG_DESCSIZE,            // bLength
+  USB_CONFIG_DESCRIPTOR,          // bDescriptorType
+  USB_CONFIG_DESCSIZE +           // wTotalLength (LSB)
+  USB_INTERFACE_DESCSIZE,
+  (USB_CONFIG_DESCSIZE +          // wTotalLength (MSB)
+  USB_INTERFACE_DESCSIZE)>>8,
+  1,                              // bNumInterfaces
+  1,                              // bConfigurationValue
+  0,                              // iConfiguration
+  CONFIG_DESC_BM_RESERVED_D7 |    // bmAttrib: Self powered
+  CONFIG_DESC_BM_SELFPOWERED,
+  CONFIG_DESC_MAXPOWER_mA( 100 ), // bMaxPower: 100 mA
+
+  // *** Interface descriptor ***
+  USB_INTERFACE_DESCSIZE,         // bLength
+  USB_INTERFACE_DESCRIPTOR,       // bDescriptorType
+  0,                              // bInterfaceNumber
+  0,                              // bAlternateSetting
+  NUM_EP_USED,                    // bNumEndpoints
+  0xFF,                           // bInterfaceClass
+  0,                              // bInterfaceSubClass
+  0,                              // bInterfaceProtocol
+  0,                              // iInterface
+};
+
+STATIC_CONST_STRING_DESC_LANGID( langID, 0x04, 0x09 );
+STATIC_CONST_STRING_DESC( iManufacturer, 'E','n','e','r','g','y',' ',       \
+                                         'M','i','c','r','o',' ','A','S' );
+STATIC_CONST_STRING_DESC( iProduct     , 'V','e','n','d','o','r',' ',       \
+                                         'U','n','i','q','u','e',' ',       \
+                                         'L','E','D',' ',                   \
+                                         'D','e','v','i','c','e' );
+STATIC_CONST_STRING_DESC( iSerialNumber, '0','0','0','0','0','0',           \
+                                         '0','0','1','2','3','4' );
+
+static const void * const strings[] =
+{
+  &langID,
+  &iManufacturer,
+  &iProduct,
+  &iSerialNumber
+};
+
+// Endpoint buffer sizes
+// 1 = single buffer, 2 = double buffering, 3 = tripple buffering ...
+static const uint8_t bufferingMultiplier[ NUM_EP_USED + 1 ] = { 1 };
+
+static const USBD_Callbacks_TypeDef callbacks =
+{
+  .usbReset        = NULL,
+  .usbStateChange  = NULL,
+  .setupCmd        = SetupCmd,
+  .isSelfPowered   = NULL,
+  .sofInt          = NULL
+};
+
+static const USBD_Init_TypeDef initstruct =
+{
+  .deviceDescriptor    = &deviceDesc,
+  .configDescriptor    = configDesc,
+  .stringDescriptors   = strings,
+  .numberOfStrings     = sizeof(strings)/sizeof(void*),
+  .callbacks           = &callbacks,
+  .bufferingMultiplier = bufferingMultiplier
+};  @endverbatim
+
+  @n Now we have to implement vendor unique USB setup commands to control the
+  LED's (see callbacks variable above). Notice that the buffer variable below is
+  statically allocated because @htmlonly USBD_Write() @endhtmlonly only
+  initiates the transfer. When the host actually performs the transfer, the
+  SetupCmd() function will have returned ! @n @n
+
+  @verbatim
+#define VND_GET_LEDS 0x10
+#define VND_SET_LED  0x11
+
+static int SetupCmd( const USB_Setup_TypeDef *setup )
+{
+  int retVal;
+  uint16_t leds;
+  static uint32_t buffer;
+  uint8_t *pBuffer = (uint8_t*)&buffer;
+
+  retVal = USB_STATUS_REQ_UNHANDLED;
+
+  if ( setup->Type == USB_SETUP_TYPE_VENDOR )
+  {
+    switch ( setup->bRequest )
+    {
+      case VND_GET_LEDS:
+      // ********************
+        *pBuffer = BSP_LedsGet() & 0x1F;
+        retVal = USBD_Write( 0, pBuffer, setup->wLength, NULL );
+        break;
+
+      case VND_SET_LED:
+      // ********************
+        leds = DVK_getLEDs() & 0x1F;
+        if ( setup->wValue )
+        {
+          leds |= LED0 << setup->wIndex;
+        }
+        else
+        {
+          leds &= ~( LED0 << setup->wIndex );
+        }
+        BSP_LedsSet( leds );
+        retVal = USB_STATUS_OK;
+        break;
+    }
+  }
+
+  return retVal;
+}@endverbatim
+
+ * @}**************************************************************************/
+
+#endif /* defined( USB_DEVICE ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/src/em_usbdep.c	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,446 @@
+/**************************************************************************//**
+ * @file em_usbdep.c
+ * @brief USB protocol stack library, USB device endpoint handlers.
+ * @version 3.20.14
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE )
+
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#include "em_usbd.h"
+
+#ifdef USB_USE_PRINTF
+static const char *epStatusStr[] = {
+    "IDLE","TRANS","RECV","IN_S","OUT_S"
+};
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+/*
+ * USBDEP_Ep0Handler() is called each time a packet has been transmitted
+ * or recieved on the default endpoint.
+ * A state machine navigate us through the phases of a control transfer
+ * according to "chapter 9" in the USB spec.
+ */
+#if !defined( USB_DOEP0INT_STUPPKTRCVD )
+void USBDEP_Ep0Handler( USBD_Device_TypeDef *device )
+{
+  int status;
+  USBD_Ep_TypeDef *ep;
+  static bool statusIn;
+  static uint32_t xferred;
+  static USB_XferCompleteCb_TypeDef callback;
+
+  ep = &device->ep[ 0 ];
+
+#ifdef __MBED__
+
+  (void)xferred;
+  (void)statusIn;
+  (void)status;
+
+  USB_PRINTF("USBDEP: ep0 %s, rem %ld, z %d\n", epStatusStr[ep->state], ep->remaining, ep->zlp);
+
+  if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
+  {
+    ep->state = D_EP_IDLE;
+
+    if ( ep->xferCompleteCb )
+    {
+      callback = ep->xferCompleteCb;
+      ep->xferCompleteCb = NULL;
+      callback( USB_STATUS_OK, ep->xferred, ep->remaining );
+    }
+
+    USBDHAL_ReenableEp0Setup(device);
+  }
+  else
+  {
+    device->callbacks->setupCmd(device->setup);
+  }
+
+#else /* not __MBED__ */
+
+  switch ( ep->state )
+  {
+    case D_EP_IDLE:
+      ep->remaining = 0;
+      ep->zlp = 0;
+      callback = NULL;
+      statusIn = false;
+
+      status = USBDCH9_SetupCmd( device );
+
+      if ( status == USB_STATUS_REQ_ERR )
+      {
+        ep->in = true;
+        USBDHAL_StallEp( ep );              /* Stall Ep0 IN                 */
+        ep->in = false;                     /* OUT for next SETUP           */
+        USBDHAL_StallEp( ep );              /* Stall Ep0 OUT                */
+        USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP packet*/
+      }
+      else /* ( Status == USB_STATUS_OK ) */
+      {
+        if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) )
+        {
+          callback = ep->xferCompleteCb;
+        }
+
+        if ( ep->state != D_EP_RECEIVING )
+        {
+          if ( ep->remaining )
+          {
+            /* Data will be sent to host, check if a ZLP must be appended */
+            if ( ( ep->remaining < device->setup->wLength ) &&
+                 ( ep->remaining % ep->packetSize == 0    )    )
+            {
+              ep->zlp = 1;
+            }
+          }
+          else
+          {
+            /* Prepare for next SETUP packet*/
+            USBDHAL_ReenableEp0Setup( device );
+
+            /* No data stage, a ZLP may have been sent. If not, send one */
+
+            xferred = 0;
+            if ( ep->zlp == 0 )
+            {
+              USBD_Write( 0, NULL, 0, NULL );             /* ACK to host */
+              ep->state = D_EP0_IN_STATUS;
+            }
+            else
+            {
+              ep->state = D_EP_IDLE;
+              ep->in = false;                      /* OUT for next SETUP */
+            }
+          }
+        }
+      }
+      break;
+
+    case D_EP_RECEIVING:
+      if ( ep->remaining )
+      {
+        /* There is more data to receive */
+        USBD_ReArmEp0( ep );
+      }
+      else
+      {
+        status = USB_STATUS_OK;
+        if ( callback != NULL )
+        {
+          status = callback( USB_STATUS_OK, ep->xferred, 0 );
+          callback = NULL;
+        }
+
+        if ( status != USB_STATUS_OK )
+        {
+          ep->in = true;
+          USBDHAL_StallEp( ep );              /* Stall Ep0 IN                */
+          ep->in = false;                     /* OUT for next SETUP           */
+          USBDHAL_StallEp( ep );              /* Stall Ep0 OUT                */
+          USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP pkt. */
+          ep->state = D_EP_IDLE;
+        }
+        else /* Everything OK, send a ZLP (ACK) to host */
+        {
+          USBDHAL_ReenableEp0Setup( device );/* Prepare for next SETUP packet*/
+
+          ep->state = D_EP_IDLE;              /* USBD_Write() sets state back*/
+                                              /* to EP_TRANSMITTING          */
+          USBD_Write( 0, NULL, 0, NULL );
+          ep->state = D_EP0_IN_STATUS;
+        }
+      }
+      break;
+
+    case D_EP_TRANSMITTING:
+      if ( ep->remaining )
+      {
+        /* There is more data to transmit */
+        USBD_ReArmEp0( ep );
+      }
+      else
+      {
+        /* All data transferred, is a ZLP packet needed ? */
+        if ( ep->zlp == 1 )
+        {
+          xferred   = ep->xferred;
+          ep->state = D_EP_IDLE;          /* USBD_Write() sets state back */
+                                          /* to EP_TRANSMITTING           */
+          USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP                     */
+          ep->zlp = 2;
+        }
+        else
+        {
+          if ( ep->zlp == 0 )
+          {
+            xferred = ep->xferred;
+          }
+
+          ep->state = D_EP_IDLE;
+          USBD_Read( 0, NULL, 0, NULL );  /* Get ZLP packet (ACK) from host */
+          statusIn = true;
+          ep->state = D_EP0_OUT_STATUS;
+        }
+      }
+      break;
+
+    case D_EP0_IN_STATUS:
+    case D_EP0_OUT_STATUS:
+      if ( statusIn )
+      {
+        USBDHAL_ReenableEp0Setup( device );
+      }
+
+      if ( callback != NULL )
+      {
+        callback( USB_STATUS_OK, xferred, 0 );
+      }
+
+      ep->state = D_EP_IDLE;
+      ep->in = false;                     /* OUT for next SETUP */
+      break;
+
+    default:
+      EFM_ASSERT( false );
+      break;
+  }
+#endif /* __MBED__ */
+}
+#endif
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+void USBDEP_Ep0Handler( USBD_Device_TypeDef *device )
+{
+  int status;
+  USBD_Ep_TypeDef *ep;
+  static uint32_t xferred;
+  static USB_XferCompleteCb_TypeDef callback;
+
+#ifdef __MBED__
+
+  (void)xferred;
+  (void)status;
+
+  ep = &device->ep[ 0 ];
+
+  if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
+  {
+    ep->state = D_EP_IDLE;
+
+    if ( ep->xferCompleteCb )
+    {
+      callback = ep->xferCompleteCb;
+      ep->xferCompleteCb = NULL;
+      callback( USB_STATUS_OK, ep->xferred, ep->remaining );
+    }
+
+    USBDHAL_StartEp0Setup( dev );
+  }
+  else
+  {
+    device->callbacks->setupCmd(device->setup);
+  }
+
+#else
+
+  ep = &device->ep[ 0 ];
+
+  switch ( ep->state )
+  {
+    case D_EP_IDLE:
+      ep->zlp       = 0;
+      ep->remaining = 0;
+      callback      = NULL;
+
+      status = USBDCH9_SetupCmd( device );
+
+      if ( status == USB_STATUS_REQ_ERR )
+      {
+        ep->in = true;
+        USBDHAL_StallEp( ep );              /* Stall Ep0 IN                 */
+        ep->in = false;                     /* OUT for next SETUP           */
+        USBDHAL_StallEp( ep );              /* Stall Ep0 OUT                */
+        USBDHAL_StartEp0Setup( dev );       /* Prepare for next SETUP packet*/
+      }
+      else /* ( Status == USB_STATUS_OK ) */
+      {
+        if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) )
+        {
+          callback = ep->xferCompleteCb;
+        }
+
+        if ( ep->state != D_EP_RECEIVING )
+        {
+          if ( ep->remaining )
+          {
+            /* Data will be sent to host, check if a ZLP must be appended */
+            if ( ( ep->remaining < device->setup->wLength ) &&
+                 ( ep->remaining % ep->packetSize == 0    )    )
+            {
+              ep->zlp = 1;
+            }
+          }
+          else
+          {
+            /* No data stage, a ZLP may have been sent. If not, send one */
+            xferred = 0;
+            if ( ep->zlp == 0 )
+            {
+              ep->state = D_EP_IDLE;
+              USBD_Write( 0, NULL, 0, NULL );             /* ACK to host */
+              ep->state = D_EP0_IN_STATUS;
+            }
+          }
+        }
+      }
+      break;
+
+    case D_EP_RECEIVING:
+      if ( ep->remaining )
+      {
+        ep->in = false;
+        USBD_ReArmEp0( ep );
+      }
+      else
+      {
+        status = USB_STATUS_OK;
+        if ( callback != NULL )
+        {
+          status = callback( USB_STATUS_OK, ep->xferred, 0 );
+          callback = NULL;
+        }
+
+        if ( status != USB_STATUS_OK )
+        {
+          ep->in = true;
+          USBDHAL_StallEp( ep );              /* Stall Ep0 IN                */
+          ep->in = false;                     /* OUT for next SETUP          */
+          USBDHAL_StallEp( ep );              /* Stall Ep0 OUT               */
+          USBDHAL_StartEp0Setup( dev );       /* Prepare for next SETUP pkt. */
+          ep->state = D_EP_IDLE;
+        }
+        else
+        {
+
+          USBDHAL_StartEp0Setup( dev );      /* Prepare for next SETUP packet*/
+          ep->state = D_EP_IDLE;             /* USBD_Write() sets state back */
+                                             /* to EP_TRANSMITTING           */
+          USBD_Write( 0, NULL, 0, NULL );
+          ep->state = D_EP0_IN_STATUS;
+        }
+      }
+      break;
+
+    case D_EP_TRANSMITTING:
+      if ( ep->remaining )
+      {
+        ep->in = true;
+        USBD_ReArmEp0( ep );
+      }
+      else
+      {
+        if ( ep->zlp == 1 )
+        {
+          xferred   = ep->xferred;
+          ep->state = D_EP_IDLE;          /* USBD_Write() sets state back */
+                                          /* to EP_TRANSMITTING           */
+          USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP                     */
+          ep->zlp = 2;
+        }
+        else
+        {
+          if ( ep->zlp == 0 )
+          {
+            xferred = ep->xferred;
+          }
+
+          ep->state = D_EP_IDLE;
+          USBD_Read( 0, NULL, 0, NULL );  /* Get ZLP packet (ACK) from host */
+          ep->state = D_EP0_OUT_STATUS;
+        }
+      }
+      break;
+
+    case D_EP0_IN_STATUS:
+      if ( ( USB->DOEP0CTL & USB_DOEP0CTL_EPENA ) == 0 )
+      {
+        /* Prepare for more SETUP Packets */
+        USBDHAL_StartEp0Setup( dev );
+      }
+      if ( callback != NULL )
+      {
+        callback( USB_STATUS_OK, xferred, 0 );
+      }
+      ep->state = D_EP_IDLE;
+      ep->in = false;                     /* OUT for next SETUP */
+      break;
+
+    case D_EP0_OUT_STATUS:
+      USBDHAL_StartEp0Setup( dev );       /* Prepare for more SETUP Packets */
+      if ( callback != NULL )
+      {
+        callback( USB_STATUS_OK, xferred, 0 );
+      }
+      ep->state = D_EP_IDLE;
+      ep->in = false;                     /* OUT for next SETUP */
+      break;
+  }
+#endif /* __MBED__ */
+}
+#endif
+
+/*
+ * USBDEP_EpHandler() is called each time a packet has been transmitted
+ * or recieved on an endpoint other than the default endpoint.
+ */
+void USBDEP_EpHandler( uint8_t epAddr )
+{
+  USB_XferCompleteCb_TypeDef callback;
+  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
+
+  if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
+  {
+    ep->state = D_EP_IDLE;
+    if ( ep->xferCompleteCb )
+    {
+      callback = ep->xferCompleteCb;
+      ep->xferCompleteCb = NULL;
+      callback( USB_STATUS_OK, ep->xferred, ep->remaining );
+    }
+  }
+  else
+  {
+    EFM_ASSERT( false );
+  }
+}
+
+/** @endcond */
+
+#endif /* defined( USB_DEVICE ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/src/em_usbdint.c	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,946 @@
+/**************************************************************************//**
+ * @file em_usbdint.c
+ * @brief USB protocol stack library, USB device peripheral interrupt handlers.
+ * @version 3.20.14
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE )
+
+#include "em_cmu.h"
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#include "em_usbd.h"
+
+#ifdef __MBED__
+extern void usbhal_allow_em2(bool em2_allow);
+#endif
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#define HANDLE_INT( x ) if ( status & x ) { Handle_##x(); status &= ~x; }
+
+static void Handle_USB_GINTSTS_ENUMDONE  ( void );
+static void Handle_USB_GINTSTS_IEPINT    ( void );
+static void Handle_USB_GINTSTS_OEPINT    ( void );
+static void Handle_USB_GINTSTS_RESETDET  ( void );
+static void Handle_USB_GINTSTS_SOF       ( void );
+static void Handle_USB_GINTSTS_USBRST    ( void );
+static void Handle_USB_GINTSTS_USBSUSP   ( void );
+static void Handle_USB_GINTSTS_WKUPINT   ( void );
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep );
+#else
+static void ProcessSetup                 ( void );
+static void ProcessOepData               ( USBD_Ep_TypeDef *ep );
+#endif
+
+#if ( USB_PWRSAVE_MODE )
+/* Variables and prototypes for USB powerdown (suspend) functionality. */
+static bool UsbPowerDown( void );
+static bool UsbPowerUp( void );
+
+volatile bool USBD_poweredDown = false;
+
+/* Storage for backing up USB core registers. */
+static uint32_t  x_USB_GINTMSK;
+#if defined(_USB_GOTGCTL_MASK)
+static uint32_t  x_USB_GOTGCTL;
+#endif
+static uint32_t  x_USB_GAHBCFG;
+static uint32_t  x_USB_GUSBCFG;
+static uint32_t  x_USB_GRXFSIZ;
+static uint32_t  x_USB_GNPTXFSIZ;
+static uint32_t  x_USB_DCFG;
+static uint32_t  x_USB_DCTL;
+static uint32_t  x_USB_DAINTMSK;
+static uint32_t  x_USB_DIEPMSK;
+static uint32_t  x_USB_DOEPMSK;
+static uint32_t  x_USB_PCGCCTL;
+
+#if ( NUM_EP_USED > 0 )
+static uint32_t  x_USB_EP_CTL[ NUM_EP_USED ];
+static uint32_t  x_USB_EP_TSIZ[ NUM_EP_USED ];
+static uint32_t  x_USB_EP_DMAADDR[ NUM_EP_USED ];
+#endif
+
+#if ( NUM_EP_USED > MAX_NUM_TX_FIFOS )
+#define FIFO_CNT MAX_NUM_TX_FIFOS
+#else
+#define FIFO_CNT NUM_EP_USED
+#endif
+
+#if ( FIFO_CNT > 0 )
+static uint32_t  x_USB_DIEPTXFS[ FIFO_CNT ];
+#endif
+
+#if ( USB_PWRSAVE_MODE )
+static uint32_t cmuStatus = 0;
+#endif
+
+#endif /* if ( USB_PWRSAVE_MODE ) */
+
+/*
+ * USB_IRQHandler() is the first level handler for the USB peripheral interrupt.
+ */
+void USB_IRQHandler( void )
+{
+  uint32_t status;
+  bool servedVbusInterrupt = false;
+
+  INT_Disable();
+
+#if ( USB_PWRSAVE_MODE )
+  if ( USBD_poweredDown )
+  {
+    /* Switch USBC clock from 32kHz to a 48MHz clock to be able to  */
+    /* read USB peripheral registers.                               */
+    /* If we woke up from EM2, HFCLK is now HFRCO.                  */
+
+    /* Restore clock oscillators.*/
+#if defined( CMU_OSCENCMD_USHFRCOEN )
+    if ( ( CMU->STATUS & CMU_STATUS_USHFRCOENS ) == 0 )/*Wakeup from EM2 ?*/
+    {
+      CMU->OSCENCMD = ( cmuStatus
+                        & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS ) )
+                      | CMU_OSCENCMD_USHFRCOEN;
+    }
+#else
+    if ( ( CMU->STATUS & CMU_STATUS_HFXOENS ) == 0 ) /* Wakeup from EM2 ? */
+    {
+      CMU->OSCENCMD = cmuStatus
+                      & ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS );
+    }
+#endif
+
+    /* Select correct USBC clock.*/
+#if defined( CMU_OSCENCMD_USHFRCOEN )
+    CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
+    while ( ( CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL ) == 0 ){}
+#else
+    CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
+    while ( ( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) == 0 ){}
+#endif
+  }
+#endif /* if ( USB_PWRSAVE_MODE ) */
+
+  if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) )
+  {
+    if ( USB->IF & USB_IF_VREGOSH )
+    {
+      USB->IFC = USB_IFC_VREGOSH;
+
+      if ( USB->STATUS & USB_STATUS_VREGOS )
+      {
+        servedVbusInterrupt = true;
+        DEBUG_USB_INT_LO_PUTS( "\nVboN" );
+
+#if ( USB_PWRSAVE_MODE )
+        if ( UsbPowerUp() )
+        {
+          USBDHAL_EnableUsbResetAndSuspendInt();
+        }
+        USBD_SetUsbState( USBD_STATE_POWERED );
+#endif
+      }
+    }
+
+    if ( USB->IF & USB_IF_VREGOSL )
+    {
+      USB->IFC = USB_IFC_VREGOSL;
+
+      if ( ( USB->STATUS & USB_STATUS_VREGOS ) == 0 )
+      {
+        servedVbusInterrupt = true;
+        DEBUG_USB_INT_LO_PUTS( "\nVboF" );
+
+#if ( USB_PWRSAVE_MODE )
+#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
+        if ( !USBD_poweredDown )
+        {
+          USB->GINTMSK = 0;
+          USB->GINTSTS = 0xFFFFFFFF;
+        }
+
+        UsbPowerDown();
+#endif
+        USBD_SetUsbState( USBD_STATE_NONE );
+#endif
+      }
+    }
+  }
+
+  status = USBHAL_GetCoreInts();
+  if ( status == 0 )
+  {
+    INT_Enable();
+    if ( !servedVbusInterrupt )
+    {
+      DEBUG_USB_INT_LO_PUTS( "\nSinT" );
+    }
+    return;
+  }
+
+  HANDLE_INT( USB_GINTSTS_RESETDET   )
+  HANDLE_INT( USB_GINTSTS_WKUPINT    )
+  HANDLE_INT( USB_GINTSTS_USBSUSP    )
+  HANDLE_INT( USB_GINTSTS_SOF        )
+  HANDLE_INT( USB_GINTSTS_ENUMDONE   )
+  HANDLE_INT( USB_GINTSTS_USBRST     )
+  HANDLE_INT( USB_GINTSTS_IEPINT     )
+  HANDLE_INT( USB_GINTSTS_OEPINT     )
+
+  INT_Enable();
+
+  if ( status != 0 )
+  {
+    DEBUG_USB_INT_LO_PUTS( "\nUinT" );
+  }
+}
+
+/*
+ * Handle port enumeration interrupt. This has nothing to do with normal
+ * device enumeration.
+ */
+static void Handle_USB_GINTSTS_ENUMDONE( void )
+{
+#if ( USB_PWRSAVE_MODE )
+  UsbPowerUp();
+#endif
+
+  USBDHAL_Ep0Activate( dev->ep0MpsCode );
+  dev->ep[ 0 ].state = D_EP_IDLE;
+  USBDHAL_EnableInts( dev );
+  DEBUG_USB_INT_LO_PUTS( "EnumD" );
+}
+
+/*
+ * Handle IN endpoint transfer interrupt.
+ */
+static void Handle_USB_GINTSTS_IEPINT( void )
+{
+  int epnum;
+  uint16_t epint;
+  uint16_t epmask;
+  uint32_t status;
+  USBD_Ep_TypeDef *ep;
+
+  DEBUG_USB_INT_HI_PUTCHAR( 'i' );
+
+  epint = USBDHAL_GetAllInEpInts();
+  for ( epnum = 0,                epmask = 1;
+        epnum <= MAX_NUM_IN_EPS;
+        epnum++,                  epmask <<= 1 )
+  {
+    if ( epint & epmask )
+    {
+      ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | epnum );
+      status = USBDHAL_GetInEpInts( ep );
+
+      if ( status & USB_DIEP_INT_XFERCOMPL )
+      {
+        USB_DINEPS[ epnum ].INT = USB_DIEP_INT_XFERCOMPL;
+
+        DEBUG_USB_INT_HI_PUTCHAR( 'c' );
+
+        if ( epnum == 0 )
+        {
+          if ( ep->remaining > ep->packetSize )
+          {
+            ep->remaining -= ep->packetSize;
+            ep->xferred += ep->packetSize;
+          }
+          else
+          {
+            ep->xferred += ep->remaining;
+            ep->remaining = 0;
+          }
+          USBDEP_Ep0Handler( dev );
+        }
+        else
+        {
+          ep->xferred = ep->remaining -
+                        ( ( USB_DINEPS[ epnum ].TSIZ      &
+                            _USB_DIEP_TSIZ_XFERSIZE_MASK    ) >>
+                          _USB_DIEP_TSIZ_XFERSIZE_SHIFT          );
+          ep->remaining -= ep->xferred;
+
+          USBDEP_EpHandler( ep->addr );
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+          if ( USB_DINEPS[ ep->num ].INT & USB_DIEP_INT_NAKINTRPT )
+          {
+            USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_NAKINTRPT;
+          }
+#endif
+        }
+      }
+    }
+  }
+}
+
+/*
+ * Handle OUT endpoint transfer interrupt.
+ */
+static void Handle_USB_GINTSTS_OEPINT( void )
+{
+  int epnum;
+  uint16_t epint;
+  uint16_t epmask;
+  uint32_t status;
+  USBD_Ep_TypeDef *ep;
+
+  DEBUG_USB_INT_HI_PUTCHAR( 'o' );
+
+  epint = USBDHAL_GetAllOutEpInts();
+  for ( epnum = 0,                epmask = 1;
+        epnum <= MAX_NUM_OUT_EPS;
+        epnum++,                  epmask <<= 1 )
+  {
+    if ( epint & epmask )
+    {
+      ep = USBD_GetEpFromAddr( epnum );
+      status = USBDHAL_GetOutEpInts( ep );
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+      HandleOutEpIntr( status, ep );
+#else
+      if ( status & USB_DOEP_INT_XFERCOMPL )
+      {
+        USB_DOUTEPS[ epnum ].INT = USB_DOEP_INT_XFERCOMPL;
+        DEBUG_USB_INT_HI_PUTCHAR( 'c' );
+        ProcessOepData( ep );
+      }
+
+      /* Setup Phase Done */
+      if ( status & USB_DOEP0INT_SETUP )
+      {
+        ProcessSetup();
+      }
+#endif
+    }
+  }
+}
+
+#if !defined( USB_DOEP0INT_STUPPKTRCVD )
+static void ProcessOepData( USBD_Ep_TypeDef *ep )
+{
+  if ( ep->num == 0 )
+  {
+
+#ifdef __MBED__
+    int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK )
+                                      >> _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
+    int setup_pkt_received = USBDHAL_GetOutEpInts( ep ) & USB_DOEP0INT_SETUP;
+
+    if ( (!setup_pkt_received && xfer_size == 0) ||
+         (setup_pkt_received && xfer_size == 8) )
+    {
+      /* Higher levels need to see the correct transfer amount for ZLPs */
+      ep->remaining = 0;
+      ep->xferred = 0;
+    }
+    else
+    {
+      /* FIXME - does not work if actual read size > 56 */
+      if ( setup_pkt_received ) xfer_size -= 8;
+
+      ep->xferred = xfer_size;
+      ep->remaining -= xfer_size;
+    }
+#else
+    if ( ep->remaining > ep->packetSize )
+    {
+      ep->remaining -= ep->packetSize;
+      ep->xferred += ep->packetSize;
+    }
+    else
+    {
+      ep->xferred += ep->remaining;
+      ep->remaining = 0;
+    }
+#endif
+
+    USBDEP_Ep0Handler( dev );
+  }
+  else
+  {
+    ep->xferred = ep->hwXferSize -
+        ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
+          _USB_DOEP_TSIZ_XFERSIZE_SHIFT );
+    ep->remaining -= ep->xferred;
+    USBDEP_EpHandler( ep->addr );
+  }
+}
+#endif
+
+#if !defined( USB_DOEP0INT_STUPPKTRCVD )
+static void ProcessSetup( void )
+{
+  DEBUG_USB_INT_LO_PUTS( "\nS" );
+
+  if ( USB->DOEP0INT & USB_DOEP0INT_BACK2BACKSETUP )
+  {                           /* Back to back setup packets received */
+    USB->DOEP0INT = USB_DOEP0INT_BACK2BACKSETUP;
+    DEBUG_USB_INT_LO_PUTS( "B2B" );
+
+    dev->setup = (USB_Setup_TypeDef*)( USB->DOEP0DMAADDR - USB_SETUP_PKT_SIZE );
+  }
+  else
+  {
+    /* Read SETUP packet counter from hw. */
+    int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
+                 >> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+
+    if ( supCnt == 3 )
+      supCnt = 2;
+
+    dev->setup = &dev->setupPkt[ 2 - supCnt ];
+  }
+  USB->DOEP0TSIZ |= 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+  USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
+  USB->DOEP0INT = USB_DOEP0INT_SETUP;
+
+  USBDEP_Ep0Handler( dev );   /* Call the SETUP handler for EP0 */
+}
+#endif
+
+/*
+ * Handle USB reset detected interrupt in suspend mode.
+ */
+static void Handle_USB_GINTSTS_RESETDET  ( void )
+{
+#if ( USB_PWRSAVE_MODE )
+  if ( ! USBD_poweredDown )
+  {
+    USB->GINTSTS = USB_GINTSTS_RESETDET;
+  }
+
+  if ( UsbPowerUp() )
+  {
+    USB->GINTSTS = USB_GINTSTS_RESETDET;
+  }
+
+#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
+  /* Power down immediately if VBUS is off. */
+  if ( ! ( USB->STATUS & USB_STATUS_VREGOS ) )
+  {
+    UsbPowerDown();
+  }
+#endif
+
+#else
+  USB->GINTSTS = USB_GINTSTS_RESETDET;
+#endif /* if ( USB_PWRSAVE_MODE ) */
+
+  if ( USB->STATUS & USB_STATUS_VREGOS )
+  {
+    USBD_SetUsbState( USBD_STATE_DEFAULT );
+  }
+  else
+  {
+    USBD_SetUsbState( USBD_STATE_NONE );
+  }
+  DEBUG_USB_INT_LO_PUTS( "RsuP\n" );
+}
+
+/*
+ * Handle Start Of Frame (SOF) interrupt.
+ */
+static void Handle_USB_GINTSTS_SOF( void )
+{
+  USB->GINTSTS = USB_GINTSTS_SOF;
+
+  if ( dev->callbacks->sofInt )
+  {
+    dev->callbacks->sofInt(
+      ( USB->DSTS & _USB_DSTS_SOFFN_MASK ) >> _USB_DSTS_SOFFN_SHIFT );
+  }
+}
+
+/*
+ * Handle USB port reset interrupt.
+ */
+static void Handle_USB_GINTSTS_USBRST( void )
+{
+  int i;
+
+  DEBUG_USB_INT_LO_PUTS( "ReseT" );
+
+  /* Clear Remote Wakeup Signalling */
+  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
+  USBHAL_FlushTxFifo( 0 );
+
+  /* Clear pending interrupts */
+  for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
+  {
+    USB_DINEPS[ i ].INT = 0xFFFFFFFF;
+  }
+
+  for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
+  {
+    USB_DOUTEPS[ i ].INT = 0xFFFFFFFF;
+  }
+
+  USB->DAINTMSK = USB_DAINTMSK_INEPMSK0 | USB_DAINTMSK_OUTEPMSK0;
+#if defined( USB_DOEPMSK_STSPHSERCVDMSK )
+  USB->DOEPMSK  = USB_DOEPMSK_SETUPMSK  | USB_DOEPMSK_XFERCOMPLMSK
+                  | USB_DOEPMSK_STSPHSERCVDMSK;
+#else
+  USB->DOEPMSK  = USB_DOEPMSK_SETUPMSK  | USB_DOEPMSK_XFERCOMPLMSK;
+#endif
+  USB->DIEPMSK  = USB_DIEPMSK_XFERCOMPLMSK;
+
+  /* Reset Device Address */
+  USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK;
+
+  /* Setup EP0 to receive SETUP packets */
+  USBDHAL_StartEp0Setup( dev );
+  USBDHAL_EnableInts( dev );
+
+  if ( dev->callbacks->usbReset )
+  {
+    dev->callbacks->usbReset();
+  }
+
+  USBD_SetUsbState( USBD_STATE_DEFAULT );
+  USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_RESET );
+}
+
+/*
+ * Handle USB port suspend interrupt.
+ */
+static void Handle_USB_GINTSTS_USBSUSP( void )
+{
+  USBD_State_TypeDef state;
+
+  USB->GINTSTS = USB_GINTSTS_USBSUSP;
+  USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_SUSPENDED );
+  DEBUG_USB_INT_LO_PUTS( "\nSusP" );
+
+  if ( USBD_GetUsbState() == USBD_STATE_NONE )
+  {
+    USBD_SetUsbState( USBD_STATE_POWERED );
+  }
+
+  state = USBD_GetUsbState();
+  if ( ( state == USBD_STATE_POWERED    ) ||
+       ( state == USBD_STATE_DEFAULT    ) ||
+       ( state == USBD_STATE_ADDRESSED  ) ||
+       ( state == USBD_STATE_CONFIGURED )    )
+  {
+#if ( USB_PWRSAVE_MODE )
+    UsbPowerDown();
+#endif
+    USBD_SetUsbState( USBD_STATE_SUSPENDED );
+  }
+}
+
+/*
+ * Handle USB port wakeup interrupt.
+ */
+static void Handle_USB_GINTSTS_WKUPINT( void )
+{
+#if ( USB_PWRSAVE_MODE )
+  if ( ! USBD_poweredDown )
+  {
+    USB->GINTSTS = USB_GINTSTS_WKUPINT;
+  }
+
+  if ( UsbPowerUp() )
+  {
+    USB->GINTSTS = USB_GINTSTS_WKUPINT;
+    USBDHAL_StartEp0Setup( dev );
+    USBDHAL_Ep0Activate( dev->ep0MpsCode );
+  }
+#else
+  USB->GINTSTS = USB_GINTSTS_WKUPINT;
+#endif
+
+  USBD_SetUsbState( dev->savedState );
+  DEBUG_USB_INT_LO_PUTS( "WkuP\n" );
+}
+
+#if ( USB_PWRSAVE_MODE )
+/*
+ * Backup essential USB core registers, and set the core in partial powerdown
+ * mode. Optionally prepare entry into EM2.
+ */
+static bool UsbPowerDown( void )
+{
+#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
+  int i;
+#endif
+#if ( NUM_EP_USED > 0 )
+  int epNum;
+  USBD_Ep_TypeDef *ep;
+#endif
+
+  if ( !USBD_poweredDown )
+  {
+    USBD_poweredDown = true;
+    DEBUG_USB_INT_LO_PUTCHAR( '\\' );
+
+    /* Backup USB core registers. */
+    x_USB_GINTMSK   = USB->GINTMSK;
+#if defined(_USB_GOTGCTL_MASK)
+    x_USB_GOTGCTL   = USB->GOTGCTL;
+#endif
+    x_USB_GAHBCFG   = USB->GAHBCFG;
+    x_USB_GUSBCFG   = USB->GUSBCFG;
+    x_USB_GRXFSIZ   = USB->GRXFSIZ;
+    x_USB_GNPTXFSIZ = USB->GNPTXFSIZ;
+    x_USB_DCFG      = USB->DCFG;
+    x_USB_DCTL      = USB->DCTL;
+    x_USB_DAINTMSK  = USB->DAINTMSK;
+    x_USB_DIEPMSK   = USB->DIEPMSK;
+    x_USB_DOEPMSK   = USB->DOEPMSK;
+    x_USB_PCGCCTL   = USB->PCGCCTL;
+
+#if ( NUM_EP_USED > 0 )
+    for ( i = 0; i < NUM_EP_USED; i++ )
+    {
+      ep = &dev->ep[ i+1 ];
+      epNum = ep->num;
+      if ( ep->in )
+      {
+        x_USB_EP_CTL[     i ] = USB_DINEPS[ epNum ].CTL;
+        x_USB_EP_TSIZ[    i ] = USB_DINEPS[ epNum ].TSIZ;
+        x_USB_EP_DMAADDR[ i ] = USB_DINEPS[ epNum ].DMAADDR;
+      }
+      else
+      {
+        x_USB_EP_CTL[     i ] = USB_DOUTEPS[ epNum ].CTL;
+        x_USB_EP_TSIZ[    i ] = USB_DOUTEPS[ epNum ].TSIZ;
+        x_USB_EP_DMAADDR[ i ] = USB_DOUTEPS[ epNum ].DMAADDR;
+      }
+    }
+#endif
+
+#if ( FIFO_CNT > 0 )
+    for ( i = 0; i < FIFO_CNT; i++ )
+    {
+      x_USB_DIEPTXFS[ i ] = USB_DIEPTXFS[ i ];
+    }
+#endif
+
+    /* Prepare for wakeup on resume and reset. */
+    USB->DCFG    = (USB->DCFG & ~_USB_DCFG_RESVALID_MASK) |
+                   (4 << _USB_DCFG_RESVALID_SHIFT);
+    USB->DCFG   |= USB_DCFG_ENA32KHZSUSP;
+    USB->GINTMSK = USB_GINTMSK_RESETDETMSK | USB_GINTMSK_WKUPINTMSK;
+
+    /* Enter partial powerdown mode. */
+    USB->PCGCCTL |= USB_PCGCCTL_PWRCLMP;
+    USB->PCGCCTL |= USB_PCGCCTL_RSTPDWNMODULE;
+    USB->PCGCCTL |= USB_PCGCCTL_STOPPCLK;
+
+    /* Record current clock settings. */
+    cmuStatus = CMU->STATUS;
+
+#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
+#ifndef __MBED__
+    /* Enter EM2 on interrupt exit. */
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk;
+#else
+    usbhal_allow_em2(true);
+#endif
+#endif
+
+    /* Switch USBC clock to 32 kHz. */
+#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
+    CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
+    while ( ( CMU->STATUS & CMU_STATUS_USBCLFXOSEL ) == 0 ){}
+#else
+    CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
+    while ( ( CMU->STATUS & CMU_STATUS_USBCLFRCOSEL ) == 0 ){}
+#endif
+
+    return true;
+  }
+  return false;
+}
+#endif /* if ( USB_PWRSAVE_MODE ) */
+
+#if ( USB_PWRSAVE_MODE )
+/*
+ * Exit USB core partial powerdown mode, restore essential USB core registers.
+ * Will prevent re-entry back to EM2.
+ * Returns true if a powerup sequence was performed.
+ */
+static bool UsbPowerUp( void )
+{
+#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
+  int i;
+#endif
+#if ( NUM_EP_USED > 0 )
+  int epNum;
+  uint32_t tmp;
+  USBD_Ep_TypeDef *ep;
+#endif
+
+  if ( USBD_poweredDown )
+  {
+    USBD_poweredDown = false;
+    DEBUG_USB_INT_LO_PUTCHAR( '/' );
+
+#if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN )
+    /* Switch HFCLK from HFRCO to HFXO. */
+    CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
+#endif
+
+    /* Turn off HFRCO when not needed. */
+    if ( ( cmuStatus & CMU_STATUS_HFRCOENS ) == 0 )
+    {
+      CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
+    }
+
+    /* Exit partial powerdown mode. */
+    USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
+    USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE);
+
+    if (( USB->GINTSTS & ( USB_GINTSTS_WKUPINT | USB_GINTSTS_RESETDET ) ) == 0)
+    {
+      USB->DCTL = x_USB_DCTL | USB_DCTL_RMTWKUPSIG;
+      USB->DCTL = x_USB_DCTL;
+    }
+
+    /* Restore USB core registers. */
+    USB->GUSBCFG = x_USB_GUSBCFG;
+    USB->DCFG    = x_USB_DCFG;
+
+#if ( FIFO_CNT > 0 )
+    for ( i = 0; i < FIFO_CNT; i++ )
+    {
+      USB_DIEPTXFS[ i ] = x_USB_DIEPTXFS[ i ];
+    }
+#endif
+
+#if ( NUM_EP_USED > 0 )
+    for ( i = 0; i < NUM_EP_USED; i++ )
+    {
+      ep = &dev->ep[ i+1 ];
+      epNum = ep->num;
+
+      tmp = x_USB_EP_CTL[ i ] &
+            ~( USB_DIEP_CTL_CNAK       | USB_DIEP_CTL_SNAK       |
+               USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF   );
+
+      if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_DPIDEOF )
+        tmp |= USB_DIEP_CTL_SETD1PIDOF;
+      else
+        tmp |= USB_DIEP_CTL_SETD0PIDEF;
+
+      if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_NAKSTS )
+        tmp |= USB_DIEP_CTL_SNAK;
+      else
+        tmp |= USB_DIEP_CTL_CNAK;
+
+      if ( ep->in )
+      {
+        USB_DINEPS[ epNum ].CTL     = tmp;
+        USB_DINEPS[ epNum ].TSIZ    = x_USB_EP_TSIZ[    i ];
+        USB_DINEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
+      }
+      else
+      {
+        USB_DOUTEPS[ epNum ].CTL     = tmp;
+        USB_DOUTEPS[ epNum ].TSIZ    = x_USB_EP_TSIZ[    i ];
+        USB_DOUTEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
+      }
+    }
+#endif
+
+    USB->PCGCCTL   = x_USB_PCGCCTL;
+    USB->DOEPMSK   = x_USB_DOEPMSK;
+    USB->DIEPMSK   = x_USB_DIEPMSK;
+    USB->DAINTMSK  = x_USB_DAINTMSK;
+    USB->DCTL      = x_USB_DCTL;
+    USB->GNPTXFSIZ = x_USB_GNPTXFSIZ;
+    USB->GRXFSIZ   = x_USB_GRXFSIZ;
+    USB->GAHBCFG   = x_USB_GAHBCFG;
+#if defined(_USB_GOTGCTL_MASK)
+    USB->GOTGCTL   = x_USB_GOTGCTL;
+#endif
+    USB->GINTMSK   = x_USB_GINTMSK;
+
+    USB->DCTL |= USB_DCTL_PWRONPRGDONE;
+
+#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
+#ifndef __MBED__
+    /* Do not reenter EM2 on interrupt exit. */
+    SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk);
+#else
+    usbhal_allow_em2(false);
+#endif
+#endif
+
+    return true;
+  }
+  return false;
+}
+#endif /* if ( USB_PWRSAVE_MODE ) */
+
+#if defined( USB_DOEP0INT_STUPPKTRCVD )
+static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep )
+{
+  uint32_t doeptsiz;
+
+  if ( ep->num == 0 )
+  {
+    if ( status & USB_DOEP0INT_XFERCOMPL )
+    {
+      USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL;
+      doeptsiz      = USB->DOEP0TSIZ;
+
+      if ( ep->state == D_EP_IDLE )
+      {
+        if ( status & USB_DOEP0INT_STUPPKTRCVD )
+        {
+          USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD;
+        }
+        status = USBDHAL_GetOutEpInts( ep );
+        doeptsiz = USB->DOEP0TSIZ;
+
+        if ( status & USB_DOEP0INT_SETUP )
+        {
+retry:
+          /* Already started data stage, clear setup */
+          USB->DOEP0INT = USB_DOEP0INT_SETUP;
+          status       &= ~USB_DOEP0INT_SETUP;
+          {
+            int supCnt = ( doeptsiz & _USB_DOEP0TSIZ_SUPCNT_MASK )
+                         >> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+
+            if ( supCnt == 3 )
+              supCnt = 2;
+
+            dev->setup = &dev->setupPkt[ 2 - supCnt ];
+          }
+          DEBUG_USB_INT_LO_PUTS( "\nS" );
+          USBDEP_Ep0Handler( dev );
+
+          /* Prepare for more setup packets */
+          if ( ep->state == D_EP0_IN_STATUS || ep->state == D_EP_TRANSMITTING )
+          {
+            USBDHAL_StartEp0Setup( dev );
+          }
+        }
+        else /* xfercompl && idle && !setup */
+        {
+            status = USBDHAL_GetOutEpInts( ep );
+            if ( status & USB_DOEP0INT_SETUP )
+              goto retry;
+            USBDHAL_StartEp0Setup( dev );
+        }
+      }
+      else /* ep0state != EP0_IDLE */
+      {
+#ifdef __MBED__
+        if ( ep->state == D_EP_RECEIVING )
+        {
+          int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK )
+                                            >> _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
+          int setup_pkt_received = status & USB_DOEP0INT_SETUP;
+
+          if ( (!setup_pkt_received && xfer_size == 0) ||
+               (setup_pkt_received && xfer_size == 8) )
+          {
+            /* Higher levels need to see the correct transfer amount for ZLPs */
+            ep->remaining = 0;
+            ep->xferred = 0;
+          }
+          else
+          {
+            /* FIXME - does not work if actual read size > 56 */
+            if ( setup_pkt_received ) xfer_size -= 8;
+
+            ep->xferred = xfer_size;
+            ep->remaining -= xfer_size;
+          }
+
+          USBDEP_Ep0Handler( dev );
+        }
+#else
+        if ( ep->state == D_EP_RECEIVING )
+        {
+          if ( ep->remaining > ep->packetSize )
+          {
+            ep->remaining -= ep->packetSize;
+            ep->xferred += ep->packetSize;
+          }
+          else
+          {
+            ep->xferred += ep->remaining;
+            ep->remaining = 0;
+          }
+          USBDEP_Ep0Handler( dev );
+        }
+        else if ( ep->state == D_EP0_OUT_STATUS )
+        {
+          USBDEP_Ep0Handler( dev );
+        }
+#endif
+      }
+    } /* if ( status & USB_DOEP0INT_XFERCOMPL ) */
+
+    if ( status & USB_DOEP0INT_STSPHSERCVD )
+    {
+      USB->DOEP0INT = USB_DOEP0INT_STSPHSERCVD;
+    }
+
+    if ( status & USB_DOEP0INT_SETUP )
+    {
+      USB->DOEP0INT = USB_DOEP0INT_SETUP;
+      {
+        int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
+                     >> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
+
+        if ( supCnt == 3 )
+          supCnt = 2;
+
+        dev->setup = &dev->setupPkt[ 2 - supCnt ];
+      }
+      DEBUG_USB_INT_LO_PUTS( "\nS" );
+      USBDEP_Ep0Handler( dev );
+    }
+  }
+  else /* epnum != 0 */
+  {
+    if ( status & USB_DOEP_INT_XFERCOMPL )
+    {
+      USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_XFERCOMPL;
+
+      ep->xferred = ep->hwXferSize -
+          ( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
+            _USB_DOEP_TSIZ_XFERSIZE_SHIFT );
+      ep->remaining -= ep->xferred;
+
+      USBDEP_EpHandler( ep->addr );
+    }
+  }
+}
+#endif
+
+/** @endcond */
+
+#endif /* defined( USB_DEVICE ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/src/em_usbhal.c	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,799 @@
+/**************************************************************************//**
+ * @file em_usbhal.c
+ * @brief USB protocol stack library, low level USB peripheral access.
+ * @version 3.20.14
+ ******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * 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 "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#if defined( USB_DEVICE )
+#include "em_usbd.h"
+#endif
+#if defined( USB_HOST )
+#include "em_usbh.h"
+#endif
+#include "em_cmu.h"
+#include "em_gpio.h"
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#define EPABORT_BREAK_LOOP_COUNT 15000              /* Approx. 100 ms */
+
+/* NOTE: The sequence of error message strings must agree with the    */
+/*       definition of USB_Status_TypeDef enum.                       */
+static const char * const errMsg[] =
+{
+  [  USB_STATUS_OK                  ] = "No errors",
+  [ -USB_STATUS_REQ_ERR             ] = "Setup request error",
+  [ -USB_STATUS_EP_BUSY             ] = "Endpoint is busy",
+  [ -USB_STATUS_REQ_UNHANDLED       ] = "Setup request not handled",
+  [ -USB_STATUS_ILLEGAL             ] = "Illegal operation attempted",
+  [ -USB_STATUS_EP_STALLED          ] = "Endpoint is stalled",
+  [ -USB_STATUS_EP_ABORTED          ] = "Transfer aborted",
+  [ -USB_STATUS_EP_ERROR            ] = "Transfer error",
+  [ -USB_STATUS_EP_NAK              ] = "Endpoint NAK",
+  [ -USB_STATUS_DEVICE_UNCONFIGURED ] = "Device is not configured",
+  [ -USB_STATUS_DEVICE_SUSPENDED    ] = "Device is suspended",
+  [ -USB_STATUS_DEVICE_RESET        ] = "Device has been reset",
+  [ -USB_STATUS_TIMEOUT             ] = "Transfer timeout",
+  [ -USB_STATUS_DEVICE_REMOVED      ] = "Device removed",
+  [ -USB_STATUS_HC_BUSY             ] = "Host channel is busy",
+  [ -USB_STATUS_DEVICE_MALFUNCTION  ] = "Device malfunction",
+  [ -USB_STATUS_PORT_OVERCURRENT    ] = "VBUS overcurrent",
+};
+/** @endcond */
+
+
+/***************************************************************************//**
+ * @brief
+ *   Return an error message string for a given error code.
+ *
+ * @param[in] error
+ *   Error code, see \ref USB_Status_TypeDef.
+ *
+ * @return
+ *   Error message string pointer.
+ ******************************************************************************/
+char *USB_GetErrorMsgString( int error )
+{
+  if ( error >= 0 )
+    return (char*)errMsg[ 0 ];
+
+  return (char*)errMsg[ -error ];
+}
+
+
+#if defined( USB_USE_PRINTF )
+/***************************************************************************//**
+ * @brief
+ *   Format and print a text string given an error code, prepends an optional user
+ *   supplied leader string.
+ *
+ * @param[in] pre
+ *   Optional leader string to prepend to error message string.
+ *
+ * @param[in] error
+ *   Error code, see \ref USB_Status_TypeDef.
+ ******************************************************************************/
+void USB_PrintErrorMsgString( char *pre, int error )
+{
+  if ( pre )
+  {
+    USB_PRINTF( "%s", pre );
+  }
+
+  if ( error > USB_STATUS_OK )
+  {
+    USB_PRINTF( "%d", error );
+  }
+  else
+  {
+    USB_PRINTF( "%s", USB_GetErrorMsgString( error ) );
+  }
+}
+#endif /* defined( USB_USE_PRINTF ) */
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#if defined( DEBUG_EFM_USER )
+static void PrintI( int i )
+{
+#if !defined ( USER_PUTCHAR )
+  (void)i;
+#else
+  if ( i >= 10 )
+  {
+    PrintI( i / 10 );
+  }
+
+  DEBUG_USB_API_PUTCHAR( ( i % 10 ) + '0' );
+#endif
+}
+
+void assertEFM( const char *file, int line )
+{
+#if !defined ( USER_PUTCHAR )
+  (void)file;
+#endif
+
+  DEBUG_USB_API_PUTS( "\nASSERT " );
+  DEBUG_USB_API_PUTS( file );
+  DEBUG_USB_API_PUTCHAR( ' ' );
+  PrintI( line );
+  for(;;){}
+}
+#endif /* defined( DEBUG_EFM_USER ) */
+
+#if defined ( USER_PUTCHAR )
+void USB_Puts( const char *p )
+{
+  while( *p )
+    USB_PUTCHAR( *p++ );
+}
+#endif /* defined ( USER_PUTCHAR ) */
+
+void USBHAL_CoreReset( void )
+{
+  USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
+  USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE);
+
+  /* Core Soft Reset */
+  USB->GRSTCTL |= USB_GRSTCTL_CSFTRST;
+  while ( USB->GRSTCTL & USB_GRSTCTL_CSFTRST ) {}
+
+  USBTIMER_DelayUs( 1 );
+
+  /* Wait for AHB master IDLE state. */
+  while ( !( USB->GRSTCTL & USB_GRSTCTL_AHBIDLE ) ) {}
+}
+
+#ifdef USB_DEVICE
+void USBDHAL_Connect( void )
+{
+  USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_SFTDISCON );
+}
+
+USB_Status_TypeDef USBDHAL_CoreInit( uint32_t totalRxFifoSize,
+                                     uint32_t totalTxFifoSize )
+{
+  uint8_t i, j;
+  uint16_t start, depth;
+  USBD_Ep_TypeDef *ep;
+
+#if !defined( USB_VBUS_SWITCH_NOT_PRESENT )
+  CMU_ClockEnable( cmuClock_GPIO, true );
+  GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
+  USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN;  /* Enable PHY pins.  */
+#else
+  USB->ROUTE = USB_ROUTE_PHYPEN;                        /* Enable PHY pins.  */
+#endif
+
+  USBHAL_CoreReset();                                   /* Reset USB core    */
+
+#if defined( USB_GUSBCFG_FORCEHSTMODE )
+  /* Force Device Mode */
+  USB->GUSBCFG = ( USB->GUSBCFG                                    &
+                  ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE )  ) |
+                 USB_GUSBCFG_FORCEDEVMODE;
+#endif
+
+  INT_Enable();
+  USBTIMER_DelayMs( 50 );
+  INT_Disable();
+
+  /* Set device speed */
+  USB->DCFG = ( USB->DCFG & ~_USB_DCFG_DEVSPD_MASK ) | 3; /* Full speed PHY */
+
+  /* Stall on non-zero len status OUT packets (ctrl transfers). */
+  USB->DCFG |= USB_DCFG_NZSTSOUTHSHK;
+
+  /* Set periodic frame interval to 80% */
+  USB->DCFG &= ~_USB_DCFG_PERFRINT_MASK;
+
+  USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
+                 USB_GAHBCFG_DMAEN | USB_GAHBCFG_HBSTLEN_INCR;
+
+  /* Ignore frame numbers on ISO transfers. */
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_IGNRFRMNUM;
+
+  /* Set Rx FIFO size */
+  start = EFM32_MAX( totalRxFifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+  USB->GRXFSIZ = ( start << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
+                 _USB_GRXFSIZ_RXFDEP_MASK;
+
+  /* Set Tx EP0 FIFO size */
+  depth = EFM32_MAX( dev->ep[ 0 ].fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+  USB->GNPTXFSIZ = ( ( depth << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
+                     _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK                 ) |
+                   ( ( start << _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
+                     _USB_GNPTXFSIZ_NPTXFSTADDR_MASK                      );
+
+
+  /* Set Tx EP FIFO sizes for all IN ep's */
+  for ( j = 1; j <= MAX_NUM_TX_FIFOS; j++ )
+  {
+    for ( i = 1; i <= MAX_NUM_IN_EPS; i++ )
+    {
+      ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | i );
+      if ( ep )                             /* Is EP in use ? */
+      {
+        if ( ep->txFifoNum == j )           /* Is it correct FIFO number ? */
+        {
+          start += depth;
+          depth = EFM32_MAX( ep->fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+          USB_DIEPTXFS[ ep->txFifoNum - 1 ] =
+                              ( depth << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT   ) |
+                              ( start &  _USB_DIEPTXF1_INEPNTXFSTADDR_MASK );
+        }
+      }
+    }
+  }
+
+  if ( totalRxFifoSize + totalTxFifoSize > MAX_DEVICE_FIFO_SIZE_INWORDS )
+    return USB_STATUS_ILLEGAL;
+
+  if ( start > MAX_DEVICE_FIFO_SIZE_INWORDS )
+    return USB_STATUS_ILLEGAL;
+
+  /* Flush the FIFO's */
+  USBHAL_FlushTxFifo( 0x10 );      /* All Tx FIFO's */
+  USBHAL_FlushRxFifo();            /* The Rx FIFO   */
+
+  /* Disable all device interrupts */
+  USB->DIEPMSK  = 0;
+  USB->DOEPMSK  = 0;
+  USB->DAINTMSK = 0;
+  USB->DIEPEMPMSK = 0;
+
+  /* Disable all EP's, clear all EP ints. */
+  for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
+  {
+    USB_DINEPS[ i ].CTL  = 0;
+    USB_DINEPS[ i ].TSIZ = 0;
+    USB_DINEPS[ i ].INT  = 0xFFFFFFFF;
+  }
+
+  for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
+  {
+    USB_DOUTEPS[ i ].CTL  = 0;
+    USB_DOUTEPS[ i ].TSIZ = 0;
+    USB_DOUTEPS[ i ].INT  = 0xFFFFFFFF;
+  }
+
+#if ( USB_DCTL_SFTDISCON_DEFAULT != 0 )
+  USBD_Connect();
+#endif
+
+  /* Enable VREGO sense. */
+  USB->CTRL |= USB_CTRL_VREGOSEN;
+  USB->IFC   = USB_IFC_VREGOSH | USB_IFC_VREGOSL;
+  USB->IEN   = USB_IFC_VREGOSH | USB_IFC_VREGOSL;
+  /* Force a VREGO interrupt. */
+  if ( USB->STATUS & USB_STATUS_VREGOS)
+    USB->IFS = USB_IFS_VREGOSH;
+  else
+    USB->IFS = USB_IFS_VREGOSL;
+
+  return USB_STATUS_OK;
+}
+
+USB_Status_TypeDef USBDHAL_ReconfigureFifos( uint32_t totalRxFifoSize,
+                                             uint32_t totalTxFifoSize )
+{
+  uint8_t i, j;
+  uint16_t start, depth;
+  USBD_Ep_TypeDef *ep;
+
+  /* Set Rx FIFO size */
+  start = EFM32_MAX( totalRxFifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+  USB->GRXFSIZ = ( start << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
+                 _USB_GRXFSIZ_RXFDEP_MASK;
+
+  /* Set Tx EP0 FIFO size */
+  depth = EFM32_MAX( dev->ep[ 0 ].fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+  USB->GNPTXFSIZ = ( ( depth << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
+                     _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK                 ) |
+                   ( ( start << _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
+                     _USB_GNPTXFSIZ_NPTXFSTADDR_MASK                      );
+
+
+  /* Set Tx EP FIFO sizes for all IN ep's */
+  for ( j = 1; j <= MAX_NUM_TX_FIFOS; j++ )
+  {
+    for ( i = 1; i <= MAX_NUM_IN_EPS; i++ )
+    {
+      ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | i );
+      if ( ep )                             /* Is EP in use ? */
+      {
+        if ( ep->txFifoNum == j )           /* Is it correct FIFO number ? */
+        {
+          start += depth;
+          depth = EFM32_MAX( ep->fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
+          USB_DIEPTXFS[ ep->txFifoNum - 1 ] =
+                              ( depth << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT   ) |
+                              ( start &  _USB_DIEPTXF1_INEPNTXFSTADDR_MASK );
+        }
+      }
+    }
+  }
+
+  if ( totalRxFifoSize + totalTxFifoSize > MAX_DEVICE_FIFO_SIZE_INWORDS )
+    return USB_STATUS_ILLEGAL;
+
+  if ( start > MAX_DEVICE_FIFO_SIZE_INWORDS )
+    return USB_STATUS_ILLEGAL;
+
+  /* Flush the FIFO's */
+  USBHAL_FlushTxFifo( 0x10 );      /* All Tx FIFO's */
+  USBHAL_FlushRxFifo();            /* The Rx FIFO   */
+
+  return USB_STATUS_OK;
+}
+
+void USBDHAL_Disconnect( void )
+{
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SFTDISCON;
+}
+
+void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep )
+{
+  /* Clear epdis & inepnakeff INT's */
+  USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
+                               USB_DIEP_INT_INEPNAKEFF;
+
+  /* Enable epdis & inepnakeff INT's */
+  USB->DIEPMSK |= USB_DIEPMSK_EPDISBLDMSK | USB_DIEPMSK_INEPNAKEFFMSK;
+  USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL  &
+                                ~DEPCTL_WO_BITMASK           ) |
+                              USB_DIEP_CTL_SNAK;
+
+  /* Wait for inepnakeff INT */
+  while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF ) ) {}
+  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
+  USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
+
+  DEBUG_USB_INT_LO_PUTCHAR( '.' );
+
+  USBDHAL_SetEPDISNAK( ep );
+  /* Wait for epdis INT */
+  while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD ) ) {}
+  USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
+  USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK;
+  USBHAL_FlushTxFifo( ep->txFifoNum );
+
+  /* Clear any interrupts generated by the abort sequence. */
+  NVIC_ClearPendingIRQ( USB_IRQn );
+
+  DEBUG_USB_INT_LO_PUTCHAR( '.' );
+}
+
+void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep )
+{
+  int cnt;
+
+  /* Clear epdis INT's */
+  USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
+
+  /* Clear Global OUT NAK if already set */
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
+  USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK;    /* Enable GOUTNAKEFF int */
+
+  /* Set Global OUT NAK */
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
+
+  /* Wait for goutnakeff */
+  cnt = EPABORT_BREAK_LOOP_COUNT;
+  while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
+  {
+    cnt--;
+  }
+
+  USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int  */
+  USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK;    /* Enable EPDIS interrupt  */
+
+  DEBUG_USB_INT_LO_PUTCHAR( ',' );
+
+  USBDHAL_SetEPDISNAK( ep );                  /* Disable ep */
+
+  /* Wait for epdis INT */
+  cnt = EPABORT_BREAK_LOOP_COUNT;
+  while ( !( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD ) && cnt )
+  {
+    cnt--;
+  }
+
+  USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
+  USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK;     /* Disable EPDIS interrupt */
+
+  /* Clear Global OUT NAK */
+  USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
+
+  /* Clear any interrupts generated by the abort sequence. */
+  NVIC_ClearPendingIRQ( USB_IRQn );
+
+  DEBUG_USB_INT_LO_PUTCHAR( ',' );
+}
+
+void USBDHAL_AbortAllEps( void )
+{
+  int i, cnt;
+  USBD_Ep_TypeDef *ep;
+  uint16_t im, om, inmask=0, outmask=0;
+
+  /* Clear epdis & inepnakeff INT's */
+  for ( i = 1; i <= NUM_EP_USED; i++ )
+  {
+    ep = &dev->ep[i];
+    if ( ep->state != D_EP_IDLE )
+    {
+      if ( ep->in )
+      {
+        inmask |= ep->mask;
+        USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
+                                     USB_DIEP_INT_INEPNAKEFF;
+      }
+      else
+      {
+        outmask |= ep->mask;
+        USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
+      }
+    }
+  }
+
+  if ( inmask )
+  {
+    /* Enable epdis & inepnakeff INT's */
+    USB->DIEPMSK |= USB_DIEPMSK_EPDISBLDMSK | USB_DIEPMSK_INEPNAKEFFMSK;
+
+    /* Set NAK on all IN ep's */
+    im = inmask;
+    for ( i = 1; i <= NUM_EP_USED; i++ )
+    {
+      ep = &dev->ep[i];
+      if ( im & ep->mask )
+      {
+        USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
+                                      ~DEPCTL_WO_BITMASK          ) |
+                                    USB_DIEP_CTL_SNAK;
+      }
+    }
+  }
+
+  if ( outmask )
+  {
+    /* Clear Global OUT NAK if already set */
+    USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
+
+    USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK;    /* Enable GOUTNAKEFF int */
+
+    /* Set Global OUT NAK */
+    USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
+
+    /* Wait for goutnakeff */
+    cnt = EPABORT_BREAK_LOOP_COUNT;
+    while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
+    {
+      cnt--;
+    }
+    USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int  */
+    USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK;    /* Enable EPDIS interrupt  */
+  }
+
+  if ( inmask )
+  {
+    /* Wait for inepnakeff INT on all IN ep's */
+    im  = inmask;
+    cnt = EPABORT_BREAK_LOOP_COUNT;
+    do
+    {
+      for ( i = 1; i <= NUM_EP_USED; i++ )
+      {
+        ep = &dev->ep[i];
+        if ( im & ep->mask )
+        {
+          if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF )
+          {
+            USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
+            im &= ~ep->mask;
+          }
+        }
+      }
+      cnt--;
+    } while ( im && cnt );
+    USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
+  }
+
+  DEBUG_USB_INT_LO_PUTCHAR( '\'' );
+
+  /* Disable ep's */
+  for ( i = 1; i <= NUM_EP_USED; i++ )
+  {
+    ep = &dev->ep[i];
+    if ( ep->state != D_EP_IDLE )
+    {
+      USBDHAL_SetEPDISNAK( ep );
+    }
+  }
+
+  /* Wait for epdis INT */
+  im  = inmask;
+  om  = outmask;
+  cnt = EPABORT_BREAK_LOOP_COUNT;
+  do
+  {
+    for ( i = 1; i <= NUM_EP_USED; i++ )
+    {
+      ep = &dev->ep[i];
+      if ( ep->in && ( im & ep->mask ) )
+      {
+        if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD )
+        {
+          USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
+          im &= ~ep->mask;
+        }
+      }
+
+      if ( !ep->in && ( om & ep->mask ) )
+      {
+        if ( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD )
+        {
+          USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
+          om &= ~ep->mask;
+        }
+      }
+    }
+    cnt--;
+  } while ( ( im || om ) && cnt );
+
+  if ( inmask )
+  {
+    USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK;     /* Disable EPDIS interrupt */
+    USBHAL_FlushTxFifo( 0x10 );                   /* Flush all Tx FIFO's     */
+  }
+
+  if ( outmask )
+  {
+    USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK;     /* Disable EPDIS interrupt */
+    /* Clear Global OUT NAK */
+    USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
+  }
+
+  DEBUG_USB_INT_LO_PUTCHAR( '\'' );
+}
+
+void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason )
+{
+  int i;
+  USBD_Ep_TypeDef *ep;
+  USB_XferCompleteCb_TypeDef callback;
+
+  if ( reason != USB_STATUS_DEVICE_RESET )
+  {
+    USBDHAL_AbortAllEps();
+  }
+
+  for ( i = 1; i <= NUM_EP_USED; i++ )
+  {
+    ep = &(dev->ep[i]);
+    if ( ep->state != D_EP_IDLE )
+    {
+      ep->state = D_EP_IDLE;
+      if ( ep->xferCompleteCb )
+      {
+        callback = ep->xferCompleteCb;
+        ep->xferCompleteCb = NULL;
+
+        if ( ( dev->lastState == USBD_STATE_CONFIGURED ) &&
+             ( dev->state     == USBD_STATE_ADDRESSED  )    )
+        {
+          USBDHAL_DeactivateEp( ep );
+        }
+
+        DEBUG_TRACE_ABORT( reason );
+        callback( reason, ep->xferred, ep->remaining );
+      }
+    }
+  }
+
+  /* Clear any interrupts generated by the abort sequence. */
+  NVIC_ClearPendingIRQ( USB_IRQn );
+}
+#endif /* defined( USB_DEVICE ) */
+
+#if defined( USB_HOST )
+USB_Status_TypeDef USBHHAL_CoreInit( uint32_t rxFifoSize,
+                                     uint32_t nptxFifoSize,
+                                     uint32_t ptxFifoSize )
+{
+  uint8_t i;
+
+  rxFifoSize   /= 4;              /* Convert from byte count to word count.  */
+  nptxFifoSize /= 4;
+  ptxFifoSize  /= 4;
+
+  CMU_ClockEnable( cmuClock_GPIO, true );
+  GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
+
+#if ( USB_VBUSOVRCUR_PORT != USB_VBUSOVRCUR_PORT_NONE )
+  /* Enable VBUS overcurrent flag pin. */
+  GPIO_PinModeSet( USB_VBUSOVRCUR_PORT, USB_VBUSOVRCUR_PIN, gpioModeInput, 0 );
+#endif
+
+  USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN;  /* Enable PHY pins.  */
+  USBHAL_CoreReset();                                   /* Reset USB core    */
+
+  /* Force Host Mode */
+  USB->GUSBCFG = ( USB->GUSBCFG                                     &
+                   ~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEDEVMODE )  ) |
+                 USB_GUSBCFG_FORCEHSTMODE;
+
+  INT_Enable();
+  USBTIMER_DelayMs( 100 );
+  INT_Disable();
+
+  /* Set 48 MHz PHY clock, FS/LS mode */
+  USB->HCFG = ( USB->HCFG & ~_USB_HCFG_FSLSPCLKSEL_MASK ) |
+              ( 1 << _USB_HCFG_FSLSPCLKSEL_SHIFT        ) |
+              ( USB_HCFG_FSLSSUPP                       );
+
+  USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
+                 USB_GAHBCFG_DMAEN | USB_GAHBCFG_HBSTLEN_INCR;
+
+  /* Set Rx FIFO size */
+  USB->GRXFSIZ = ( rxFifoSize << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
+                 _USB_GRXFSIZ_RXFDEP_MASK;
+
+  /* Set Tx FIFO sizes */
+  USB->GNPTXFSIZ = ( ( nptxFifoSize <<
+                       _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
+                     _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK        ) |
+                   ( ( rxFifoSize <<
+                       _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT      ) &
+                     _USB_GNPTXFSIZ_NPTXFSTADDR_MASK             );
+
+  USB->HPTXFSIZ  = ( ( ptxFifoSize  << _USB_HPTXFSIZ_PTXFSIZE_SHIFT   ) &
+                     _USB_HPTXFSIZ_PTXFSIZE_MASK                          ) |
+                   ( ( ( rxFifoSize + nptxFifoSize )
+                                    << _USB_HPTXFSIZ_PTXFSTADDR_SHIFT ) &
+                     _USB_HPTXFSIZ_PTXFSTADDR_MASK                        );
+
+  /* Flush Tx and Rx FIFO's */
+  USBHAL_FlushTxFifo( 0x10 );
+  USBHAL_FlushRxFifo();
+
+  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
+  {
+    USB->HC[ i ].CHAR = USB_HC_CHAR_CHDIS;      /* Disable channel          */
+    USB->HC[ i ].INT = 0xFFFFFFFF;              /* Clear pending interrupts */
+  }
+
+  /* Enable and halt all channels */
+  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
+  {
+    USB->HC[ i ].CHAR |= USB_HC_CHAR_CHDIS | USB_HC_CHAR_CHENA;
+    do
+    {
+      __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
+    }
+    while ( USB->HC[ i ].CHAR & USB_HC_CHAR_CHENA );
+  }
+
+  /* Disable all interrupts */
+  for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
+  {
+    USB->HC[ i ].INTMSK = 0;
+  }
+
+  USB->HAINTMSK = 0;
+
+  return USB_STATUS_OK;
+}
+
+void USBHHAL_HCHalt( int hcnum, uint32_t hcchar )
+{
+  hcchar |= USB_HC_CHAR_CHENA | USB_HC_CHAR_CHDIS;
+  USB->HC[ hcnum ].CHAR = hcchar;
+}
+
+void USBHHAL_HCInit( int hcnum )
+{
+  USBH_Ep_TypeDef *ep;
+
+  ep = hcs[ hcnum ].ep;
+  USB->HC[ hcnum ].INT = 0xFFFFFFFF;      /* Clear all interrupt flags      */
+
+  switch ( ep->type )                     /* Enable host channel int. types */
+  {
+    case USB_EPTYPE_CTRL:
+    case USB_EPTYPE_BULK:
+    case USB_EPTYPE_INTR:
+      USB->HC[ hcnum ].INTMSK = USB_HC_INT_CHHLTD;
+      break;
+  }
+
+  hcs[ hcnum ].errorCnt = 0;
+
+  USB->HAINTMSK |= 1 << hcnum;            /* Enable host channel interrupt  */
+
+  USB->HC[ hcnum ].CHAR =                 /* Program HCCHAR register        */
+      ( ep->parentDevice->addr     <<   _USB_HC_CHAR_DEVADDR_SHIFT     ) |
+      ( ( ep->addr & USB_EPNUM_MASK ) << _USB_HC_CHAR_EPNUM_SHIFT      ) |
+      ( ep->type                   <<   _USB_HC_CHAR_EPTYPE_SHIFT      ) |
+      ( ep->packetSize             <<   _USB_HC_CHAR_MPS_SHIFT         ) |
+      ( ep->in                      ?   USB_HC_CHAR_EPDIR         : 0  ) |
+      ( ep->parentDevice->speed ==
+                           HPRT_L_SPEED >> _USB_HPRT_PRTSPD_SHIFT
+                                    ?   USB_HC_CHAR_LSPDDEV       : 0  );
+}
+
+void USBHHAL_HCStart( int hcnum )
+{
+  USBH_Hc_TypeDef *hc;
+  uint16_t packets, len;
+
+  hc = &hcs[ hcnum ];
+  hc->status = 0;
+  hc->idle = false;
+
+  if ( hc->remaining > 0 )
+  {
+    packets = ( hc->remaining + hc->ep->packetSize - 1 ) / hc->ep->packetSize;
+  }
+  else
+  {
+    packets = 1;
+  }
+
+  if ( hc->ep->in )
+  {
+    len = packets * hc->ep->packetSize;
+  }
+  else
+  {
+    len = hc->remaining;
+  }
+
+  /* Initialize the HCTSIZn register */
+  hc->hwXferSize = len;
+  USB->HC[ hcnum ].TSIZ =
+          ( ( len             << _USB_HC_TSIZ_XFERSIZE_SHIFT ) &
+                                 _USB_HC_TSIZ_XFERSIZE_MASK       ) |
+          ( ( packets         << _USB_HC_TSIZ_PKTCNT_SHIFT   ) &
+                                 _USB_HC_TSIZ_PKTCNT_MASK         ) |
+          ( ( hc->ep->toggle  << _USB_HC_TSIZ_PID_SHIFT      ) &
+                                 _USB_HC_TSIZ_PID_MASK            );
+
+  USB->HC[ hcnum ].DMAADDR = (uint32_t)hc->buf;
+
+  USBHHAL_HCActivate( hcnum,
+                      USB->HC[ hcnum ].CHAR,
+                      hc->ep->type == USB_EPTYPE_INTR );
+}
+#endif /* defined( USB_HOST ) */
+
+/** @endcond */
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/TARGET_Silicon_Labs/src/em_usbtimer.c	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,381 @@
+/***************************************************************************//**
+ * @file em_usbtimer.c
+ * @brief USB protocol stack library, timer API.
+ * @version 3.20.14
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ * 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 "em_device.h"
+#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
+#include "em_usb.h"
+#if defined( USB_DEVICE ) || defined( USB_HOST )
+#include "em_cmu.h"
+#include "em_timer.h"
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+
+#include "device_peripherals.h"
+
+/*
+ *  Use one HW timer to serve n software milisecond timers.
+ *  A timer is, when running, in a linked list of timers.
+ *  A given timers timeout period is the acculmulated timeout
+ *  of all timers preceeding it in the queue.
+ *  This makes timer start (linked list insertion) computing intensive,
+ *  but the checking of the queue at each tick very effective.
+ *             ______          ______          ______
+ *            |      |    --->|      |    --->|      |
+ *   head --> |      |   |    |      |   |    |      |
+ *            |______|---     |______|---     |______|---/ NULL
+ */
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#ifndef USB_TIMER
+#error HW platform must define the timer to use for USB
+#endif
+
+#if ( USB_TIMER == USB_TIMER0 ) && ( TIMER_COUNT >= 1 )
+  #define TIMER             TIMER0
+  #define TIMER_CLK         cmuClock_TIMER0
+  #define TIMER_IRQ         TIMER0_IRQn
+  #define TIMER_IRQHandler  TIMER0_IRQHandler
+
+#elif ( USB_TIMER == USB_TIMER1 ) && ( TIMER_COUNT >= 2 )
+  #define TIMER             TIMER1
+  #define TIMER_CLK         cmuClock_TIMER1
+  #define TIMER_IRQ         TIMER1_IRQn
+  #define TIMER_IRQHandler  TIMER1_IRQHandler
+
+#elif ( USB_TIMER == USB_TIMER2 ) && ( TIMER_COUNT >= 3 )
+  #define TIMER             TIMER2
+  #define TIMER_CLK         cmuClock_TIMER2
+  #define TIMER_IRQ         TIMER2_IRQn
+  #define TIMER_IRQHandler  TIMER2_IRQHandler
+
+#elif ( USB_TIMER == USB_TIMER3 ) && ( TIMER_COUNT == 4 )
+  #define TIMER             TIMER3
+  #define TIMER_CLK         cmuClock_TIMER3
+  #define TIMER_IRQ         TIMER3_IRQn
+  #define TIMER_IRQHandler  TIMER3_IRQHandler
+
+#else
+#error "Illegal USB TIMER definition"
+#endif
+
+typedef struct _timer
+{
+  uint32_t                  timeout;  /* Delta value relative to prev. timer */
+  struct _timer             *next;
+  USBTIMER_Callback_TypeDef callback;
+  bool                      running;
+} USBTIMER_Timer_TypeDef;
+
+#if ( NUM_QTIMERS > 0 )
+static USBTIMER_Timer_TypeDef timers[ NUM_QTIMERS ];
+static USBTIMER_Timer_TypeDef *head = NULL;
+#endif
+
+static uint32_t ticksPrMs, ticksPr1us, ticksPr10us, ticksPr100us;
+
+#if ( NUM_QTIMERS > 0 )
+
+static void TimerTick( void );
+
+void TIMER_IRQHandler( void )
+{
+  uint32_t flags;
+
+  flags = TIMER_IntGet( TIMER );
+
+  if ( flags & TIMER_IF_CC0 )
+  {
+    TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
+    TIMER_CompareSet( TIMER, 0, TIMER_CaptureGet( TIMER, 0 ) + ticksPrMs );
+    TimerTick();
+  }
+}
+#endif /* ( NUM_QTIMERS > 0 ) */
+
+static void DelayTicks( uint16_t ticks )
+{
+  uint16_t startTime;
+  volatile uint16_t now;
+
+  if ( ticks )
+  {
+    startTime = TIMER_CounterGet( TIMER );
+    do
+    {
+      now = TIMER_CounterGet(TIMER);
+    } while ( (uint16_t)( now - startTime ) < ticks );
+  }
+}
+
+/** @endcond */
+
+/** @addtogroup USB_COMMON
+ *  @{*/
+
+/***************************************************************************//**
+ * @brief
+ *   Active wait millisecond delay function. Can also be used inside
+ *   interrupt handlers.
+ *
+ * @param[in] msec
+ *   Number of milliseconds to wait.
+ ******************************************************************************/
+void USBTIMER_DelayMs( uint32_t msec )
+{
+  uint64_t totalTicks;
+
+  totalTicks = (uint64_t)ticksPrMs * msec;
+  while ( totalTicks > 20000 )
+  {
+    DelayTicks( 20000 );
+    totalTicks -= 20000;
+  }
+  DelayTicks( (uint16_t)totalTicks );
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Active wait microsecond delay function. Can also be used inside
+ *   interrupt handlers.
+ *
+ * @param[in] usec
+ *   Number of microseconds to wait.
+ ******************************************************************************/
+void USBTIMER_DelayUs( uint32_t usec )
+{
+  uint64_t totalTicks;
+
+  totalTicks = (uint64_t)ticksPr1us * usec;
+  if ( totalTicks == 0 )
+  {
+    usec /= 10;
+    totalTicks = (uint64_t)ticksPr10us * usec;
+
+    if ( totalTicks == 0 )
+    {
+      usec /= 10;
+      totalTicks = (uint64_t)ticksPr100us * usec;
+    }
+  }
+
+  while ( totalTicks > 60000 )
+  {
+    DelayTicks( 60000 );
+    totalTicks -= 60000;
+  }
+  DelayTicks( (uint16_t)totalTicks );
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Activate the hardware timer used to pace the 1 millisecond timer system.
+ *
+ * @details
+ *   Call this function whenever the HFPERCLK frequency is changed.
+ *   This function is initially called by HOST and DEVICE stack xxxx_Init()
+ *   functions.
+ ******************************************************************************/
+void USBTIMER_Init( void )
+{
+  uint32_t freq;
+  TIMER_Init_TypeDef timerInit     = TIMER_INIT_DEFAULT;
+  TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
+
+  freq = CMU_ClockFreqGet( cmuClock_HFPER );
+  ticksPrMs = ( freq + 500 ) / 1000;
+  ticksPr1us = ( freq + 500000 ) / 1000000;
+  ticksPr10us = ( freq + 50000 ) / 100000;
+  ticksPr100us = ( freq + 5000 ) / 10000;
+
+  timerCCInit.mode = timerCCModeCompare;
+  CMU_ClockEnable( TIMER_CLK, true );
+  TIMER_TopSet( TIMER, 0xFFFF );
+  TIMER_InitCC( TIMER, 0, &timerCCInit );
+  TIMER_Init( TIMER, &timerInit );
+
+#if ( NUM_QTIMERS > 0 )
+  TIMER_IntClear( TIMER, 0xFFFFFFFF );
+  TIMER_IntEnable( TIMER, TIMER_IEN_CC0 );
+  TIMER_CompareSet( TIMER, 0, TIMER_CounterGet( TIMER ) + ticksPrMs );
+  NVIC_ClearPendingIRQ( TIMER_IRQ );
+  NVIC_EnableIRQ( TIMER_IRQ );
+#endif /* ( NUM_QTIMERS > 0 ) */
+}
+
+#if ( NUM_QTIMERS > 0 ) || defined( DOXY_DOC_ONLY )
+/***************************************************************************//**
+ * @brief
+ *   Start a timer.
+ *
+ * @details
+ *   If the timer is already running, it will be restarted with new timeout.
+ *
+ * @param[in] id
+ *   Timer id (0..).
+ *
+ * @param[in] timeout
+ *   Number of milliseconds before timer will elapse.
+ *
+ * @param[in] callback
+ *   Function to be called on timer elapse, ref. @ref USBTIMER_Callback_TypeDef.
+ ******************************************************************************/
+void USBTIMER_Start( uint32_t id, uint32_t timeout,
+                     USBTIMER_Callback_TypeDef callback )
+{
+  uint32_t accumulated;
+  USBTIMER_Timer_TypeDef *this, **last;
+
+  INT_Disable();
+
+  if ( timers[ id ].running )
+  {
+    USBTIMER_Stop( id );
+  }
+
+  if ( timeout == 0 )
+  {
+    callback();
+    INT_Enable();
+    return;
+  }
+
+  timers[ id ].running  = true;
+  timers[ id ].callback = callback;
+  timers[ id ].next     = NULL;
+
+  if ( !head )                                        /* Queue empty ? */
+  {
+    timers[ id ].timeout  = timeout;
+    head = &timers[ id ];
+  }
+  else
+  {
+    this = head;
+    last = &head;
+    accumulated = 0;
+
+    /* Do a sorted insert */
+    while ( this  )
+    {
+      if ( timeout < accumulated + this->timeout )  /* Insert before "this" ? */
+      {
+        timers[ id ].timeout  = timeout - accumulated;
+        timers[ id ].next     = this;
+        *last = &timers[ id ];
+        this->timeout -= timers[ id ].timeout;        /* Adjust timeout     */
+        break;
+      }
+      else if ( this->next == NULL )                  /* At end of queue ?  */
+      {
+        timers[ id ].timeout  = timeout - accumulated - this->timeout;
+        this->next = &timers[ id ];
+        break;
+      }
+      accumulated += this->timeout;
+      last = &this->next;
+      this = this->next;
+    }
+  }
+
+  INT_Enable();
+}
+
+/***************************************************************************//**
+ * @brief
+ *   Stop a timer.
+ *
+ * @param[in] id
+ *   Timer id (0..).
+ ******************************************************************************/
+void USBTIMER_Stop( uint32_t id )
+{
+  USBTIMER_Timer_TypeDef *this, **last;
+
+  INT_Disable();
+
+  if ( head )                                           /* Queue empty ?    */
+  {
+    this = head;
+    last = &head;
+    timers[ id ].running = false;
+
+    while ( this  )
+    {
+      if ( this == &timers[ id ] )                      /* Correct timer ?  */
+      {
+        if ( this->next )
+        {
+          this->next->timeout += timers[ id ].timeout;  /* Adjust timeout   */
+        }
+        *last = this->next;
+        break;
+      }
+      last = &this->next;
+      this = this->next;
+    }
+  }
+
+  INT_Enable();
+}
+#endif /* ( NUM_QTIMERS > 0 ) */
+
+/** @} (end addtogroup USB_COMMON) */
+
+#if ( NUM_QTIMERS > 0 )
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+static void TimerTick( void )
+{
+  USBTIMER_Callback_TypeDef cb;
+
+  INT_Disable();
+
+  if ( head )
+  {
+    head->timeout--;
+
+    while ( head  )
+    {
+      if ( head->timeout == 0 )
+      {
+        cb = head->callback;
+        head->running = false;
+        head = head->next;
+        /* The callback may place new items in the queue !!! */
+        if ( cb )
+        {
+          (cb)();
+        }
+        continue; /* There might be more than one timeout pr. tick */
+      }
+      break;
+    }
+  }
+
+  INT_Enable();
+}
+/** @endcond */
+#endif /* ( NUM_QTIMERS > 0 ) */
+
+#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
+#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
--- a/USBDevice/USBEndpoints.h	Wed Jul 08 14:46:06 2015 +0100
+++ b/USBDevice/USBEndpoints.h	Thu Aug 13 15:46:06 2015 +0100
@@ -49,6 +49,8 @@
 #include "USBEndpoints_RZ_A1H.h"
 #elif defined(TARGET_Maxim)
 #include "USBEndpoints_Maxim.h"
+#elif defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32HG_STK3400)
+#include "USBEndpoints_EFM32.h"
 #else
 #error "Unknown target type"
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBEndpoints_EFM32.h	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,65 @@
+
+#ifndef TARGET_EFM32HG_STK3400
+# define NUMBER_OF_LOGICAL_ENDPOINTS   (6)
+#else
+# define NUMBER_OF_LOGICAL_ENDPOINTS   (3)
+#endif
+
+#define NUMBER_OF_PHYSICAL_ENDPOINTS  (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+#define NUMBER_OF_ENDPOINTS           (NUMBER_OF_PHYSICAL_ENDPOINTS + 2)  /* Includes EP0 */
+
+#define EP0OUT      (0)
+#define EP0IN       (1)
+#define EP1OUT      (2)
+#define EP1IN       (3)
+#define EP2OUT      (4)
+#define EP2IN       (5)
+#define EP3OUT      (6)
+#define EP3IN       (7)
+#ifndef TARGET_EFM32HG_STK3400
+# define EP4OUT     (8)
+# define EP4IN      (9)
+# define EP5OUT     (10)
+# define EP5IN      (11)
+# define EP6OUT     (12)
+# define EP6IN      (13)
+#endif
+
+#define USB_EP_TO_INDEX(ep) (ep)
+#define USB_EP_TO_ADDR(ep)  (((ep)>>1) | (((ep) & 1   ) ? 0x80 : 0x00))
+#define USB_ADDR_TO_EP(ep)  (((ep)<<1) | (((ep) & 0x80) ? 0x01 : 0x00))
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0   64
+#define MAX_PACKET_SIZE_EP1   64
+#define MAX_PACKET_SIZE_EP2   64
+#define MAX_PACKET_SIZE_EP3   64
+#ifndef TARGET_EFM32HG_STK3400
+# define MAX_PACKET_SIZE_EP4  64
+# define MAX_PACKET_SIZE_EP5  64
+# define MAX_PACKET_SIZE_EP6  64
+#endif
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoints */
+#define EPBULK_OUT            EP2OUT
+#define EPBULK_IN             EP2IN
+#define EPBULK_OUT_callback   EP2_OUT_callback
+#define EPBULK_IN_callback    EP2_IN_callback
+/* Interrupt endpoints */
+#define EPINT_OUT             EP1OUT
+#define EPINT_IN              EP1IN
+#define EPINT_OUT_callback    EP1_OUT_callback
+#define EPINT_IN_callback     EP1_IN_callback
+/* Isochronous endpoints */
+#define EPISO_OUT             EP3OUT
+#define EPISO_IN              EP3IN
+#define EPISO_OUT_callback    EP3_OUT_callback
+#define EPISO_IN_callback     EP3_IN_callback
+
+#define MAX_PACKET_SIZE_EPBULK  64
+#define MAX_PACKET_SIZE_EPINT   64
+#define MAX_PACKET_SIZE_EPISO   1023
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBHAL_EFM32.cpp	Thu Aug 13 15:46:06 2015 +0100
@@ -0,0 +1,775 @@
+/* Copyright 2015 Silicon Labs, http://www.silabs.com
+ *
+ * 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.
+ */
+
+#if defined TARGET_EFM32GG_STK3700 || \
+    defined TARGET_EFM32LG_STK3600 || \
+    defined TARGET_EFM32WG_STK3800 || \
+    defined TARGET_EFM32HG_STK3400
+
+#include "USBHAL.h"
+#include "em_usb.h"
+#include "em_usbtypes.h"
+#include "em_usbhal.h"
+#include "em_usbd.h"
+
+#include "sleepmodes.h"
+
+enum USBISRCommand {
+    CMD_HANDLED = 0,
+    CMD_EP0SETUP,
+    CMD_EP0IN,
+    CMD_EP0OUT,
+    CMD_EP_XFER_COMPLETED,
+    CMD_SOF,
+    CMD_BUSRESET,
+    CMD_SUSPEND_STATE_CHANGED,
+    CMD_ENUM_END_MARKER
+};
+
+enum IEPStatus {
+    NOT_CONFIGURED = 0,
+    IDLE = 1,
+    READ_PENDING = 2,
+    WRITE_PENDING = 3,
+    READ_COMPLETE = 4,
+    WRITE_COMPLETE = 5,
+    FAILED_INVALID = 6,
+    FAILED_STALLED = 7
+};
+
+typedef struct {
+    IEPStatus status;
+    uint32_t byte_count;
+    uint32_t max_packet;
+    USB_XferCompleteCb_TypeDef intern_cb;
+    uint8_t *data_buf;
+} ep_state_t;
+
+USBHAL * USBHAL::instance;
+static uint8_t ep0setupdata[8];
+static ep_state_t ep_state[NUMBER_OF_ENDPOINTS];
+#ifdef USB_USE_DYNAMIC_MEMORY
+static uint8_t ep0in_data_buf[MAX_PACKET_SIZE_EP0] __attribute__ ((aligned (4)));
+static uint8_t ep0out_data_buf[MAX_PACKET_SIZE_EP0]; // FIXME: does this need to be this big?
+#else
+static uint8_t ep_data_buf[NUMBER_OF_ENDPOINTS][64] __attribute__ ((aligned (4)));
+#endif
+
+static void run_cmd(USBISRCommand cmd, uint32_t param);
+static void (*isrptr)() = NULL;
+static USBISRCommand usb_isrcmd = CMD_HANDLED;
+static uint32_t usb_isrcmd_param = 0;
+
+extern "C" void usbhal_allow_em2(bool allow_em2);
+
+#ifdef DEBUG_USB_API
+#define TRACE(fmt,...)            printf("USB:   %s: " fmt "\n", __func__, __VA_ARGS__);
+#define TRACE_FUNC_IN             printf("USB: > %s\n",__func__);
+#define TRACE_FUNC_IN_P(fmt, ...) printf("USB: > %s: " fmt "\n", __func__, __VA_ARGS__);
+#else
+#define TRACE(fmt,...)
+#define TRACE_FUNC_IN
+#define TRACE_FUNC_IN_P(fmt, ...)
+#endif
+
+static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize);
+
+static int usbhal_xfer_complete_cb(uint8_t epaddr, USB_Status_TypeDef status,
+                                   uint32_t xferred, uint32_t remaining);
+static void usbhal_free_buffers(void);
+
+/* Internal EP transfer complete callbacks */
+#define EPCB(n) static int usbhal_xfer_complete_cb_##n(USB_Status_TypeDef status,              \
+                                                       uint32_t xferred, uint32_t remaining) { \
+        return usbhal_xfer_complete_cb(n, status, xferred, remaining);                         \
+}
+/*   ------^   */
+EPCB(EP0OUT)
+EPCB(EP0IN)
+EPCB(EP1OUT)
+EPCB(EP1IN)
+EPCB(EP2OUT)
+EPCB(EP2IN)
+EPCB(EP3OUT)
+EPCB(EP3IN)
+#ifndef TARGET_EFM32HG_STK3400
+EPCB(EP4OUT)
+EPCB(EP4IN)
+EPCB(EP5OUT)
+EPCB(EP5IN)
+EPCB(EP6OUT)
+EPCB(EP6IN)
+#endif
+
+static inline bool is_aligned(const void *pointer, size_t byte_count)
+{
+    return ((uintptr_t)pointer % byte_count == 0);
+}
+
+USBHAL::USBHAL(void)
+{
+    TRACE_FUNC_IN;
+
+    isrptr = &USBHAL::_usbisr;
+
+    if (instance) {
+        TRACE("Assert self failed! instance=%p", instance);
+        abort();
+    }
+    instance = this;
+
+    // When USB is active, we can't go below EM1. This block may
+    // be dynamically removed/reinstated to allow deeper sleep.
+    usbhal_allow_em2(false);
+
+    // When in suspend / Vbus off we can go to EM2, but never below
+    // that as long as USB is being used. Despite the name the call here
+    // blocks entering modes _below_ EM2, but allows EM2.
+    blockSleepMode(EM2);
+
+    epCallback[EP0OUT] = NULL;
+    epCallback[EP0IN ] = NULL;
+    epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
+    epCallback[EP1IN ] = &USBHAL::EP1_IN_callback;
+    epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback;
+    epCallback[EP2IN ] = &USBHAL::EP2_IN_callback;
+    epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback;
+    epCallback[EP3IN ] = &USBHAL::EP3_IN_callback;
+#ifndef TARGET_EFM32HG_STK3400
+    epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback;
+    epCallback[EP4IN ] = &USBHAL::EP4_IN_callback;
+    epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback;
+    epCallback[EP5IN ] = &USBHAL::EP5_IN_callback;
+    epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback;
+    epCallback[EP6IN ] = &USBHAL::EP6_IN_callback;
+#endif
+
+    memset(ep_state, 0, sizeof(ep_state));
+
+    ep_state[EP0OUT].intern_cb = usbhal_xfer_complete_cb_EP0OUT;
+    ep_state[EP0IN ].intern_cb = usbhal_xfer_complete_cb_EP0IN;
+    ep_state[EP1OUT].intern_cb = usbhal_xfer_complete_cb_EP1OUT;
+    ep_state[EP1IN ].intern_cb = usbhal_xfer_complete_cb_EP1IN;
+    ep_state[EP2OUT].intern_cb = usbhal_xfer_complete_cb_EP2OUT;
+    ep_state[EP2IN ].intern_cb = usbhal_xfer_complete_cb_EP2IN;
+    ep_state[EP3OUT].intern_cb = usbhal_xfer_complete_cb_EP3OUT;
+    ep_state[EP3IN ].intern_cb = usbhal_xfer_complete_cb_EP3IN;
+#ifndef TARGET_EFM32HG_STK3400
+    ep_state[EP4OUT].intern_cb = usbhal_xfer_complete_cb_EP4OUT;
+    ep_state[EP4IN ].intern_cb = usbhal_xfer_complete_cb_EP4IN;
+    ep_state[EP5OUT].intern_cb = usbhal_xfer_complete_cb_EP5OUT;
+    ep_state[EP5IN ].intern_cb = usbhal_xfer_complete_cb_EP5IN;
+    ep_state[EP6OUT].intern_cb = usbhal_xfer_complete_cb_EP6OUT;
+    ep_state[EP6IN ].intern_cb = usbhal_xfer_complete_cb_EP6IN;
+#endif
+
+#ifdef USB_USE_DYNAMIC_MEMORY
+    ep_state[EP0OUT].data_buf = ep0out_data_buf;
+    ep_state[EP0IN].data_buf = ep0in_data_buf;
+#else
+    for (int i=0 ; i<NUMBER_OF_ENDPOINTS ; i++) {
+        ep_state[i].data_buf = ep_data_buf[i];
+    }
+#endif
+}
+
+USBHAL::~USBHAL(void)
+{
+    TRACE_FUNC_IN;
+    USBD_AbortAllTransfers();
+    USBD_Disconnect();
+    usbhal_free_buffers();
+
+    usbhal_allow_em2(true);
+    unblockSleepMode(EM2);
+}
+
+extern "C" void usbhal_allow_em2(bool allow_em2)
+{
+    if (allow_em2) {
+        // unblockSleepMode is safe to call even if we would unblock
+        // an already unblocked mode, so no checks here.
+        unblockSleepMode(EM1);
+    } else {
+        blockSleepMode(EM1);
+    }
+}
+
+static void usbhal_reset_cb(void)
+{
+    TRACE_FUNC_IN;
+    run_cmd(CMD_BUSRESET, 0);
+}
+
+#ifdef DEBUG_USB_API
+static const char *usbstate[] = { "NONE", "ATTACHED", "POWERED", "DEFAULT",
+                                  "ADDRESSED", "CONFIGURED", "SUSPENDED", "???" };
+#endif
+
+static void usbhal_state_change_cb(USBD_State_TypeDef oldState,
+                                   USBD_State_TypeDef newState)
+{
+    TRACE("state changed %s -> %s", usbstate[oldState], usbstate[newState]);
+
+    if (oldState == USBD_STATE_SUSPENDED) {
+        run_cmd(CMD_SUSPEND_STATE_CHANGED, 0);
+    }
+
+    if (newState == USBD_STATE_SUSPENDED) {
+        run_cmd(CMD_SUSPEND_STATE_CHANGED, 1);
+    }
+
+    // Should call connectStateChanged from here as well but there is
+    // no documentation on when to actually do so. (And the implementation
+    // in USBDevice.cpp is a stub)
+
+    // HACK! Since connectStateChanged is not used, indicate the loss
+    // off connection by reporting a bus reset. This causes USBDevice
+    // to realise that at least it's not in CONFIGURED anymore, and
+    // stop trying to read/write in a busyloop.
+    if (newState == USBD_STATE_NONE) {
+        run_cmd(CMD_BUSRESET, 0);
+    }
+}
+
+static int usbhal_setupcmd_cb(const USB_Setup_TypeDef *setup)
+{
+    TRACE_FUNC_IN;
+    if (!setup) {
+        EFM_ASSERT(false);
+        return USB_STATUS_REQ_ERR;
+    }
+
+    memcpy(ep0setupdata, setup, 8);
+    run_cmd(CMD_EP0SETUP, 0);
+
+    return USB_STATUS_OK;
+}
+
+static void usbhal_sof_cb(uint16_t frameNum)
+{
+    run_cmd(CMD_SOF, frameNum);
+}
+
+static void usbhal_free_buffers(void)
+{
+#ifdef USB_USE_DYNAMIC_MEMORY
+    TRACE_FUNC_IN;
+
+    for (int i=EP1OUT ; i<NUMBER_OF_ENDPOINTS ; i++ ) {
+        if (ep_state[i].data_buf) {
+            free(ep_state[i].data_buf);
+            ep_state[i].data_buf = NULL;
+        }
+    }
+#endif
+}
+
+void USBHAL::connect(void)
+{
+    TRACE_FUNC_IN;
+
+    // Init datastructures must be static - driver will use these even after the init function exits!
+
+    static const uint8_t buffer_multiplier[] = { 1 }; // Mult 1 for control EP
+    static const USBD_Callbacks_TypeDef usbd_callbacks = {
+        .usbReset = usbhal_reset_cb,
+        .usbStateChange = usbhal_state_change_cb,
+        .setupCmd = usbhal_setupcmd_cb,
+        .isSelfPowered = NULL,
+        .sofInt = usbhal_sof_cb
+    };
+
+    USBD_Init_TypeDef initdata = {
+        .deviceDescriptor = NULL,
+        .configDescriptor = NULL,
+        .stringDescriptors = NULL,
+        .numberOfStrings = 0,
+        .bufferingMultiplier = buffer_multiplier,
+        .callbacks = &usbd_callbacks,
+        .reserved = 0
+    };
+
+    int ret = USBD_Init(&initdata);
+
+    TRACE("init = %d, devicedesc = %lx, configdesc = %lx", ret,
+          (uint32_t) initdata.deviceDescriptor,
+          (uint32_t) initdata.configDescriptor);
+
+    EFM_ASSERT(ret == USB_STATUS_OK);
+}
+
+void USBHAL::disconnect(void)
+{
+    TRACE_FUNC_IN;
+    USBD_Disconnect();
+}
+
+void USBHAL::configureDevice(void)
+{
+    TRACE_FUNC_IN;
+    USBD_SetUsbState(USBD_STATE_CONFIGURED);
+}
+
+void USBHAL::unconfigureDevice(void)
+{
+    TRACE_FUNC_IN;
+    USBD_SetUsbState(USBD_STATE_DEFAULT);
+    usbhal_free_buffers();
+}
+
+void USBHAL::setAddress(uint8_t address)
+{
+    TRACE_FUNC_IN_P("addr 0x%x", (unsigned)address);
+    USBD_SetAddress(address);
+}
+
+void USBHAL::remoteWakeup(void)
+{
+    TRACE_FUNC_IN;
+    USBD_RemoteWakeup();
+}
+
+void USBHAL::EP0setup(uint8_t *buffer)
+{
+    TRACE_FUNC_IN;
+    EFM_ASSERT(buffer);
+    if (buffer) {
+        memcpy(buffer, ep0setupdata, 8);
+    }
+}
+
+void USBHAL::EP0read(void)
+{
+    TRACE_FUNC_IN;
+    (void)internEndpointRead(0, MAX_PACKET_SIZE_EP0);
+}
+
+void USBHAL::EP0readStage(void)
+{
+    TRACE_FUNC_IN;
+    // Not needed
+}
+
+uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
+{
+    TRACE_FUNC_IN;
+    EFM_ASSERT(buffer);
+
+    uint32_t read = 0;
+    endpointReadResult(0, buffer, &read);
+    return read;
+}
+
+static int usbhal_xfer_complete_cb(uint8_t ep, USB_Status_TypeDef status,
+                                   uint32_t xferred, uint32_t remaining)
+{
+    TRACE_FUNC_IN_P("ep 0x%x, status %u, xferred %lu, rem %lu",
+                    ep, status, xferred, remaining);
+
+    if (ep >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return USB_STATUS_REQ_ERR;
+    }
+
+    switch (ep) {
+        case EP0OUT:
+            if (ep_state[EP0OUT].status == READ_PENDING) {
+                ep_state[EP0OUT].status = READ_COMPLETE;
+                ep_state[EP0OUT].byte_count = xferred;
+                // drop zlp
+                if (xferred == 0) {
+                    break;
+                }
+            }
+            run_cmd(CMD_EP0OUT, 0);
+            break;
+
+        case EP0IN:
+            run_cmd(CMD_EP0IN, 0);
+            break;
+
+        default:
+            bool write = ep & 1;
+
+            if (status == USB_STATUS_OK) {
+                if (!write && ep_state[ep].status == READ_PENDING) {
+                    ep_state[ep].status = READ_COMPLETE;
+                    ep_state[ep].byte_count = xferred;
+                } else if (write && ep_state[ep].status == WRITE_PENDING) {
+                    ep_state[ep].status = WRITE_COMPLETE;
+                } else {
+                    ep_state[ep].status = FAILED_INVALID;
+                }
+            } else {
+                ep_state[ep].status = FAILED_INVALID;
+            }
+
+            if (ep_state[ep].status != FAILED_INVALID) {
+                run_cmd(CMD_EP_XFER_COMPLETED, ep);
+            }
+            break;
+    }
+
+    return USB_STATUS_OK;
+}
+
+void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
+{
+    //TRACE_FUNC_IN_P("buffer %lx, size %lu", (uint32_t) buffer, size);
+
+    int ret;
+    USB_XferCompleteCb_TypeDef cb = ep_state[EP0IN].intern_cb;
+
+    EFM_ASSERT((buffer != NULL) || (size == 0));
+    EFM_ASSERT(size <= MAX_PACKET_SIZE_EP0);
+
+    if (!buffer || size == 0) {
+        // No callback after writing EP0 ZLP
+        cb = NULL;
+    }
+
+    if (buffer && !is_aligned(buffer,4)) {
+        // Copy unaligned data to write-buffer before USBD_Write
+        memcpy(ep_state[EP0IN].data_buf, buffer, size);
+        ret = USBD_Write(0, ep_state[EP0IN].data_buf, size, cb);
+    } else {
+        ret = USBD_Write(0, buffer, size, cb);
+    }
+
+    if (ret != USB_STATUS_OK) {
+        TRACE("FAILED - ret %d", ret);
+    }
+}
+
+void USBHAL::EP0stall(void)
+{
+    TRACE_FUNC_IN;
+    USBD_StallEp0();
+}
+
+static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize)
+{
+    //TRACE_FUNC_IN_P("endpoint 0x%x, size %ld, cb %d", (unsigned)ep, maxSize, useCallback);
+
+    if (ep >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    ep_state[ep].status = READ_PENDING;
+
+    int ret = USBD_Read(USB_EP_TO_ADDR(ep), ep_state[ep].data_buf, maxSize,
+                        ep_state[ep].intern_cb);
+
+    if (ret == USB_STATUS_OK) {
+        return EP_PENDING;
+    } else {
+        TRACE("FAILED - ret %d", ret);
+
+        if (ret == USB_STATUS_EP_STALLED) {
+            return EP_STALLED;
+        } else {
+            return EP_INVALID;
+        }
+    }
+}
+
+EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
+{
+    return internEndpointRead(endpoint, maximumSize);
+}
+
+EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead)
+{
+    TRACE_FUNC_IN;
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    EFM_ASSERT(data);
+    EFM_ASSERT(bytesRead);
+    if (!data || !bytesRead) {
+        return EP_INVALID;
+    }
+
+    switch (ep_state[endpoint].status) {
+        case READ_PENDING:
+            return EP_PENDING;
+
+        case READ_COMPLETE:
+            memcpy(data, ep_state[endpoint].data_buf, ep_state[endpoint].byte_count);
+            *bytesRead = ep_state[endpoint].byte_count;
+            ep_state[endpoint].status = IDLE;
+            return EP_COMPLETED;
+
+        case FAILED_STALLED:
+            ep_state[endpoint].status = IDLE;
+            return EP_STALLED;
+
+        default:
+            ep_state[endpoint].status = IDLE;
+            return EP_INVALID;
+    }
+}
+
+EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
+{
+    TRACE_FUNC_IN_P("endpoint 0x%x, data 0x%lx, size %lu", (unsigned )endpoint, (uint32_t)data, size);
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT(endpoint > EP0IN);
+    EFM_ASSERT(size <= ep_state[endpoint].max_packet);
+    EFM_ASSERT(data);
+
+    uint8_t ep = USB_EP_TO_INDEX(endpoint);
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS || endpoint <= EP0IN) {
+        return EP_INVALID;
+    }
+
+    if (size > ep_state[endpoint].max_packet) {
+        return EP_INVALID;
+    }
+
+    if (!data) {
+        return EP_INVALID;
+    }
+
+    memcpy(ep_state[ep].data_buf, data, size);
+
+    ep_state[ep].status = WRITE_PENDING;
+    int ret = USBD_Write(USB_EP_TO_ADDR(endpoint), ep_state[ep].data_buf, size, ep_state[ep].intern_cb);
+
+    if (ret == USB_STATUS_EP_STALLED) {
+        ep_state[ep].status = IDLE;
+        return EP_STALLED;
+    } else if (ret != USB_STATUS_OK) {
+        ep_state[ep].status = IDLE;
+        return EP_INVALID;
+    }
+
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
+{
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return EP_INVALID;
+    }
+
+    switch (ep_state[endpoint].status) {
+        case WRITE_PENDING:
+            return EP_PENDING;
+
+        case WRITE_COMPLETE:
+            ep_state[endpoint].status = IDLE;
+            return EP_COMPLETED;
+
+        case FAILED_STALLED:
+            ep_state[endpoint].status = IDLE;
+            return EP_STALLED;
+
+        default:
+            ep_state[endpoint].status = IDLE;
+            return EP_INVALID;
+    }
+}
+
+void USBHAL::stallEndpoint(uint8_t endpoint)
+{
+    TRACE_FUNC_IN;
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
+
+    USBD_StallEp(USB_EP_TO_ADDR(endpoint));
+}
+
+void USBHAL::unstallEndpoint(uint8_t endpoint)
+{
+    TRACE_FUNC_IN;
+
+    EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
+    EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
+
+    USBD_UnStallEp(USB_EP_TO_ADDR(endpoint));
+}
+
+bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
+{
+    TRACE_FUNC_IN_P("endpoint %d, packetsize %ld, options 0x%lx", endpoint,
+                    maxPacket, options);
+
+    int mult = 1; // RX/TX buffer size multiplier
+    int type = USB_EPTYPE_INTR;
+
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    if (endpoint == EP0IN || endpoint == EP0OUT) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    ep_state[endpoint].max_packet = 0;
+
+    if (endpoint == EPISO_OUT || endpoint ==  EPISO_IN) {
+        if (maxPacket > MAX_PACKET_SIZE_EPISO) {
+            EFM_ASSERT(false);
+            return false;
+        }
+    } else if ((maxPacket > MAX_PACKET_SIZE_EPBULK) || (maxPacket > MAX_PACKET_SIZE_EPINT)) {
+        EFM_ASSERT(false);
+        return false;
+    }
+
+    // USBDevice performs a read right after creating the endpoints,
+    // before calling configureDevice. The read will fail since
+    // at that point the device state is still ADDRESSED. Workaround
+    // is to force configured state here.
+    //
+    // This relies on USBDevice to not call realiseEndpoint unless
+    // it is transitioning to the CONFIGURED state.
+    USBD_SetUsbState(USBD_STATE_CONFIGURED);
+
+    // Why doesn't this function have a type param? This is silly...
+    switch (endpoint) {
+        case EPBULK_OUT:
+        case EPBULK_IN:
+            type = USB_EPTYPE_BULK;
+            mult = 2;
+            break;
+        case EPINT_OUT:
+        case EPINT_IN:
+            type = USB_EPTYPE_INTR;
+            mult = 1;
+            break;
+        case EPISO_OUT:
+        case EPISO_IN:
+            type = USB_EPTYPE_ISOC;
+            mult = 2; // ?
+            break;
+    }
+
+    // Some options force the endpoint to a specific type
+    if( options & ISOCHRONOUS ) {
+        type = USB_EPTYPE_ISOC;
+        mult = 2; // ?
+    } else if ( options & RATE_FEEDBACK_MODE ) {
+        // No support for whatever rate feedback is, but for interrupt only
+        type = USB_EPTYPE_INTR;
+        mult = 1;
+    }
+
+#ifdef USB_USE_DYNAMIC_MEMORY
+    if (ep_state[endpoint].data_buf) {
+        free(ep_state[endpoint].data_buf);
+    }
+
+    ep_state[endpoint].data_buf = (uint8_t *)malloc(maxPacket);
+
+    if (!ep_state[endpoint].data_buf) {
+        EFM_ASSERT(false);
+        return false;
+    }
+#endif
+
+    int ret = USBD_AddEndpoint(USB_EP_TO_ADDR(endpoint), type, maxPacket, mult);
+
+    if (ret == USB_STATUS_OK) {
+        ep_state[endpoint].status = IDLE;
+        ep_state[endpoint].max_packet = maxPacket;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool USBHAL::getEndpointStallState(unsigned char endpoint)
+{
+    TRACE_FUNC_IN;
+    if (endpoint >= NUMBER_OF_ENDPOINTS) {
+        EFM_ASSERT(false);
+        return false;
+    }
+    return USBD_EpIsStalled(USB_EP_TO_ADDR(endpoint));
+}
+
+static void run_cmd(USBISRCommand cmd, uint32_t param)
+{
+    if (usb_isrcmd != CMD_HANDLED || cmd >= CMD_ENUM_END_MARKER) {
+        EFM_ASSERT(false);
+        abort();
+    }
+
+    usb_isrcmd = cmd;
+    usb_isrcmd_param = param;
+    isrptr();
+}
+
+void USBHAL::_usbisr(void)
+{
+    EFM_ASSERT(instance);
+    instance->usbisr();
+}
+
+void USBHAL::usbisr(void)
+{
+    //TRACE_FUNC_IN;
+
+    // This "ISR" is used just to route callbacks from SiL USB driver
+    // callback context (which can not call protected/private USBHAL
+    // methods), to the actual USBHAL.
+
+    EFM_ASSERT(usb_isrcmd != CMD_HANDLED);
+    switch (usb_isrcmd) {
+        case CMD_EP0SETUP:
+            this->EP0setupCallback();
+            break;
+        case CMD_EP0IN:
+            this->EP0in();
+            break;
+        case CMD_EP0OUT:
+            this->EP0out();
+            break;
+        case CMD_BUSRESET:
+            this->busReset();
+            break;
+        case CMD_EP_XFER_COMPLETED:
+            if (epCallback[usb_isrcmd_param] && instance) {
+                (instance->*(epCallback[usb_isrcmd_param]))();
+            }
+            break;
+        case CMD_SOF:
+            this->SOF(usb_isrcmd_param);
+            break;
+        case CMD_SUSPEND_STATE_CHANGED:
+            this->suspendStateChanged(usb_isrcmd_param);
+            break;
+        default:
+            EFM_ASSERT(false);
+            break;
+    }
+    usb_isrcmd = CMD_HANDLED;
+}
+#endif
+
+// End of file