USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Files at this revision

API Documentation at this revision

Comitter:
setcom_001
Date:
Mon Jul 22 21:16:27 2013 +0000
Parent:
11:8038fdeea4d4
Commit message:
docs update

Changed in this revision

USBAudio/USBAudio.cpp Show annotated file Show diff for this revision Revisions of this file
USBAudio/USBAudio.h Show annotated file Show diff for this revision Revisions of this file
USBAudio/USBAudio_Types.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDescriptor.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBDevice_Types.h 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_LPC11U.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBEndpoints_LPC17_LPC23.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHAL.h Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHAL_LPC11U.cpp Show annotated file Show diff for this revision Revisions of this file
USBDevice/USBHAL_LPC17.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBHID.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBHID.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBHID_Types.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBKeyboard.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBMouse.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBMouse.h Show annotated file Show diff for this revision Revisions of this file
USBHID/USBMouseKeyboard.cpp Show annotated file Show diff for this revision Revisions of this file
USBHID/USBMouseKeyboard.h Show annotated file Show diff for this revision Revisions of this file
USBMIDI/MIDIMessage.h Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.cpp Show annotated file Show diff for this revision Revisions of this file
USBMIDI/USBMIDI.h Show annotated file Show diff for this revision Revisions of this file
USBMSD/USBMSD.cpp Show annotated file Show diff for this revision Revisions of this file
USBMSD/USBMSD.h Show annotated file Show diff for this revision Revisions of this file
USBSerial/CircBuffer.h Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBCDC.cpp Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBCDC.h Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBSerial.cpp Show annotated file Show diff for this revision Revisions of this file
USBSerial/USBSerial.h Show annotated file Show diff for this revision Revisions of this file
diff -r 8038fdeea4d4 -r a9671b78d24e USBAudio/USBAudio.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBAudio/USBAudio.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,693 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBAudio.h"
+#include "USBAudio_Types.h"
+
+
+
+USBAudio::USBAudio( uint32_t frequency_in, uint8_t channel_nb_in, uint32_t frequency_out, uint8_t channel_nb_out, uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
+{
+    mute = 0;
+    volCur = 0x0080;
+    volMin = 0x0000;
+    volMax = 0x0100;
+    volRes = 0x0004;
+    available = false;
+    FREQ_IN = frequency_in;
+    FREQ_OUT = frequency_out;
+    this->channel_nb_in = channel_nb_in;
+    this->channel_nb_out = channel_nb_out;
+    // stereo -> *2, mono -> *1
+    PACKET_SIZE_ISO_IN = ( FREQ_IN / 500 ) * channel_nb_in;
+    PACKET_SIZE_ISO_OUT = ( FREQ_OUT / 500 ) * channel_nb_out;
+    // STEREO -> left and right
+    channel_config_in = ( channel_nb_in == 1 ) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
+    channel_config_out = ( channel_nb_out == 1 ) ? CHANNEL_M : CHANNEL_L + CHANNEL_R;
+    SOF_handler = false;
+    buf_stream_out = NULL;
+    buf_stream_in = NULL;
+    interruptOUT = false;
+    writeIN = false;
+    interruptIN = false;
+    available = false;
+    volume = 0;
+    // connect the device
+    USBDevice::connect();
+}
+
+bool USBAudio::read( uint8_t *buf )
+{
+    buf_stream_in = buf;
+    SOF_handler = false;
+
+    while ( !available || !SOF_handler );
+
+    available = false;
+    return true;
+}
+
+bool USBAudio::readNB( uint8_t *buf )
+{
+    buf_stream_in = buf;
+    SOF_handler = false;
+
+    while ( !SOF_handler );
+
+    if ( available )
+    {
+        available = false;
+        buf_stream_in = NULL;
+        return true;
+    }
+
+    return false;
+}
+
+bool USBAudio::readWrite( uint8_t *buf_read, uint8_t *buf_write )
+{
+    buf_stream_in = buf_read;
+    SOF_handler = false;
+    writeIN = false;
+
+    if ( interruptIN )
+    {
+        USBDevice::writeNB( EP3IN, buf_write, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT );
+    }
+    else
+    {
+        buf_stream_out = buf_write;
+    }
+
+    while ( !available );
+
+    if ( interruptIN )
+    {
+        while ( !writeIN );
+    }
+
+    while ( !SOF_handler );
+
+    return true;
+}
+
+
+bool USBAudio::write( uint8_t *buf )
+{
+    writeIN = false;
+    SOF_handler = false;
+
+    if ( interruptIN )
+    {
+        USBDevice::writeNB( EP3IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT );
+    }
+    else
+    {
+        buf_stream_out = buf;
+    }
+
+    while ( !SOF_handler );
+
+    if ( interruptIN )
+    {
+        while ( !writeIN );
+    }
+
+    return true;
+}
+
+
+float USBAudio::getVolume()
+{
+    return ( mute ) ? 0.0 : volume;
+}
+
+
+bool USBAudio::EP3_OUT_callback()
+{
+    uint32_t size = 0;
+    interruptOUT = true;
+
+    if ( buf_stream_in != NULL )
+    {
+        readEP( EP3OUT, ( uint8_t * )buf_stream_in, &size, PACKET_SIZE_ISO_IN );
+        available = true;
+        buf_stream_in = NULL;
+    }
+
+    readStart( EP3OUT, PACKET_SIZE_ISO_IN );
+    return false;
+}
+
+
+bool USBAudio::EP3_IN_callback()
+{
+    interruptIN = true;
+    writeIN = true;
+    return true;
+}
+
+
+
+// Called in ISR context on each start of frame
+void USBAudio::SOF( int frameNumber )
+{
+    uint32_t size = 0;
+
+    if ( !interruptOUT )
+    {
+        // read the isochronous endpoint
+        if ( buf_stream_in != NULL )
+        {
+            if ( USBDevice::readEP_NB( EP3OUT, ( uint8_t * )buf_stream_in, &size, PACKET_SIZE_ISO_IN ) )
+            {
+                if ( size )
+                {
+                    available = true;
+                    readStart( EP3OUT, PACKET_SIZE_ISO_IN );
+                    buf_stream_in = NULL;
+                }
+            }
+        }
+    }
+
+    if ( !interruptIN )
+    {
+        // write if needed
+        if ( buf_stream_out != NULL )
+        {
+            USBDevice::writeNB( EP3IN, ( uint8_t * )buf_stream_out, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT );
+            buf_stream_out = NULL;
+        }
+    }
+
+    SOF_handler = true;
+}
+
+
+// Called in ISR context
+// Set configuration. Return false if the configuration is not supported.
+bool USBAudio::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure isochronous endpoint
+    realiseEndpoint( EP3OUT, PACKET_SIZE_ISO_IN, ISOCHRONOUS );
+    realiseEndpoint( EP3IN, PACKET_SIZE_ISO_OUT, ISOCHRONOUS );
+    // activate readings on this endpoint
+    readStart( EP3OUT, PACKET_SIZE_ISO_IN );
+    return true;
+}
+
+
+// Called in ISR context
+// Set alternate setting. Return false if the alternate setting is not supported
+bool USBAudio::USBCallback_setInterface( uint16_t interface, uint8_t alternate )
+{
+    if ( interface == 0 && alternate == 0 )
+    {
+        return true;
+    }
+
+    if ( interface == 1 && ( alternate == 0 || alternate == 1 ) )
+    {
+        return true;
+    }
+
+    if ( interface == 2 && ( alternate == 0 || alternate == 1 ) )
+    {
+        return true;
+    }
+
+    return false;
+}
+
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests and class specific requests.
+// Return true if class handles this request
+bool USBAudio::USBCallback_request()
+{
+    bool success = false;
+    CONTROL_TRANSFER *transfer = getTransferPtr();
+
+    // Process class-specific requests
+    if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
+    {
+        // Feature Unit: Interface = 0, ID = 2
+        if ( transfer->setup.wIndex == 0x0200 )
+        {
+            // Master Channel
+            if ( ( transfer->setup.wValue & 0xff ) == 0 )
+            {
+                switch ( transfer->setup.wValue >> 8 )
+                {
+                    case MUTE_CONTROL:
+                        switch ( transfer->setup.bRequest )
+                        {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 1;
+                                transfer->ptr = &mute;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 1;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+
+                            default:
+                                break;
+                        }
+
+                        break;
+
+                    case VOLUME_CONTROL:
+                        switch ( transfer->setup.bRequest )
+                        {
+                            case REQUEST_GET_CUR:
+                                transfer->remaining = 2;
+                                transfer->ptr = ( uint8_t * )&volCur;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_GET_MIN:
+                                transfer->remaining = 2;
+                                transfer->ptr = ( uint8_t * )&volMin;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_GET_MAX:
+                                transfer->remaining = 2;
+                                transfer->ptr = ( uint8_t * )&volMax;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_GET_RES:
+                                transfer->remaining = 2;
+                                transfer->ptr = ( uint8_t * )&volRes;
+                                transfer->direction = DEVICE_TO_HOST;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_CUR:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_MIN:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_MAX:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+
+                            case REQUEST_SET_RES:
+                                transfer->remaining = 2;
+                                transfer->notify = true;
+                                transfer->direction = HOST_TO_DEVICE;
+                                success = true;
+                                break;
+                        }
+
+                        break;
+
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
+    return success;
+}
+
+
+// Called in ISR context when a data OUT stage has been performed
+void USBAudio::USBCallback_requestCompleted( uint8_t *buf, uint32_t length )
+{
+    if ( ( length == 1 ) || ( length == 2 ) )
+    {
+        uint16_t data = ( length == 1 ) ? *buf : *( ( uint16_t * )buf );
+        CONTROL_TRANSFER *transfer = getTransferPtr();
+
+        switch ( transfer->setup.wValue >> 8 )
+        {
+            case MUTE_CONTROL:
+                switch ( transfer->setup.bRequest )
+                {
+                    case REQUEST_SET_CUR:
+                        mute = data & 0xff;
+                        updateVol.call();
+                        break;
+
+                    default:
+                        break;
+                }
+
+                break;
+
+            case VOLUME_CONTROL:
+                switch ( transfer->setup.bRequest )
+                {
+                    case REQUEST_SET_CUR:
+                        volCur = data;
+                        volume = ( float )volCur / ( float )volMax;
+                        updateVol.call();
+                        break;
+
+                    default:
+                        break;
+                }
+
+                break;
+
+            default:
+                break;
+        }
+    }
+}
+
+
+
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                                 + (5 * INTERFACE_DESCRIPTOR_LENGTH) \
+                                 + (1 * CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1) \
+                                 + (2 * INPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                                 + (1 * FEATURE_UNIT_DESCRIPTOR_LENGTH) \
+                                 + (2 * OUTPUT_TERMINAL_DESCRIPTOR_LENGTH) \
+                                 + (2 * STREAMING_INTERFACE_DESCRIPTOR_LENGTH) \
+                                 + (2 * FORMAT_TYPE_I_DESCRIPTOR_LENGTH) \
+                                 + (2 * (ENDPOINT_DESCRIPTOR_LENGTH + 2)) \
+                                 + (2 * STREAMING_ENDPOINT_DESCRIPTOR_LENGTH) )
+
+#define TOTAL_CONTROL_INTF_LENGTH    (CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1 + \
+                                      2*INPUT_TERMINAL_DESCRIPTOR_LENGTH     + \
+                                      FEATURE_UNIT_DESCRIPTOR_LENGTH    + \
+                                      2*OUTPUT_TERMINAL_DESCRIPTOR_LENGTH)
+
+uint8_t *USBAudio::configurationDesc()
+{
+    static uint8_t configDescriptor[] =
+    {
+        // Configuration 1
+        CONFIGURATION_DESCRIPTOR_LENGTH,        // bLength
+        CONFIGURATION_DESCRIPTOR,               // bDescriptorType
+        LSB( TOTAL_DESCRIPTOR_LENGTH ),         // wTotalLength (LSB)
+        MSB( TOTAL_DESCRIPTOR_LENGTH ),         // wTotalLength (MSB)
+        0x03,                                   // bNumInterfaces
+        DEFAULT_CONFIGURATION,                  // bConfigurationValue
+        0x00,                                   // iConfiguration
+        0x80,                                   // bmAttributes
+        50,                                     // bMaxPower
+
+        // Interface 0, Alternate Setting 0, Audio Control
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x00,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOCONTROL,                  // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+
+        // Audio Control Interface
+        CONTROL_INTERFACE_DESCRIPTOR_LENGTH + 1,// bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_HEADER,                         // bDescriptorSubtype
+        LSB( 0x0100 ),                          // bcdADC (LSB)
+        MSB( 0x0100 ),                          // bcdADC (MSB)
+        LSB( TOTAL_CONTROL_INTF_LENGTH ),       // wTotalLength
+        MSB( TOTAL_CONTROL_INTF_LENGTH ),       // wTotalLength
+        0x02,                                   // bInCollection
+        0x01,                                   // baInterfaceNr
+        0x02,                                   // baInterfaceNr
+
+        // Audio Input Terminal (Speaker)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x01,                                   // bTerminalID
+        LSB( TERMINAL_USB_STREAMING ),          // wTerminalType
+        MSB( TERMINAL_USB_STREAMING ),          // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb_in,                          // bNrChannels
+        LSB( channel_config_in ),               // wChannelConfig
+        MSB( channel_config_in ),               // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Feature Unit (Speaker)
+        FEATURE_UNIT_DESCRIPTOR_LENGTH,         // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_FEATURE_UNIT,                   // bDescriptorSubtype
+        0x02,                                   // bUnitID
+        0x01,                                   // bSourceID
+        0x01,                                   // bControlSize
+        CONTROL_MUTE |
+        CONTROL_VOLUME,                         // bmaControls(0)
+        0x00,                                   // bmaControls(1)
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Speaker)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x03,                                   // bTerminalID
+        LSB( TERMINAL_SPEAKER ),                // wTerminalType
+        MSB( TERMINAL_SPEAKER ),                // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x02,                                   // bSourceID
+        0x00,                                   // iTerminal
+
+
+        // Audio Input Terminal (Microphone)
+        INPUT_TERMINAL_DESCRIPTOR_LENGTH,       // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_INPUT_TERMINAL,                 // bDescriptorSubtype
+        0x04,                                   // bTerminalID
+        LSB( TERMINAL_MICROPHONE ),             // wTerminalType
+        MSB( TERMINAL_MICROPHONE ),             // wTerminalType
+        0x00,                                   // bAssocTerminal
+        channel_nb_out,                         // bNrChannels
+        LSB( channel_config_out ),              // wChannelConfig
+        MSB( channel_config_out ),              // wChannelConfig
+        0x00,                                   // iChannelNames
+        0x00,                                   // iTerminal
+
+        // Audio Output Terminal (Microphone)
+        OUTPUT_TERMINAL_DESCRIPTOR_LENGTH,      // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        CONTROL_OUTPUT_TERMINAL,                // bDescriptorSubtype
+        0x05,                                   // bTerminalID
+        LSB( TERMINAL_USB_STREAMING ),          // wTerminalType
+        MSB( TERMINAL_USB_STREAMING ),          // wTerminalType
+        0x00,                                   // bAssocTerminal
+        0x04,                                   // bSourceID
+        0x00,                                   // iTerminal
+
+
+
+
+
+
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x01,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_GENERAL,                      // bDescriptorSubtype
+        0x01,                                   // bTerminalLink
+        0x00,                                   // bDelay
+        LSB( FORMAT_PCM ),                      // wFormatTag
+        MSB( FORMAT_PCM ),                      // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        STREAMING_FORMAT_TYPE,                  // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb_in,                          // bNrChannels
+        0x02,                                   // bSubFrameSize
+        16,                                     // bBitResolution
+        0x01,                                   // bSamFreqType
+        LSB( FREQ_IN ),                         // tSamFreq
+        ( FREQ_IN >> 8 ) & 0xff,                // tSamFreq
+        ( FREQ_IN >> 16 ) & 0xff,               // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC( EPISO_OUT ),               // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        LSB( PACKET_SIZE_ISO_IN ),                 // wMaxPacketSize
+        MSB( PACKET_SIZE_ISO_IN ),                 // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB( 0x0000 ),                          // wLockDelay
+        MSB( 0x0000 ),                          // wLockDelay
+
+
+
+
+
+
+
+        // Interface 1, Alternate Setting 0, Audio Streaming - Zero Bandwith
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x00,                                   // bAlternateSetting
+        0x00,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Interface 1, Alternate Setting 1, Audio Streaming - Operational
+        INTERFACE_DESCRIPTOR_LENGTH,            // bLength
+        INTERFACE_DESCRIPTOR,                   // bDescriptorType
+        0x02,                                   // bInterfaceNumber
+        0x01,                                   // bAlternateSetting
+        0x01,                                   // bNumEndpoints
+        AUDIO_CLASS,                            // bInterfaceClass
+        SUBCLASS_AUDIOSTREAMING,                // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0x00,                                   // iInterface
+
+        // Audio Streaming Interface
+        STREAMING_INTERFACE_DESCRIPTOR_LENGTH,  // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOCONTROL,                  // bDescriptorSubtype
+        0x05,                                   // bTerminalLink (output terminal microphone)
+        0x01,                                   // bDelay
+        0x01,                                   // wFormatTag
+        0x00,                                   // wFormatTag
+
+        // Audio Type I Format
+        FORMAT_TYPE_I_DESCRIPTOR_LENGTH,        // bLength
+        INTERFACE_DESCRIPTOR_TYPE,              // bDescriptorType
+        SUBCLASS_AUDIOSTREAMING,                // bDescriptorSubtype
+        FORMAT_TYPE_I,                          // bFormatType
+        channel_nb_out,                         // bNrChannels
+        0x02,                                   // bSubFrameSize
+        0x10,                                   // bBitResolution
+        0x01,                                   // bSamFreqType
+        LSB( FREQ_OUT ),                        // tSamFreq
+        ( FREQ_OUT >> 8 ) & 0xff,               // tSamFreq
+        ( FREQ_OUT >> 16 ) & 0xff,              // tSamFreq
+
+        // Endpoint - Standard Descriptor
+        ENDPOINT_DESCRIPTOR_LENGTH + 2,         // bLength
+        ENDPOINT_DESCRIPTOR,                    // bDescriptorType
+        PHY_TO_DESC( EPISO_IN ),                // bEndpointAddress
+        E_ISOCHRONOUS,                          // bmAttributes
+        LSB( PACKET_SIZE_ISO_OUT ),                 // wMaxPacketSize
+        MSB( PACKET_SIZE_ISO_OUT ),                 // wMaxPacketSize
+        0x01,                                   // bInterval
+        0x00,                                   // bRefresh
+        0x00,                                   // bSynchAddress
+
+        // Endpoint - Audio Streaming
+        STREAMING_ENDPOINT_DESCRIPTOR_LENGTH,   // bLength
+        ENDPOINT_DESCRIPTOR_TYPE,               // bDescriptorType
+        ENDPOINT_GENERAL,                       // bDescriptor
+        0x00,                                   // bmAttributes
+        0x00,                                   // bLockDelayUnits
+        LSB( 0x0000 ),                          // wLockDelay
+        MSB( 0x0000 ),                          // wLockDelay
+
+        // Terminator
+        0                                       // bLength
+    };
+    return configDescriptor;
+}
+
+uint8_t *USBAudio::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x0c,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 //bString iInterface - Audio
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBAudio::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBAudio/USBAudio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBAudio/USBAudio.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,290 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAudio_H
+#define USBAudio_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBDevice/USBDevice/USBDevice.h"
+
+
+/**
+* USBAudio example
+*
+* #include "mbed.h"
+* #include "USBAudio.h"
+*
+* Serial pc(USBTX, USBRX);
+*
+* // frequency: 48 kHz
+* #define FREQ 48000
+*
+* // 1 channel: mono
+* #define NB_CHA 1
+*
+* // length of an audio packet: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there is one channel, the length will be 48 * 2 * 1
+* #define AUDIO_LENGTH_PACKET 48 * 2 * 1
+*
+* // USBAudio
+* USBAudio audio(FREQ, NB_CHA);
+*
+* int main() {
+*    int16_t buf[AUDIO_LENGTH_PACKET/2];
+*
+*    while (1) {
+*        // read an audio packet
+*        audio.read((uint8_t *)buf);
+*
+*
+*        // print packet received
+*        pc.printf("recv: ");
+*        for(int i = 0; i < AUDIO_LENGTH_PACKET/2; i++) {
+*            pc.printf("%d ", buf[i]);
+*        }
+*        pc.printf("\r\n");
+*    }
+* }
+* @endcode
+*/
+class USBAudio: public USBDevice
+{
+public:
+
+    /**
+    * Constructor
+    *
+    * @param frequency_in frequency in Hz (default: 48000)
+    * @param channel_nb_in channel number (1 or 2) (default: 1)
+    * @param frequency_out frequency in Hz (default: 8000)
+    * @param channel_nb_out_in channel number (1 or 2) (default: 1)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBAudio( uint32_t frequency_in = 48000, uint8_t channel_nb_in = 1, uint32_t frequency_out = 8000, uint8_t channel_nb_out = 1, uint16_t vendor_id = 0x7bb8, uint16_t product_id = 0x1111, uint16_t product_release = 0x0100 );
+
+    /**
+    * Get current volume between 0.0 and 1.0
+    *
+    * @returns volume
+    */
+    float getVolume();
+
+    /**
+    * Read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Blocking
+    *
+    * @param buf pointer on a buffer which will be filled with an audio packet
+    *
+    * @returns true if successfull
+    */
+    bool read( uint8_t *buf );
+
+    /**
+    * Try to read an audio packet. During a frame, only a single reading (you can't write and read an audio packet during the same frame)can be done using this method. Warning: Non Blocking
+    *
+    * @param buf pointer on a buffer which will be filled if an audio packet is available
+    *
+    * @returns true if successfull
+    */
+    bool readNB( uint8_t *buf );
+
+    /**
+    * Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method.
+    *
+    * @param buf pointer on the audio packet which will be sent
+    * @returns true if successful
+    */
+    bool write( uint8_t *buf );
+
+    /**
+    * Write and read an audio packet at the same time (on the same frame)
+    *
+    * @param buf_read pointer on a buffer which will be filled with an audio packet
+    * @param buf_write pointer on the audio packet which will be sent
+    * @returns true if successful
+    */
+    bool readWrite( uint8_t *buf_read, uint8_t *buf_write );
+
+
+    /** attach a handler to update the volume
+     *
+     * @param function Function to attach
+     *
+     */
+    void attach( void( *fptr )( void ) )
+    {
+        updateVol.attach( fptr );
+    }
+
+    /** Attach a nonstatic void/void member function to update the volume
+     *
+     * @param tptr Object pointer
+     * @param mptr Member function pointer
+     *
+     */
+    template<typename T>
+    void attach( T *tptr, void( T::*mptr )( void ) )
+    {
+        updateVol.attach( tptr, mptr );
+    }
+
+
+protected:
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+    /*
+     * Called by USBDevice layer. Set interface/alternate of the device.
+     *
+     * @param interface Number of the interface to be configured
+     * @param alternate Number of the alternate to be configured
+     * @returns true if class handles this request
+     */
+    virtual bool USBCallback_setInterface( uint16_t interface, uint8_t alternate );
+
+    /*
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    *
+    * @param buf buffer received on endpoint 0
+    * @param length length of this buffer
+    */
+    virtual void USBCallback_requestCompleted( uint8_t *buf, uint32_t length );
+
+    /*
+    * Callback called on each Start of Frame event
+    */
+    virtual void SOF( int frameNumber );
+
+    /*
+    * Callback called when a packet is received
+    */
+    virtual bool EP3_OUT_callback();
+
+    /*
+    * Callback called when a packet has been sent
+    */
+    virtual bool EP3_IN_callback();
+
+private:
+
+    // stream available ?
+    volatile bool available;
+
+    // interrupt OUT has been received
+    volatile bool interruptOUT;
+
+    // interrupt IN has been received
+    volatile bool interruptIN;
+
+    // audio packet has been written
+    volatile bool writeIN;
+
+    // FREQ
+    uint32_t FREQ_OUT;
+    uint32_t FREQ_IN;
+
+    // size of the maximum packet for the isochronous endpoint
+    uint32_t PACKET_SIZE_ISO_IN;
+    uint32_t PACKET_SIZE_ISO_OUT;
+
+    // mono, stereo,...
+    uint8_t channel_nb_in;
+    uint8_t channel_nb_out;
+
+    // channel config: master, left, right
+    uint8_t channel_config_in;
+    uint8_t channel_config_out;
+
+    // mute state
+    uint8_t mute;
+
+    // Volume Current Value
+    uint16_t volCur;
+
+    // Volume Minimum Value
+    uint16_t volMin;
+
+    // Volume Maximum Value
+    uint16_t volMax;
+
+    // Volume Resolution
+    uint16_t volRes;
+
+    // Buffer containing one audio packet (to be read)
+    volatile uint8_t *buf_stream_in;
+
+    // Buffer containing one audio packet (to be written)
+    volatile uint8_t *buf_stream_out;
+
+    // callback to update volume
+    FunctionPointer updateVol;
+
+    // boolean showing that the SOF handler has been called. Useful for readNB.
+    volatile bool SOF_handler;
+
+    volatile float volume;
+
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBAudio/USBAudio_Types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBAudio/USBAudio_Types.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,98 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBAUDIO_TYPES_H
+#define USBAUDIO_TYPES_H
+
+
+#define DEFAULT_CONFIGURATION (1)
+
+// Audio Request Codes
+#define REQUEST_SET_CUR     0x01
+#define REQUEST_GET_CUR     0x81
+#define REQUEST_SET_MIN     0x02
+#define REQUEST_GET_MIN     0x82
+#define REQUEST_SET_MAX     0x03
+#define REQUEST_GET_MAX     0x83
+#define REQUEST_SET_RES     0x04
+#define REQUEST_GET_RES     0x84
+
+#define MUTE_CONTROL        0x01
+#define VOLUME_CONTROL      0x02
+
+
+// Audio Descriptor Sizes
+#define CONTROL_INTERFACE_DESCRIPTOR_LENGTH       0x09
+#define STREAMING_INTERFACE_DESCRIPTOR_LENGTH     0x07
+#define INPUT_TERMINAL_DESCRIPTOR_LENGTH          0x0C
+#define OUTPUT_TERMINAL_DESCRIPTOR_LENGTH         0x09
+#define FEATURE_UNIT_DESCRIPTOR_LENGTH            0x09
+#define STREAMING_ENDPOINT_DESCRIPTOR_LENGTH      0x07
+
+// Audio Format Type Descriptor Sizes
+#define FORMAT_TYPE_I_DESCRIPTOR_LENGTH   0x0b
+
+#define AUDIO_CLASS                       0x01
+#define SUBCLASS_AUDIOCONTROL             0x01
+#define SUBCLASS_AUDIOSTREAMING           0x02
+
+// Audio Descriptor Types
+#define INTERFACE_DESCRIPTOR_TYPE         0x24
+#define ENDPOINT_DESCRIPTOR_TYPE          0x25
+
+// Audio Control Interface Descriptor Subtypes
+#define CONTROL_HEADER                    0x01
+#define CONTROL_INPUT_TERMINAL            0x02
+#define CONTROL_OUTPUT_TERMINAL           0x03
+#define CONTROL_FEATURE_UNIT              0x06
+
+// USB Terminal Types
+#define TERMINAL_USB_STREAMING            0x0101
+
+// Predefined Audio Channel Configuration Bits
+// Mono
+#define CHANNEL_M                         0x0000
+#define CHANNEL_L                         0x0001  /* Left Front */
+#define CHANNEL_R                         0x0002  /* Right Front */
+
+// Feature Unit Control Bits
+#define CONTROL_MUTE                      0x0001
+#define CONTROL_VOLUME                    0x0002
+
+// Input Terminal Types
+#define TERMINAL_MICROPHONE               0x0201
+
+// Output Terminal Types
+#define TERMINAL_SPEAKER                  0x0301
+#define TERMINAL_HEADPHONES               0x0302
+
+// Audio Streaming Interface Descriptor Subtypes
+#define STREAMING_GENERAL                 0x01
+#define STREAMING_FORMAT_TYPE             0x02
+
+// Audio Data Format Type I Codes
+#define FORMAT_PCM                        0x0001
+
+// Audio Format Types
+#define FORMAT_TYPE_I                     0x01
+
+// Audio Endpoint Descriptor Subtypes
+#define ENDPOINT_GENERAL                  0x01
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBDescriptor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBDescriptor.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,75 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/* Standard descriptor types */
+#define DEVICE_DESCRIPTOR        (1)
+#define CONFIGURATION_DESCRIPTOR (2)
+#define STRING_DESCRIPTOR        (3)
+#define INTERFACE_DESCRIPTOR     (4)
+#define ENDPOINT_DESCRIPTOR      (5)
+#define QUALIFIER_DESCRIPTOR     (6)
+
+/* Standard descriptor lengths */
+#define DEVICE_DESCRIPTOR_LENGTH        (0x12)
+#define CONFIGURATION_DESCRIPTOR_LENGTH (0x09)
+#define INTERFACE_DESCRIPTOR_LENGTH     (0x09)
+#define ENDPOINT_DESCRIPTOR_LENGTH      (0x07)
+
+
+/*string offset*/
+#define STRING_OFFSET_LANGID            (0)
+#define STRING_OFFSET_IMANUFACTURER     (1)
+#define STRING_OFFSET_IPRODUCT          (2)
+#define STRING_OFFSET_ISERIAL           (3)
+#define STRING_OFFSET_ICONFIGURATION    (4)
+#define STRING_OFFSET_IINTERFACE        (5)
+
+/* USB Specification Release Number */
+#define USB_VERSION_2_0 (0x0200)
+
+/* Least/Most significant byte of short integer */
+#define LSB(n)  ((n)&0xff)
+#define MSB(n)  (((n)&0xff00)>>8)
+
+/* Convert physical endpoint number to descriptor endpoint number */
+#define PHY_TO_DESC(endpoint) (((endpoint)>>1) | (((endpoint) & 1) ? 0x80:0))
+
+/* bmAttributes in configuration descriptor */
+/* C_RESERVED must always be set */
+#define C_RESERVED      (1U<<7)
+#define C_SELF_POWERED  (1U<<6)
+#define C_REMOTE_WAKEUP (1U<<5)
+
+/* bMaxPower in configuration descriptor */
+#define C_POWER(mA)     ((mA)/2)
+
+/* bmAttributes in endpoint descriptor */
+#define E_CONTROL       (0x00)
+#define E_ISOCHRONOUS   (0x01)
+#define E_BULK          (0x02)
+#define E_INTERRUPT     (0x03)
+
+/* For isochronous endpoints only: */
+#define E_NO_SYNCHRONIZATION    (0x00)
+#define E_ASYNCHRONOUS          (0x04)
+#define E_ADAPTIVE              (0x08)
+#define E_SYNCHRONOUS           (0x0C)
+#define E_DATA                  (0x00)
+#define E_FEEDBACK              (0x10)
+#define E_IMPLICIT_FEEDBACK     (0x20)
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBDevice.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBDevice.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,1028 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+
+#include "USBEndpoints.h"
+#include "USBDevice.h"
+#include "USBDescriptor.h"
+
+//#define DEBUG
+
+/* Device status */
+#define DEVICE_STATUS_SELF_POWERED  (1U<<0)
+#define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
+
+/* Endpoint status */
+#define ENDPOINT_STATUS_HALT        (1U<<0)
+
+/* Standard feature selectors */
+#define DEVICE_REMOTE_WAKEUP        (1)
+#define ENDPOINT_HALT               (0)
+
+/* Macro to convert wIndex endpoint number to physical endpoint number */
+#define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
+                                      ((endpoint & 0x80) ? 1 : 0))
+
+
+bool USBDevice::requestGetDescriptor( void )
+{
+    bool success = false;
+#ifdef DEBUG
+    printf( "get descr: type: %d\r\n", DESCRIPTOR_TYPE( transfer.setup.wValue ) );
+#endif
+
+    switch ( DESCRIPTOR_TYPE( transfer.setup.wValue ) )
+    {
+        case DEVICE_DESCRIPTOR:
+            if ( deviceDesc() != NULL )
+            {
+                if ( ( deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH ) \
+                        && ( deviceDesc()[1] == DEVICE_DESCRIPTOR ) )
+                {
+#ifdef DEBUG
+                    printf( "device descr\r\n" );
+#endif
+                    transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
+                    transfer.ptr = deviceDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+
+            break;
+
+        case CONFIGURATION_DESCRIPTOR:
+            if ( configurationDesc() != NULL )
+            {
+                if ( ( configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH ) \
+                        && ( configurationDesc()[1] == CONFIGURATION_DESCRIPTOR ) )
+                {
+#ifdef DEBUG
+                    printf( "conf descr request\r\n" );
+#endif
+                    /* Get wTotalLength */
+                    transfer.remaining = configurationDesc()[2] \
+                                         | ( configurationDesc()[3] << 8 );
+                    transfer.ptr = configurationDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                }
+            }
+
+            break;
+
+        case STRING_DESCRIPTOR:
+#ifdef DEBUG
+            printf( "str descriptor\r\n" );
+#endif
+
+            switch ( DESCRIPTOR_INDEX( transfer.setup.wValue ) )
+            {
+                case STRING_OFFSET_LANGID:
+#ifdef DEBUG
+                    printf( "1\r\n" );
+#endif
+                    transfer.remaining = stringLangidDesc()[0];
+                    transfer.ptr = stringLangidDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+
+                case STRING_OFFSET_IMANUFACTURER:
+#ifdef DEBUG
+                    printf( "2\r\n" );
+#endif
+                    transfer.remaining =  stringImanufacturerDesc()[0];
+                    transfer.ptr = stringImanufacturerDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+
+                case STRING_OFFSET_IPRODUCT:
+#ifdef DEBUG
+                    printf( "3\r\n" );
+#endif
+                    transfer.remaining = stringIproductDesc()[0];
+                    transfer.ptr = stringIproductDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+
+                case STRING_OFFSET_ISERIAL:
+#ifdef DEBUG
+                    printf( "4\r\n" );
+#endif
+                    transfer.remaining = stringIserialDesc()[0];
+                    transfer.ptr = stringIserialDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+
+                case STRING_OFFSET_ICONFIGURATION:
+#ifdef DEBUG
+                    printf( "5\r\n" );
+#endif
+                    transfer.remaining = stringIConfigurationDesc()[0];
+                    transfer.ptr = stringIConfigurationDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+
+                case STRING_OFFSET_IINTERFACE:
+#ifdef DEBUG
+                    printf( "6\r\n" );
+#endif
+                    transfer.remaining = stringIinterfaceDesc()[0];
+                    transfer.ptr = stringIinterfaceDesc();
+                    transfer.direction = DEVICE_TO_HOST;
+                    success = true;
+                    break;
+            }
+
+            break;
+
+        case INTERFACE_DESCRIPTOR:
+#ifdef DEBUG
+            printf( "interface descr\r\n" );
+#endif
+
+        case ENDPOINT_DESCRIPTOR:
+#ifdef DEBUG
+            printf( "endpoint descr\r\n" );
+#endif
+            /* TODO: Support is optional, not implemented here */
+            break;
+
+        default:
+#ifdef DEBUG
+            printf( "ERROR\r\n" );
+#endif
+            break;
+    }
+
+    return success;
+}
+
+void USBDevice::decodeSetupPacket( uint8_t *data, SETUP_PACKET *packet )
+{
+    /* Fill in the elements of a SETUP_PACKET structure from raw data */
+    packet->bmRequestType.dataTransferDirection = ( data[0] & 0x80 ) >> 7;
+    packet->bmRequestType.Type = ( data[0] & 0x60 ) >> 5;
+    packet->bmRequestType.Recipient = data[0] & 0x1f;
+    packet->bRequest = data[1];
+    packet->wValue = ( data[2] | ( uint16_t )data[3] << 8 );
+    packet->wIndex = ( data[4] | ( uint16_t )data[5] << 8 );
+    packet->wLength = ( data[6] | ( uint16_t )data[7] << 8 );
+}
+
+
+bool USBDevice::controlOut( void )
+{
+    /* Control transfer data OUT stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+    uint32_t packetSize;
+
+    /* Check we should be transferring data OUT */
+    if ( transfer.direction != HOST_TO_DEVICE )
+    {
+        return false;
+    }
+
+    /* Read from endpoint */
+    packetSize = EP0getReadResult( buffer );
+
+    /* Check if transfer size is valid */
+    if ( packetSize > transfer.remaining )
+    {
+        /* Too big */
+        return false;
+    }
+
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+
+    /* Check if transfer has completed */
+    if ( transfer.remaining == 0 )
+    {
+        /* Transfer completed */
+        if ( transfer.notify )
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted( buffer, packetSize );
+            transfer.notify = false;
+        }
+
+        /* Status stage */
+        EP0write( NULL, 0 );
+    }
+    else
+    {
+        EP0read();
+    }
+
+    return true;
+}
+
+bool USBDevice::controlIn( void )
+{
+    /* Control transfer data IN stage */
+    uint32_t packetSize;
+
+    /* Check if transfer has completed (status stage transactions */
+    /* also have transfer.remaining == 0) */
+    if ( transfer.remaining == 0 )
+    {
+        if ( transfer.zlp )
+        {
+            /* Send zero length packet */
+            EP0write( NULL, 0 );
+            transfer.zlp = false;
+        }
+
+        /* Transfer completed */
+        if ( transfer.notify )
+        {
+            /* Notify class layer. */
+            USBCallback_requestCompleted( NULL, 0 );
+            transfer.notify = false;
+        }
+
+        EP0read();
+        /* Completed */
+        return true;
+    }
+
+    /* Check we should be transferring data IN */
+    if ( transfer.direction != DEVICE_TO_HOST )
+    {
+        return false;
+    }
+
+    packetSize = transfer.remaining;
+
+    if ( packetSize > MAX_PACKET_SIZE_EP0 )
+    {
+        packetSize = MAX_PACKET_SIZE_EP0;
+    }
+
+    /* Write to endpoint */
+    EP0write( transfer.ptr, packetSize );
+    /* Update transfer */
+    transfer.ptr += packetSize;
+    transfer.remaining -= packetSize;
+    return true;
+}
+
+bool USBDevice::requestSetAddress( void )
+{
+    /* Set the device address */
+    setAddress( transfer.setup.wValue );
+
+    if ( transfer.setup.wValue == 0 )
+    {
+        device.state = DEFAULT;
+    }
+    else
+    {
+        device.state = ADDRESS;
+    }
+
+    return true;
+}
+
+bool USBDevice::requestSetConfiguration( void )
+{
+    device.configuration = transfer.setup.wValue;
+
+    /* Set the device configuration */
+    if ( device.configuration == 0 )
+    {
+        /* Not configured */
+        unconfigureDevice();
+        device.state = ADDRESS;
+    }
+    else
+    {
+        if ( USBCallback_setConfiguration( device.configuration ) )
+        {
+            /* Valid configuration */
+            configureDevice();
+            device.state = CONFIGURED;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool USBDevice::requestGetConfiguration( void )
+{
+    /* Send the device configuration */
+    transfer.ptr = &device.configuration;
+    transfer.remaining = sizeof( device.configuration );
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestGetInterface( void )
+{
+    /* Return the selected alternate setting for an interface */
+    if ( device.state != CONFIGURED )
+    {
+        return false;
+    }
+
+    /* Send the alternate setting */
+    transfer.setup.wIndex = currentInterface;
+    transfer.ptr = &currentAlternate;
+    transfer.remaining = sizeof( currentAlternate );
+    transfer.direction = DEVICE_TO_HOST;
+    return true;
+}
+
+bool USBDevice::requestSetInterface( void )
+{
+    bool success = false;
+
+    if( USBCallback_setInterface( transfer.setup.wIndex, transfer.setup.wValue ) )
+    {
+        success = true;
+        currentInterface = transfer.setup.wIndex;
+        currentAlternate = transfer.setup.wValue;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestSetFeature()
+{
+    bool success = false;
+
+    if ( device.state != CONFIGURED )
+    {
+        /* Endpoint or interface must be zero */
+        if ( transfer.setup.wIndex != 0 )
+        {
+            return false;
+        }
+    }
+
+    switch ( transfer.setup.bmRequestType.Recipient )
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+
+        case ENDPOINT_RECIPIENT:
+            if ( transfer.setup.wValue == ENDPOINT_HALT )
+            {
+                /* TODO: We should check that the endpoint number is valid */
+                stallEndpoint(
+                    WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
+                success = true;
+            }
+
+            break;
+
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestClearFeature()
+{
+    bool success = false;
+
+    if ( device.state != CONFIGURED )
+    {
+        /* Endpoint or interface must be zero */
+        if ( transfer.setup.wIndex != 0 )
+        {
+            return false;
+        }
+    }
+
+    switch ( transfer.setup.bmRequestType.Recipient )
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Remote wakeup feature not supported */
+            break;
+
+        case ENDPOINT_RECIPIENT:
+
+            /* TODO: We should check that the endpoint number is valid */
+            if ( transfer.setup.wValue == ENDPOINT_HALT )
+            {
+                unstallEndpoint( WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
+                success = true;
+            }
+
+            break;
+
+        default:
+            break;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestGetStatus( void )
+{
+    static uint16_t status;
+    bool success = false;
+
+    if ( device.state != CONFIGURED )
+    {
+        /* Endpoint or interface must be zero */
+        if ( transfer.setup.wIndex != 0 )
+        {
+            return false;
+        }
+    }
+
+    switch ( transfer.setup.bmRequestType.Recipient )
+    {
+        case DEVICE_RECIPIENT:
+            /* TODO: Currently only supports self powered devices */
+            status = DEVICE_STATUS_SELF_POWERED;
+            success = true;
+            break;
+
+        case INTERFACE_RECIPIENT:
+            status = 0;
+            success = true;
+            break;
+
+        case ENDPOINT_RECIPIENT:
+
+            /* TODO: We should check that the endpoint number is valid */
+            if ( getEndpointStallState(
+                        WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) ) )
+            {
+                status = ENDPOINT_STATUS_HALT;
+            }
+            else
+            {
+                status = 0;
+            }
+
+            success = true;
+            break;
+
+        default:
+            break;
+    }
+
+    if ( success )
+    {
+        /* Send the status */
+        transfer.ptr = ( uint8_t * )&status; /* Assumes little endian */
+        transfer.remaining = sizeof( status );
+        transfer.direction = DEVICE_TO_HOST;
+    }
+
+    return success;
+}
+
+bool USBDevice::requestSetup( void )
+{
+    bool success = false;
+
+    /* Process standard requests */
+    if ( ( transfer.setup.bmRequestType.Type == STANDARD_TYPE ) )
+    {
+        switch ( transfer.setup.bRequest )
+        {
+            case GET_STATUS:
+                success = requestGetStatus();
+                break;
+
+            case CLEAR_FEATURE:
+                success = requestClearFeature();
+                break;
+
+            case SET_FEATURE:
+                success = requestSetFeature();
+                break;
+
+            case SET_ADDRESS:
+                success = requestSetAddress();
+                break;
+
+            case GET_DESCRIPTOR:
+                success = requestGetDescriptor();
+                break;
+
+            case SET_DESCRIPTOR:
+                /* TODO: Support is optional, not implemented here */
+                success = false;
+                break;
+
+            case GET_CONFIGURATION:
+                success = requestGetConfiguration();
+                break;
+
+            case SET_CONFIGURATION:
+                success = requestSetConfiguration();
+                break;
+
+            case GET_INTERFACE:
+                success = requestGetInterface();
+                break;
+
+            case SET_INTERFACE:
+                success = requestSetInterface();
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+bool USBDevice::controlSetup( void )
+{
+    bool success = false;
+    /* Control transfer setup stage */
+    uint8_t buffer[MAX_PACKET_SIZE_EP0];
+    EP0setup( buffer );
+    /* Initialise control transfer state */
+    decodeSetupPacket( buffer, &transfer.setup );
+    transfer.ptr = NULL;
+    transfer.remaining = 0;
+    transfer.direction = 0;
+    transfer.zlp = false;
+    transfer.notify = false;
+#ifdef DEBUG
+    printf( "dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n", transfer.setup.bmRequestType.dataTransferDirection,
+            transfer.setup.bmRequestType.Type,
+            transfer.setup.bmRequestType.Recipient,
+            transfer.setup.bRequest,
+            transfer.setup.wValue,
+            transfer.setup.wIndex,
+            transfer.setup.wLength );
+#endif
+    /* Class / vendor specific */
+    success = USBCallback_request();
+
+    if ( !success )
+    {
+        /* Standard requests */
+        if ( !requestSetup() )
+        {
+#ifdef DEBUG
+            printf( "fail!!!!\r\n" );
+#endif
+            return false;
+        }
+    }
+
+    /* Check transfer size and direction */
+    if ( transfer.setup.wLength > 0 )
+    {
+        if ( transfer.setup.bmRequestType.dataTransferDirection \
+                == DEVICE_TO_HOST )
+        {
+            /* IN data stage is required */
+            if ( transfer.direction != DEVICE_TO_HOST )
+            {
+                return false;
+            }
+
+            /* Transfer must be less than or equal to the size */
+            /* requested by the host */
+            if ( transfer.remaining > transfer.setup.wLength )
+            {
+                transfer.remaining = transfer.setup.wLength;
+            }
+        }
+        else
+        {
+            /* OUT data stage is required */
+            if ( transfer.direction != HOST_TO_DEVICE )
+            {
+                return false;
+            }
+
+            /* Transfer must be equal to the size requested by the host */
+            if ( transfer.remaining != transfer.setup.wLength )
+            {
+                return false;
+            }
+        }
+    }
+    else
+    {
+        /* No data stage; transfer size must be zero */
+        if ( transfer.remaining != 0 )
+        {
+            return false;
+        }
+    }
+
+    /* Data or status stage if applicable */
+    if ( transfer.setup.wLength > 0 )
+    {
+        if ( transfer.setup.bmRequestType.dataTransferDirection \
+                == DEVICE_TO_HOST )
+        {
+            /* Check if we'll need to send a zero length packet at */
+            /* the end of this transfer */
+            if ( transfer.setup.wLength > transfer.remaining )
+            {
+                /* Device wishes to transfer less than host requested */
+                if ( ( transfer.remaining % MAX_PACKET_SIZE_EP0 ) == 0 )
+                {
+                    /* Transfer is a multiple of EP0 max packet size */
+                    transfer.zlp = true;
+                }
+            }
+
+            /* IN stage */
+            controlIn();
+        }
+        else
+        {
+            /* OUT stage */
+            EP0read();
+        }
+    }
+    else
+    {
+        /* Status stage */
+        EP0write( NULL, 0 );
+    }
+
+    return true;
+}
+
+void USBDevice::busReset( void )
+{
+    device.state = DEFAULT;
+    device.configuration = 0;
+    device.suspended = false;
+    /* Call class / vendor specific busReset function */
+    USBCallback_busReset();
+}
+
+void USBDevice::EP0setupCallback( void )
+{
+    /* Endpoint 0 setup event */
+    if ( !controlSetup() )
+    {
+        /* Protocol stall */
+        EP0stall();
+    }
+
+    /* Return true if an OUT data stage is expected */
+}
+
+void USBDevice::EP0out( void )
+{
+    /* Endpoint 0 OUT data event */
+    if ( !controlOut() )
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+void USBDevice::EP0in( void )
+{
+#ifdef DEBUG
+    printf( "EP0IN\r\n" );
+#endif
+
+    /* Endpoint 0 IN data event */
+    if ( !controlIn() )
+    {
+        /* Protocol stall; this will stall both endpoints */
+        EP0stall();
+    }
+}
+
+bool USBDevice::configured( void )
+{
+    /* Returns true if device is in the CONFIGURED state */
+    return ( device.state == CONFIGURED );
+}
+
+void USBDevice::connect( void )
+{
+    /* Connect device */
+    USBHAL::connect();
+
+    /* Block if not configured */
+    while ( !configured() );
+}
+
+void USBDevice::disconnect( void )
+{
+    /* Disconnect device */
+    USBHAL::disconnect();
+}
+
+CONTROL_TRANSFER *USBDevice::getTransferPtr( void )
+{
+    return &transfer;
+}
+
+bool USBDevice::addEndpoint( uint8_t endpoint, uint32_t maxPacket )
+{
+    return realiseEndpoint( endpoint, maxPacket, 0 );
+}
+
+bool USBDevice::addRateFeedbackEndpoint( uint8_t endpoint, uint32_t maxPacket )
+{
+    /* For interrupt endpoints only */
+    return realiseEndpoint( endpoint, maxPacket, RATE_FEEDBACK_MODE );
+}
+
+uint8_t *USBDevice::findDescriptor( uint8_t descriptorType )
+{
+    /* Find a descriptor within the list of descriptors */
+    /* following a configuration descriptor. */
+    uint16_t wTotalLength;
+    uint8_t *ptr;
+
+    if ( configurationDesc() == NULL )
+    {
+        return NULL;
+    }
+
+    /* Check this is a configuration descriptor */
+    if ( ( configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH ) \
+            || ( configurationDesc()[1] != CONFIGURATION_DESCRIPTOR ) )
+    {
+        return NULL;
+    }
+
+    wTotalLength = configurationDesc()[2] | ( configurationDesc()[3] << 8 );
+
+    /* Check there are some more descriptors to follow */
+    if ( wTotalLength <= ( CONFIGURATION_DESCRIPTOR_LENGTH + 2 ) )
+        /* +2 is for bLength and bDescriptorType of next descriptor */
+    {
+        return false;
+    }
+
+    /* Start at first descriptor after the configuration descriptor */
+    ptr = &( configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH] );
+
+    do
+    {
+        if ( ptr[1] /* bDescriptorType */ == descriptorType )
+        {
+            /* Found */
+            return ptr;
+        }
+
+        /* Skip to next descriptor */
+        ptr += ptr[0]; /* bLength */
+    }
+    while ( ptr < ( configurationDesc() + wTotalLength ) );
+
+    /* Reached end of the descriptors - not found */
+    return NULL;
+}
+
+
+void USBDevice::connectStateChanged( unsigned int connected )
+{
+}
+
+void USBDevice::suspendStateChanged( unsigned int suspended )
+{
+}
+
+
+USBDevice::USBDevice( uint16_t vendor_id, uint16_t product_id, uint16_t product_release )
+{
+    VENDOR_ID = vendor_id;
+    PRODUCT_ID = product_id;
+    PRODUCT_RELEASE = product_release;
+    /* Set initial device state */
+    device.state = POWERED;
+    device.configuration = 0;
+    device.suspended = false;
+};
+
+
+bool USBDevice::readStart( uint8_t endpoint, uint32_t maxSize )
+{
+    return endpointRead( endpoint, maxSize ) == EP_PENDING;
+}
+
+
+bool USBDevice::write( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
+{
+    EP_STATUS result;
+
+    if ( size > maxSize )
+    {
+        return false;
+    }
+
+    if( !configured() )
+    {
+        return false;
+    }
+
+    /* Send report */
+    result = endpointWrite( endpoint, buffer, size );
+
+    if ( result != EP_PENDING )
+    {
+        return false;
+    }
+
+    /* Wait for completion */
+    do
+    {
+        result = endpointWriteResult( endpoint );
+    }
+    while ( ( result == EP_PENDING ) && configured() );
+
+    return ( result == EP_COMPLETED );
+}
+
+
+bool USBDevice::writeNB( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
+{
+    EP_STATUS result;
+
+    if ( size > maxSize )
+    {
+        return false;
+    }
+
+    if( !configured() )
+    {
+        return false;
+    }
+
+    /* Send report */
+    result = endpointWrite( endpoint, buffer, size );
+
+    if ( result != EP_PENDING )
+    {
+        return false;
+    }
+
+    result = endpointWriteResult( endpoint );
+    return ( result == EP_COMPLETED );
+}
+
+
+
+bool USBDevice::readEP( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
+{
+    EP_STATUS result;
+
+    if( !configured() )
+    {
+        return false;
+    }
+
+    /* Wait for completion */
+    do
+    {
+        result = endpointReadResult( endpoint, buffer, size );
+    }
+    while ( ( result == EP_PENDING ) && configured() );
+
+    return ( result == EP_COMPLETED );
+}
+
+
+bool USBDevice::readEP_NB( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
+{
+    EP_STATUS result;
+
+    if( !configured() )
+    {
+        return false;
+    }
+
+    result = endpointReadResult( endpoint, buffer, size );
+    return ( result == EP_COMPLETED );
+}
+
+
+
+uint8_t *USBDevice::deviceDesc()
+{
+    static uint8_t deviceDescriptor[] =
+    {
+        DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
+        DEVICE_DESCRIPTOR,              /* bDescriptorType */
+        LSB( USB_VERSION_2_0 ),         /* bcdUSB (LSB) */
+        MSB( USB_VERSION_2_0 ),         /* bcdUSB (MSB) */
+        0x00,                           /* bDeviceClass */
+        0x00,                           /* bDeviceSubClass */
+        0x00,                           /* bDeviceprotocol */
+        MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
+        LSB( VENDOR_ID ),               /* idVendor (LSB) */
+        MSB( VENDOR_ID ),               /* idVendor (MSB) */
+        LSB( PRODUCT_ID ),              /* idProduct (LSB) */
+        MSB( PRODUCT_ID ),              /* idProduct (MSB) */
+        LSB( PRODUCT_RELEASE ),         /* bcdDevice (LSB) */
+        MSB( PRODUCT_RELEASE ),         /* bcdDevice (MSB) */
+        STRING_OFFSET_IMANUFACTURER,    /* iManufacturer */
+        STRING_OFFSET_IPRODUCT,         /* iProduct */
+        STRING_OFFSET_ISERIAL,          /* iSerialNumber */
+        0x01                            /* bNumConfigurations */
+    };
+    return deviceDescriptor;
+}
+
+uint8_t *USBDevice::stringLangidDesc()
+{
+    static uint8_t stringLangidDescriptor[] =
+    {
+        0x04,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        0x09, 0x00,         /*bString Lang ID - 0x009 - English*/
+    };
+    return stringLangidDescriptor;
+}
+
+uint8_t *USBDevice::stringImanufacturerDesc()
+{
+    static uint8_t stringImanufacturerDescriptor[] =
+    {
+        0x12,                                            /*bLength*/
+        STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
+        'm', 0, 'b', 0, 'e', 0, 'd', 0, '.', 0, 'o', 0, 'r', 0, 'g', 0, /*bString iManufacturer - mbed.org*/
+    };
+    return stringImanufacturerDescriptor;
+}
+
+uint8_t *USBDevice::stringIserialDesc()
+{
+    static uint8_t stringIserialDescriptor[] =
+    {
+        0x16,                                                           /*bLength*/
+        STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
+        '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0, '9', 0, /*bString iSerial - 0123456789*/
+    };
+    return stringIserialDescriptor;
+}
+
+uint8_t *USBDevice::stringIConfigurationDesc()
+{
+    static uint8_t stringIconfigurationDescriptor[] =
+    {
+        0x06,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        '0', 0, '1', 0,     /*bString iConfiguration - 01*/
+    };
+    return stringIconfigurationDescriptor;
+}
+
+uint8_t *USBDevice::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x08,               /*bLength*/
+        STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
+        'U', 0, 'S', 0, 'B', 0, /*bString iInterface - USB*/
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBDevice::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,                                                       /*bLength*/
+        STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
+        'U', 0, 'S', 0, 'B', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0 /*bString iProduct - USB DEVICE*/
+    };
+    return stringIproductDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBDevice.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBDevice.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,285 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBDEVICE_H
+#define USBDEVICE_H
+
+#include "mbed.h"
+#include "USBDevice_Types.h"
+#include "USBHAL.h"
+
+class USBDevice: public USBHAL
+{
+public:
+    USBDevice( uint16_t vendor_id, uint16_t product_id, uint16_t product_release );
+
+    /*
+    * Check if the device is configured
+    *
+    * @returns true if configured, false otherwise
+    */
+    bool configured( void );
+
+    /*
+    * Connect a device
+    */
+    void connect( void );
+
+    /*
+    * Disconnect a device
+    */
+    void disconnect( void );
+
+    /*
+    * Add an endpoint
+    *
+    * @param endpoint endpoint which will be added
+    * @param maxPacket Maximum size of a packet which can be sent for this endpoint
+    * @returns true if successful, false otherwise
+    */
+    bool addEndpoint( uint8_t endpoint, uint32_t maxPacket );
+
+    /*
+    * Start a reading on a certain endpoint.
+    * You can access the result of the reading by USBDevice_read
+    *
+    * @param endpoint endpoint which will be read
+    * @param maxSize the maximum length that can be read
+    * @return true if successful
+    */
+    bool readStart( uint8_t endpoint, uint32_t maxSize );
+
+    /*
+    * Read a certain endpoint. Before calling this function, USBUSBDevice_readStart
+    * must be called.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize );
+
+    /*
+    * Read a certain endpoint.
+    *
+    * Warning: non blocking
+    *
+    * @param endpoint endpoint which will be read
+    * @param buffer buffer will be filled with the data received (if data are available)
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP_NB( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize );
+
+    /*
+    * Write a certain endpoint.
+    *
+    * Warning: blocking
+    *
+    * @param endpoint endpoint to write
+    * @param buffer data contained in buffer will be write
+    * @param size the number of bytes to write
+    * @param maxSize the maximum length that can be written on this endpoint
+    */
+    bool write( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize );
+
+
+    /*
+    * Write a certain endpoint.
+    *
+    * Warning: non blocking
+    *
+    * @param endpoint endpoint to write
+    * @param buffer data contained in buffer will be write
+    * @param size the number of bytes to write
+    * @param maxSize the maximum length that can be written on this endpoint
+    */
+    bool writeNB( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize );
+
+
+    /*
+    * Called by USBDevice layer on bus reset. Warning: Called in ISR context
+    *
+    * May be used to reset state
+    */
+    virtual void USBCallback_busReset( void ) {};
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request()
+    {
+        return false;
+    };
+
+    /*
+    * Called by USBDevice on Endpoint0 request completion
+    * if the 'notify' flag has been set to true. Warning: Called in ISR context
+    *
+    * In this case it is used to indicate that a HID report has
+    * been received from the host on endpoint 0
+    *
+    * @param buf buffer received on endpoint 0
+    * @param length length of this buffer
+    */
+    virtual void USBCallback_requestCompleted( uint8_t *buf, uint32_t length ) {};
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    */
+    virtual bool USBCallback_setConfiguration( uint8_t configuration )
+    {
+        return false;
+    };
+
+    /*
+     * Called by USBDevice layer. Set interface/alternate of the device.
+     *
+     * @param interface Number of the interface to be configured
+     * @param alternate Number of the alternate to be configured
+     * @returns true if class handles this request
+     */
+    virtual bool USBCallback_setInterface( uint16_t interface, uint8_t alternate )
+    {
+        return false;
+    };
+
+    /*
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t *deviceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc()
+    {
+        return NULL;
+    };
+
+    /*
+    * Get string lang id descriptor
+    *
+    * @return pointer to the string lang id descriptor
+    */
+    virtual uint8_t *stringLangidDesc();
+
+    /*
+    * Get string manufacturer descriptor
+    *
+    * @returns pointer to the string manufacturer descriptor
+    */
+    virtual uint8_t *stringImanufacturerDesc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string serial descriptor
+    *
+    * @returns pointer to the string serial descriptor
+    */
+    virtual uint8_t *stringIserialDesc();
+
+    /*
+    * Get string configuration descriptor
+    *
+    * @returns pointer to the string configuration descriptor
+    */
+    virtual uint8_t *stringIConfigurationDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get the length of the report descriptor
+    *
+    * @returns length of the report descriptor
+    */
+    virtual uint16_t reportDescLength()
+    {
+        return 0;
+    };
+
+
+
+protected:
+    virtual void busReset( void );
+    virtual void EP0setupCallback( void );
+    virtual void EP0out( void );
+    virtual void EP0in( void );
+    virtual void connectStateChanged( unsigned int connected );
+    virtual void suspendStateChanged( unsigned int suspended );
+    uint8_t *findDescriptor( uint8_t descriptorType );
+    CONTROL_TRANSFER *getTransferPtr( void );
+
+    uint16_t VENDOR_ID;
+    uint16_t PRODUCT_ID;
+    uint16_t PRODUCT_RELEASE;
+
+private:
+    bool addRateFeedbackEndpoint( uint8_t endpoint, uint32_t maxPacket );
+    bool requestGetDescriptor( void );
+    bool controlOut( void );
+    bool controlIn( void );
+    bool requestSetAddress( void );
+    bool requestSetConfiguration( void );
+    bool requestSetFeature( void );
+    bool requestClearFeature( void );
+    bool requestGetStatus( void );
+    bool requestSetup( void );
+    bool controlSetup( void );
+    void decodeSetupPacket( uint8_t *data, SETUP_PACKET *packet );
+    bool requestGetConfiguration( void );
+    bool requestGetInterface( void );
+    bool requestSetInterface( void );
+
+    CONTROL_TRANSFER transfer;
+    USB_DEVICE device;
+
+    uint16_t currentInterface;
+    uint8_t currentAlternate;
+};
+
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBDevice_Types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBDevice_Types.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,88 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBDEVICE_TYPES_H
+#define USBDEVICE_TYPES_H
+
+/* Standard requests */
+#define GET_STATUS        (0)
+#define CLEAR_FEATURE     (1)
+#define SET_FEATURE       (3)
+#define SET_ADDRESS       (5)
+#define GET_DESCRIPTOR    (6)
+#define SET_DESCRIPTOR    (7)
+#define GET_CONFIGURATION (8)
+#define SET_CONFIGURATION (9)
+#define GET_INTERFACE     (10)
+#define SET_INTERFACE     (11)
+
+/* bmRequestType.dataTransferDirection */
+#define HOST_TO_DEVICE (0)
+#define DEVICE_TO_HOST (1)
+
+/* bmRequestType.Type*/
+#define STANDARD_TYPE  (0)
+#define CLASS_TYPE     (1)
+#define VENDOR_TYPE    (2)
+#define RESERVED_TYPE  (3)
+
+/* bmRequestType.Recipient */
+#define DEVICE_RECIPIENT    (0)
+#define INTERFACE_RECIPIENT (1)
+#define ENDPOINT_RECIPIENT  (2)
+#define OTHER_RECIPIENT     (3)
+
+/* Descriptors */
+#define DESCRIPTOR_TYPE(wValue)  (wValue >> 8)
+#define DESCRIPTOR_INDEX(wValue) (wValue & 0xf)
+
+typedef struct
+{
+    struct
+    {
+        uint8_t dataTransferDirection;
+        uint8_t Type;
+        uint8_t Recipient;
+    } bmRequestType;
+    uint8_t  bRequest;
+    uint16_t wValue;
+    uint16_t wIndex;
+    uint16_t wLength;
+} SETUP_PACKET;
+
+typedef struct
+{
+    SETUP_PACKET setup;
+    uint8_t *ptr;
+    uint32_t remaining;
+    uint8_t direction;
+    bool zlp;
+    bool notify;
+} CONTROL_TRANSFER;
+
+typedef enum {ATTACHED, POWERED, DEFAULT, ADDRESS, CONFIGURED} DEVICE_STATE;
+
+typedef struct
+{
+    volatile DEVICE_STATE state;
+    uint8_t configuration;
+    bool suspended;
+} USB_DEVICE;
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBEndpoints.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBEndpoints.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,50 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBENDPOINTS_H
+#define USBENDPOINTS_H
+
+/* SETUP packet size */
+#define SETUP_PACKET_SIZE (8)
+
+/* Options flags for configuring endpoints */
+#define DEFAULT_OPTIONS     (0)
+#define SINGLE_BUFFERED     (1U << 0)
+#define ISOCHRONOUS         (1U << 1)
+#define RATE_FEEDBACK_MODE  (1U << 2) /* Interrupt endpoints only */
+
+/* Endpoint transfer status, for endpoints > 0 */
+typedef enum
+{
+    EP_COMPLETED,   /* Transfer completed */
+    EP_PENDING,     /* Transfer in progress */
+    EP_INVALID,     /* Invalid parameter */
+    EP_STALLED,     /* Endpoint stalled */
+} EP_STATUS;
+
+/* Include configuration for specific target */
+#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
+#include "USBEndpoints_LPC17_LPC23.h"
+#elif defined(TARGET_LPC11U24)
+#include "USBEndpoints_LPC11U.h"
+#else
+#error "Unknown target type"
+#endif
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBEndpoints_LPC11U.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBEndpoints_LPC11U.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,66 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (5)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP1IN       (3)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2OUT      (4)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP2IN       (5)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3OUT      (6)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP3IN       (7)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4OUT      (8)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+#define EP4IN       (9)  /* Int/Bulk/Iso  64/64/1023  Yes           */
+
+/* Maximum Packet sizes */
+
+#define MAX_PACKET_SIZE_EP0 (64)
+#define MAX_PACKET_SIZE_EP1 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP2 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP3 (64) /* Int/Bulk */
+#define MAX_PACKET_SIZE_EP4 (64) /* Int/Bulk */
+
+#define MAX_PACKET_SIZE_EP1_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP2_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP3_ISO (1023) /* Isochronous */
+#define MAX_PACKET_SIZE_EP4_ISO (1023) /* Isochronous */
+
+/* Generic endpoints - intended to be portable accross devices */
+/* and be suitable for simple USB devices. */
+
+/* Bulk endpoint */
+#define EPBULK_OUT  (EP2OUT)
+#define EPBULK_IN   (EP2IN)
+/* Interrupt endpoint */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+/* Isochronous endpoint */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3_ISO)
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBEndpoints_LPC17_LPC23.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBEndpoints_LPC17_LPC23.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,94 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#define NUMBER_OF_LOGICAL_ENDPOINTS (16)
+#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
+
+/* Define physical endpoint numbers */
+
+/*      Endpoint    No.     Type(s)       MaxPacket   DoubleBuffer  */
+/*      ----------------    ------------  ----------  ---           */
+#define EP0OUT      (0)  /* Control       64          No            */
+#define EP0IN       (1)  /* Control       64          No            */
+#define EP1OUT      (2)  /* Interrupt     64          No            */
+#define EP1IN       (3)  /* Interrupt     64          No            */
+#define EP2OUT      (4)  /* Bulk          64          Yes           */
+#define EP2IN       (5)  /* Bulk          64          Yes           */
+#define EP3OUT      (6)  /* Isochronous   1023        Yes           */
+#define EP3IN       (7)  /* Isochronous   1023        Yes           */
+#define EP4OUT      (8)  /* Interrupt     64          No            */
+#define EP4IN       (9)  /* Interrupt     64          No            */
+#define EP5OUT      (10) /* Bulk          64          Yes           */
+#define EP5IN       (11) /* Bulk          64          Yes           */
+#define EP6OUT      (12) /* Isochronous   1023        Yes           */
+#define EP6IN       (13) /* Isochronous   1023        Yes           */
+#define EP7OUT      (14) /* Interrupt     64          No            */
+#define EP7IN       (15) /* Interrupt     64          No            */
+#define EP8OUT      (16) /* Bulk          64          Yes           */
+#define EP8IN       (17) /* Bulk          64          Yes           */
+#define EP9OUT      (18) /* Isochronous   1023        Yes           */
+#define EP9IN       (19) /* Isochronous   1023        Yes           */
+#define EP10OUT     (20) /* Interrupt     64          No            */
+#define EP10IN      (21) /* Interrupt     64          No            */
+#define EP11OUT     (22) /* Bulk          64          Yes           */
+#define EP11IN      (23) /* Bulk          64          Yes           */
+#define EP12OUT     (24) /* Isochronous   1023        Yes           */
+#define EP12IN      (25) /* Isochronous   1023        Yes           */
+#define EP13OUT     (26) /* Interrupt     64          No            */
+#define EP13IN      (27) /* Interrupt     64          No            */
+#define EP14OUT     (28) /* Bulk          64          Yes           */
+#define EP14IN      (29) /* Bulk          64          Yes           */
+#define EP15OUT     (30) /* Bulk          64          Yes           */
+#define EP15IN      (31) /* Bulk          64          Yes           */
+
+/* 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  (1023)
+#define MAX_PACKET_SIZE_EP4  (64)
+#define MAX_PACKET_SIZE_EP5  (64)
+#define MAX_PACKET_SIZE_EP6  (1023)
+#define MAX_PACKET_SIZE_EP7  (64)
+#define MAX_PACKET_SIZE_EP8  (64)
+#define MAX_PACKET_SIZE_EP9  (1023)
+#define MAX_PACKET_SIZE_EP10 (64)
+#define MAX_PACKET_SIZE_EP11 (64)
+#define MAX_PACKET_SIZE_EP12 (1023)
+#define MAX_PACKET_SIZE_EP13 (64)
+#define MAX_PACKET_SIZE_EP14 (64)
+#define MAX_PACKET_SIZE_EP15 (64)
+
+/* 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)
+/* Interrupt endpoints */
+#define EPINT_OUT   (EP1OUT)
+#define EPINT_IN    (EP1IN)
+/* Isochronous endpoints */
+#define EPISO_OUT   (EP3OUT)
+#define EPISO_IN    (EP3IN)
+
+#define MAX_PACKET_SIZE_EPBULK  (MAX_PACKET_SIZE_EP2)
+#define MAX_PACKET_SIZE_EPINT   (MAX_PACKET_SIZE_EP1)
+#define MAX_PACKET_SIZE_EPISO   (MAX_PACKET_SIZE_EP3)
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBHAL.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBHAL.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,102 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBBUSINTERFACE_H
+#define USBBUSINTERFACE_H
+
+#include "mbed.h"
+#include "USBEndpoints.h"
+
+#define USB_ERRATA_WORKAROUND
+
+class USBHAL
+{
+public:
+    /* Configuration */
+    USBHAL();
+    ~USBHAL();
+    void connect( void );
+    void disconnect( void );
+#ifndef USB_ERRATA_WORKAROUND
+    bool vbusDetected( void );
+#endif
+    void configureDevice( void );
+    void unconfigureDevice( void );
+    void setAddress( uint8_t address );
+    void remoteWakeup( void );
+
+    /* Endpoint 0 */
+    void EP0setup( uint8_t *buffer );
+    void EP0read( void );
+    uint32_t EP0getReadResult( uint8_t *buffer );
+    void EP0write( uint8_t *buffer, uint32_t size );
+    void EP0getWriteResult( void );
+    void EP0stall( void );
+
+    /* Other endpoints */
+    EP_STATUS endpointRead( uint8_t endpoint, uint32_t maximumSize );
+    EP_STATUS endpointReadResult( uint8_t endpoint, uint8_t *data, uint32_t *bytesRead );
+    EP_STATUS endpointWrite( uint8_t endpoint, uint8_t *data, uint32_t size );
+    EP_STATUS endpointWriteResult( uint8_t endpoint );
+    void stallEndpoint( uint8_t endpoint );
+    void unstallEndpoint( uint8_t endpoint );
+    bool realiseEndpoint( uint8_t endpoint, uint32_t maxPacket, uint32_t options );
+    bool getEndpointStallState( unsigned char endpoint );
+    uint32_t endpointReadcore( uint8_t endpoint, uint8_t *buffer );
+
+protected:
+    virtual void busReset( void ) {};
+    virtual void EP0setupCallback( void ) {};
+    virtual void EP0out( void ) {};
+    virtual void EP0in( void ) {};
+    virtual void connectStateChanged( unsigned int connected ) {};
+    virtual void suspendStateChanged( unsigned int suspended ) {};
+    virtual void SOF( int frameNumber ) {};
+    virtual bool EP1_OUT_callback()
+    {
+        return false;
+    };
+    virtual bool EP1_IN_callback()
+    {
+        return false;
+    };
+    virtual bool EP2_OUT_callback()
+    {
+        return false;
+    };
+    virtual bool EP2_IN_callback()
+    {
+        return false;
+    };
+    virtual bool EP3_OUT_callback()
+    {
+        return false;
+    };
+    virtual bool EP3_IN_callback()
+    {
+        return false;
+    };
+
+private:
+    void usbisr( void );
+    static void _usbisr( void );
+    static USBHAL *instance;
+};
+#endif
+
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBHAL_LPC11U.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBHAL_LPC11U.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,830 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifdef TARGET_LPC11U24
+
+#include "USBHAL.h"
+
+USBHAL *USBHAL::instance;
+
+
+// Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+#define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Convert physical to logical
+#define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// USB RAM
+#define USB_RAM_START (0x20004000)
+#define USB_RAM_SIZE  (0x00000800)
+
+// SYSAHBCLKCTRL
+#define CLK_USB     (1UL<<14)
+#define CLK_USBRAM  (1UL<<27)
+
+// USB Information register
+#define FRAME_NR(a)     ((a) & 0x7ff)   // Frame number
+
+// USB Device Command/Status register
+#define DEV_ADDR_MASK   (0x7f)          // Device address
+#define DEV_ADDR(a)     ((a) & DEV_ADDR_MASK)
+#define DEV_EN          (1UL<<7)        // Device enable
+#define SETUP           (1UL<<8)        // SETUP token received
+#define PLL_ON          (1UL<<9)        // PLL enabled in suspend
+#define DCON            (1UL<<16)       // Device status - connect
+#define DSUS            (1UL<<17)       // Device status - suspend
+#define DCON_C          (1UL<<24)       // Connect change
+#define DSUS_C          (1UL<<25)       // Suspend change
+#define DRES_C          (1UL<<26)       // Reset change
+#define VBUSDEBOUNCED   (1UL<<28)       // Vbus detected
+
+// Endpoint Command/Status list
+#define CMDSTS_A                 (1UL<<31)          // Active
+#define CMDSTS_D                 (1UL<<30)          // Disable
+#define CMDSTS_S                 (1UL<<29)          // Stall
+#define CMDSTS_TR                (1UL<<28)          // Toggle Reset
+#define CMDSTS_RF                (1UL<<27)          // Rate Feedback mode
+#define CMDSTS_TV                (1UL<<27)          // Toggle Value
+#define CMDSTS_T                 (1UL<<26)          // Endpoint Type
+#define CMDSTS_NBYTES(n)         (((n)&0x3ff)<<16)  // Number of bytes
+#define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff)  // Buffer start address
+
+#define BYTES_REMAINING(s)       (((s)>>16)&0x3ff)  // Bytes remaining after transfer
+
+// USB Non-endpoint interrupt sources
+#define FRAME_INT   (1UL<<30)
+#define DEV_INT     (1UL<<31)
+
+static volatile int epComplete = 0;
+
+// One entry for a double-buffered logical endpoint in the endpoint
+// command/status list. Endpoint 0 is single buffered, out[1] is used
+// for the SETUP packet and in[1] is not used
+typedef __packed struct
+{
+    uint32_t out[2];
+    uint32_t in[2];
+} EP_COMMAND_STATUS;
+
+typedef __packed struct
+{
+    uint8_t out[MAX_PACKET_SIZE_EP0];
+    uint8_t in[MAX_PACKET_SIZE_EP0];
+    uint8_t setup[SETUP_PACKET_SIZE];
+} CONTROL_TRANSFER;
+
+typedef __packed struct
+{
+    uint32_t    maxPacket;
+    uint32_t    buffer[2];
+    uint32_t    options;
+} EP_STATE;
+
+static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
+
+// Pointer to the endpoint command/status list
+static EP_COMMAND_STATUS *ep = NULL;
+
+// Pointer to endpoint 0 data (IN/OUT and SETUP)
+static CONTROL_TRANSFER *ct = NULL;
+
+// Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
+// initiating a remote wakeup event.
+static volatile uint32_t devCmdStat;
+
+// Pointers used to allocate USB RAM
+static uint32_t usbRamPtr = USB_RAM_START;
+static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
+
+#define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
+
+void USBMemCopy( uint8_t *dst, uint8_t *src, uint32_t size );
+void USBMemCopy( uint8_t *dst, uint8_t *src, uint32_t size )
+{
+    if ( size > 0 )
+    {
+        do
+        {
+            *dst++ = *src++;
+        }
+        while ( --size > 0 );
+    }
+}
+
+
+USBHAL::USBHAL( void )
+{
+    NVIC_DisableIRQ( USB_IRQn );
+#ifndef USB_ERRATA_WORKAROUND
+    // control the CONNECT pin and VBUS as stdIO rather than by the peripheral
+    // http://www.nxp.com/documents/errata_sheet/ES_LPC11U1X.pdf - BS
+    // nUSB_CONNECT output
+    LPC_IOCON->PIO0_6 = 0x00000001;
+#endif
+    // Enable clocks (USB registers, USB RAM)
+    LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
+    // Ensure device disconnected (DCON not set)
+    LPC_USB->DEVCMDSTAT = 0;
+    // to ensure that the USB host sees the device as
+    // disconnected if the target CPU is reset.
+    wait( 0.3 );
+    // Reserve space in USB RAM for endpoint command/status list
+    // Must be 256 byte aligned
+    usbRamPtr = ROUND_UP_TO_MULTIPLE( usbRamPtr, 256 );
+    ep = ( EP_COMMAND_STATUS * )usbRamPtr;
+    usbRamPtr += ( sizeof( EP_COMMAND_STATUS ) * NUMBER_OF_LOGICAL_ENDPOINTS );
+    LPC_USB->EPLISTSTART = ( uint32_t )( ep ) & 0xffffff00;
+    // Reserve space in USB RAM for Endpoint 0
+    // Must be 64 byte aligned
+    usbRamPtr = ROUND_UP_TO_MULTIPLE( usbRamPtr, 64 );
+    ct = ( CONTROL_TRANSFER * )usbRamPtr;
+    usbRamPtr += sizeof( CONTROL_TRANSFER );
+    LPC_USB->DATABUFSTART = ( uint32_t )( ct ) & 0xffc00000;
+    // Setup command/status list for EP0
+    ep[0].out[0] = 0;
+    ep[0].in[0] =  0;
+    ep[0].out[1] = CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->setup );
+    // Route all interrupts to IRQ, some can be routed to
+    // USB_FIQ if you wish.
+    LPC_USB->INTROUTING = 0;
+    // Set device address 0, enable USB device, no remote wakeup
+    devCmdStat = DEV_ADDR( 0 ) | DEV_EN | DSUS;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+    // Enable interrupts for device events and EP0
+    LPC_USB->INTEN = DEV_INT | EP( EP0IN ) | EP( EP0OUT ) | FRAME_INT;
+    instance = this;
+    //attach IRQ handler and enable interrupts
+    NVIC_SetVector( USB_IRQn, ( uint32_t )&_usbisr );
+    NVIC_EnableIRQ( USB_IRQn );
+}
+
+USBHAL::~USBHAL( void )
+{
+    // Ensure device disconnected (DCON not set)
+    LPC_USB->DEVCMDSTAT = 0;
+    // Disable USB interrupts
+    NVIC_DisableIRQ( USB_IRQn );
+}
+
+void USBHAL::connect( void )
+{
+    devCmdStat |= DCON;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+void USBHAL::disconnect( void )
+{
+    devCmdStat &= ~DCON;
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+#ifndef USB_ERRATA_WORKAROUND
+bool USBHAL::vbusDetected( void )
+{
+    return ( LPC_USB->DEVCMDSTAT & ( 1 << 28 ) ) ? 1 : 0;
+}
+#endif
+
+void USBHAL::configureDevice( void )
+{
+}
+
+void USBHAL::unconfigureDevice( void )
+{
+}
+
+void USBHAL::EP0setup( uint8_t *buffer )
+{
+    // Copy setup packet data
+    USBMemCopy( buffer, ct->setup, SETUP_PACKET_SIZE );
+}
+
+void USBHAL::EP0read( void )
+{
+    // Start an endpoint 0 read
+    // The USB ISR will call USBDevice_EP0out() when a packet has been read,
+    // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
+    // read the data.
+    ep[0].out[0] = CMDSTS_A | CMDSTS_NBYTES( MAX_PACKET_SIZE_EP0 ) \
+                   | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->out );
+}
+
+uint32_t USBHAL::EP0getReadResult( uint8_t *buffer )
+{
+    // Complete an endpoint 0 read
+    uint32_t bytesRead;
+    // Find how many bytes were read
+    bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING( ep[0].out[0] );
+    // Copy data
+    USBMemCopy( buffer, ct->out, bytesRead );
+    return bytesRead;
+}
+
+void USBHAL::EP0write( uint8_t *buffer, uint32_t size )
+{
+    // Start and endpoint 0 write
+    // The USB ISR will call USBDevice_EP0in() when the data has
+    // been written, the USBDevice layer then calls
+    // USBBusInterface_EP0getWriteResult() to complete the transaction.
+    // Copy data
+    USBMemCopy( ct->in, buffer, size );
+    // Start transfer
+    ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES( size ) \
+                  | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->in );
+}
+
+
+EP_STATUS USBHAL::endpointRead( uint8_t endpoint, uint32_t maximumSize )
+{
+    uint8_t bf = 0;
+    uint32_t flags = 0;
+
+    //check which buffer must be filled
+    if ( LPC_USB->EPBUFCFG & EP( endpoint ) )
+    {
+        // Double buffered
+        if ( LPC_USB->EPINUSE & EP( endpoint ) )
+        {
+            bf = 1;
+        }
+        else
+        {
+            bf = 0;
+        }
+    }
+
+    // if isochronous endpoint, T = 1
+    if( endpointState[endpoint].options & ISOCHRONOUS )
+    {
+        flags |= CMDSTS_T;
+    }
+
+    //Active the endpoint for reading
+    ep[PHY_TO_LOG( endpoint )].out[bf] = CMDSTS_A | CMDSTS_NBYTES( maximumSize ) \
+                                         | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->out ) | flags;
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult( uint8_t endpoint, uint8_t *data, uint32_t *bytesRead )
+{
+    uint8_t bf = 0;
+
+    if ( !( epComplete & EP( endpoint ) ) )
+    {
+        return EP_PENDING;
+    }
+    else
+    {
+        epComplete &= ~EP( endpoint );
+
+        //check which buffer has been filled
+        if ( LPC_USB->EPBUFCFG & EP( endpoint ) )
+        {
+            // Double buffered (here we read the previous buffer which was used)
+            if ( LPC_USB->EPINUSE & EP( endpoint ) )
+            {
+                bf = 0;
+            }
+            else
+            {
+                bf = 1;
+            }
+        }
+
+        // Find how many bytes were read
+        *bytesRead = ( uint32_t ) ( endpointState[endpoint].maxPacket - BYTES_REMAINING( ep[PHY_TO_LOG( endpoint )].out[bf] ) );
+        // Copy data
+        USBMemCopy( data, ct->out, *bytesRead );
+        return EP_COMPLETED;
+    }
+}
+
+void USBHAL::EP0getWriteResult( void )
+{
+    // Complete an endpoint 0 write
+    // Nothing required for this target
+    return;
+}
+
+void USBHAL::EP0stall( void )
+{
+    ep[0].in[0] = CMDSTS_S;
+    ep[0].out[0] = CMDSTS_S;
+}
+
+void USBHAL::setAddress( uint8_t address )
+{
+    devCmdStat &= ~DEV_ADDR_MASK;
+    devCmdStat |= DEV_ADDR( address );
+    LPC_USB->DEVCMDSTAT = devCmdStat;
+}
+
+EP_STATUS USBHAL::endpointWrite( uint8_t endpoint, uint8_t *data, uint32_t size )
+{
+    uint32_t flags = 0;
+    uint32_t bf;
+
+    // Validate parameters
+    if ( data == NULL )
+    {
+        return EP_INVALID;
+    }
+
+    if ( endpoint > LAST_PHYSICAL_ENDPOINT )
+    {
+        return EP_INVALID;
+    }
+
+    if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) )
+    {
+        return EP_INVALID;
+    }
+
+    if ( size > endpointState[endpoint].maxPacket )
+    {
+        return EP_INVALID;
+    }
+
+    if ( LPC_USB->EPBUFCFG & EP( endpoint ) )
+    {
+        // Double buffered
+        if ( LPC_USB->EPINUSE & EP( endpoint ) )
+        {
+            bf = 1;
+        }
+        else
+        {
+            bf = 0;
+        }
+    }
+    else
+    {
+        // Single buffered
+        bf = 0;
+    }
+
+    // Check if already active
+    if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_A )
+    {
+        return EP_INVALID;
+    }
+
+    // Check if stalled
+    if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_S )
+    {
+        return EP_STALLED;
+    }
+
+    // Copy data to USB RAM
+    USBMemCopy( ( uint8_t * )endpointState[endpoint].buffer[bf], data, size );
+
+    // Add options
+    if ( endpointState[endpoint].options & RATE_FEEDBACK_MODE )
+    {
+        flags |= CMDSTS_RF;
+    }
+
+    if ( endpointState[endpoint].options & ISOCHRONOUS )
+    {
+        flags |= CMDSTS_T;
+    }
+
+    // Add transfer
+    ep[PHY_TO_LOG( endpoint )].in[bf] = CMDSTS_ADDRESS_OFFSET( \
+                                        endpointState[endpoint].buffer[bf] ) \
+                                        | CMDSTS_NBYTES( size ) | CMDSTS_A | flags;
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult( uint8_t endpoint )
+{
+    uint32_t bf;
+    // Validate parameters
+
+    if ( endpoint > LAST_PHYSICAL_ENDPOINT )
+    {
+        return EP_INVALID;
+    }
+
+    if ( OUT_EP( endpoint ) )
+    {
+        return EP_INVALID;
+    }
+
+    if ( LPC_USB->EPBUFCFG & EP( endpoint ) )
+    {
+        // Double buffered     // TODO: FIX THIS
+        if ( LPC_USB->EPINUSE & EP( endpoint ) )
+        {
+            bf = 1;
+        }
+        else
+        {
+            bf = 0;
+        }
+    }
+    else
+    {
+        // Single buffered
+        bf = 0;
+    }
+
+    // Check if endpoint still active
+    if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_A )
+    {
+        return EP_PENDING;
+    }
+
+    // Check if stalled
+    if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_S )
+    {
+        return EP_STALLED;
+    }
+
+    return EP_COMPLETED;
+}
+
+void USBHAL::stallEndpoint( uint8_t endpoint )
+{
+    // TODO: should this clear active bit?
+    if ( IN_EP( endpoint ) )
+    {
+        ep[PHY_TO_LOG( endpoint )].in[0] |= CMDSTS_S;
+        ep[PHY_TO_LOG( endpoint )].in[1] |= CMDSTS_S;
+    }
+    else
+    {
+        ep[PHY_TO_LOG( endpoint )].out[0] |= CMDSTS_S;
+        ep[PHY_TO_LOG( endpoint )].out[1] |= CMDSTS_S;
+    }
+}
+
+void USBHAL::unstallEndpoint( uint8_t endpoint )
+{
+    if ( LPC_USB->EPBUFCFG & EP( endpoint ) )
+    {
+        // Double buffered
+        if ( IN_EP( endpoint ) )
+        {
+            ep[PHY_TO_LOG( endpoint )].in[0] = 0; // S = 0
+            ep[PHY_TO_LOG( endpoint )].in[1] = 0; // S = 0
+
+            if ( LPC_USB->EPINUSE & EP( endpoint ) )
+            {
+                ep[PHY_TO_LOG( endpoint )].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
+            }
+            else
+            {
+                ep[PHY_TO_LOG( endpoint )].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
+            }
+        }
+        else
+        {
+            ep[PHY_TO_LOG( endpoint )].out[0] = 0; // S = 0
+            ep[PHY_TO_LOG( endpoint )].out[1] = 0; // S = 0
+
+            if ( LPC_USB->EPINUSE & EP( endpoint ) )
+            {
+                ep[PHY_TO_LOG( endpoint )].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
+            }
+            else
+            {
+                ep[PHY_TO_LOG( endpoint )].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
+            }
+        }
+    }
+    else
+    {
+        // Single buffered
+        if ( IN_EP( endpoint ) )
+        {
+            ep[PHY_TO_LOG( endpoint )].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
+        }
+        else
+        {
+            ep[PHY_TO_LOG( endpoint )].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
+        }
+    }
+}
+
+bool USBHAL::getEndpointStallState( unsigned char endpoint )
+{
+    if ( IN_EP( endpoint ) )
+    {
+        if ( LPC_USB->EPINUSE & EP( endpoint ) )
+        {
+            if ( ep[PHY_TO_LOG( endpoint )].in[1] & CMDSTS_S )
+            {
+                return true;
+            }
+        }
+        else
+        {
+            if ( ep[PHY_TO_LOG( endpoint )].in[0] & CMDSTS_S )
+            {
+                return true;
+            }
+        }
+    }
+    else
+    {
+        if ( LPC_USB->EPINUSE & EP( endpoint ) )
+        {
+            if ( ep[PHY_TO_LOG( endpoint )].out[1] & CMDSTS_S )
+            {
+                return true;
+            }
+        }
+        else
+        {
+            if ( ep[PHY_TO_LOG( endpoint )].out[0] & CMDSTS_S )
+            {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool USBHAL::realiseEndpoint( uint8_t endpoint, uint32_t maxPacket, uint32_t options )
+{
+    uint32_t tmpEpRamPtr;
+
+    if ( endpoint > LAST_PHYSICAL_ENDPOINT )
+    {
+        return false;
+    }
+
+    // Not applicable to the control endpoints
+    if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) )
+    {
+        return false;
+    }
+
+    // Allocate buffers in USB RAM
+    tmpEpRamPtr = epRamPtr;
+    // Must be 64 byte aligned
+    tmpEpRamPtr = ROUND_UP_TO_MULTIPLE( tmpEpRamPtr, 64 );
+
+    if ( ( tmpEpRamPtr + maxPacket ) > ( USB_RAM_START + USB_RAM_SIZE ) )
+    {
+        // Out of memory
+        return false;
+    }
+
+    // Allocate first buffer
+    endpointState[endpoint].buffer[0] = tmpEpRamPtr;
+    tmpEpRamPtr += maxPacket;
+
+    if ( !( options & SINGLE_BUFFERED ) )
+    {
+        // Must be 64 byte aligned
+        tmpEpRamPtr = ROUND_UP_TO_MULTIPLE( tmpEpRamPtr, 64 );
+
+        if ( ( tmpEpRamPtr + maxPacket ) > ( USB_RAM_START + USB_RAM_SIZE ) )
+        {
+            // Out of memory
+            return false;
+        }
+
+        // Allocate second buffer
+        endpointState[endpoint].buffer[1] = tmpEpRamPtr;
+        tmpEpRamPtr += maxPacket;
+    }
+
+    // Commit to this USB RAM allocation
+    epRamPtr = tmpEpRamPtr;
+    // Remaining endpoint state values
+    endpointState[endpoint].maxPacket = maxPacket;
+    endpointState[endpoint].options = options;
+
+    // Enable double buffering if required
+    if ( options & SINGLE_BUFFERED )
+    {
+        LPC_USB->EPBUFCFG &= ~EP( endpoint );
+    }
+    else
+    {
+        // Double buffered
+        LPC_USB->EPBUFCFG |= EP( endpoint );
+    }
+
+    // Enable interrupt
+    LPC_USB->INTEN |= EP( endpoint );
+    // Enable endpoint
+    unstallEndpoint( endpoint );
+    return true;
+}
+
+void USBHAL::remoteWakeup( void )
+{
+    // Clearing DSUS bit initiates a remote wakeup if the
+    // device is currently enabled and suspended - otherwise
+    // it has no effect.
+    LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
+}
+
+
+static void disableEndpoints( void )
+{
+    uint32_t logEp;
+
+    // Ref. Table 158 "When a bus reset is received, software
+    // must set the disable bit of all endpoints to 1".
+
+    for ( logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++ )
+    {
+        ep[logEp].out[0] = CMDSTS_D;
+        ep[logEp].out[1] = CMDSTS_D;
+        ep[logEp].in[0] =  CMDSTS_D;
+        ep[logEp].in[1] =  CMDSTS_D;
+    }
+
+    // Start of USB RAM for endpoints > 0
+    epRamPtr = usbRamPtr;
+}
+
+
+
+void USBHAL::_usbisr( void )
+{
+    instance->usbisr();
+}
+
+void USBHAL::usbisr( void )
+{
+    // Start of frame
+    if ( LPC_USB->INTSTAT & FRAME_INT )
+    {
+        // Clear SOF interrupt
+        LPC_USB->INTSTAT = FRAME_INT;
+        // SOF event, read frame number
+        SOF( FRAME_NR( LPC_USB->INFO ) );
+    }
+
+    // Device state
+    if ( LPC_USB->INTSTAT & DEV_INT )
+    {
+        LPC_USB->INTSTAT = DEV_INT;
+
+        if ( LPC_USB->DEVCMDSTAT & DSUS_C )
+        {
+            // Suspend status changed
+            LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
+
+            if( ( LPC_USB->DEVCMDSTAT & DSUS ) != 0 )
+            {
+                suspendStateChanged( 1 );
+            }
+        }
+
+        if ( LPC_USB->DEVCMDSTAT & DRES_C )
+        {
+            // Bus reset
+            LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
+            suspendStateChanged( 0 );
+            // Disable endpoints > 0
+            disableEndpoints();
+            // Bus reset event
+            busReset();
+        }
+    }
+
+    // Endpoint 0
+    if ( LPC_USB->INTSTAT & EP( EP0OUT ) )
+    {
+        // Clear EP0OUT/SETUP interrupt
+        LPC_USB->INTSTAT = EP( EP0OUT );
+
+        // Check if SETUP
+        if ( LPC_USB->DEVCMDSTAT & SETUP )
+        {
+            // Clear Active and Stall bits for EP0
+            // Documentation does not make it clear if we must use the
+            // EPSKIP register to achieve this, Fig. 16 and NXP reference
+            // code suggests we can just clear the Active bits - check with
+            // NXP to be sure.
+            ep[0].in[0] = 0;
+            ep[0].out[0] = 0;
+            // Clear EP0IN interrupt
+            LPC_USB->INTSTAT = EP( EP0IN );
+            // Clear SETUP (and INTONNAK_CI/O) in device status register
+            LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
+            // EP0 SETUP event (SETUP data received)
+            EP0setupCallback();
+        }
+        else
+        {
+            // EP0OUT ACK event (OUT data received)
+            EP0out();
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP0IN ) )
+    {
+        // Clear EP0IN interrupt
+        LPC_USB->INTSTAT = EP( EP0IN );
+        // EP0IN ACK event (IN data sent)
+        EP0in();
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP1IN ) )
+    {
+        // Clear EP1IN interrupt
+        LPC_USB->INTSTAT = EP( EP1IN );
+        epComplete |= EP( EP1IN );
+
+        if ( EP1_IN_callback() )
+        {
+            epComplete &= ~EP( EP1IN );
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP1OUT ) )
+    {
+        // Clear EP1OUT interrupt
+        LPC_USB->INTSTAT = EP( EP1OUT );
+        epComplete |= EP( EP1OUT );
+
+        if ( EP1_OUT_callback() )
+        {
+            epComplete &= ~EP( EP1OUT );
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP2IN ) )
+    {
+        // Clear EPBULK_IN interrupt
+        LPC_USB->INTSTAT = EP( EP2IN );
+        epComplete |= EP( EP2IN );
+
+        if ( EP2_IN_callback() )
+        {
+            epComplete &= ~EP( EP2IN );
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP2OUT ) )
+    {
+        // Clear EPBULK_OUT interrupt
+        LPC_USB->INTSTAT = EP( EP2OUT );
+        epComplete |= EP( EP2OUT );
+
+        //Call callback function. If true, clear epComplete
+        if ( EP2_OUT_callback() )
+        {
+            epComplete &= ~EP( EP2OUT );
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP3IN ) )
+    {
+        // Clear EP3_IN interrupt
+        LPC_USB->INTSTAT = EP( EP3IN );
+        epComplete |= EP( EP3IN );
+
+        if ( EP3_IN_callback() )
+        {
+            epComplete &= ~EP( EP3IN );
+        }
+    }
+
+    if ( LPC_USB->INTSTAT & EP( EP3OUT ) )
+    {
+        // Clear EP3_OUT interrupt
+        LPC_USB->INTSTAT = EP( EP3OUT );
+        epComplete |= EP( EP3OUT );
+
+        //Call callback function. If true, clear epComplete
+        if ( EP3_OUT_callback() )
+        {
+            epComplete &= ~EP( EP3OUT );
+        }
+    }
+}
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBDevice/USBHAL_LPC17.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice/USBHAL_LPC17.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,728 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifdef TARGET_LPC1768
+
+#include "USBHAL.h"
+
+
+// Get endpoint direction
+#define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
+#define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
+
+// Convert physical endpoint number to register bit
+#define EP(endpoint) (1UL<<endpoint)
+
+// Power Control for Peripherals register
+#define PCUSB      (1UL<<31)
+
+// USB Clock Control register
+#define DEV_CLK_EN (1UL<<1)
+#define AHB_CLK_EN (1UL<<4)
+
+// USB Clock Status register
+#define DEV_CLK_ON (1UL<<1)
+#define AHB_CLK_ON (1UL<<4)
+
+// USB Device Interupt registers
+#define FRAME      (1UL<<0)
+#define EP_FAST    (1UL<<1)
+#define EP_SLOW    (1UL<<2)
+#define DEV_STAT   (1UL<<3)
+#define CCEMPTY    (1UL<<4)
+#define CDFULL     (1UL<<5)
+#define RxENDPKT   (1UL<<6)
+#define TxENDPKT   (1UL<<7)
+#define EP_RLZED   (1UL<<8)
+#define ERR_INT    (1UL<<9)
+
+// USB Control register
+#define RD_EN (1<<0)
+#define WR_EN (1<<1)
+#define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
+
+// USB Receive Packet Length register
+#define DV      (1UL<<10)
+#define PKT_RDY (1UL<<11)
+#define PKT_LNGTH_MASK (0x3ff)
+
+// Serial Interface Engine (SIE)
+#define SIE_WRITE   (0x01)
+#define SIE_READ    (0x02)
+#define SIE_COMMAND (0x05)
+#define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
+
+// SIE Command codes
+#define SIE_CMD_SET_ADDRESS        (0xD0)
+#define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
+#define SIE_CMD_SET_MODE           (0xF3)
+#define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
+#define SIE_CMD_READ_TEST_REGISTER (0xFD)
+#define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
+#define SIE_CMD_GET_ERROR_CODE     (0xFF)
+#define SIE_CMD_READ_ERROR_STATUS  (0xFB)
+
+#define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
+#define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
+#define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
+
+#define SIE_CMD_CLEAR_BUFFER    (0xF2)
+#define SIE_CMD_VALIDATE_BUFFER (0xFA)
+
+// SIE Device Status register
+#define SIE_DS_CON    (1<<0)
+#define SIE_DS_CON_CH (1<<1)
+#define SIE_DS_SUS    (1<<2)
+#define SIE_DS_SUS_CH (1<<3)
+#define SIE_DS_RST    (1<<4)
+
+// SIE Device Set Address register
+#define SIE_DSA_DEV_EN  (1<<7)
+
+// SIE Configue Device register
+#define SIE_CONF_DEVICE (1<<0)
+
+// Select Endpoint register
+#define SIE_SE_FE       (1<<0)
+#define SIE_SE_ST       (1<<1)
+#define SIE_SE_STP      (1<<2)
+#define SIE_SE_PO       (1<<3)
+#define SIE_SE_EPN      (1<<4)
+#define SIE_SE_B_1_FULL (1<<5)
+#define SIE_SE_B_2_FULL (1<<6)
+
+// Set Endpoint Status command
+#define SIE_SES_ST      (1<<0)
+#define SIE_SES_DA      (1<<5)
+#define SIE_SES_RF_MO   (1<<6)
+#define SIE_SES_CND_ST  (1<<7)
+
+
+USBHAL *USBHAL::instance;
+
+volatile int epComplete;
+uint32_t endpointStallState;
+
+static void SIECommand( uint32_t command )
+{
+    // The command phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CCEMPTY;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_COMMAND, command );
+
+    while ( !( LPC_USB->USBDevIntSt & CCEMPTY ) );
+}
+
+static void SIEWriteData( uint8_t data )
+{
+    // The data write phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CCEMPTY;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_WRITE, data );
+
+    while ( !( LPC_USB->USBDevIntSt & CCEMPTY ) );
+}
+
+static uint8_t SIEReadData( uint32_t command )
+{
+    // The data read phase of a SIE transaction
+    LPC_USB->USBDevIntClr = CDFULL;
+    LPC_USB->USBCmdCode = SIE_CMD_CODE( SIE_READ, command );
+
+    while ( !( LPC_USB->USBDevIntSt & CDFULL ) );
+
+    return ( uint8_t )LPC_USB->USBCmdData;
+}
+
+static void SIEsetDeviceStatus( uint8_t status )
+{
+    // Write SIE device status register
+    SIECommand( SIE_CMD_SET_DEVICE_STATUS );
+    SIEWriteData( status );
+}
+
+static uint8_t SIEgetDeviceStatus( void )
+{
+    // Read SIE device status register
+    SIECommand( SIE_CMD_GET_DEVICE_STATUS );
+    return SIEReadData( SIE_CMD_GET_DEVICE_STATUS );
+}
+
+void SIEsetAddress( uint8_t address )
+{
+    // Write SIE device address register
+    SIECommand( SIE_CMD_SET_ADDRESS );
+    SIEWriteData( ( address & 0x7f ) | SIE_DSA_DEV_EN );
+}
+
+static uint8_t SIEselectEndpoint( uint8_t endpoint )
+{
+    // SIE select endpoint command
+    SIECommand( SIE_CMD_SELECT_ENDPOINT( endpoint ) );
+    return SIEReadData( SIE_CMD_SELECT_ENDPOINT( endpoint ) );
+}
+
+static uint8_t SIEclearBuffer( void )
+{
+    // SIE clear buffer command
+    SIECommand( SIE_CMD_CLEAR_BUFFER );
+    return SIEReadData( SIE_CMD_CLEAR_BUFFER );
+}
+
+static void SIEvalidateBuffer( void )
+{
+    // SIE validate buffer command
+    SIECommand( SIE_CMD_VALIDATE_BUFFER );
+}
+
+static void SIEsetEndpointStatus( uint8_t endpoint, uint8_t status )
+{
+    // SIE set endpoint status command
+    SIECommand( SIE_CMD_SET_ENDPOINT_STATUS( endpoint ) );
+    SIEWriteData( status );
+}
+
+static uint16_t SIEgetFrameNumber( void ) __attribute__ ( ( unused ) );
+static uint16_t SIEgetFrameNumber( void )
+{
+    // Read current frame number
+    uint16_t lowByte;
+    uint16_t highByte;
+    SIECommand( SIE_CMD_READ_FRAME_NUMBER );
+    lowByte = SIEReadData( SIE_CMD_READ_FRAME_NUMBER );
+    highByte = SIEReadData( SIE_CMD_READ_FRAME_NUMBER );
+    return ( highByte << 8 ) | lowByte;
+}
+
+static void SIEconfigureDevice( void )
+{
+    // SIE Configure device command
+    SIECommand( SIE_CMD_CONFIGURE_DEVICE );
+    SIEWriteData( SIE_CONF_DEVICE );
+}
+
+static void SIEunconfigureDevice( void )
+{
+    // SIE Configure device command
+    SIECommand( SIE_CMD_CONFIGURE_DEVICE );
+    SIEWriteData( 0 );
+}
+
+static void SIEconnect( void )
+{
+    // Connect USB device
+    uint8_t status;
+    status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus( status | SIE_DS_CON );
+}
+
+
+static void SIEdisconnect( void )
+{
+    // Disconnect USB device
+    uint8_t status;
+    status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus( status & ~SIE_DS_CON );
+}
+
+
+static uint8_t selectEndpointClearInterrupt( uint8_t endpoint )
+{
+    // Implemented using using EP_INT_CLR.
+    LPC_USB->USBEpIntClr = EP( endpoint );
+
+    while ( !( LPC_USB->USBDevIntSt & CDFULL ) );
+
+    return ( uint8_t )LPC_USB->USBCmdData;
+}
+
+
+
+
+
+static void enableEndpointEvent( uint8_t endpoint )
+{
+    // Enable an endpoint interrupt
+    LPC_USB->USBEpIntEn |= EP( endpoint );
+}
+
+static void disableEndpointEvent( uint8_t endpoint ) __attribute__ ( ( unused ) );
+static void disableEndpointEvent( uint8_t endpoint )
+{
+    // Disable an endpoint interrupt
+    LPC_USB->USBEpIntEn &= ~EP( endpoint );
+}
+
+static volatile uint32_t __attribute__( ( used ) ) dummyRead;
+
+
+uint32_t USBHAL::endpointReadcore( uint8_t endpoint, uint8_t *buffer )
+{
+    // Read from an OUT endpoint
+    uint32_t size;
+    uint32_t i;
+    uint32_t data = 0;
+    uint8_t offset;
+    LPC_USB->USBCtrl = LOG_ENDPOINT( endpoint ) | RD_EN;
+
+    while ( !( LPC_USB->USBRxPLen & PKT_RDY ) );
+
+    size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
+    offset = 0;
+
+    if ( size > 0 )
+    {
+        for ( i = 0; i < size; i++ )
+        {
+            if ( offset == 0 )
+            {
+                // Fetch up to four bytes of data as a word
+                data = LPC_USB->USBRxData;
+            }
+
+            // extract a byte
+            *buffer = ( data >> offset ) & 0xff;
+            buffer++;
+            // move on to the next byte
+            offset = ( offset + 8 ) % 32;
+        }
+    }
+    else
+    {
+        dummyRead = LPC_USB->USBRxData;
+    }
+
+    LPC_USB->USBCtrl = 0;
+
+    if ( ( endpoint >> 1 ) % 3 || ( endpoint >> 1 ) == 0 )
+    {
+        SIEselectEndpoint( endpoint );
+        SIEclearBuffer();
+    }
+
+    return size;
+}
+
+static void endpointWritecore( uint8_t endpoint, uint8_t *buffer, uint32_t size )
+{
+    // Write to an IN endpoint
+    uint32_t temp, data;
+    uint8_t offset;
+    LPC_USB->USBCtrl = LOG_ENDPOINT( endpoint ) | WR_EN;
+    LPC_USB->USBTxPLen = size;
+    offset = 0;
+    data = 0;
+
+    if ( size > 0 )
+    {
+        do
+        {
+            // Fetch next data byte into a word-sized temporary variable
+            temp = *buffer++;
+            // Add to current data word
+            temp = temp << offset;
+            data = data | temp;
+            // move on to the next byte
+            offset = ( offset + 8 ) % 32;
+            size--;
+
+            if ( ( offset == 0 ) || ( size == 0 ) )
+            {
+                // Write the word to the endpoint
+                LPC_USB->USBTxData = data;
+                data = 0;
+            }
+        }
+        while ( size > 0 );
+    }
+    else
+    {
+        LPC_USB->USBTxData = 0;
+    }
+
+    // Clear WR_EN to cover zero length packet case
+    LPC_USB->USBCtrl = 0;
+    SIEselectEndpoint( endpoint );
+    SIEvalidateBuffer();
+}
+
+
+
+
+
+
+
+USBHAL::USBHAL( void )
+{
+    // Disable IRQ
+    NVIC_DisableIRQ( USB_IRQn );
+    // Enable power to USB device controller
+    LPC_SC->PCONP |= PCUSB;
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+
+    while ( LPC_USB->USBClkSt != ( DEV_CLK_ON | AHB_CLK_ON ) );
+
+    // Configure pins P0.29 and P0.30 to be USB D+ and USB D-
+    LPC_PINCON->PINSEL1 &= 0xc3ffffff;
+    LPC_PINCON->PINSEL1 |= 0x14000000;
+    // Disconnect USB device
+    SIEdisconnect();
+    // Configure pin P2.9 to be Connect
+    LPC_PINCON->PINSEL4 &= 0xfffcffff;
+    LPC_PINCON->PINSEL4 |= 0x00040000;
+    // Connect must be low for at least 2.5uS
+    wait( 0.3 );
+    // Set the maximum packet size for the control endpoints
+    realiseEndpoint( EP0IN, MAX_PACKET_SIZE_EP0, 0 );
+    realiseEndpoint( EP0OUT, MAX_PACKET_SIZE_EP0, 0 );
+    // Attach IRQ
+    instance = this;
+    NVIC_SetVector( USB_IRQn, ( uint32_t )&_usbisr );
+    NVIC_EnableIRQ( USB_IRQn );
+    // Enable interrupts for device events and EP0
+    LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT | FRAME;
+    enableEndpointEvent( EP0IN );
+    enableEndpointEvent( EP0OUT );
+}
+
+USBHAL::~USBHAL( void )
+{
+    // Ensure device disconnected
+    SIEdisconnect();
+    // Disable USB interrupts
+    NVIC_DisableIRQ( USB_IRQn );
+}
+
+void USBHAL::connect( void )
+{
+    // Connect USB device
+    SIEconnect();
+}
+
+void USBHAL::disconnect( void )
+{
+    // Disconnect USB device
+    SIEdisconnect();
+}
+
+void USBHAL::configureDevice( void )
+{
+    SIEconfigureDevice();
+}
+
+void USBHAL::unconfigureDevice( void )
+{
+    SIEunconfigureDevice();
+}
+
+void USBHAL::setAddress( uint8_t address )
+{
+    SIEsetAddress( address );
+}
+
+void USBHAL::EP0setup( uint8_t *buffer )
+{
+    endpointReadcore( EP0OUT, buffer );
+}
+
+void USBHAL::EP0read( void )
+{
+    // Not required
+}
+
+uint32_t USBHAL::EP0getReadResult( uint8_t *buffer )
+{
+    return endpointReadcore( EP0OUT, buffer );
+}
+
+void USBHAL::EP0write( uint8_t *buffer, uint32_t size )
+{
+    endpointWritecore( EP0IN, buffer, size );
+}
+
+void USBHAL::EP0getWriteResult( void )
+{
+    // Not required
+}
+
+void USBHAL::EP0stall( void )
+{
+    // This will stall both control endpoints
+    stallEndpoint( EP0OUT );
+}
+
+EP_STATUS USBHAL::endpointRead( uint8_t endpoint, uint32_t maximumSize )
+{
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointReadResult( uint8_t endpoint, uint8_t *buffer, uint32_t *bytesRead )
+{
+    //for isochronous endpoint, we don't wait an interrupt
+    if ( ( endpoint >> 1 ) % 3 || ( endpoint >> 1 ) == 0 )
+    {
+        if ( !( epComplete & EP( endpoint ) ) )
+        {
+            return EP_PENDING;
+        }
+    }
+
+    *bytesRead = endpointReadcore( endpoint, buffer );
+    epComplete &= ~EP( endpoint );
+    return EP_COMPLETED;
+}
+
+EP_STATUS USBHAL::endpointWrite( uint8_t endpoint, uint8_t *data, uint32_t size )
+{
+    if ( getEndpointStallState( endpoint ) )
+    {
+        return EP_STALLED;
+    }
+
+    epComplete &= ~EP( endpoint );
+    endpointWritecore( endpoint, data, size );
+    return EP_PENDING;
+}
+
+EP_STATUS USBHAL::endpointWriteResult( uint8_t endpoint )
+{
+    if ( epComplete & EP( endpoint ) )
+    {
+        epComplete &= ~EP( endpoint );
+        return EP_COMPLETED;
+    }
+
+    return EP_PENDING;
+}
+
+bool USBHAL::realiseEndpoint( uint8_t endpoint, uint32_t maxPacket, uint32_t flags )
+{
+    // Realise an endpoint
+    LPC_USB->USBDevIntClr = EP_RLZED;
+    LPC_USB->USBReEp |= EP( endpoint );
+    LPC_USB->USBEpInd = endpoint;
+    LPC_USB->USBMaxPSize = maxPacket;
+
+    while ( !( LPC_USB->USBDevIntSt & EP_RLZED ) );
+
+    LPC_USB->USBDevIntClr = EP_RLZED;
+    // Clear stall state
+    endpointStallState &= ~EP( endpoint );
+    enableEndpointEvent( endpoint );
+    return true;
+}
+
+void USBHAL::stallEndpoint( uint8_t endpoint )
+{
+    // Stall an endpoint
+    if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) )
+    {
+        // Conditionally stall both control endpoints
+        SIEsetEndpointStatus( EP0OUT, SIE_SES_CND_ST );
+    }
+    else
+    {
+        SIEsetEndpointStatus( endpoint, SIE_SES_ST );
+        // Update stall state
+        endpointStallState |= EP( endpoint );
+    }
+}
+
+void USBHAL::unstallEndpoint( uint8_t endpoint )
+{
+    // Unstall an endpoint. The endpoint will also be reinitialised
+    SIEsetEndpointStatus( endpoint, 0 );
+    // Update stall state
+    endpointStallState &= ~EP( endpoint );
+}
+
+bool USBHAL::getEndpointStallState( uint8_t endpoint )
+{
+    // Returns true if endpoint stalled
+    return endpointStallState & EP( endpoint );
+}
+
+void USBHAL::remoteWakeup( void )
+{
+    // Remote wakeup
+    uint8_t status;
+    // Enable USB clocks
+    LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
+
+    while ( LPC_USB->USBClkSt != ( DEV_CLK_ON | AHB_CLK_ON ) );
+
+    status = SIEgetDeviceStatus();
+    SIEsetDeviceStatus( status & ~SIE_DS_SUS );
+}
+
+
+
+
+
+void USBHAL::_usbisr( void )
+{
+    instance->usbisr();
+}
+
+
+void USBHAL::usbisr( void )
+{
+    uint8_t devStat;
+
+    if ( LPC_USB->USBDevIntSt & FRAME )
+    {
+        // Start of frame event
+        SOF( SIEgetFrameNumber() );
+        // Clear interrupt status flag
+        LPC_USB->USBDevIntClr = FRAME;
+    }
+
+    if ( LPC_USB->USBDevIntSt & DEV_STAT )
+    {
+        // Device Status interrupt
+        // Must clear the interrupt status flag before reading the device status from the SIE
+        LPC_USB->USBDevIntClr = DEV_STAT;
+        // Read device status from SIE
+        devStat = SIEgetDeviceStatus();
+        //printf("devStat: %d\r\n", devStat);
+
+        if ( devStat & SIE_DS_SUS_CH )
+        {
+            // Suspend status changed
+            if( ( devStat & SIE_DS_SUS ) != 0 )
+            {
+                suspendStateChanged( 0 );
+            }
+        }
+
+        if ( devStat & SIE_DS_RST )
+        {
+            // Bus reset
+            if( ( devStat & SIE_DS_SUS ) == 0 )
+            {
+                suspendStateChanged( 1 );
+            }
+
+            busReset();
+        }
+    }
+
+    if ( LPC_USB->USBDevIntSt & EP_SLOW )
+    {
+        // (Slow) Endpoint Interrupt
+
+        // Process each endpoint interrupt
+        if ( LPC_USB->USBEpIntSt & EP( EP0OUT ) )
+        {
+            if ( selectEndpointClearInterrupt( EP0OUT ) & SIE_SE_STP )
+            {
+                // this is a setup packet
+                EP0setupCallback();
+            }
+            else
+            {
+                EP0out();
+            }
+
+            LPC_USB->USBDevIntClr = EP_SLOW;
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP0IN ) )
+        {
+            selectEndpointClearInterrupt( EP0IN );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+            EP0in();
+        }
+
+        // TODO: This should cover all endpoints, not just EP1,2,3:
+        if ( LPC_USB->USBEpIntSt & EP( EP1IN ) )
+        {
+            selectEndpointClearInterrupt( EP1IN );
+            epComplete |= EP( EP1IN );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP1_IN_callback() )
+            {
+                epComplete &= ~EP( EP1IN );
+            }
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP1OUT ) )
+        {
+            selectEndpointClearInterrupt( EP1OUT );
+            epComplete |= EP( EP1OUT );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP1_OUT_callback() )
+            {
+                epComplete &= ~EP( EP1OUT );
+            }
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP2IN ) )
+        {
+            selectEndpointClearInterrupt( EP2IN );
+            epComplete |= EP( EP2IN );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP2_IN_callback() )
+            {
+                epComplete &= ~EP( EP2IN );
+            }
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP2OUT ) )
+        {
+            selectEndpointClearInterrupt( EP2OUT );
+            epComplete |= EP( EP2OUT );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP2_OUT_callback() )
+            {
+                epComplete &= ~EP( EP2OUT );
+            }
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP3IN ) )
+        {
+            selectEndpointClearInterrupt( EP3IN );
+            epComplete |= EP( EP3IN );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP3_IN_callback() )
+            {
+                epComplete &= ~EP( EP3IN );
+            }
+        }
+
+        if ( LPC_USB->USBEpIntSt & EP( EP3OUT ) )
+        {
+            selectEndpointClearInterrupt( EP3OUT );
+            epComplete |= EP( EP3OUT );
+            LPC_USB->USBDevIntClr = EP_SLOW;
+
+            if ( EP3_OUT_callback() )
+            {
+                epComplete &= ~EP( EP3OUT );
+            }
+        }
+    }
+}
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBHID.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBHID.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,301 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBDevice/USBDevice/USBHAL.h"
+#include "USBHID.h"
+
+
+USBHID::USBHID( uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release, bool connect ): USBDevice( vendor_id, product_id, product_release )
+{
+    output_length = output_report_length;
+    input_length = input_report_length;
+
+    if( connect )
+    {
+        USBDevice::connect();
+    }
+}
+
+
+bool USBHID::send( HID_REPORT *report )
+{
+    return write( EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE );
+}
+
+bool USBHID::sendNB( HID_REPORT *report )
+{
+    return writeNB( EPINT_IN, report->data, report->length, MAX_HID_REPORT_SIZE );
+}
+
+
+bool USBHID::read( HID_REPORT *report )
+{
+    uint32_t bytesRead = 0;
+    bool result;
+    result = USBDevice::readEP( EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE );
+
+    if( !readStart( EPINT_OUT, MAX_HID_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    report->length = bytesRead;
+    return result;
+}
+
+
+bool USBHID::readNB( HID_REPORT *report )
+{
+    uint32_t bytesRead = 0;
+    bool result;
+    result = USBDevice::readEP_NB( EPINT_OUT, report->data, &bytesRead, MAX_HID_REPORT_SIZE );
+    report->length = bytesRead;
+
+    if( !readStart( EPINT_OUT, MAX_HID_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return result;
+}
+
+
+uint16_t USBHID::reportDescLength()
+{
+    reportDesc();
+    return reportLength;
+}
+
+
+
+//
+//  Route callbacks from lower layers to class(es)
+//
+
+
+// Called in ISR context
+// Called by USBDevice on Endpoint0 request
+// This is used to handle extensions to standard requests
+// and class specific requests
+// Return true if class handles this request
+bool USBHID::USBCallback_request()
+{
+    bool success = false;
+    CONTROL_TRANSFER *transfer = getTransferPtr();
+    uint8_t *hidDescriptor;
+
+    // Process additional standard requests
+
+    if ( ( transfer->setup.bmRequestType.Type == STANDARD_TYPE ) )
+    {
+        switch ( transfer->setup.bRequest )
+        {
+            case GET_DESCRIPTOR:
+                switch ( DESCRIPTOR_TYPE( transfer->setup.wValue ) )
+                {
+                    case REPORT_DESCRIPTOR:
+                        if ( ( reportDesc() != NULL ) \
+                                && ( reportDescLength() != 0 ) )
+                        {
+                            transfer->remaining = reportDescLength();
+                            transfer->ptr = reportDesc();
+                            transfer->direction = DEVICE_TO_HOST;
+                            success = true;
+                        }
+
+                        break;
+
+                    case HID_DESCRIPTOR:
+                        // Find the HID descriptor, after the configuration descriptor
+                        hidDescriptor = findDescriptor( HID_DESCRIPTOR );
+
+                        if ( hidDescriptor != NULL )
+                        {
+                            transfer->remaining = HID_DESCRIPTOR_LENGTH;
+                            transfer->ptr = hidDescriptor;
+                            transfer->direction = DEVICE_TO_HOST;
+                            success = true;
+                        }
+
+                        break;
+
+                    default:
+                        break;
+                }
+
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    // Process class-specific requests
+
+    if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
+    {
+        switch ( transfer->setup.bRequest )
+        {
+            case SET_REPORT:
+                // First byte will be used for report ID
+                outputReport.data[0] = transfer->setup.wValue & 0xff;
+                outputReport.length = transfer->setup.wLength + 1;
+                transfer->remaining = sizeof( outputReport.data ) - 1;
+                transfer->ptr = &outputReport.data[1];
+                transfer->direction = HOST_TO_DEVICE;
+                transfer->notify = true;
+                success = true;
+
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+#define DEFAULT_CONFIGURATION (1)
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported
+bool USBHID::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint( EPINT_IN, MAX_PACKET_SIZE_EPINT );
+    addEndpoint( EPINT_OUT, MAX_PACKET_SIZE_EPINT );
+    // We activate the endpoint to be able to recceive data
+    readStart( EPINT_OUT, MAX_PACKET_SIZE_EPINT );
+    return true;
+}
+
+
+uint8_t *USBHID::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x08,               //bLength
+        STRING_DESCRIPTOR,  //bDescriptorType 0x03
+        'H', 0, 'I', 0, 'D', 0, //bString iInterface - HID
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBHID::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'H', 0, 'I', 0, 'D', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0 //bString iProduct - HID device
+    };
+    return stringIproductDescriptor;
+}
+
+
+
+uint8_t *USBHID::reportDesc()
+{
+    static uint8_t reportDescriptor[] =
+    {
+        0x06, LSB( 0xFFAB ), MSB( 0xFFAB ),
+        0x0A, LSB( 0x0200 ), MSB( 0x0200 ),
+        0xA1, 0x01,         // Collection 0x01
+        0x75, 0x08,         // report size = 8 bits
+        0x15, 0x00,         // logical minimum = 0
+        0x26, 0xFF, 0x00,   // logical maximum = 255
+        0x95, input_length,           // report count
+        0x09, 0x01,         // usage
+        0x81, 0x02,         // Input (array)
+        0x95, output_length,           // report count
+        0x09, 0x02,         // usage
+        0x91, 0x02,         // Output (array)
+        0xC0                // end collection
+
+    };
+    reportLength = sizeof( reportDescriptor );
+    return reportDescriptor;
+}
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                                 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                                 + (1 * HID_DESCRIPTOR_LENGTH) \
+                                 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t *USBHID::configurationDesc()
+{
+    static uint8_t configurationDescriptor[] =
+    {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (LSB)
+        MSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER( 0 ),                   // bMaxPower
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        HID_SUBCLASS_NONE,              // bInterfaceSubClass
+        HID_PROTOCOL_NONE,              // bInterfaceProtocol
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB( HID_VERSION_1_11 ),        // bcdHID (LSB)
+        MSB( HID_VERSION_1_11 ),        // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        LSB( this->reportDescLength() ), // wDescriptorLength (LSB)
+        MSB( this->reportDescLength() ), // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_IN ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_OUT ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBHID.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBHID.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,174 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USB_HID_H
+#define USB_HID_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBHID_Types.h"
+#include "USBDevice/USBDevice/USBDevice.h"
+
+
+/**
+ * USBHID example
+ * @code
+ * #include "mbed.h"
+ * #include "USBHID.h"
+ *
+ * USBHID hid;
+ * HID_REPORT recv;
+ * BusOut leds(LED1,LED2,LED3,LED4);
+ *
+ * int main(void) {
+ *    while (1) {
+ *        hid.read(&recv);
+ *        leds = recv.data[0];
+ *    }
+ * }
+ * @endcode
+ */
+
+class USBHID: public USBDevice
+{
+public:
+
+    /**
+    * Constructor
+    *
+    * @param output_report_length Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
+    * @param input_report_length Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    * @param connect Connect the device
+    */
+    USBHID( uint8_t output_report_length = 64, uint8_t input_report_length = 64, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0006, uint16_t product_release = 0x0001, bool connect = true );
+
+
+    /**
+    * Send a Report. warning: blocking
+    *
+    * @param report Report which will be sent (a report is defined by all data and the length)
+    * @returns true if successful
+    */
+    bool send( HID_REPORT *report );
+
+
+    /**
+    * Send a Report. warning: non blocking
+    *
+    * @param report Report which will be sent (a report is defined by all data and the length)
+    * @returns true if successful
+    */
+    bool sendNB( HID_REPORT *report );
+
+    /**
+    * Read a report: blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool read( HID_REPORT *report );
+
+    /**
+    * Read a report: non blocking
+    *
+    * @param report pointer to the report to fill
+    * @returns true if successful
+    */
+    bool readNB( HID_REPORT *report );
+
+protected:
+    uint16_t reportLength;
+
+    /*
+    * Get the Report descriptor
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t *reportDesc();
+
+    /*
+    * Get the length of the report descriptor
+    *
+    * @returns the length of the report descriptor
+    */
+    virtual uint16_t reportDescLength();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+
+    /*
+    * HID Report received by SET_REPORT request. Warning: Called in ISR context
+    * First byte of data will be the report ID
+    *
+    * @param report Data and length received
+    */
+    virtual void HID_callbackSetReport( HID_REPORT *report ) {};
+
+
+    /*
+    * Called by USBDevice on Endpoint0 request. Warning: Called in ISR context
+    * This is used to handle extensions to standard requests
+    * and class specific requests
+    *
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_request();
+
+
+    /*
+    * Called by USBDevice layer. Set configuration of the device.
+    * For instance, you can add all endpoints that you need on this function.
+    *
+    * @param configuration Number of the configuration
+    * @returns true if class handles this request
+    */
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+
+private:
+    HID_REPORT outputReport;
+    uint8_t output_length;
+    uint8_t input_length;
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBHID_Types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBHID_Types.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,93 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBCLASS_HID_TYPES
+#define USBCLASS_HID_TYPES
+
+#include <stdint.h>
+
+/* */
+#define HID_VERSION_1_11    (0x0111)
+
+/* HID Class */
+#define HID_CLASS           (3)
+#define HID_SUBCLASS_NONE   (0)
+#define HID_PROTOCOL_NONE   (0)
+
+/* Descriptors */
+#define HID_DESCRIPTOR          (33)
+#define HID_DESCRIPTOR_LENGTH   (0x09)
+#define REPORT_DESCRIPTOR       (34)
+
+/* Class requests */
+#define GET_REPORT (0x1)
+#define GET_IDLE   (0x2)
+#define SET_REPORT (0x9)
+#define SET_IDLE   (0xa)
+
+/* HID Class Report Descriptor */
+/* Short items: size is 0, 1, 2 or 3 specifying 0, 1, 2 or 4 (four) bytes */
+/* of data as per HID Class standard */
+
+/* Main items */
+#define INPUT(size)             (0x80 | size)
+#define OUTPUT(size)            (0x90 | size)
+#define FEATURE(size)           (0xb0 | size)
+#define COLLECTION(size)        (0xa0 | size)
+#define END_COLLECTION(size)    (0xc0 | size)
+
+/* Global items */
+#define USAGE_PAGE(size)        (0x04 | size)
+#define LOGICAL_MINIMUM(size)   (0x14 | size)
+#define LOGICAL_MAXIMUM(size)   (0x24 | size)
+#define PHYSICAL_MINIMUM(size)  (0x34 | size)
+#define PHYSICAL_MAXIMUM(size)  (0x44 | size)
+#define UNIT_EXPONENT(size)     (0x54 | size)
+#define UNIT(size)              (0x64 | size)
+#define REPORT_SIZE(size)       (0x74 | size)
+#define REPORT_ID(size)         (0x84 | size)
+#define REPORT_COUNT(size)      (0x94 | size)
+#define PUSH(size)              (0xa4 | size)
+#define POP(size)               (0xb4 | size)
+
+/* Local items */
+#define USAGE(size)                 (0x08 | size)
+#define USAGE_MINIMUM(size)         (0x18 | size)
+#define USAGE_MAXIMUM(size)         (0x28 | size)
+#define DESIGNATOR_INDEX(size)      (0x38 | size)
+#define DESIGNATOR_MINIMUM(size)    (0x48 | size)
+#define DESIGNATOR_MAXIMUM(size)    (0x58 | size)
+#define STRING_INDEX(size)          (0x78 | size)
+#define STRING_MINIMUM(size)        (0x88 | size)
+#define STRING_MAXIMUM(size)        (0x98 | size)
+#define DELIMITER(size)             (0xa8 | size)
+
+/* HID Report */
+/* Where report IDs are used the first byte of 'data' will be the */
+/* report ID and 'length' will include this report ID byte. */
+
+#define MAX_HID_REPORT_SIZE (64)
+
+typedef struct
+{
+    uint32_t length;
+    uint8_t data[MAX_HID_REPORT_SIZE];
+} HID_REPORT;
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBKeyboard.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBKeyboard.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,564 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+
+#include "USBKeyboard.h"
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_VOLUME   3
+
+
+typedef struct
+{
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x34, KEY_SHIFT},      /* " */
+    {0x20, KEY_SHIFT},      /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x1f, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x31, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x31, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x35, KEY_SHIFT},      /* ~ */
+    {0, 0},             /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x1f, KEY_SHIFT},      /* " */
+    {0x32, 0},          /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x34, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x64, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x64, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x32, KEY_SHIFT},      /* ~ */
+    {0, 0},            /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+#endif
+
+uint8_t *USBKeyboard::reportDesc()
+{
+    static uint8_t reportDescriptor[] =
+    {
+        USAGE_PAGE( 1 ), 0x01,                  // Generic Desktop
+        USAGE( 1 ), 0x06,                       // Keyboard
+        COLLECTION( 1 ), 0x01,                  // Application
+        REPORT_ID( 1 ),       REPORT_ID_KEYBOARD,
+
+        USAGE_PAGE( 1 ), 0x07,                  // Key Codes
+        USAGE_MINIMUM( 1 ), 0xE0,
+        USAGE_MAXIMUM( 1 ), 0xE7,
+        LOGICAL_MINIMUM( 1 ), 0x00,
+        LOGICAL_MAXIMUM( 1 ), 0x01,
+        REPORT_SIZE( 1 ), 0x01,
+        REPORT_COUNT( 1 ), 0x08,
+        INPUT( 1 ), 0x02,                       // Data, Variable, Absolute
+        REPORT_COUNT( 1 ), 0x01,
+        REPORT_SIZE( 1 ), 0x08,
+        INPUT( 1 ), 0x01,                       // Constant
+
+
+        REPORT_COUNT( 1 ), 0x05,
+        REPORT_SIZE( 1 ), 0x01,
+        USAGE_PAGE( 1 ), 0x08,                  // LEDs
+        USAGE_MINIMUM( 1 ), 0x01,
+        USAGE_MAXIMUM( 1 ), 0x05,
+        OUTPUT( 1 ), 0x02,                      // Data, Variable, Absolute
+        REPORT_COUNT( 1 ), 0x01,
+        REPORT_SIZE( 1 ), 0x03,
+        OUTPUT( 1 ), 0x01,                      // Constant
+
+
+        REPORT_COUNT( 1 ), 0x06,
+        REPORT_SIZE( 1 ), 0x08,
+        LOGICAL_MINIMUM( 1 ), 0x00,
+        LOGICAL_MAXIMUM( 1 ), 0x65,
+        USAGE_PAGE( 1 ), 0x07,                  // Key Codes
+        USAGE_MINIMUM( 1 ), 0x00,
+        USAGE_MAXIMUM( 1 ), 0x65,
+        INPUT( 1 ), 0x00,                       // Data, Array
+        END_COLLECTION( 0 ),
+
+        // Media Control
+        USAGE_PAGE( 1 ), 0x0C,
+        USAGE( 1 ), 0x01,
+        COLLECTION( 1 ), 0x01,
+        REPORT_ID( 1 ), REPORT_ID_VOLUME,
+        USAGE_PAGE( 1 ), 0x0C,
+        LOGICAL_MINIMUM( 1 ), 0x00,
+        LOGICAL_MAXIMUM( 1 ), 0x01,
+        REPORT_SIZE( 1 ), 0x01,
+        REPORT_COUNT( 1 ), 0x07,
+        USAGE( 1 ), 0xB5,           // Next Track
+        USAGE( 1 ), 0xB6,           // Previous Track
+        USAGE( 1 ), 0xB7,           // Stop
+        USAGE( 1 ), 0xCD,           // Play / Pause
+        USAGE( 1 ), 0xE2,           // Mute
+        USAGE( 1 ), 0xE9,           // Volume Up
+        USAGE( 1 ), 0xEA,           // Volume Down
+        INPUT( 1 ), 0x02,           // Input (Data, Variable, Absolute)
+        REPORT_COUNT( 1 ), 0x01,
+        INPUT( 1 ), 0x01,
+        END_COLLECTION( 0 ),
+    };
+    reportLength = sizeof( reportDescriptor );
+    return reportDescriptor;
+}
+
+
+bool USBKeyboard::EP1_OUT_callback()
+{
+    uint32_t bytesRead = 0;
+    uint8_t led[65];
+    USBDevice::readEP( EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE );
+    // we take led[1] because led[0] is the report ID
+    lock_status = led[1] & 0x07;
+
+    // We activate the endpoint to be able to recceive data
+    if ( !readStart( EPINT_OUT, MAX_HID_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+uint8_t USBKeyboard::lockStatus()
+{
+    return lock_status;
+}
+
+int USBKeyboard::_putc( int c )
+{
+    return keyCode( c, keymap[c].modifier );
+}
+
+bool USBKeyboard::keyCode( uint8_t key, uint8_t modifier )
+{
+    // Send a simulated keyboard keypress. Returns true if successful.
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+    report.length = 9;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool USBKeyboard::mediaControl( MEDIA_KEY key )
+{
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = ( 1 << key ) & 0x7f;
+    report.length = 2;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+    report.length = 2;
+    return send( &report );
+}
+
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                                 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                                 + (1 * HID_DESCRIPTOR_LENGTH) \
+                                 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t *USBKeyboard::configurationDesc()
+{
+    static uint8_t configurationDescriptor[] =
+    {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (LSB)
+        MSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER( 0 ),                   // bMaxPowerHello World from Mbed
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        1,                              // bInterfaceSubClass
+        1,                              // bInterfaceProtocol (keyboard)
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB( HID_VERSION_1_11 ),        // bcdHID (LSB)
+        MSB( HID_VERSION_1_11 ),        // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        LSB( reportDescLength() ), // wDescriptorLength (LSB)
+        MSB( reportDescLength() ), // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_IN ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_OUT ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                             // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBKeyboard.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBKeyboard.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,190 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBKEYBOARD_H
+#define USBKEYBOARD_H
+
+#include "USBHID.h"
+#include "Stream.h"
+
+/* Modifiers */
+enum MODIFIER_KEY
+{
+    KEY_CTRL = 1,
+    KEY_SHIFT = 2,
+    KEY_ALT = 4,
+};
+
+
+enum MEDIA_KEY
+{
+    KEY_NEXT_TRACK,     /*!< next Track Button */
+    KEY_PREVIOUS_TRACK, /*!< Previous track Button */
+    KEY_STOP,           /*!< Stop Button */
+    KEY_PLAY_PAUSE,     /*!< Play/Pause Button */
+    KEY_MUTE,           /*!< Mute Button */
+    KEY_VOLUME_UP,      /*!< Volume Up Button */
+    KEY_VOLUME_DOWN,    /*!< Volume Down Button */
+};
+
+enum FUNCTION_KEY
+{
+    KEY_F1 = 128,   /* F1 key */
+    KEY_F2,         /* F2 key */
+    KEY_F3,         /* F3 key */
+    KEY_F4,         /* F4 key */
+    KEY_F5,         /* F5 key */
+    KEY_F6,         /* F6 key */
+    KEY_F7,         /* F7 key */
+    KEY_F8,         /* F8 key */
+    KEY_F9,         /* F9 key */
+    KEY_F10,        /* F10 key */
+    KEY_F11,        /* F11 key */
+    KEY_F12,        /* F12 key */
+
+    KEY_PRINT_SCREEN,   /* Print Screen key */
+    KEY_SCROLL_LOCK,    /* Scroll lock */
+    KEY_CAPS_LOCK,      /* caps lock */
+    KEY_NUM_LOCK,       /* num lock */
+    KEY_INSERT,         /* Insert key */
+    KEY_HOME,           /* Home key */
+    KEY_PAGE_UP,        /* Page Up key */
+    KEY_PAGE_DOWN,      /* Page Down key */
+
+    RIGHT_ARROW,        /* Right arrow */
+    LEFT_ARROW,         /* Left arrow */
+    DOWN_ARROW,         /* Down arrow */
+    UP_ARROW,           /* Up arrow */
+};
+
+/**
+ * USBKeyboard example
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBKeyboard.h"
+ *
+ * USBKeyboard key;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *       key.printf("Hello World\r\n");
+ *       wait(1);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBKeyboard: public USBHID, public Stream
+{
+public:
+
+    /**
+    *   Constructor
+    *
+    *
+    * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK
+    * @param vendor_id Your vendor_id (default: 0x1235)
+    * @param product_id Your product_id (default: 0x0050)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBKeyboard( uint16_t vendor_id = 0x1235, uint16_t product_id = 0x0050, uint16_t product_release = 0x0001 ):
+        USBHID( 0, 0, vendor_id, product_id, product_release, false )
+    {
+        lock_status = 0;
+        connect();
+    };
+
+    /**
+    * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
+    *
+    * @code
+    * //To send CTRL + s (save)
+    *  keyboard.keyCode('s', KEY_CTRL);
+    * @endcode
+    *
+    * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0)
+    * @param key character to send
+    * @returns true if there is no error, false otherwise
+    */
+    bool keyCode( uint8_t key, uint8_t modifier = 0 );
+
+    /**
+    * Send a character
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc( int c );
+
+    /**
+    * Control media keys
+    *
+    * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+    * @returns true if there is no error, false otherwise
+    */
+    bool mediaControl( MEDIA_KEY key );
+
+    /*
+    * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t *reportDesc();
+
+    /*
+    * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
+    *
+    * @returns if handle by subclass, return true
+    */
+    virtual bool EP1_OUT_callback();
+
+    /**
+    * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important:
+    *   - First bit: NUM_LOCK
+    *   - Second bit: CAPS_LOCK
+    *   - Third bit: SCROLL_LOCK
+    *
+    * @returns status of lock keys
+    */
+    uint8_t lockStatus();
+
+protected:
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+private:
+    //dummy otherwise it doesn,t compile (we must define all methods of an abstract class)
+    virtual int _getc()
+    {
+        return -1;
+    };
+
+    uint8_t lock_status;
+
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBMouse.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBMouse.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,290 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMouse.h"
+
+bool USBMouse::update( int16_t x, int16_t y, uint8_t button, int8_t z )
+{
+    switch ( mouse_type )
+    {
+        case REL_MOUSE:
+            while ( x > 127 )
+            {
+                if ( !mouseSend( 127, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x - 127;
+            }
+
+            while ( x < -128 )
+            {
+                if ( !mouseSend( -128, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x + 128;
+            }
+
+            while ( y > 127 )
+            {
+                if ( !mouseSend( 0, 127, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y - 127;
+            }
+
+            while ( y < -128 )
+            {
+                if ( !mouseSend( 0, -128, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y + 128;
+            }
+
+            return mouseSend( x, y, button, z );
+
+        case ABS_MOUSE:
+            HID_REPORT report;
+            report.data[0] = x & 0xff;
+            report.data[1] = ( x >> 8 ) & 0xff;
+            report.data[2] = y & 0xff;
+            report.data[3] = ( y >> 8 ) & 0xff;
+            report.data[4] = -z;
+            report.data[5] = button & 0x07;
+            report.length = 6;
+            return send( &report );
+
+        default:
+            return false;
+    }
+}
+
+bool USBMouse::mouseSend( int8_t x, int8_t y, uint8_t buttons, int8_t z )
+{
+    HID_REPORT report;
+    report.data[0] = buttons & 0x07;
+    report.data[1] = x;
+    report.data[2] = y;
+    report.data[3] = -z; // >0 to scroll down, <0 to scroll up
+    report.length = 4;
+    return send( &report );
+}
+
+bool USBMouse::move( int16_t x, int16_t y )
+{
+    return update( x, y, button, 0 );
+}
+
+bool USBMouse::scroll( int8_t z )
+{
+    return update( 0, 0, button, z );
+}
+
+
+bool USBMouse::doubleClick()
+{
+    if ( !click( MOUSE_LEFT ) )
+    {
+        return false;
+    }
+
+    wait( 0.1 );
+    return click( MOUSE_LEFT );
+}
+
+bool USBMouse::click( uint8_t button )
+{
+    if ( !update( 0, 0, button, 0 ) )
+    {
+        return false;
+    }
+
+    wait( 0.01 );
+    return update( 0, 0, 0, 0 );
+}
+
+bool USBMouse::press( uint8_t button_ )
+{
+    button = button_ & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+bool USBMouse::release( uint8_t button_ )
+{
+    button = ( button & ( ~button_ ) ) & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+
+uint8_t *USBMouse::reportDesc()
+{
+    if ( mouse_type == REL_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+            USAGE_PAGE( 1 ),      0x01,     // Genric Desktop
+            USAGE( 1 ),           0x02,     // Mouse
+            COLLECTION( 1 ),      0x01,     // Application
+            USAGE( 1 ),           0x01,     // Pointer
+            COLLECTION( 1 ),      0x00,     // Physical
+
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x09,     // Buttons
+            USAGE_MINIMUM( 1 ),       0x1,
+            USAGE_MAXIMUM( 1 ),       0x3,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x05,
+            INPUT( 1 ),           0x01,
+
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x08,
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x30,     // X
+            USAGE( 1 ),           0x31,     // Y
+            USAGE( 1 ),           0x38,     // scroll
+            LOGICAL_MINIMUM( 1 ),     0x81,
+            LOGICAL_MAXIMUM( 1 ),     0x7f,
+            INPUT( 1 ),           0x06,     // Relative data
+
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 ),
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+    else if ( mouse_type == ABS_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+
+            USAGE_PAGE( 1 ), 0x01,         // Generic Desktop
+            USAGE( 1 ), 0x02,              // Mouse
+            COLLECTION( 1 ), 0x01,         // Application
+            USAGE( 1 ), 0x01,              // Pointer
+            COLLECTION( 1 ), 0x00,         // Physical
+
+            USAGE_PAGE( 1 ), 0x01,          // Generic Desktop
+            USAGE( 1 ), 0x30,               // X
+            USAGE( 1 ), 0x31,               // Y
+            LOGICAL_MINIMUM( 1 ), 0x00,     // 0
+            LOGICAL_MAXIMUM( 2 ), 0xff, 0x7f, // 32767
+            REPORT_SIZE( 1 ), 0x10,
+            REPORT_COUNT( 1 ), 0x02,
+            INPUT( 1 ), 0x02,               // Data, Variable, Absolute
+
+            USAGE_PAGE( 1 ), 0x01,          // Generic Desktop
+            USAGE( 1 ), 0x38,               // scroll
+            LOGICAL_MINIMUM( 1 ), 0x81,     // -127
+            LOGICAL_MAXIMUM( 1 ), 0x7f,     // 127
+            REPORT_SIZE( 1 ), 0x08,
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x06,               // Data, Variable, Relative
+
+            USAGE_PAGE( 1 ), 0x09,          // Buttons
+            USAGE_MINIMUM( 1 ), 0x01,
+            USAGE_MAXIMUM( 1 ), 0x03,
+            LOGICAL_MINIMUM( 1 ), 0x00,     // 0
+            LOGICAL_MAXIMUM( 1 ), 0x01,     // 1
+            REPORT_COUNT( 1 ), 0x03,
+            REPORT_SIZE( 1 ), 0x01,
+            INPUT( 1 ), 0x02,               // Data, Variable, Absolute
+            REPORT_COUNT( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x05,
+            INPUT( 1 ), 0x01,               // Constant
+
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 )
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+
+    return NULL;
+}
+
+#define DEFAULT_CONFIGURATION (1)
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+                                 + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+                                 + (1 * HID_DESCRIPTOR_LENGTH) \
+                                 + (2 * ENDPOINT_DESCRIPTOR_LENGTH))
+
+uint8_t *USBMouse::configurationDesc()
+{
+    static uint8_t configurationDescriptor[] =
+    {
+        CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+        CONFIGURATION_DESCRIPTOR,       // bDescriptorType
+        LSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (LSB)
+        MSB( TOTAL_DESCRIPTOR_LENGTH ), // wTotalLength (MSB)
+        0x01,                           // bNumInterfaces
+        DEFAULT_CONFIGURATION,          // bConfigurationValue
+        0x00,                           // iConfiguration
+        C_RESERVED | C_SELF_POWERED,    // bmAttributes
+        C_POWER( 0 ),                   // bMaxPowerHello World from Mbed
+
+        INTERFACE_DESCRIPTOR_LENGTH,    // bLength
+        INTERFACE_DESCRIPTOR,           // bDescriptorType
+        0x00,                           // bInterfaceNumber
+        0x00,                           // bAlternateSetting
+        0x02,                           // bNumEndpoints
+        HID_CLASS,                      // bInterfaceClass
+        1,                              // bInterfaceSubClass
+        2,                              // bInterfaceProtocol (mouse)
+        0x00,                           // iInterface
+
+        HID_DESCRIPTOR_LENGTH,          // bLength
+        HID_DESCRIPTOR,                 // bDescriptorType
+        LSB( HID_VERSION_1_11 ),        // bcdHID (LSB)
+        MSB( HID_VERSION_1_11 ),        // bcdHID (MSB)
+        0x00,                           // bCountryCode
+        0x01,                           // bNumDescriptors
+        REPORT_DESCRIPTOR,              // bDescriptorType
+        LSB( reportDescLength() ),      // wDescriptorLength (LSB)
+        MSB( reportDescLength() ),      // wDescriptorLength (MSB)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_IN ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                              // bInterval (milliseconds)
+
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_OUT ),       // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        1,                              // bInterval (milliseconds)
+    };
+    return configurationDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBMouse.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBMouse.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,210 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMOUSE_H
+#define USBMOUSE_H
+
+#include "USBHID.h"
+
+#define REPORT_ID_MOUSE   2
+
+/* Common usage */
+
+enum MOUSE_BUTTON
+{
+    MOUSE_LEFT = 1,
+    MOUSE_RIGHT = 2,
+    MOUSE_MIDDLE = 4,
+};
+
+/* X and Y limits */
+/* These values do not directly map to screen pixels */
+/* Zero may be interpreted as meaning 'no movement' */
+#define X_MIN_ABS    (1)        /*!< Minimum value on x-axis */
+#define Y_MIN_ABS    (1)        /*!< Minimum value on y-axis */
+#define X_MAX_ABS    (0x7fff)   /*!< Maximum value on x-axis */
+#define Y_MAX_ABS    (0x7fff)   /*!< Maximum value on y-axis */
+
+#define X_MIN_REL    (-127)     /*!< The maximum value that we can move to the left on the x-axis */
+#define Y_MIN_REL    (-127)     /*!< The maximum value that we can move up on the y-axis */
+#define X_MAX_REL    (127)      /*!< The maximum value that we can move to the right on the x-axis */
+#define Y_MAX_REL    (127)      /*!< The maximum value that we can move down on the y-axis */
+
+enum MOUSE_TYPE
+{
+    ABS_MOUSE,
+    REL_MOUSE,
+};
+
+/**
+ *
+ * USBMouse example
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ *
+ * USBMouse mouse;
+ *
+ * int main(void)
+ * {
+ *   while (1)
+ *   {
+ *      mouse.move(20, 0);
+ *      wait(0.5);
+ *   }
+ * }
+ *
+ * @endcode
+ *
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "USBMouse.h"
+ * #include <math.h>
+ *
+ * USBMouse mouse(ABS_MOUSE);
+ *
+ * int main(void)
+ * {
+ *   uint16_t x_center = (X_MAX_ABS - X_MIN_ABS)/2;
+ *   uint16_t y_center = (Y_MAX_ABS - Y_MIN_ABS)/2;
+ *   uint16_t x_screen = 0;
+ *   uint16_t y_screen = 0;
+ *
+ *   uint32_t x_origin = x_center;
+ *   uint32_t y_origin = y_center;
+ *   uint32_t radius = 5000;
+ *   uint32_t angle = 0;
+ *
+ *   while (1)
+ *   {
+ *       x_screen = x_origin + cos((double)angle*3.14/180.0)*radius;
+ *       y_screen = y_origin + sin((double)angle*3.14/180.0)*radius;
+ *
+ *       mouse.move(x_screen, y_screen);
+ *       angle += 3;
+ *       wait(0.01);
+ *   }
+ * }
+ *
+ * @endcode
+ */
+class USBMouse: public USBHID
+{
+public:
+
+    /**
+    *   Constructor
+    *
+    * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+    * @param vendor_id Your vendor_id (default: 0x1234)
+    * @param product_id Your product_id (default: 0x0001)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBMouse( MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0001, uint16_t product_release = 0x0001 ):
+        USBHID( 0, 0, vendor_id, product_id, product_release, false )
+    {
+        button = 0;
+        this->mouse_type = mouse_type;
+        connect();
+    };
+
+    /**
+    * Write a state of the mouse
+    *
+    * @param x x-axis position
+    * @param y y-axis position
+    * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+    * @param z wheel state (>0 to scroll down, <0 to scroll up)
+    * @returns true if there is no error, false otherwise
+    */
+    bool update( int16_t x, int16_t y, uint8_t buttons, int8_t z );
+
+
+    /**
+    * Move the cursor to (x, y)
+    *
+    * @param x-axis position
+    * @param y-axis position
+    * @returns true if there is no error, false otherwise
+    */
+    bool move( int16_t x, int16_t y );
+
+    /**
+    * Press one or several buttons
+    *
+    * @param button button state (ex: press(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool press( uint8_t button );
+
+    /**
+    * Release one or several buttons
+    *
+    * @param button button state (ex: release(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool release( uint8_t button );
+
+    /**
+    * Double click (MOUSE_LEFT)
+    *
+    * @returns true if there is no error, false otherwise
+    */
+    bool doubleClick();
+
+    /**
+    * Click
+    *
+    * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool click( uint8_t button );
+
+    /**
+    * Scrolling
+    *
+    * @param z value of the wheel (>0 to go down, <0 to go up)
+    * @returns true if there is no error, false otherwise
+    */
+    bool scroll( int8_t z );
+
+    /*
+    * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t *reportDesc();
+
+protected:
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+private:
+    MOUSE_TYPE mouse_type;
+    uint8_t button;
+    bool mouseSend( int8_t x, int8_t y, uint8_t buttons, int8_t z );
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBMouseKeyboard.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBMouseKeyboard.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,751 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMouseKeyboard.h"
+
+typedef struct
+{
+    unsigned char usage;
+    unsigned char modifier;
+} KEYMAP;
+
+#ifdef US_KEYBOARD
+/* US keyboard (as HID standard) */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x34, KEY_SHIFT},      /* " */
+    {0x20, KEY_SHIFT},      /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x1f, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x31, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x31, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x35, KEY_SHIFT},      /* ~ */
+    {0, 0},             /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+
+#else
+/* UK keyboard */
+#define KEYMAP_SIZE (152)
+const KEYMAP keymap[KEYMAP_SIZE] =
+{
+    {0, 0},             /* NUL */
+    {0, 0},             /* SOH */
+    {0, 0},             /* STX */
+    {0, 0},             /* ETX */
+    {0, 0},             /* EOT */
+    {0, 0},             /* ENQ */
+    {0, 0},             /* ACK */
+    {0, 0},             /* BEL */
+    {0x2a, 0},          /* BS  */  /* Keyboard Delete (Backspace) */
+    {0x2b, 0},          /* TAB */  /* Keyboard Tab */
+    {0x28, 0},          /* LF  */  /* Keyboard Return (Enter) */
+    {0, 0},             /* VT  */
+    {0, 0},             /* FF  */
+    {0, 0},             /* CR  */
+    {0, 0},             /* SO  */
+    {0, 0},             /* SI  */
+    {0, 0},             /* DEL */
+    {0, 0},             /* DC1 */
+    {0, 0},             /* DC2 */
+    {0, 0},             /* DC3 */
+    {0, 0},             /* DC4 */
+    {0, 0},             /* NAK */
+    {0, 0},             /* SYN */
+    {0, 0},             /* ETB */
+    {0, 0},             /* CAN */
+    {0, 0},             /* EM  */
+    {0, 0},             /* SUB */
+    {0, 0},             /* ESC */
+    {0, 0},             /* FS  */
+    {0, 0},             /* GS  */
+    {0, 0},             /* RS  */
+    {0, 0},             /* US  */
+    {0x2c, 0},          /*   */
+    {0x1e, KEY_SHIFT},      /* ! */
+    {0x1f, KEY_SHIFT},      /* " */
+    {0x32, 0},          /* # */
+    {0x21, KEY_SHIFT},      /* $ */
+    {0x22, KEY_SHIFT},      /* % */
+    {0x24, KEY_SHIFT},      /* & */
+    {0x34, 0},          /* ' */
+    {0x26, KEY_SHIFT},      /* ( */
+    {0x27, KEY_SHIFT},      /* ) */
+    {0x25, KEY_SHIFT},      /* * */
+    {0x2e, KEY_SHIFT},      /* + */
+    {0x36, 0},          /* , */
+    {0x2d, 0},          /* - */
+    {0x37, 0},          /* . */
+    {0x38, 0},          /* / */
+    {0x27, 0},          /* 0 */
+    {0x1e, 0},          /* 1 */
+    {0x1f, 0},          /* 2 */
+    {0x20, 0},          /* 3 */
+    {0x21, 0},          /* 4 */
+    {0x22, 0},          /* 5 */
+    {0x23, 0},          /* 6 */
+    {0x24, 0},          /* 7 */
+    {0x25, 0},          /* 8 */
+    {0x26, 0},          /* 9 */
+    {0x33, KEY_SHIFT},      /* : */
+    {0x33, 0},          /* ; */
+    {0x36, KEY_SHIFT},      /* < */
+    {0x2e, 0},          /* = */
+    {0x37, KEY_SHIFT},      /* > */
+    {0x38, KEY_SHIFT},      /* ? */
+    {0x34, KEY_SHIFT},      /* @ */
+    {0x04, KEY_SHIFT},      /* A */
+    {0x05, KEY_SHIFT},      /* B */
+    {0x06, KEY_SHIFT},      /* C */
+    {0x07, KEY_SHIFT},      /* D */
+    {0x08, KEY_SHIFT},      /* E */
+    {0x09, KEY_SHIFT},      /* F */
+    {0x0a, KEY_SHIFT},      /* G */
+    {0x0b, KEY_SHIFT},      /* H */
+    {0x0c, KEY_SHIFT},      /* I */
+    {0x0d, KEY_SHIFT},      /* J */
+    {0x0e, KEY_SHIFT},      /* K */
+    {0x0f, KEY_SHIFT},      /* L */
+    {0x10, KEY_SHIFT},      /* M */
+    {0x11, KEY_SHIFT},      /* N */
+    {0x12, KEY_SHIFT},      /* O */
+    {0x13, KEY_SHIFT},      /* P */
+    {0x14, KEY_SHIFT},      /* Q */
+    {0x15, KEY_SHIFT},      /* R */
+    {0x16, KEY_SHIFT},      /* S */
+    {0x17, KEY_SHIFT},      /* T */
+    {0x18, KEY_SHIFT},      /* U */
+    {0x19, KEY_SHIFT},      /* V */
+    {0x1a, KEY_SHIFT},      /* W */
+    {0x1b, KEY_SHIFT},      /* X */
+    {0x1c, KEY_SHIFT},      /* Y */
+    {0x1d, KEY_SHIFT},      /* Z */
+    {0x2f, 0},          /* [ */
+    {0x64, 0},          /* \ */
+    {0x30, 0},          /* ] */
+    {0x23, KEY_SHIFT},      /* ^ */
+    {0x2d, KEY_SHIFT},      /* _ */
+    {0x35, 0},          /* ` */
+    {0x04, 0},          /* a */
+    {0x05, 0},          /* b */
+    {0x06, 0},          /* c */
+    {0x07, 0},          /* d */
+    {0x08, 0},          /* e */
+    {0x09, 0},          /* f */
+    {0x0a, 0},          /* g */
+    {0x0b, 0},          /* h */
+    {0x0c, 0},          /* i */
+    {0x0d, 0},          /* j */
+    {0x0e, 0},          /* k */
+    {0x0f, 0},          /* l */
+    {0x10, 0},          /* m */
+    {0x11, 0},          /* n */
+    {0x12, 0},          /* o */
+    {0x13, 0},          /* p */
+    {0x14, 0},          /* q */
+    {0x15, 0},          /* r */
+    {0x16, 0},          /* s */
+    {0x17, 0},          /* t */
+    {0x18, 0},          /* u */
+    {0x19, 0},          /* v */
+    {0x1a, 0},          /* w */
+    {0x1b, 0},          /* x */
+    {0x1c, 0},          /* y */
+    {0x1d, 0},          /* z */
+    {0x2f, KEY_SHIFT},      /* { */
+    {0x64, KEY_SHIFT},      /* | */
+    {0x30, KEY_SHIFT},      /* } */
+    {0x32, KEY_SHIFT},      /* ~ */
+    {0, 0},            /* DEL */
+
+    {0x3a, 0},          /* F1 */
+    {0x3b, 0},          /* F2 */
+    {0x3c, 0},          /* F3 */
+    {0x3d, 0},          /* F4 */
+    {0x3e, 0},          /* F5 */
+    {0x3f, 0},          /* F6 */
+    {0x40, 0},          /* F7 */
+    {0x41, 0},          /* F8 */
+    {0x42, 0},          /* F9 */
+    {0x43, 0},          /* F10 */
+    {0x44, 0},          /* F11 */
+    {0x45, 0},          /* F12 */
+
+    {0x46, 0},          /* PRINT_SCREEN */
+    {0x47, 0},          /* SCROLL_LOCK */
+    {0x39, 0},          /* CAPS_LOCK */
+    {0x53, 0},          /* NUM_LOCK */
+    {0x49, 0},          /* INSERT */
+    {0x4a, 0},          /* HOME */
+    {0x4b, 0},          /* PAGE_UP */
+    {0x4e, 0},          /* PAGE_DOWN */
+
+    {0x4f, 0},          /* RIGHT_ARROW */
+    {0x50, 0},          /* LEFT_ARROW */
+    {0x51, 0},          /* DOWN_ARROW */
+    {0x52, 0},          /* UP_ARROW */
+};
+#endif
+
+
+uint8_t *USBMouseKeyboard::reportDesc()
+{
+    if ( mouse_type == REL_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+            // Keyboard
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x06,
+            COLLECTION( 1 ),      0x01,
+            REPORT_ID( 1 ),       REPORT_ID_KEYBOARD,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0xE0,
+            USAGE_MAXIMUM( 1 ),       0xE7,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            REPORT_SIZE( 1 ),     0x01,
+            REPORT_COUNT( 1 ),    0x08,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x08,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x05,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x08,
+            USAGE_MINIMUM( 1 ),       0x01,
+            USAGE_MAXIMUM( 1 ),       0x05,
+            OUTPUT( 1 ),          0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x03,
+            OUTPUT( 1 ),          0x01,
+            REPORT_COUNT( 1 ),    0x06,
+            REPORT_SIZE( 1 ),     0x08,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 2 ),     0xff, 0x00,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0x00,
+            USAGE_MAXIMUM( 2 ),       0xff, 0x00,
+            INPUT( 1 ),           0x00,
+            END_COLLECTION( 0 ),
+
+            // Mouse
+            USAGE_PAGE( 1 ),      0x01,         // Generic Desktop
+            USAGE( 1 ),           0x02,         // Mouse
+            COLLECTION( 1 ),      0x01,         // Application
+            USAGE( 1 ),           0x01,         // Pointer
+            COLLECTION( 1 ),      0x00,         // Physical
+            REPORT_ID( 1 ),       REPORT_ID_MOUSE,
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x09,         // Buttons
+            USAGE_MINIMUM( 1 ),       0x1,
+            USAGE_MAXIMUM( 1 ),       0x3,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x05,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x03,
+            REPORT_SIZE( 1 ),     0x08,
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x30,         // X
+            USAGE( 1 ),           0x31,         // Y
+            USAGE( 1 ),           0x38,         // scroll
+            LOGICAL_MINIMUM( 1 ),     0x81,
+            LOGICAL_MAXIMUM( 1 ),     0x7f,
+            INPUT( 1 ),           0x06,
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 ),
+
+
+            // Media Control
+            USAGE_PAGE( 1 ), 0x0C,
+            USAGE( 1 ), 0x01,
+            COLLECTION( 1 ), 0x01,
+            REPORT_ID( 1 ), REPORT_ID_VOLUME,
+            USAGE_PAGE( 1 ), 0x0C,
+            LOGICAL_MINIMUM( 1 ), 0x00,
+            LOGICAL_MAXIMUM( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x01,
+            REPORT_COUNT( 1 ), 0x07,
+            USAGE( 1 ), 0xB5,           // Next Track
+            USAGE( 1 ), 0xB6,           // Previous Track
+            USAGE( 1 ), 0xB7,           // Stop
+            USAGE( 1 ), 0xCD,           // Play / Pause
+            USAGE( 1 ), 0xE2,           // Mute
+            USAGE( 1 ), 0xE9,           // Volume Up
+            USAGE( 1 ), 0xEA,           // Volume Down
+            INPUT( 1 ), 0x02,           // Input (Data, Variable, Absolute)
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x01,
+            END_COLLECTION( 0 ),
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+    else if ( mouse_type == ABS_MOUSE )
+    {
+        static uint8_t reportDescriptor[] =
+        {
+
+            // Keyboard
+            USAGE_PAGE( 1 ),      0x01,
+            USAGE( 1 ),           0x06,
+            COLLECTION( 1 ),      0x01,
+            REPORT_ID( 1 ),       REPORT_ID_KEYBOARD,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0xE0,
+            USAGE_MAXIMUM( 1 ),       0xE7,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 1 ),     0x01,
+            REPORT_SIZE( 1 ),     0x01,
+            REPORT_COUNT( 1 ),    0x08,
+            INPUT( 1 ),           0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x08,
+            INPUT( 1 ),           0x01,
+            REPORT_COUNT( 1 ),    0x05,
+            REPORT_SIZE( 1 ),     0x01,
+            USAGE_PAGE( 1 ),      0x08,
+            USAGE_MINIMUM( 1 ),       0x01,
+            USAGE_MAXIMUM( 1 ),       0x05,
+            OUTPUT( 1 ),          0x02,
+            REPORT_COUNT( 1 ),    0x01,
+            REPORT_SIZE( 1 ),     0x03,
+            OUTPUT( 1 ),          0x01,
+            REPORT_COUNT( 1 ),    0x06,
+            REPORT_SIZE( 1 ),     0x08,
+            LOGICAL_MINIMUM( 1 ),     0x00,
+            LOGICAL_MAXIMUM( 2 ),     0xff, 0x00,
+            USAGE_PAGE( 1 ),      0x07,
+            USAGE_MINIMUM( 1 ),       0x00,
+            USAGE_MAXIMUM( 2 ),       0xff, 0x00,
+            INPUT( 1 ),           0x00,
+            END_COLLECTION( 0 ),
+
+            // Mouse
+            USAGE_PAGE( 1 ), 0x01,             // Generic Desktop
+            USAGE( 1 ), 0x02,                  // Mouse
+            COLLECTION( 1 ), 0x01,             // Application
+            USAGE( 1 ), 0x01,                  // Pointer
+            COLLECTION( 1 ), 0x00,             // Physical
+            REPORT_ID( 1 ),       REPORT_ID_MOUSE,
+
+            USAGE_PAGE( 1 ), 0x01,              // Generic Desktop
+            USAGE( 1 ), 0x30,                   // X
+            USAGE( 1 ), 0x31,                   // Y
+            LOGICAL_MINIMUM( 1 ), 0x00,         // 0
+            LOGICAL_MAXIMUM( 2 ), 0xff, 0x7f,   // 32767
+            REPORT_SIZE( 1 ), 0x10,
+            REPORT_COUNT( 1 ), 0x02,
+            INPUT( 1 ), 0x02,                   // Data, Variable, Absolute
+
+            USAGE_PAGE( 1 ), 0x01,              // Generic Desktop
+            USAGE( 1 ), 0x38,                   // scroll
+            LOGICAL_MINIMUM( 1 ), 0x81,         // -127
+            LOGICAL_MAXIMUM( 1 ), 0x7f,         // 127
+            REPORT_SIZE( 1 ), 0x08,
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x06,                   // Data, Variable, Relative
+
+            USAGE_PAGE( 1 ), 0x09,              // Buttons
+            USAGE_MINIMUM( 1 ), 0x01,
+            USAGE_MAXIMUM( 1 ), 0x03,
+            LOGICAL_MINIMUM( 1 ), 0x00,         // 0
+            LOGICAL_MAXIMUM( 1 ), 0x01,         // 1
+            REPORT_COUNT( 1 ), 0x03,
+            REPORT_SIZE( 1 ), 0x01,
+            INPUT( 1 ), 0x02,                   // Data, Variable, Absolute
+            REPORT_COUNT( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x05,
+            INPUT( 1 ), 0x01,                   // Constant
+
+            END_COLLECTION( 0 ),
+            END_COLLECTION( 0 ),
+
+            // Media Control
+            USAGE_PAGE( 1 ), 0x0C,
+            USAGE( 1 ), 0x01,
+            COLLECTION( 1 ), 0x01,
+            REPORT_ID( 1 ), REPORT_ID_VOLUME,
+            USAGE_PAGE( 1 ), 0x0C,
+            LOGICAL_MINIMUM( 1 ), 0x00,
+            LOGICAL_MAXIMUM( 1 ), 0x01,
+            REPORT_SIZE( 1 ), 0x01,
+            REPORT_COUNT( 1 ), 0x07,
+            USAGE( 1 ), 0xB5,           // Next Track
+            USAGE( 1 ), 0xB6,           // Previous Track
+            USAGE( 1 ), 0xB7,           // Stop
+            USAGE( 1 ), 0xCD,           // Play / Pause
+            USAGE( 1 ), 0xE2,           // Mute
+            USAGE( 1 ), 0xE9,           // Volume Up
+            USAGE( 1 ), 0xEA,           // Volume Down
+            INPUT( 1 ), 0x02,           // Input (Data, Variable, Absolute)
+            REPORT_COUNT( 1 ), 0x01,
+            INPUT( 1 ), 0x01,
+            END_COLLECTION( 0 ),
+        };
+        reportLength = sizeof( reportDescriptor );
+        return reportDescriptor;
+    }
+
+    return NULL;
+}
+
+bool USBMouseKeyboard::EP1_OUT_callback()
+{
+    uint32_t bytesRead = 0;
+    uint8_t led[65];
+    USBDevice::readEP( EPINT_OUT, led, &bytesRead, MAX_HID_REPORT_SIZE );
+    // we take led[1] because led[0] is the report ID
+    lock_status = led[1] & 0x07;
+
+    // We activate the endpoint to be able to recceive data
+    if ( !readStart( EPINT_OUT, MAX_HID_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+uint8_t USBMouseKeyboard::lockStatus()
+{
+    return lock_status;
+}
+
+bool USBMouseKeyboard::update( int16_t x, int16_t y, uint8_t button, int8_t z )
+{
+    switch ( mouse_type )
+    {
+        case REL_MOUSE:
+            while ( x > 127 )
+            {
+                if ( !mouseSend( 127, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x - 127;
+            }
+
+            while ( x < -128 )
+            {
+                if ( !mouseSend( -128, 0, button, z ) )
+                {
+                    return false;
+                }
+
+                x = x + 128;
+            }
+
+            while ( y > 127 )
+            {
+                if ( !mouseSend( 0, 127, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y - 127;
+            }
+
+            while ( y < -128 )
+            {
+                if ( !mouseSend( 0, -128, button, z ) )
+                {
+                    return false;
+                }
+
+                y = y + 128;
+            }
+
+            return mouseSend( x, y, button, z );
+
+        case ABS_MOUSE:
+            HID_REPORT report;
+            report.data[0] = REPORT_ID_MOUSE;
+            report.data[1] = x & 0xff;
+            report.data[2] = ( x >> 8 ) & 0xff;
+            report.data[3] = y & 0xff;
+            report.data[4] = ( y >> 8 ) & 0xff;
+            report.data[5] = -z;
+            report.data[6] = button & 0x07;
+            report.length = 7;
+            return send( &report );
+
+        default:
+            return false;
+    }
+}
+
+bool USBMouseKeyboard::mouseSend( int8_t x, int8_t y, uint8_t buttons, int8_t z )
+{
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_MOUSE;
+    report.data[1] = buttons & 0x07;
+    report.data[2] = x;
+    report.data[3] = y;
+    report.data[4] = -z; // >0 to scroll down, <0 to scroll up
+    report.length = 5;
+    return send( &report );
+}
+
+bool USBMouseKeyboard::move( int16_t x, int16_t y )
+{
+    return update( x, y, button, 0 );
+}
+
+bool USBMouseKeyboard::scroll( int8_t z )
+{
+    return update( 0, 0, button, z );
+}
+
+bool USBMouseKeyboard::doubleClick()
+{
+    if ( !click( MOUSE_LEFT ) )
+    {
+        return false;
+    }
+
+    wait( 0.1 );
+    return click( MOUSE_LEFT );
+}
+
+bool USBMouseKeyboard::click( uint8_t button )
+{
+    if ( !update( 0, 0, button, 0 ) )
+    {
+        return false;
+    }
+
+    wait( 0.01 );
+    return update( 0, 0, 0, 0 );
+}
+
+bool USBMouseKeyboard::press( uint8_t button_ )
+{
+    button = button_ & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+bool USBMouseKeyboard::release( uint8_t button_ )
+{
+    button = ( button & ( ~button_ ) ) & 0x07;
+    return update( 0, 0, button, 0 );
+}
+
+int USBMouseKeyboard::_putc( int c )
+{
+    return keyCode( c, keymap[c].modifier );
+}
+
+bool USBMouseKeyboard::keyCode( uint8_t key, uint8_t modifier )
+{
+    // Send a simulated keyboard keypress. Returns true if successful.
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_KEYBOARD;
+    report.data[1] = modifier;
+    report.data[2] = 0;
+    report.data[3] = keymap[key].usage;
+    report.data[4] = 0;
+    report.data[5] = 0;
+    report.data[6] = 0;
+    report.data[7] = 0;
+    report.data[8] = 0;
+    report.length = 9;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    report.data[1] = 0;
+    report.data[3] = 0;
+
+    if ( !send( &report ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool USBMouseKeyboard::mediaControl( MEDIA_KEY key )
+{
+    HID_REPORT report;
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = ( 1 << key ) & 0x7f;
+    report.length = 2;
+    send( &report );
+    report.data[0] = REPORT_ID_VOLUME;
+    report.data[1] = 0;
+    report.length = 2;
+    return send( &report );
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBHID/USBMouseKeyboard.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHID/USBMouseKeyboard.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,224 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMOUSEKEYBOARD_H
+#define USBMOUSEKEYBOARD_H
+
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_MOUSE 2
+#define REPORT_ID_VOLUME 3
+
+#include "USBMouse.h"
+#include "USBKeyboard.h"
+#include "Stream.h"
+#include "USBHID.h"
+
+/**
+ * USBMouseKeyboard example
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse;
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(20, 0);
+ *       key_mouse.printf("Hello From MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ *
+ *
+ * @code
+ *
+ * #include "mbed.h"
+ * #include "USBMouseKeyboard.h"
+ *
+ * USBMouseKeyboard key_mouse(ABS_MOUSE);
+ *
+ * int main(void)
+ * {
+ *   while(1)
+ *   {
+ *       key_mouse.move(X_MAX_ABS/2, Y_MAX_ABS/2);
+ *       key_mouse.printf("Hello from MBED\r\n");
+ *       wait(1);
+ *   }
+ * }
+ * @endcode
+ */
+class USBMouseKeyboard: public USBHID, public Stream
+{
+public:
+
+    /**
+    *   Constructor
+    *
+    * @param mouse_type Mouse type: ABS_MOUSE (absolute mouse) or REL_MOUSE (relative mouse) (default: REL_MOUSE)
+    * @param leds Leds bus: first: NUM_LOCK, second: CAPS_LOCK, third: SCROLL_LOCK
+    * @param vendor_id Your vendor_id (default: 0x1234)
+    * @param product_id Your product_id (default: 0x0001)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBMouseKeyboard( MOUSE_TYPE mouse_type = REL_MOUSE, uint16_t vendor_id = 0x0021, uint16_t product_id = 0x0011, uint16_t product_release = 0x0001 ):
+        USBHID( 0, 0, vendor_id, product_id, product_release, false )
+    {
+        lock_status = 0;
+        button = 0;
+        this->mouse_type = mouse_type;
+        connect();
+    };
+
+    /**
+    * Write a state of the mouse
+    *
+    * @param x x-axis position
+    * @param y y-axis position
+    * @param buttons buttons state (first bit represents MOUSE_LEFT, second bit MOUSE_RIGHT and third bit MOUSE_MIDDLE)
+    * @param z wheel state (>0 to scroll down, <0 to scroll up)
+    * @returns true if there is no error, false otherwise
+    */
+    bool update( int16_t x, int16_t y, uint8_t buttons, int8_t z );
+
+
+    /**
+    * Move the cursor to (x, y)
+    *
+    * @param x x-axis position
+    * @param y y-axis position
+    * @returns true if there is no error, false otherwise
+    */
+    bool move( int16_t x, int16_t y );
+
+    /**
+    * Press one or several buttons
+    *
+    * @param button button state (ex: press(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool press( uint8_t button );
+
+    /**
+    * Release one or several buttons
+    *
+    * @param button button state (ex: release(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool release( uint8_t button );
+
+    /**
+    * Double click (MOUSE_LEFT)
+    *
+    * @returns true if there is no error, false otherwise
+    */
+    bool doubleClick();
+
+    /**
+    * Click
+    *
+    * @param button state of the buttons ( ex: clic(MOUSE_LEFT))
+    * @returns true if there is no error, false otherwise
+    */
+    bool click( uint8_t button );
+
+    /**
+    * Scrolling
+    *
+    * @param z value of the wheel (>0 to go down, <0 to go up)
+    * @returns true if there is no error, false otherwise
+    */
+    bool scroll( int8_t z );
+
+    /**
+    * To send a character defined by a modifier(CTRL, SHIFT, ALT) and the key
+    *
+    * @code
+    * //To send CTRL + s (save)
+    *  keyboard.keyCode('s', KEY_CTRL);
+    * @endcode
+    *
+    * @param modifier bit 0: KEY_CTRL, bit 1: KEY_SHIFT, bit 2: KEY_ALT (default: 0)
+    * @param key character to send
+    * @returns true if there is no error, false otherwise
+    */
+    bool keyCode( uint8_t key, uint8_t modifier = 0 );
+
+    /**
+    * Send a character
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc( int c );
+
+    /**
+    * Control media keys
+    *
+    * @param key media key pressed (KEY_NEXT_TRACK, KEY_PREVIOUS_TRACK, KEY_STOP, KEY_PLAY_PAUSE, KEY_MUTE, KEY_VOLUME_UP, KEY_VOLUME_DOWN)
+    * @returns true if there is no error, false otherwise
+    */
+    bool mediaControl( MEDIA_KEY key );
+
+    /**
+    * Read status of lock keys. Useful to switch-on/off leds according to key pressed. Only the first three bits of the result is important:
+    *   - First bit: NUM_LOCK
+    *   - Second bit: CAPS_LOCK
+    *   - Third bit: SCROLL_LOCK
+    *
+    * @returns status of lock keys
+    */
+    uint8_t lockStatus();
+
+    /*
+    * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the report descriptor
+    */
+    virtual uint8_t *reportDesc();
+
+    /*
+    * Called when a data is received on the OUT endpoint. Useful to switch on LED of LOCK keys
+    *
+    * @returns if handle by subclass, return true
+    */
+    virtual bool EP1_OUT_callback();
+
+
+private:
+    bool mouseWrite( int8_t x, int8_t y, uint8_t buttons, int8_t z );
+    MOUSE_TYPE mouse_type;
+    uint8_t button;
+    bool mouseSend( int8_t x, int8_t y, uint8_t buttons, int8_t z );
+
+    uint8_t lock_status;
+
+    //dummy otherwise it doesn't compile (we must define all methods of an abstract class)
+    virtual int _getc()
+    {
+        return -1;
+    }
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBMIDI/MIDIMessage.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMIDI/MIDIMessage.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,294 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MIDIMESSAGE_H
+#define MIDIMESSAGE_H
+
+#include "mbed.h"
+
+// MIDI Message Format
+//
+// [ msg(4) | channel(4) ] [ 0 | n(7) ] [ 0 | m(7) ]
+//
+// MIDI Data Messages (Channel Specific)
+//
+// Message               msg n          m
+// ---------------------------------------------
+// Note Off              0x8 Key        Velocity
+// Note On               0x9 Key        Velocity
+// Polyphonic Aftertouch 0xA Key        Pressure
+// Control Change        0xB Controller Value
+// Program Change        0xC Program    -
+// Channel Aftertouch    0xD Pressure   -
+// Pitch Wheel           0xE LSB        MSB
+
+#define CABLE_NUM (0<<4)
+
+/** A MIDI message container */
+class MIDIMessage
+{
+public:
+    MIDIMessage() {}
+
+    MIDIMessage( uint8_t *buf )
+    {
+        *( ( uint32_t * )data ) = *( ( uint32_t * )buf );
+    }
+
+    // create messages
+
+    /** Create a NoteOff message
+     * @param key Key ID
+     * @param velocity Key velocity (0-127, default = 127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage NoteOff( int key, int velocity = 127, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x08;
+        msg.data[1] = 0x80 | ( channel & 0x0F );
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = velocity & 0x7F;
+        return msg;
+    }
+
+    /** Create a NoteOn message
+     * @param key Key ID
+     * @param velocity Key velocity (0-127, default = 127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage NoteOn( int key, int velocity = 127, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x09;
+        msg.data[1] = 0x90 | ( channel & 0x0F );
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = velocity & 0x7F;
+        return msg;
+    }
+
+    /** Create a PolyPhonic Aftertouch message
+     * @param key Key ID
+     * @param pressure Aftertouch pressure (0-127)
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage PolyphonicAftertouch( int key, int pressure, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0A;
+        msg.data[1] = 0xA0 | ( channel & 0x0F );
+        msg.data[2] = key & 0x7F;
+        msg.data[3] = pressure & 0x7F;
+        return msg;
+    }
+
+    /** Create a Control Change message
+     * @param control Controller ID
+     * @param value Controller value (0-127)
+     * @param channel Controller channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ControlChange( int control, int value, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0B;
+        msg.data[1] = 0xB0 | ( channel & 0x0F );
+        msg.data[2] = control & 0x7F;
+        msg.data[3] = value & 0x7F;
+        return msg;
+    }
+
+    /** Create a Program Change message
+     * @param program Program ID
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ProgramChange( int program, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0C;
+        msg.data[1] = 0xC0 | ( channel & 0x0F );
+        msg.data[2] = program & 0x7F;
+        msg.data[3] = 0x00;
+        return msg;
+    }
+
+    /** Create a Channel Aftertouch message
+     * @param pressure Pressure
+     * @param channel Key channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage ChannelAftertouch( int pressure, int channel = 0 )
+    {
+        MIDIMessage msg;
+        msg.data[0] = CABLE_NUM | 0x0D;
+        msg.data[1] = 0xD0 | ( channel & 0x0F );
+        msg.data[2] = pressure & 0x7F;
+        msg.data[3] = 0x00;
+        return msg;
+    }
+
+    /** Create a Pitch Wheel message
+     * @param pitch Pitch (-8192 - 8191, default = 0)
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage PitchWheel( int pitch = 0, int channel = 0 )
+    {
+        MIDIMessage msg;
+        int p = pitch + 8192;    // 0 - 16383, 8192 is center
+        msg.data[0] = CABLE_NUM | 0x0E;
+        msg.data[1] = 0xE0 | ( channel & 0x0F );
+        msg.data[2] = p & 0x7F;
+        msg.data[3] = ( p >> 7 ) & 0x7F;
+        return msg;
+    }
+
+    /** Create an All Notes Off message
+     * @param channel Channel (0-15, default 0)
+     * @returns A MIDIMessage
+     */
+    static MIDIMessage AllNotesOff( int channel = 0 )
+    {
+        return ControlChange( 123, 0, channel );
+    }
+
+    // decode messages
+
+    /** MIDI Message Types */
+    enum MIDIMessageType
+    {
+        ErrorType,
+        NoteOffType,
+        NoteOnType,
+        PolyphonicAftertouchType,
+        ControlChangeType,
+        ProgramChangeType,
+        ChannelAftertouchType,
+        PitchWheelType,
+        AllNotesOffType
+    };
+
+    /** Read the message type
+     * @returns MIDIMessageType
+     */
+    MIDIMessageType type()
+    {
+        switch( ( data[1] >> 4 ) & 0xF )
+        {
+            case 0x8:
+                return NoteOffType;
+
+            case 0x9:
+                return NoteOnType;
+
+            case 0xA:
+                return PolyphonicAftertouchType;
+
+            case 0xB:
+                if( controller() < 120 ) // standard controllers
+                {
+                    return ControlChangeType;
+                }
+                else if( controller() == 123 )
+                {
+                    return AllNotesOffType;
+                }
+                else
+                {
+                    return ErrorType; // unsupported atm
+                }
+
+            case 0xC:
+                return ProgramChangeType;
+
+            case 0xD:
+                return ChannelAftertouchType;
+
+            case 0xE:
+                return PitchWheelType;
+
+            default:
+                return ErrorType;
+        }
+    }
+
+    /** Read the channel number */
+    int channel()
+    {
+        return ( data[1] & 0x0F );
+    }
+
+    /** Read the key ID */
+    int key()
+    {
+        return ( data[2] & 0x7F );
+    }
+
+    /** Read the velocity */
+    int velocity()
+    {
+        return ( data[3] & 0x7F );
+    }
+
+    /** Read the controller value */
+    int value()
+    {
+        return ( data[3] & 0x7F );
+    }
+
+    /** Read the aftertouch pressure */
+    int pressure()
+    {
+        if( type() == PolyphonicAftertouchType )
+        {
+            return ( data[3] & 0x7F );
+        }
+        else
+        {
+            return ( data[2] & 0x7F );
+        }
+    }
+
+    /** Read the controller number */
+    int controller()
+    {
+        return ( data[2] & 0x7F );
+    }
+
+    /** Read the program number */
+    int program()
+    {
+        return ( data[2] & 0x7F );
+    }
+
+    /** Read the pitch value */
+    int pitch()
+    {
+        int p = ( ( data[3] & 0x7F ) << 7 ) | ( data[2] & 0x7F );
+        return p - 8192; // 0 - 16383, 8192 is center
+    }
+
+    uint8_t data[4];
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBMIDI/USBMIDI.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMIDI/USBMIDI.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,135 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMIDI.h"
+
+
+USBMIDI::USBMIDI( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
+{
+    midi_evt = NULL;
+    USBDevice::connect();
+}
+
+void USBMIDI::write( MIDIMessage m )
+{
+    USBDevice::write( EPBULK_IN, m.data, 4, MAX_PACKET_SIZE_EPBULK );
+}
+
+
+void USBMIDI::attach( void ( *fptr )( MIDIMessage ) )
+{
+    midi_evt = fptr;
+}
+
+
+bool USBMIDI::EP2_OUT_callback()
+{
+    uint8_t buf[64];
+    uint32_t len;
+    readEP( EPBULK_OUT, buf, &len, 64 );
+
+    if ( midi_evt != NULL )
+    {
+        for ( int i = 0; i < len; i += 4 )
+        {
+            midi_evt( MIDIMessage( buf + i ) );
+        }
+    }
+
+    // We reactivate the endpoint to receive next characters
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBMIDI::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK );
+    addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    // We activate the endpoint to be able to receive data
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+
+uint8_t *USBMIDI::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x0c,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 //bString iInterface - Audio
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBMIDI::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,                                                       //bLength
+        STRING_DESCRIPTOR,                                          //bDescriptorType 0x03
+        'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
+
+
+uint8_t *USBMIDI::configurationDesc()
+{
+    static uint8_t configDescriptor[] =
+    {
+        // configuration descriptor
+        0x09, 0x02, 0x65, 0x00, 0x02, 0x01, 0x00, 0xc0, 0x50,
+
+        // The Audio Interface Collection
+        0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, // Standard AC Interface Descriptor
+        0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x01, // Class-specific AC Interface Descriptor
+        0x09, 0x04, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, // MIDIStreaming Interface Descriptors
+        0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00,             // Class-Specific MS Interface Header Descriptor
+
+        // MIDI IN JACKS
+        0x06, 0x24, 0x02, 0x01, 0x01, 0x00,
+        0x06, 0x24, 0x02, 0x02, 0x02, 0x00,
+
+        // MIDI OUT JACKS
+        0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00,
+        0x09, 0x24, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x00,
+
+        // OUT endpoint descriptor
+        0x09, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+        0x05, 0x25, 0x01, 0x01, 0x01,
+
+        // IN endpoint descriptor
+        0x09, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
+        0x05, 0x25, 0x01, 0x01, 0x03,
+    };
+    return configDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBMIDI/USBMIDI.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMIDI/USBMIDI.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,111 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBMIDI_H
+#define USBMIDI_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBDevice/USBDevice/USBDevice.h"
+#include "MIDIMessage.h"
+
+#define DEFAULT_CONFIGURATION (1)
+
+/**
+* USBMIDI example
+*
+* @code
+* #include "mbed.h"
+* #include "USBMIDI.h"
+*
+* USBMIDI midi;
+*
+* int main() {
+*    while (1) {
+*        for(int i=48; i<83; i++) {     // send some messages!
+*            midi.write(MIDIMessage::NoteOn(i));
+*            wait(0.25);
+*            midi.write(MIDIMessage::NoteOff(i));
+*            wait(0.5);
+*        }
+*    }
+* }
+* @endcode
+*/
+class USBMIDI: public USBDevice
+{
+public:
+
+    /**
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBMIDI( uint16_t vendor_id = 0x0700, uint16_t product_id = 0x0101, uint16_t product_release = 0x0001 );
+
+    /**
+     * Send a MIDIMessage
+     *
+     * @param m The MIDIMessage to send
+     */
+    void write( MIDIMessage m );
+
+    /**
+     * Attach a callback for when a MIDIEvent is received
+     *
+     * @param fptr function pointer
+     */
+    void attach( void ( *fptr )( MIDIMessage ) );
+
+
+protected:
+    virtual bool EP2_OUT_callback();
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+private:
+    void ( *midi_evt )( MIDIMessage );
+
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBMSD/USBMSD.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMSD/USBMSD.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,756 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBMSD.h"
+
+#define DISK_OK         0x00
+#define NO_INIT         0x01
+#define NO_DISK         0x02
+#define WRITE_PROTECT   0x04
+
+#define CBW_Signature   0x43425355
+#define CSW_Signature   0x53425355
+
+// SCSI Commands
+#define TEST_UNIT_READY            0x00
+#define REQUEST_SENSE              0x03
+#define FORMAT_UNIT                0x04
+#define INQUIRY                    0x12
+#define MODE_SELECT6               0x15
+#define MODE_SENSE6                0x1A
+#define START_STOP_UNIT            0x1B
+#define MEDIA_REMOVAL              0x1E
+#define READ_FORMAT_CAPACITIES     0x23
+#define READ_CAPACITY              0x25
+#define READ10                     0x28
+#define WRITE10                    0x2A
+#define VERIFY10                   0x2F
+#define READ12                     0xA8
+#define WRITE12                    0xAA
+#define MODE_SELECT10              0x55
+#define MODE_SENSE10               0x5A
+
+// MSC class specific requests
+#define MSC_REQUEST_RESET          0xFF
+#define MSC_REQUEST_GET_MAX_LUN    0xFE
+
+#define DEFAULT_CONFIGURATION (1)
+
+// max packet size
+#define MAX_PACKET  MAX_PACKET_SIZE_EPBULK
+
+// CSW Status
+enum Status
+{
+    CSW_PASSED,
+    CSW_FAILED,
+    CSW_ERROR,
+};
+
+
+USBMSD::USBMSD( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
+{
+}
+
+
+
+// Called in ISR context to process a class specific request
+bool USBMSD::USBCallback_request( void )
+{
+    bool success = false;
+    CONTROL_TRANSFER *transfer = getTransferPtr();
+    static uint8_t maxLUN[1] = {0};
+
+    if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
+    {
+        switch ( transfer->setup.bRequest )
+        {
+            case MSC_REQUEST_RESET:
+                reset();
+                success = true;
+                break;
+
+            case MSC_REQUEST_GET_MAX_LUN:
+                transfer->remaining = 1;
+                transfer->ptr = maxLUN;
+                transfer->direction = DEVICE_TO_HOST;
+                success = true;
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+bool USBMSD::connect()
+{
+    //disk initialization
+    if ( disk_status() & NO_INIT )
+    {
+        if ( disk_initialize() )
+        {
+            return false;
+        }
+    }
+
+    // get number of blocks
+    BlockCount = disk_sectors();
+    // get memory size
+    MemorySize = disk_size();
+
+    if ( BlockCount >= 0 )
+    {
+        BlockSize = MemorySize / BlockCount;
+
+        if ( BlockSize != 0 )
+        {
+            page = ( uint8_t * )malloc( BlockSize * sizeof( uint8_t ) );
+
+            if ( page == NULL )
+            {
+                return false;
+            }
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    //connect the device
+    USBDevice::connect();
+    return true;
+}
+
+
+void USBMSD::reset()
+{
+    stage = READ_CBW;
+}
+
+
+// Called in ISR context called when a data is received
+bool USBMSD::EP2_OUT_callback()
+{
+    uint32_t size = 0;
+    uint8_t buf[MAX_PACKET_SIZE_EPBULK];
+    readEP( EPBULK_OUT, buf, &size, MAX_PACKET_SIZE_EPBULK );
+
+    switch ( stage )
+    {
+            // the device has to decode the CBW received
+        case READ_CBW:
+            CBWDecode( buf, size );
+            break;
+
+            // the device has to receive data from the host
+        case PROCESS_CBW:
+            switch ( cbw.CB[0] )
+            {
+                case WRITE10:
+                case WRITE12:
+                    memoryWrite( buf, size );
+                    break;
+
+                case VERIFY10:
+                    memoryVerify( buf, size );
+                    break;
+            }
+
+            break;
+
+            // an error has occured: stall endpoint and send CSW
+        default:
+            stallEndpoint( EPBULK_OUT );
+            csw.Status = CSW_ERROR;
+            sendCSW();
+            break;
+    }
+
+    //reactivate readings on the OUT bulk endpoint
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+// Called in ISR context when a data has been transferred
+bool USBMSD::EP2_IN_callback()
+{
+    switch ( stage )
+    {
+            // the device has to send data to the host
+        case PROCESS_CBW:
+            switch ( cbw.CB[0] )
+            {
+                case READ10:
+                case READ12:
+                    memoryRead();
+                    break;
+            }
+
+            break;
+
+            //the device has to send a CSW
+        case SEND_CSW:
+            sendCSW();
+            break;
+
+            // an error has occured
+        case ERROR:
+            stallEndpoint( EPBULK_IN );
+            sendCSW();
+            break;
+
+            // the host has received the CSW -> we wait a CBW
+        case WAIT_CSW:
+            stage = READ_CBW;
+            break;
+    }
+
+    return true;
+}
+
+
+void USBMSD::memoryWrite ( uint8_t *buf, uint16_t size )
+{
+    if ( ( addr + size ) > MemorySize )
+    {
+        size = MemorySize - addr;
+        stage = ERROR;
+        stallEndpoint( EPBULK_OUT );
+    }
+
+    // we fill an array in RAM of 1 block before writing it in memory
+    for ( int i = 0; i < size; i++ )
+    {
+        page[addr % BlockSize + i] = buf[i];
+    }
+
+    // if the array is filled, write it in memory
+    if ( !( ( addr + size ) % BlockSize ) )
+    {
+        if ( !( disk_status() & WRITE_PROTECT ) )
+        {
+            disk_write( ( const char * )page, addr / BlockSize );
+        }
+    }
+
+    addr += size;
+    length -= size;
+    csw.DataResidue -= size;
+
+    if ( ( !length ) || ( stage != PROCESS_CBW ) )
+    {
+        csw.Status = ( stage == ERROR ) ? CSW_FAILED : CSW_PASSED;
+        sendCSW();
+    }
+}
+
+void USBMSD::memoryVerify ( uint8_t *buf, uint16_t size )
+{
+    uint32_t n;
+
+    if ( ( addr + size ) > MemorySize )
+    {
+        size = MemorySize - addr;
+        stage = ERROR;
+        stallEndpoint( EPBULK_OUT );
+    }
+
+    // beginning of a new block -> load a whole block in RAM
+    if ( !( addr % BlockSize ) )
+    {
+        disk_read( ( char * )page, addr / BlockSize );
+    }
+
+    // info are in RAM -> no need to re-read memory
+    for ( n = 0; n < size; n++ )
+    {
+        if ( page[addr % BlockSize + n] != buf[n] )
+        {
+            memOK = false;
+            break;
+        }
+    }
+
+    addr += size;
+    length -= size;
+    csw.DataResidue -= size;
+
+    if ( !length || ( stage != PROCESS_CBW ) )
+    {
+        csw.Status = ( memOK && ( stage == PROCESS_CBW ) ) ? CSW_PASSED : CSW_FAILED;
+        sendCSW();
+    }
+}
+
+
+bool USBMSD::inquiryRequest ( void )
+{
+    uint8_t inquiry[] = { 0x00, 0x80, 0x00, 0x01,
+                          36 - 4, 0x80, 0x00, 0x00,
+                          'M', 'B', 'E', 'D', '.', 'O', 'R', 'G',
+                          'M', 'B', 'E', 'D', ' ', 'U', 'S', 'B', ' ', 'D', 'I', 'S', 'K', ' ', ' ', ' ',
+                          '1', '.', '0', ' ',
+                        };
+
+    if ( !write( inquiry, sizeof( inquiry ) ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool USBMSD::readFormatCapacity()
+{
+    uint8_t capacity[] = { 0x00, 0x00, 0x00, 0x08,
+                           ( BlockCount >> 24 ) & 0xff,
+                           ( BlockCount >> 16 ) & 0xff,
+                           ( BlockCount >> 8 ) & 0xff,
+                           ( BlockCount >> 0 ) & 0xff,
+
+                           0x02,
+                           ( BlockSize >> 16 ) & 0xff,
+                           ( BlockSize >> 8 ) & 0xff,
+                           ( BlockSize >> 0 ) & 0xff,
+                         };
+
+    if ( !write( capacity, sizeof( capacity ) ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool USBMSD::readCapacity ( void )
+{
+    uint8_t capacity[] =
+    {
+        ( ( BlockCount - 1 ) >> 24 ) & 0xff,
+        ( ( BlockCount - 1 ) >> 16 ) & 0xff,
+        ( ( BlockCount - 1 ) >> 8 ) & 0xff,
+        ( ( BlockCount - 1 ) >> 0 ) & 0xff,
+
+        ( BlockSize >> 24 ) & 0xff,
+        ( BlockSize >> 16 ) & 0xff,
+        ( BlockSize >> 8 ) & 0xff,
+        ( BlockSize >> 0 ) & 0xff,
+    };
+
+    if ( !write( capacity, sizeof( capacity ) ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool USBMSD::write ( uint8_t *buf, uint16_t size )
+{
+    if ( size >= cbw.DataLength )
+    {
+        size = cbw.DataLength;
+    }
+
+    stage = SEND_CSW;
+
+    if ( !writeNB( EPBULK_IN, buf, size, MAX_PACKET_SIZE_EPBULK ) )
+    {
+        return false;
+    }
+
+    csw.DataResidue -= size;
+    csw.Status = CSW_PASSED;
+    return true;
+}
+
+
+bool USBMSD::modeSense6 ( void )
+{
+    uint8_t sense6[] = { 0x03, 0x00, 0x00, 0x00 };
+
+    if ( !write( sense6, sizeof( sense6 ) ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void USBMSD::sendCSW()
+{
+    csw.Signature = CSW_Signature;
+    writeNB( EPBULK_IN, ( uint8_t * )&csw, sizeof( CSW ), MAX_PACKET_SIZE_EPBULK );
+    stage = WAIT_CSW;
+}
+
+bool USBMSD::requestSense ( void )
+{
+    uint8_t request_sense[] =
+    {
+        0x70,
+        0x00,
+        0x05,   // Sense Key: illegal request
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+        0x0A,
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+        0x30,
+        0x01,
+        0x00,
+        0x00,
+        0x00,
+        0x00,
+    };
+
+    if ( !write( request_sense, sizeof( request_sense ) ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void USBMSD::fail()
+{
+    csw.Status = CSW_FAILED;
+    sendCSW();
+}
+
+
+void USBMSD::CBWDecode( uint8_t *buf, uint16_t size )
+{
+    if ( size == sizeof( cbw ) )
+    {
+        memcpy( ( uint8_t * )&cbw, buf, size );
+
+        if ( cbw.Signature == CBW_Signature )
+        {
+            csw.Tag = cbw.Tag;
+            csw.DataResidue = cbw.DataLength;
+
+            if ( ( cbw.CBLength <  1 ) || ( cbw.CBLength > 16 ) )
+            {
+                fail();
+            }
+            else
+            {
+                switch ( cbw.CB[0] )
+                {
+                    case TEST_UNIT_READY:
+                        testUnitReady();
+                        break;
+
+                    case REQUEST_SENSE:
+                        requestSense();
+                        break;
+
+                    case INQUIRY:
+                        inquiryRequest();
+                        break;
+
+                    case MODE_SENSE6:
+                        modeSense6();
+                        break;
+
+                    case READ_FORMAT_CAPACITIES:
+                        readFormatCapacity();
+                        break;
+
+                    case READ_CAPACITY:
+                        readCapacity();
+                        break;
+
+                    case READ10:
+                    case READ12:
+                        if ( infoTransfer() )
+                        {
+                            if ( ( cbw.Flags & 0x80 ) )
+                            {
+                                stage = PROCESS_CBW;
+                                memoryRead();
+                            }
+                            else
+                            {
+                                stallEndpoint( EPBULK_OUT );
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+
+                        break;
+
+                    case WRITE10:
+                    case WRITE12:
+                        if ( infoTransfer() )
+                        {
+                            if ( !( cbw.Flags & 0x80 ) )
+                            {
+                                stage = PROCESS_CBW;
+                            }
+                            else
+                            {
+                                stallEndpoint( EPBULK_IN );
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+
+                        break;
+
+                    case VERIFY10:
+                        if ( !( cbw.CB[1] & 0x02 ) )
+                        {
+                            csw.Status = CSW_PASSED;
+                            sendCSW();
+                            break;
+                        }
+
+                        if ( infoTransfer() )
+                        {
+                            if ( !( cbw.Flags & 0x80 ) )
+                            {
+                                stage = PROCESS_CBW;
+                                memOK = true;
+                            }
+                            else
+                            {
+                                stallEndpoint( EPBULK_IN );
+                                csw.Status = CSW_ERROR;
+                                sendCSW();
+                            }
+                        }
+
+                        break;
+
+                    default:
+                        fail();
+                        break;
+                }
+            }
+        }
+    }
+}
+
+void USBMSD::testUnitReady ( void )
+{
+    if ( cbw.DataLength != 0 )
+    {
+        if ( ( cbw.Flags & 0x80 ) != 0 )
+        {
+            stallEndpoint( EPBULK_IN );
+        }
+        else
+        {
+            stallEndpoint( EPBULK_OUT );
+        }
+    }
+
+    csw.Status = CSW_PASSED;
+    sendCSW();
+}
+
+
+void USBMSD::memoryRead ( void )
+{
+    uint32_t n;
+    n = ( length > MAX_PACKET ) ? MAX_PACKET : length;
+
+    if ( ( addr + n ) > MemorySize )
+    {
+        n = MemorySize - addr;
+        stage = ERROR;
+    }
+
+    // we read an entire block
+    if ( !( addr % BlockSize ) )
+    {
+        disk_read( ( char * )page, addr / BlockSize );
+    }
+
+    // write data which are in RAM
+    writeNB( EPBULK_IN, &page[addr % BlockSize], n, MAX_PACKET_SIZE_EPBULK );
+    addr += n;
+    length -= n;
+    csw.DataResidue -= n;
+
+    if ( !length || ( stage != PROCESS_CBW ) )
+    {
+        csw.Status = ( stage == PROCESS_CBW ) ? CSW_PASSED : CSW_FAILED;
+        stage = ( stage == PROCESS_CBW ) ? SEND_CSW : stage;
+    }
+}
+
+
+bool USBMSD::infoTransfer ( void )
+{
+    uint32_t n;
+    // Logical Block Address of First Block
+    n = ( cbw.CB[2] << 24 ) | ( cbw.CB[3] << 16 ) | ( cbw.CB[4] <<  8 ) | ( cbw.CB[5] <<  0 );
+    addr = n * BlockSize;
+
+    // Number of Blocks to transfer
+    switch ( cbw.CB[0] )
+    {
+        case READ10:
+        case WRITE10:
+        case VERIFY10:
+            n = ( cbw.CB[7] <<  8 ) | ( cbw.CB[8] <<  0 );
+            break;
+
+        case READ12:
+        case WRITE12:
+            n = ( cbw.CB[6] << 24 ) | ( cbw.CB[7] << 16 ) | ( cbw.CB[8] <<  8 ) | ( cbw.CB[9] <<  0 );
+            break;
+    }
+
+    length = n * BlockSize;
+
+    if ( !cbw.DataLength )              // host requests no data
+    {
+        csw.Status = CSW_FAILED;
+        sendCSW();
+        return false;
+    }
+
+    if ( cbw.DataLength != length )
+    {
+        if ( ( cbw.Flags & 0x80 ) != 0 )
+        {
+            stallEndpoint( EPBULK_IN );
+        }
+        else
+        {
+            stallEndpoint( EPBULK_OUT );
+        }
+
+        csw.Status = CSW_FAILED;
+        sendCSW();
+        return false;
+    }
+
+    return true;
+}
+
+
+
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBMSD::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK );
+    addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    //activate readings
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+
+uint8_t *USBMSD::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x08,                           //bLength
+        STRING_DESCRIPTOR,              //bDescriptorType 0x03
+        'M', 0, 'S', 0, 'D', 0          //bString iInterface - MSD
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBMSD::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x12,                                           //bLength
+        STRING_DESCRIPTOR,                              //bDescriptorType 0x03
+        'M', 0, 'b', 0, 'e', 0, 'd', 0, ' ', 0, 'M', 0, 'S', 0, 'D', 0 //bString iProduct - Mbed Audio
+    };
+    return stringIproductDescriptor;
+}
+
+
+uint8_t *USBMSD::configurationDesc()
+{
+    static uint8_t configDescriptor[] =
+    {
+
+        // Configuration 1
+        9,      // bLength
+        2,      // bDescriptorType
+        LSB( 9 + 9 + 7 + 7 ), // wTotalLength
+        MSB( 9 + 9 + 7 + 7 ),
+        0x01,   // bNumInterfaces
+        0x01,   // bConfigurationValue: 0x01 is used to select this configuration
+        0x00,   // iConfiguration: no string to describe this configuration
+        0xC0,   // bmAttributes
+        100,    // bMaxPower, device power consumption is 100 mA
+
+        // Interface 0, Alternate Setting 0, MSC Class
+        9,      // bLength
+        4,      // bDescriptorType
+        0x00,   // bInterfaceNumber
+        0x00,   // bAlternateSetting
+        0x02,   // bNumEndpoints
+        0x08,   // bInterfaceClass
+        0x06,   // bInterfaceSubClass
+        0x50,   // bInterfaceProtocol
+        0x04,   // iInterface
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                          // bLength
+        5,                          // bDescriptorType
+        PHY_TO_DESC( EPBULK_IN ),   // bEndpointAddress
+        0x02,                       // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB)
+        0,                          // bInterval
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                          // bLength
+        5,                          // bDescriptorType
+        PHY_TO_DESC( EPBULK_OUT ),  // bEndpointAddress
+        0x02,                       // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ), // wMaxPacketSize (MSB)
+        0                           // bInterval
+    };
+    return configDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBMSD/USBMSD.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBMSD/USBMSD.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,244 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#ifndef USBMSD_H
+#define USBMSD_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBDevice/USBDevice/USBDevice.h"
+
+/**
+ * USBMSD class: generic class in order to use all kinds of blocks storage chip
+ *
+ * Introduction
+ *
+ * The USBMSD implements the MSD protocol. It permits to access a memory chip (flash, sdcard,...)
+ * from a computer over USB. But this class doesn't work standalone, you need to subclass this class
+ * and define virtual functions which are called in USBMSD.
+ *
+ * How to use this class with your chip ?
+ *
+ * You have to inherit and define some pure virtual functions (mandatory step):
+ *   - virtual int disk_read(char * data, int block): function to read a block
+ *   - virtual int disk_write(const char * data, int block): function to write a block
+ *   - virtual int disk_initialize(): function to initialize the memory
+ *   - virtual int disk_sectors(): return the number of blocks
+ *   - virtual int disk_size(): return the memory size
+ *   - virtual int disk_status(): return the status of the storage chip (0: OK, 1: not initialized, 2: no medium in the drive, 4: write protection)
+ *
+ * All functions names are compatible with the fat filesystem library. So you can imagine using your own class with
+ * USBMSD and the fat filesystem library in the same program. Just be careful because there are two different parts which
+ * will access the sd card. You can do a master/slave system using the disk_status method.
+ *
+ * Once these functions defined, you can call connect() (at the end of the constructor of your class for instance)
+ * of USBMSD to connect your mass storage device. connect() will first call disk_status() to test the status of the disk.
+ * If disk_status() returns 1 (disk not initialized), then disk_initialize() is called. After this step, connect() will collect information
+ * such as the number of blocks and the memory size.
+ */
+class USBMSD: public USBDevice
+{
+public:
+
+    /**
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBMSD( uint16_t vendor_id = 0x0703, uint16_t product_id = 0x0104, uint16_t product_release = 0x0001 );
+
+    /**
+    * Connect the USB MSD device. Establish disk initialization before really connect the device.
+    *
+    * @returns true if successful
+    */
+    bool connect();
+
+
+protected:
+
+    /*
+    * read a block on a storage chip
+    *
+    * @param data pointer where will be stored read data
+    * @param block block number
+    * @returns 0 if successful
+    */
+    virtual int disk_read( char *data, int block ) = 0;
+
+    /*
+    * write a block on a storage chip
+    *
+    * @param data data to write
+    * @param block block number
+    * @returns 0 if successful
+    */
+    virtual int disk_write( const char *data, int block ) = 0;
+
+    /*
+    * Disk initilization
+    */
+    virtual int disk_initialize() = 0;
+
+    /*
+    * Return the number of blocks
+    *
+    * @returns number of blocks
+    */
+    virtual int disk_sectors() = 0;
+
+    /*
+    * Return memory size
+    *
+    * @returns memory size
+    */
+    virtual int disk_size() = 0;
+
+
+    /*
+    * To check the status of the storage chip
+    *
+    * @returns status: 0: OK, 1: disk not initialized, 2: no medium in the drive, 4: write protected
+    */
+    virtual int disk_status() = 0;
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+    /*
+    * Callback called when a packet is received
+    */
+    virtual bool EP2_OUT_callback();
+
+    /*
+    * Callback called when a packet has been sent
+    */
+    virtual bool EP2_IN_callback();
+
+    /*
+    * Set configuration of device. Add endpoints
+    */
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+
+    /*
+    * Callback called to process class specific requests
+    */
+    virtual bool USBCallback_request();
+
+
+private:
+
+    // MSC Bulk-only Stage
+    enum Stage
+    {
+        READ_CBW,     // wait a CBW
+        ERROR,        // error
+        PROCESS_CBW,  // process a CBW request
+        SEND_CSW,     // send a CSW
+        WAIT_CSW,     // wait that a CSW has been effectively sent
+    };
+
+    // Bulk-only CBW
+    typedef __packed struct
+    {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataLength;
+        uint8_t  Flags;
+        uint8_t  LUN;
+        uint8_t  CBLength;
+        uint8_t  CB[16];
+    } CBW;
+
+    // Bulk-only CSW
+    typedef __packed struct
+    {
+        uint32_t Signature;
+        uint32_t Tag;
+        uint32_t DataResidue;
+        uint8_t  Status;
+    } CSW;
+
+    //state of the bulk-only state machine
+    Stage stage;
+
+    // current CBW
+    CBW cbw;
+
+    // CSW which will be sent
+    CSW csw;
+
+    // addr where will be read or written data
+    uint32_t addr;
+
+    // length of a reading or writing
+    uint32_t length;
+
+    // memory OK (after a memoryVerify)
+    bool memOK;
+
+    // cache in RAM before writing in memory. Useful also to read a block.
+    uint8_t *page;
+
+    int BlockSize;
+    int MemorySize;
+    int BlockCount;
+
+    void CBWDecode( uint8_t *buf, uint16_t size );
+    void sendCSW ( void );
+    bool inquiryRequest ( void );
+    bool write ( uint8_t *buf, uint16_t size );
+    bool readFormatCapacity();
+    bool readCapacity ( void );
+    bool infoTransfer ( void );
+    void memoryRead ( void );
+    bool modeSense6 ( void );
+    void testUnitReady ( void );
+    bool requestSense ( void );
+    void memoryVerify ( uint8_t *buf, uint16_t size );
+    void memoryWrite ( uint8_t *buf, uint16_t size );
+    void reset();
+    void fail();
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBSerial/CircBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial/CircBuffer.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,82 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef CIRCBUFFER_H
+#define CIRCBUFFER_H
+
+template <class T>
+class CircBuffer
+{
+public:
+    CircBuffer( int length )
+    {
+        write = 0;
+        read = 0;
+        size = length + 1;
+        buf = ( T * )malloc( size * sizeof( T ) );
+    };
+
+    bool isFull()
+    {
+        return ( ( write + 1 ) % size == read );
+    };
+
+    bool isEmpty()
+    {
+        return ( read == write );
+    };
+
+    void queue( T k )
+    {
+        if ( isFull() )
+        {
+            read++;
+            read %= size;
+        }
+
+        buf[write++] = k;
+        write %= size;
+    }
+
+    uint16_t available()
+    {
+        return ( write >= read ) ? write - read : size - read + write;
+    };
+
+    bool dequeue( T *c )
+    {
+        bool empty = isEmpty();
+
+        if ( !empty )
+        {
+            *c = buf[read++];
+            read %= size;
+        }
+
+        return( !empty );
+    };
+
+private:
+    volatile uint16_t write;
+    volatile uint16_t read;
+    uint16_t size;
+    T *buf;
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBSerial/USBCDC.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial/USBCDC.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,279 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBCDC.h"
+
+static uint8_t cdc_line_coding[7] = {0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08};
+
+#define DEFAULT_CONFIGURATION (1)
+
+#define CDC_SET_LINE_CODING        0x20
+#define CDC_GET_LINE_CODING        0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+
+#define MAX_CDC_REPORT_SIZE MAX_PACKET_SIZE_EPBULK
+
+USBCDC::USBCDC( uint16_t vendor_id, uint16_t product_id, uint16_t product_release ): USBDevice( vendor_id, product_id, product_release )
+{
+    // Moving this up into the USBSerial class
+    //USBDevice::connect();
+    terminal_status = 0;
+}
+
+uint8_t USBCDC::terminalIsOpen( void )
+{
+    return ( terminal_status ) ? 1 : 0;
+}
+
+bool USBCDC::USBCallback_request( void )
+{
+    /* Called in ISR context */
+    bool success = false;
+    CONTROL_TRANSFER *transfer = getTransferPtr();
+
+    /* Process class-specific requests */
+
+    if ( transfer->setup.bmRequestType.Type == CLASS_TYPE )
+    {
+        switch ( transfer->setup.bRequest )
+        {
+            case CDC_GET_LINE_CODING:
+                transfer->remaining = 7;
+                transfer->ptr = cdc_line_coding;
+                transfer->direction = DEVICE_TO_HOST;
+                success = true;
+                break;
+
+            case CDC_SET_LINE_CODING:
+                transfer->remaining = 7;
+                success = true;
+                break;
+
+            case CDC_SET_CONTROL_LINE_STATE:
+                // Look at DTR to determine if the terminal is opened on the PC
+                terminal_status = ( uint8_t )transfer->setup.wValue & 0x01;
+                success = true;
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    return success;
+}
+
+
+// Called in ISR context
+// Set configuration. Return false if the
+// configuration is not supported.
+bool USBCDC::USBCallback_setConfiguration( uint8_t configuration )
+{
+    if ( configuration != DEFAULT_CONFIGURATION )
+    {
+        return false;
+    }
+
+    // Configure endpoints > 0
+    addEndpoint( EPINT_IN, MAX_PACKET_SIZE_EPINT );
+    addEndpoint( EPBULK_IN, MAX_PACKET_SIZE_EPBULK );
+    addEndpoint( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    // We activate the endpoint to be able to recceive data
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+bool USBCDC::send( uint8_t *buffer, uint32_t size )
+{
+    return USBDevice::write( EPBULK_IN, buffer, size, MAX_CDC_REPORT_SIZE );
+}
+
+bool USBCDC::readEP( uint8_t *buffer, uint32_t *size )
+{
+    if ( !USBDevice::readEP( EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    if ( !readStart( EPBULK_OUT, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool USBCDC::readEP_NB( uint8_t *buffer, uint32_t *size )
+{
+    if ( !USBDevice::readEP_NB( EPBULK_OUT, buffer, size, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    if ( !readStart( EPBULK_OUT, MAX_CDC_REPORT_SIZE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+uint8_t *USBCDC::deviceDesc()
+{
+    static uint8_t deviceDescriptor[] =
+    {
+        18,                   // bLength
+        1,                    // bDescriptorType
+        0x10, 0x01,           // bcdUSB
+        2,                    // bDeviceClass
+        0,                    // bDeviceSubClass
+        0,                    // bDeviceProtocol
+        MAX_PACKET_SIZE_EP0,  // bMaxPacketSize0
+        LSB( VENDOR_ID ), MSB( VENDOR_ID ), // idVendor
+        LSB( PRODUCT_ID ), MSB( PRODUCT_ID ), // idProduct
+        0x00, 0x01,           // bcdDevice
+        1,                    // iManufacturer
+        2,                    // iProduct
+        3,                    // iSerialNumber
+        1                     // bNumConfigurations
+    };
+    return deviceDescriptor;
+}
+
+uint8_t *USBCDC::stringIinterfaceDesc()
+{
+    static uint8_t stringIinterfaceDescriptor[] =
+    {
+        0x08,
+        STRING_DESCRIPTOR,
+        'C', 0, 'D', 0, 'C', 0,
+    };
+    return stringIinterfaceDescriptor;
+}
+
+uint8_t *USBCDC::stringIproductDesc()
+{
+    static uint8_t stringIproductDescriptor[] =
+    {
+        0x16,
+        STRING_DESCRIPTOR,
+        'C', 0, 'D', 0, 'C', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0
+    };
+    return stringIproductDescriptor;
+}
+
+
+#define CONFIG1_DESC_SIZE (9+9+5+5+4+5+7+9+7+7)
+
+uint8_t *USBCDC::configurationDesc()
+{
+    static uint8_t configDescriptor[] =
+    {
+        9,                      // bLength;
+        2,                      // bDescriptorType;
+        LSB( CONFIG1_DESC_SIZE ), // wTotalLength
+        MSB( CONFIG1_DESC_SIZE ),
+        2,                      // bNumInterfaces
+        1,                      // bConfigurationValue
+        0,                      // iConfiguration
+        0x80,                   // bmAttributes
+        50,                     // bMaxPower
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                      // bLength
+        4,                      // bDescriptorType
+        0,                      // bInterfaceNumber
+        0,                      // bAlternateSetting
+        1,                      // bNumEndpoints
+        0x02,                   // bInterfaceClass
+        0x02,                   // bInterfaceSubClass
+        0x01,                   // bInterfaceProtocol
+        0,                      // iInterface
+
+        // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x00,                   // bDescriptorSubtype
+        0x10, 0x01,             // bcdCDC
+
+        // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x01,                   // bDescriptorSubtype
+        0x03,                   // bmCapabilities
+        1,                      // bDataInterface
+
+        // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
+        4,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x02,                   // bDescriptorSubtype
+        0x06,                   // bmCapabilities
+
+        // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
+        5,                      // bFunctionLength
+        0x24,                   // bDescriptorType
+        0x06,                   // bDescriptorSubtype
+        0,                      // bMasterInterface
+        1,                      // bSlaveInterface0
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        ENDPOINT_DESCRIPTOR_LENGTH,     // bLength
+        ENDPOINT_DESCRIPTOR,            // bDescriptorType
+        PHY_TO_DESC( EPINT_IN ),        // bEndpointAddress
+        E_INTERRUPT,                    // bmAttributes (0x03=intr)
+        LSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPINT ),   // wMaxPacketSize (MSB)
+        16,                             // bInterval
+
+
+
+
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,          // bLength
+        4,          // bDescriptorType
+        1,          // bInterfaceNumber
+        0,          // bAlternateSetting
+        2,          // bNumEndpoints
+        0x0A,       // bInterfaceClass
+        0x00,       // bInterfaceSubClass
+        0x00,       // bInterfaceProtocol
+        0,          // iInterface
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                      // bLength
+        5,                      // bDescriptorType
+        PHY_TO_DESC( EPBULK_IN ), // bEndpointAddress
+        0x02,                   // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (MSB)
+        0,                      // bInterval
+
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                      // bLength
+        5,                      // bDescriptorType
+        PHY_TO_DESC( EPBULK_OUT ), // bEndpointAddress
+        0x02,                   // bmAttributes (0x02=bulk)
+        LSB( MAX_PACKET_SIZE_EPBULK ),  // wMaxPacketSize (LSB)
+        MSB( MAX_PACKET_SIZE_EPBULK ),   // wMaxPacketSize (MSB)
+        0                       // bInterval
+    };
+    return configDescriptor;
+}
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBSerial/USBCDC.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial/USBCDC.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBCDC_H
+#define USBCDC_H
+
+/* These headers are included for child class. */
+#include "USBDevice/USBDevice/USBEndpoints.h"
+#include "USBDevice/USBDevice/USBDescriptor.h"
+#include "USBDevice/USBDevice/USBDevice_Types.h"
+
+#include "USBDevice/USBDevice/USBDevice.h"
+
+class USBCDC: public USBDevice
+{
+private:
+    volatile uint8_t terminal_status;
+
+public:
+
+    /*
+    * Constructor
+    *
+    * @param vendor_id Your vendor_id
+    * @param product_id Your product_id
+    * @param product_release Your preoduct_release
+    */
+    USBCDC( uint16_t vendor_id, uint16_t product_id, uint16_t product_release );
+
+    uint8_t terminalIsOpen( void );
+
+protected:
+
+    /*
+    * Get device descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual uint8_t *deviceDesc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual uint8_t *stringIproductDesc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual uint8_t *stringIinterfaceDesc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @returns pointer to the configuration descriptor
+    */
+    virtual uint8_t *configurationDesc();
+
+    /*
+    * Send a buffer
+    *
+    * @param endpoint endpoint which will be sent the buffer
+    * @param buffer buffer to be sent
+    * @param size length of the buffer
+    * @returns true if successful
+    */
+    bool send( uint8_t *buffer, uint32_t size );
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP( uint8_t *buffer, uint32_t *size );
+
+    /*
+    * Read a buffer from a certain endpoint. Warning: non blocking
+    *
+    * @param endpoint endpoint to read
+    * @param buffer buffer where will be stored bytes
+    * @param size the number of bytes read will be stored in *size
+    * @param maxSize the maximum length that can be read
+    * @returns true if successful
+    */
+    bool readEP_NB( uint8_t *buffer, uint32_t *size );
+
+    virtual bool USBCallback_request();
+    virtual bool USBCallback_setConfiguration( uint8_t configuration );
+
+};
+
+#endif
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBSerial/USBSerial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial/USBSerial.cpp	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,151 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBSerial.h"
+#include <stdarg.h>
+
+USBSerial::USBSerial( uint16_t vendor_id, uint16_t product_id, uint16_t product_release )
+    : USBCDC( vendor_id, product_id, product_release )
+    , buf( 128 )
+#ifdef USB_ERRATA_WORKAROUND
+    , _connect( P0_6 )
+    , _vbus( P0_3 )
+#endif
+{
+#ifdef USB_ERRATA_WORKAROUND
+    _connect = 1;
+#endif
+    return;
+}
+
+int USBSerial::_putc( int c )
+{
+    send( ( uint8_t * )&c, 1 );
+    return 1;
+}
+
+int USBSerial::_getc()
+{
+    uint8_t c;
+
+    while ( buf.isEmpty() );
+
+    buf.dequeue( &c );
+    return c;
+}
+
+void USBSerial::flush( void )
+{
+    while( available() )
+    {
+        _getc();
+    }
+
+    return;
+}
+
+void USBSerial::printf( const char *format, ... )
+{
+    static char buf[128];
+    uint32_t len = 0;
+    va_list arg;
+
+    if ( strlen( format ) < 64 )
+    {
+        va_start( arg, format );
+        vsprintf( buf, format, arg );
+        va_end( arg );
+        // write to the peripheral
+        len = strlen( buf );
+        send( ( uint8_t * )buf, len );
+        // and erase the buffer conents
+        memset( buf, 0, len );
+    }
+
+    return;
+}
+
+bool USBSerial::writeBlock( uint8_t *buf, uint16_t size )
+{
+    if( size > MAX_PACKET_SIZE_EPBULK )
+    {
+        return false;
+    }
+
+    if( !send( buf, size ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool USBSerial::writeBlock( const char *buf )
+{
+    uint16_t cnt = 0;
+
+    while( buf[cnt++] != 0 );
+
+    return writeBlock( ( uint8_t * )buf, cnt );
+}
+
+bool USBSerial::EP2_OUT_callback()
+{
+    uint8_t c[65];
+    uint32_t size = 0;
+    //we read the packet received and put it on the circular buffer
+    readEP( c, &size );
+
+    for ( int i = 0; i < size; i++ )
+    {
+        buf.queue( c[i] );
+    }
+
+    //call a potential handler
+    rx.call();
+    // We reactivate the endpoint to receive next characters
+    readStart( EPBULK_OUT, MAX_PACKET_SIZE_EPBULK );
+    return true;
+}
+
+uint8_t USBSerial::available()
+{
+    return buf.available();
+}
+
+#ifdef USB_ERRATA_WORKAROUND
+void USBSerial::connect( void )
+{
+    _connect = 0;
+    USBHAL::connect();
+    return;
+}
+void USBSerial::disconnect( void )
+{
+    _connect = 1;
+    USBHAL::disconnect();
+    return;
+}
+bool USBSerial::vbusDetected( void )
+{
+    return _vbus;
+}
+#endif
+
+
diff -r 8038fdeea4d4 -r a9671b78d24e USBSerial/USBSerial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBSerial/USBSerial.h	Mon Jul 22 21:16:27 2013 +0000
@@ -0,0 +1,154 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef USBSERIAL_H
+#define USBSERIAL_H
+
+#include "USBCDC.h"
+#include "Stream.h"
+#include "CircBuffer.h"
+
+
+/**
+* USBSerial example
+*
+* @code
+* #include "mbed.h"
+* #include "USBSerial.h"
+*
+* //Virtual serial port over USB
+* USBSerial serial;
+*
+* int main(void) {
+*
+*    while(1)
+*    {
+*        serial.printf("I am a virtual serial port\n");
+*        wait(1);
+*    }
+* }
+* @endcode
+*/
+class USBSerial: public USBCDC//, public Stream
+{
+public:
+
+    /**
+    *   Constructor
+    *
+    * @param vendor_id Your vendor_id (default: 0x1f00)
+    * @param product_id Your product_id (default: 0x2012)
+    * @param product_release Your preoduct_release (default: 0x0001)
+    *
+    */
+    USBSerial( uint16_t vendor_id = 0x1f00, uint16_t product_id = 0x2012, uint16_t product_release = 0x0001 );
+
+
+    /**
+    * Send a character. You can use puts, printf.
+    *
+    * @param c character to be sent
+    * @returns true if there is no error, false otherwise
+    */
+    virtual int _putc( int c );
+
+    /**
+    * Read a character: blocking
+    *
+    * @returns character read
+    */
+    virtual int _getc();
+
+    /**
+    * Check the number of bytes available.
+    *
+    * @returns the number of bytes available
+    */
+    uint8_t available();
+
+
+    /**
+     * Check the number of bytes available.
+     */
+    void flush( void );
+
+    /**
+    * Write a block of data.
+    *
+    * For more efficiency, a block of size 64 (maximum size of a bulk endpoint) has to be written.
+    *
+    * @param buf pointer on data which will be written
+    * @param size size of the buffer. The maximum size of a block is limited by the size of the endpoint (64 bytes)
+    *
+    * @returns true if successfull
+    */
+    bool writeBlock( uint8_t *buf, uint16_t size );
+    bool writeBlock( const char *buf );
+    void printf( const char *format, ... );
+
+#ifdef USB_ERRATA_WORKAROUND
+    void connect( void );
+    void disconnect( void );
+    bool vbusDetected( void );
+#endif
+
+    /**
+     *  Attach a member function to call when a packet is received.
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach( T *tptr, void ( T::*mptr )( void ) )
+    {
+        if( ( mptr != NULL ) && ( tptr != NULL ) )
+        {
+            rx.attach( tptr, mptr );
+        }
+    }
+
+    /**
+     * Attach a callback called when a packet is received
+     *
+     * @param fptr function pointer
+     */
+    void attach( void ( *fn )( void ) )
+    {
+        if( fn != NULL )
+        {
+            rx.attach( fn );
+        }
+    }
+
+
+protected:
+    virtual bool EP2_OUT_callback();
+
+private:
+    FunctionPointer rx;
+    CircBuffer<uint8_t> buf;
+
+#ifdef USB_ERRATA_WORKAROUND
+    DigitalOut _connect;
+    DigitalIn _vbus;
+#endif
+
+};
+
+#endif
+